Rails-4 Devise + CanCan not hiding edit and destroy links
I am using CanCan and Devise, but the devise users is managed via custom
UsersController. I want only a logged_in user to see the edit and destroy
links. But right now depend on what is passed to the ability class, it
either hids the edit and destroy links for all users including logged_in
user or it exposes the edit and destroy links of all users to any
signed_in user, hence they can edit any user account event if it wasn't
theirs.
users/index.html.erb
<% @users.each do |user| %>
<div class="col-lg-3 col-sm-4 col-6">
<div><%= user.email %></div>
<% if user_signed_in? %>
<% if can? :update, user %>
<div class=" btn "><%= link_to "Edit", edit_user_path(user) %>
</div>
<% end %>
<% if can? :destroy, user %>
<div class="btn btn-danger"><%= link_to 'Remove', user, method:
:delete, data: {confirmation: 'Are you sure'} %></div>
<% end %>
<div><%= link_to "Sign Out", destroy_user_session_path, method:
:delete %> </div>
<% end %> <!-- closes user_signed_in? -->
</div>
<% end %>
The ability class
class Ability
include CanCan::Ability
def initialize(user)
#to ensure user object is not nil when no user object is passed in
user ||= User.new
can :manage, User do |user|
#this exposes the destroy and edit links for all users including
users not yet signed_in
#user.id == user.id
#this hide the destroy and edit links for all users including
signed_in user
user == :user_id
end
end
end
Please Note that I added the Userscontroller below the 2nd screenshot
screen shot 1 shows that if user.id == user.id in the ability class is
uncommented, exposes the destroy and edit links for all users including
users not yet signed_in and the signed_in user can edit accounts not
belonging to him. In the screenshot, the real signed_in user's email is
a@test.com but you can see that he has access to the edit and destroy
links for the user that is not signed_in which b@test.com
Screen shot 2, is what we get when we uncomment user == :user_id in the
ability class. The edit and destroy links are hidden even from the
signed_in user.
Shortened version of the User controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :update, :destroy]
before_filter :authenticate_user!, except: [:new, :create]
load_and_authorize_resource , only: [:index, :edit, :destroy]
respond_to :html, :json
def index
@users = User.all
respond_with @users
end
def edit
#@user = User.find(params[:id])
#respond_with @user
end
def destroy
@user.destroy
redirect_to users_path, {notice: 'A user was removed'}
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
The sessions controller
class UsersSessionsController < Devise::SessionsController
respond_to :html, :json
def create
super
if signed_in?(resource)
#call the code to transfer guest cart to signed_in user
load_current_cart
end
end
end
No comments:
Post a Comment