How to extend UserEngine to provide roles on a per project b

OK, I’ve not seen anything out there on this, but maybe you guys can
make a suggestion.

I have Users, and they of course have Roles. However, the Roles they
have are not global, they are only in place for certain Projects.
There are some Roles that are generic - e.g. a ‘General User’ role
applies to all Users, irrespective of Project

So, a user might be a ‘Manager’ for one project and a ‘Designer’ on
another project.

I need to be able to simply manage this process and over-ride stuff
in lib like link_if_authorized.

I have spent two days writing code, it’s an absolute mess, and I
think it’s because I’m not thinking clearly about how to handle what
is in effect a 3-way HABTM relationship: Projects HABTM Users, Users
HABTM Roles, Roles HABTM Projects.

As a result, I’m not going to paste any code here - just curious if
anybody has any ideas about how they would approach this to help me
clear my head.


Paul R.

I’ve thought about this a bit, and there are a couple of ways to deal
with it.

The simplest I can think of is to add a project_id column to the
permissions table. Let it default to NULL, which means that if a
permission is set then it applies across all projects the user has
access to. The project_id could either be a real association to a
project, or just a yaml encoded list of valid projects.

Then you need to override the authorization functions to use this value
as well, so your calls might look like.

link_if_authorized ‘action’, :controller=>‘cont’, :action=>‘action’,
:project=>proj.id

You would also need to set up the permission entries view to handle
multiple projects for assignment. This could get really messy, or you
could have an admin view on a per project basis.

On Thursday, April 20, 2006, at 12:15 PM, Paul R. wrote:

clear my head.


Paul R.


engine-users mailing list
[email protected]
http://lists.rails-engines.org/listinfo.cgi/engine-users-rails-engines.org

_Kevin

On 20 Apr 2006, at 18:29, Kevin O. wrote:

The simplest I can think of is to add a project_id column to the
permissions table.

That’s interesting. Because I’ve specified it on the users_roles
table. I’m thinking users have roles in projects. Your approach
though… hmmmm…

Let it default to NULL, which means that if a
permission is set then it applies across all projects the user has
access to. The project_id could either be a real association to a
project, or just a yaml encoded list of valid projects.

Project is < ActiveRecord::Base so making it a real association is
sensible.

Then you need to override the authorization functions to use this
value
as well, so your calls might look like.

link_if_authorized ‘action’, :controller=>‘cont’, :action=>‘action’,
:project=>proj.id

Yeah, that’s what I was thinking.

You would also need to set up the permission entries view to handle
multiple projects for assignment. This could get really messy, or you
could have an admin view on a per project basis.

I’m thinking the latter.

Where I got really stuck is that I’m trying to manage a 3-way HABTM
relationship, so when I’m managing the roles a user has, I’m trying to

@user.projects.roles.each do |role| …

which of course just doesn’t work. I think I need to have a think
about your suggestion but it might work - I suspect I’m going to end
up back here again but with permissions rather than roles.

I think when I have more time after this project is over, I’m going
to extend UserEngine somewhat to provide this kind of functionality -
I’m just confused about the best way to do it right now. :slight_smile:


Paul R.

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
action.

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)

On 14 May 2006, at 23:01, James A. wrote:

Paul,

You probably want to have some has_many :through style association,
i.e. User has many Roles through ProjectPosition, or something like
that.

It gets more complicated than that. I did manage to finally do it by
effectively passing some data around, but it’s still not perfect.

When I get a spare day or three, I think I’m going to look at either
extending user_engine properly or building something from scratch to
make this kind of work much easier in future.


Paul R.

Paul,

You probably want to have some has_many :through style association,
i.e. User has many Roles through ProjectPosition, or something like
that.

  • james

Hi,

I dont’l know if it is a ‘match’ for you, but have you looked at
ActiveRBAC
https://activerbac.turingstudio.com/trac ?