Reputation: 208
I've got a page for administrating multiple objects (like users and groups), and I want to ensure that only users who have access to create at least one of those types of objects can view the page.
Basically, I want to be able to write something like
(authorize! :create, User) || (authorize! :create, Group)
Any suggestions?
Upvotes: 4
Views: 907
Reputation: 884
The best I can come up with is to use multiple can?
statements and raise AccessDenied
on failure. You also should avoid authorization checks against a model class, and instead authorize against a model instance. See CanCanCan - Common Mistakes.
user = User.new(...)
group = Group.new(...)
raise CanCan::AccessDenied.new(nil, :create, [user, group]) \
unless can?(:create, user) || can?(:create, group)
AccessDenied.new(nil, ..) -> nil
for the first argument result in the default error message.
See cancan/exceptions.
I'd probably move this into a helper to a method named def authorize create_group_or_user!
That said, maybe you are doing too much in this controller? Alternatively, you could make this controller redirect without authorization to the appropriate GroupController
or UserController
, and perform the appropriate authorization checks in those locations.
Alternate Option 2: Maybe use an accessible_by
restriction on the content, and don't call authorize!
at all.
Upvotes: 0
Reputation: 3962
One way to achieve this is by mixing
load_and_authorize_resource :user
load_and_authorize_resource :through => :user
this is a convenience helper for calling authorize on all resources in a controller that does something like this:
class GroupsController < ActionController::Base
load_and_authorize_resource
load_and_authorize_resource :through => :user
def create
# Automatically does the following:
# @group = Group.find(group_params[:id])
# authorize! :create, @group
# @user= User.find(group_params[:user_id])
# authorize! :create, @user
end
end
so where in your controller you load the Group and User objects it will auto authorize them against your rules/Abilities like
can [:create], [User, Group]
Of course you will need your Groups to be a nested resource:
resources :users do
resources :groups
end
Hope it helps.
Upvotes: 0