I’m in a very similar situation myself. I have the same three way join
between users, roles, and sections (equivalent to your projects). I’ve
been calling this an assignment (for want of a better name) in that a
user is ‘assigned’ a role for a section. I’m not doing this with the
user engine but the problem is effectively the same.
For each role you can set a permission for a variety of action verbs
(not Rails actions but the more general sense of the word). So for
example you can create a ‘contributor’ that can view all stuff, add new
stuff, edit their own stuff, delete their own stuff and so on. Basically
for each action you can either do nothing (i.e. no permissions), perform
the action on only items you own, or perform the action on all items.
The list of actions is a bit generalised as I didn’t want to have to
create a rule for each and every controller action I ever come up with.
In effect you need to determine which action verb is appropriate when
applying a permission test. For example I might have a ‘classify’ action
verb that could be used to determine if a user can apply tags or place
an item in a category. This means you can’t get as granular as you might
want to bit it does simplify things.
I then have an admin page where you can select which role a user should
be given for each ‘section’ including an option to have no role (i.e. no
entry in the assignment relationship).
In my user model I have methods like @user.can_edit?(@some_section) and
@user.can_delete?(@section) which I think read quite nicely. Behind the
scenes this looks up the relevant assignment for the user for the
section in question and then inspects the role to see if the user can do
the required action. I’ve been thinking about making this use
method_missing so the @user.can_xxx? stuff is all neat and tidy. The xxx
bit equates to the action verb and the underlying code is the same
regardless of the actual action being tested.
The hardest part is actually applying all the permission tests
everywhere they need to be - and this is the part I’m currently in the
midst of. I’m using a similar ‘link_to_if’ approach which works OK in
the view but can get messy when there are a lot of things to protect. My
HTML is looking less and less like HTML and more and more like ruby.
Then there’s obviously the need to ensure a user can’t just bypass a
link in the page and format a request to do something they are not
allowed to. Before_filters help to a point here but I’m finding that
often times the permission logic needs to be deeper within a controllers
I’ve also come across problems where I allow batch editing of items. For
example deleting from a list of items by selecting a check-box next to
the relevant items and then hitting a delete button. Problem is that you
might have rights to delete some of the items but not others. I can’t
just hide the check-box in such cases as I also use them to allow batch
enabling/disabling of items from the same list. You might have
permission to delete some items and enable/disable others. There’s no
way to accurately hide/show the correct check-boxes as they are very
likely to clash
Doubt my rambling helps to clear your head but it felt good getting it
all out ;o)