ryanb/cancan — Issue #518: Authorization based on 2 different parent resources for 2 different roles
Author: emmek
Created: 2011-11-22 13:03:37+00:00
State: open

I have inherited resources working in my controllers and I use cancan for authorization. However, I have a problem writing required abilities.

I can display order list (or particular order) in 2 nested ways:

/profile/123/orders
/store/456/orders

In controller I started with:

class OrdersController < ApplicationController
inherit_resources
belongs_to :profile, :store, :optional => true
...
end

Roles are:

* customer (User that has one Profile; then Order belongs to Profile)
* manager (User that has one Account; then Store belongs to Account; then Order belongs to Store )

The requirements (in words) are:

* Manager can display order(s) in context of (that belongs to) his store.
* Manager cannot display order(s) in context of any user's profile (Access should be denied)
* User can display order(s) in context of his profile
* User cannot display order(s) in context of any store (denied)

I couldn't meet these requirements, maybe I should load resource in special way or actually in 2 ways? Intuition says to me, that access to orders should be based on the access to parent resource in both cases.

Abilities so far:

if user.customer?:

can :read, Order, :profile => {:user_id => user.id}
can :manage, Profile, :user_id => user.id

if user.manager?:

can :read, Order, :store => {:account_id => user.account.id}
can :manage, Store, :account => {:user_id => user.id}

I tried few things; the closest was to use authorization of just parent resource in the way below (OrdersController):

authorize_resource :profile
authorize_resource :store

The problem was that as a manager I could not display orders in my store (via /store/456/orders/321) - it seems the application wants a profile to be authorized in this case, what is impossible for the manager.

Could You straighten out my thinking? Thank You for help.