Reputation: 147
My question is absolutely theoretic, like "Is it right thing to do?". I'm new to Rails in particular and to Ruby in general, and I'm trying to use Cancan autorization solution for my Rails appilcation.
Let's consider we have a simple contoller like this, a pair of associated views and an User model with DB table.
class UsersController < ApplicationController
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
end
The goal is to restrict access to the "index" method to all but admins and permit regular users to see only their own pages, e.g. to permit user with id==5 to see page "users/5". For this scope I've create an ability class for Cancan. Here it is:
class Ability
include CanCan::Ability
def initialize user, options = {}
default_rules
if user
admin_rules(user) if user.role.eql? "admin"
player_rules(user) if user.role.eql? "player"
end
end
def admin_rules user
can :read, UsersController
end
def player_rules user
can :read, User do |user_requested|
user_requested.id == user.id
end
end
def default_rules
end
end
My question is that: Should I use UsersController as an object in "can" method if I do not have a handy one of type User? To applicate it later by "authorize! :show, UsersController" in the "index" method of the controller. Or it should be done in some other way? Thank you for your suggestions.
Upvotes: 0
Views: 687
Reputation: 89
+1 to @Tigraine.
Follow his instructions...
class Ability
include CanCan::Ability
def initialize user, options = {}
default_rules
if user
admin_rules(user) if user.role.eql? "admin"
player_rules(user) if user.role.eql? "player"
end
end
def admin_rules user
can :manage, User
end
def player_rules user
can :manage, User :id => user.id
end
def default_rules
end
end
and do this in your controller...
class UsersController < ApplicationController
load_and_authorize_resource
# => @users for index
# => @user for show
def index
end
def show
end
end
for details on load_and_authorize_resource see the bottom of this link
Upvotes: 0
Reputation: 89
In the wiki I found another way to set the ability. It's kind of advanced though, check it out here.
ApplicationController.subclasses.each do |controller|
if controller.respond_to?(:permission)
clazz, description = controller.permission
write_permission(clazz, "manage", description, "All operations")
controller.action_methods.each do |action|
...
Upvotes: 0
Reputation: 23648
No you don't want to add the UsersController to CanCan.
CanCan is meant to authorize resources, not Rails Controllers.
I would suggest the following:
def initialize(user)
if user.is_admin?
can :manage, User
else
can :manage, User, :id => user.id
end
end
This would allow the user only access to his own user unless he is an admin. See the Defining abilities page in CanCan Wiki
Upvotes: 2
Reputation: 38
I use a symbol, e.g., in the Ability class
def initialize(user)
if user.is_admin?
can :any, :admin
end
end
and in the controller
authorize! :any, :admin
Upvotes: 0