with_permission_to confusion

19 views
Skip to first unread message

marct...@googlemail.com

unread,
Dec 22, 2012, 2:17:27 PM12/22/12
to declarative_...@googlegroups.com

Users have permission to manage articles for particular combinations of location and category.

For example Dave may be allowed to manage HR articles for Paris. Paul may be allowed to manage Business articles for London.

The models and their associations are as follows:

  • user has many permissions
  • permission belongs to user, location and category
  • category has many articles and belongs to permission
  • location has many articles and belongs to permission
  • article belongs to location and category

I can say:

has_permission_on :articles, :to => :manage do
  if_attribute :location => { :permissions => { :user_id => is {user.id} }, :category => { :permissions => { :user_id => is {user.id} } }
end
 

When I call permitted_to?(:delete) on an article record (whose category id is 1893 and location id is 2939), the following queries are run:

SELECT `categories`.*  FROM `categories`  WHERE `categories`.`id` = 1893 LIMIT 1
SELECT `permissions`.* FROM `permissions` WHERE (`permissions`.category_id = 1893)
SELECT `locations`.*   FROM `locations`   WHERE `locations`.`id` = 2939 LIMIT 1
SELECT `permissions`.* FROM `permissions` WHERE (`permissions`.location_id = 2939)
 

What I need to be run is really:

SELECT `permissions`.* FROM `permissions` WHERE (`permissions`.category_id = 1893 AND `permissions`.location_id = 2939)

Is there any way to achieve this?

Thanks in advance.


Update

Ok, so I now have an instance method in the article model:

def permitted_user_ids
  Permission.select('user_id').where(:location_id => location_id, :category_id => category_id).map(&:user_id)
end
 

and my rule is now:

has_permission_on :articles, :to => :manage do
  if_attribute :permitted_user_ids => contains { user.id }
end

Now when I call permitted_to?(:delete) (or read/update/create/manage) on an article record whose category id is 1893 and location id is 2939, the following query is run:

SELECT user_id FROM `permissions` WHERE `permissions`.`category_id` = 1893 AND `permissions`.`location_id` = 2939

...which is exactly what I want.

Except, that the with_permissions_to scope is behaving very oddly.

Article.with_permissions_to(:read)

Now generates:

SELECT `articles`.* FROM `articles` WHERE (`articles`.`id` = 9473)

...where 9473 is the ID of the current user!

I am very confused.

I've read steffenb's comments in in this post which makes me think this is a known shortcoming but I can't help think I've missed something obvious.

Reply all
Reply to author
Forward
0 new messages