permissions on polymorphic relationships

70 views
Skip to first unread message

Edward Rudd

unread,
Aug 24, 2011, 6:55:36 PM8/24/11
to declarative_authorization
I have a set of models that are configured like this.

def Event < ActiveRecord::Base
belongs_to :eventable, :polymorphic => true
end

def Fruit < ActiveRecord::Base
has_many :events, :as => :eventable, :dependent => :destroy
end

def Snack < ActiveRecord::Base
has_many :events, :as => :eventable, :dependent => :destroy
end

This allows both "Fruit" instances and "Snack" instances to link to
Events..
Now I want to restrict access on Events based on the effective
permissions of "Fruit" and "Snack"

authorization do
role :user do
has_permission_on [:fruits, :snacks], :to => :create
has_permission_on [:fruits, :snacks], :to => :manage do
if_attribute :user => is { user }
end
has_permission_on :events, :to => :create
has_permission_on :events, :to => [:read, :delete] do
if_permitted_to :read, :eventable
end
end
end

Now, the issue here, of course is that if_permitted_to trying to check
for a :eventabls context which doesn't exist. I really need it to
inspect the object that is contained in the :eventable property (or
check the :eventable_type attribute which contains the "Type" (e.g.
Fruit or Snack).

Is this possible? or does this functionality need to be added in?? If
the later, where/how would it be best added in (I'll create a patch
and send a pull request)

Edward Rudd

unread,
Aug 30, 2011, 5:40:43 PM8/30/11
to declarative_authorization
I've done some more research and am going to simplify things down to
point to the exact cause

def Event < ActiveRecord::Base
  belongs_to :eventable, :polymorphic => true
end
def Fruit < ActiveRecord::Base
   has_many :events, :as => :eventable, :dependent => :destroy
end
def Snack < ActiveRecord::Base
   has_many :events, :as => :eventable, :dependent => :destroy
end

authorization do
  role :user do
     has_permission_on :fruits, :to => :manage
     has_permission_on :events, :to => :manage do
       if_permitted_to :read, :eventable
     end
end
end

Given this seed.

apple = Fruit.create :name => 'Apple'
apple_event apple.events.create :subject => 'Create', :type =>
'Create'
cookie = Snack.create :name => 'Cookie'
cookie_event = cookie.events.create :subject => 'Create', :type =>
'Create'

These pass
permitted_to? :edit, apple
permitted_to? :edit, apple_event

These fail
permitted_to? :edit, cookie
permitted_to? :edit, cookie_event

Which is correct and as expected.. Where this blows up is when I do
this

Event.with_permissions_to(:read)

That is what is causing my error being thrown with an unknown context
of :eventables

So, I'm not sure if there is any easy way to accomplish this, as the
only way I current can see this being done cleanly is a iteration over
the complete result set and individually checking each :eventable
instance

Steffen Bartsch

unread,
Aug 31, 2011, 3:03:47 PM8/31/11
to declarative_...@googlegroups.com
Am Dienstag, 30. August 2011 schrieb Edward Rudd:
> Event.with_permissions_to(:read)
>
> That is what is causing my error being thrown with an unknown context
> of :eventables

if_permitted_to needs to infer the context to check the permission against.
In your case, you might try to set it explicitly with

has_permission_on :fruits, :to => :manage
has_permission_on :events, :to => :manage do

if_permitted_to :read, :eventable, :context => :fruits
if_permitted_to :read, :eventable, :context => :snacks
end

cf. http://www.tzi.org/~sbartsch/declarative_authorization/master/Authorization/Reader/AuthorizationRulesReader.html#method-i-
if_permitted_to

Else, it might be an error in the handling of polymorphic associations.
Maybe we should then rather take this to the issues tracker on Github.
Can you post the error stack there?

Steffen

Derek Atkins

unread,
Oct 10, 2012, 5:08:34 PM10/10/12
to declarative_...@googlegroups.com
Hi,

I realize it's been a year since this thread has been touched, but I'm still having this issue.  I found github issue #114 but it hasn't been touched in a year, either.  I don't have a github account so I cannot respond there at this time.

I have an events table that has among other things an action and a polymorphic object (upon which the action was taken).  I'm trying to find a list of events where the current_user has the "action" privilege on the (polymorphic) object.  Considering I've found no way to apply the action attribute *as* the privilege, I've unrolled the loop manually, so I have authorization rules that look like:

     has_permission_on :events, :to => :read, :join_by => :and do
      if_attribute :action => "update"
      if_permitted_to :update, :object, :context => :devices
    end

But when I execute this I get:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.length

And the Full Trace looks like:

declarative_authorization (0.5.5) lib/declarative_authorization/obligation_scope.rb:120:in `follow_comparison' declarative_authorization (0.5.5) lib/declarative_authorization/obligation_scope.rb:87:in `follow_path' declarative_authorization (0.5.5) lib/declarative_authorization/obligation_scope.rb:81:in `each' declarative_authorization (0.5.5) lib/declarative_authorization/obligation_scope.rb:81:in `follow_path' declarative_authorization (0.5.5) lib/declarative_authorization/obligation_scope.rb:69:in `parse!' declarative_authorization (0.5.5) lib/declarative_authorization/in_model.rb:76:in `obligation_scope_for' declarative_authorization (0.5.5) lib/declarative_authorization/in_model.rb:75:in `each' declarative_authorization (0.5.5) lib/declarative_authorization/in_model.rb:75:in `obligation_scope_for' declarative_authorization (0.5.5) lib/declarative_authorization/in_model.rb:124:in `with_permissions_to' activerecord (3.1.3) lib/active_record/relation.rb:455:in `send' activerecord (3.1.3) lib/active_record/relation.rb:455:in `method_missing' activerecord (3.1.3) lib/active_record/relation.rb:180:in `scoping' activerecord (3.1.3) lib/active_record/base.rb:1196:in `with_scope' activerecord (3.1.3) lib/active_record/relation.rb:180:in `send' activerecord (3.1.3) lib/active_record/relation.rb:180:in `scoping' activerecord (3.1.3) lib/active_record/relation.rb:455:in `method_missing' app/models/event.rb:23:in `my_events'

If I leave out the context then I get the expected context issue:

Authorization::NotAuthorized in EventsController#index

Missing authorization in collecting obligations: No matching rules found for update for #<User ...

with the following stacktrace:

declarative_authorization (0.5.5) lib/declarative_authorization/authorization.rb:459:in `obligations'
declarative_authorization (0.5.5) lib/declarative_authorization/authorization.rb:238:in `obligations'
declarative_authorization (0.5.5) lib/declarative_authorization/authorization.rb:237:in `collect'
declarative_authorization (0.5.5) lib/declarative_authorization/authorization.rb:237:in `obligations'
declarative_authorization (0.5.5) lib/declarative_authorization/in_model.rb:75:in `obligation_scope_for'
declarative_authorization (0.5.5) lib/declarative_authorization/in_model.rb:124:in `with_permissions_to'

Am I doing something wrong or is this still broken in d_a? I'm happy to work with you to get this solved!

Thanks,

-derek



Reply all
Reply to author
Forward
0 new messages