views:

58

answers:

2

I have a ruby app running with declarative authorization and I have made the roles:

admin ( app admin ) org_admin ( organization administratr ) org_colab ( organization colaborator ) org_visitor ( organization visitor )

a User can has_many Organizations and he can be an admin or a colaborator.

I link them using a Affiliation table

What is the best strategy to solve this many to many roles?

To put a extra attribute on the Affiliation table ? like : Affiliation(:user_id:integer, :organization_id:integer, :affiliation_type:integer)

and the affiliation type can be 0 for org_admin and 1 for org_colab and 2 for org_visitor?

I imagine there must be a better way to assign roles to a particular organization...

+1  A: 

It's the classic "User-Group-Role" model. It's a ternary relationship. User-Group is many-to-many; so is Group-Role. You'll need five tables to capture all of it.

You'll start with a User table. It'll have a primary key (of course). Same with Group and Role.

You'll have a UserGroup table sitting in-between the User and Group tables in your E/R diagram. UserGroup will have two columns: user_id and group_id. The primary key will be the combination (user_id, group_id). The user_id column will have a foreign key relationship with the primary key of the User table. Ditto for the group_id column and the Group table.

There will be a similar arrangement with Group and Role. Each will have a primary key. The GroupRole table will sit between the two in your E/R diagram. Repeat the verbiage above and you'll have it.

I'd create an E/R diagram to show you, but I'm busy doing some other things. I hope this is sufficient for you. If not, perhaps I'll add it later.

So Users don't have Roles; Groups do. You add a User to a Group, and that User gets all the authorizations that the Group has. That way you can add a particular Role (e.g., admin permissions for the Admin group) one for a particular Group. Then everyone who is added to that Group will get those permissions.

duffymo
That was a little vague for me.Let see, I have this:User * ---1 Affiliation 1--- * GroupAnd I was thinking of putting an extra atribute in the Affiliation table for Role type.Can you explain how the 5 column model is?
Victor Martins
Not a five column model, a five table model. You'll have User, Group, and Role tables. You'll also have UserGroup and GroupRole relationship tables to carry the many-to-many relationships.
duffymo
Victor Martins
I think i've got what you are saying. with that model, i can have user1, user2, and user3 belonging to a group of admins, so they all are admins. But what I'm after is something like. user1, user2, and user3 belongs to a organization. and user1 is the admin, user2 is the manager, and user3 is the client. It's not a case of grouping roles togueter, but grouping users to a group and have them have a particular role in that group...
Victor Martins
Okay, so have groups Admin, Manager, Client. Give each one permissions/roles. Then assign users to the groups. That's how I'd do it. That's what I recall from BEA's model for WebLogic. If you have another design in mind, go for it. I think you'll need JOIN tables no matter how you do it.
duffymo
But the problem is that then one group_admin will be admin in every group and not just in some specific groups that he got assigned to. Right?
Victor Martins
Groups need to be distinguished somehow. The "Admin" group was an example. If you need a portal admin, a database admin, etc., then maybe you need additional groups.
duffymo
Hi, I've been helping Victor with this one (as of now). The problem that exists and that might not be solvable with this classic U-G-R system is that the Organizations he mentions isn't necessarily a group in itsself, but more of a user. The idea is that users can be part of one or more organizations, assuming one or more roles in those organizations; but users can have roles related to the system, also. the UGR relation will wokr well system-wise, but matbe we need to create a few parallel tables or extra connections to get the organization in to the picture.
MytyMyky
I agree - sounds like you have many-to-many relationships, so you'll need join tables. You know your situation best - model it appropriately. Good luck.
duffymo
How did you get on with this? I'm in exactly the same position!
ro
+1  A: 

Hi Victor,

i actually implement something similar to my project. To clarify if i understand you correct - your user might have a role in the whole application-context, as well as a specific role in the organizational-context which may not depend on each other.

A pragmatic solution might be to implement two different rolesets. Let's think of the following construct: You have a user-model (having application-wide informations), a organization-model (which defines an organization and might possibly be owned by a user) and a collaborative-model which defines a relationship between a user and a organization.

In this case it would be the best to store roles in the user-model (which do the application-wide stuff) and to store organization-specific roles in the collaborative-model.

I used a string based roles-store in the models in combination with ryan bates cancan-gem - its easy & fast to use and puts roles-logic in a defined place.

This might not work for thousands of different roles and groups and stuff, in that case you should implement the role-storage in an extra model (with a polymorphic relation to users and collaboratives).

Best wishes - Florian

edit: To make that implementation searchable by ActiveRecord you might want to use the 'serialize'-feature for the :roles-field, as described in ActiveRecord::Base.

florianb
Thanks for your help Florian.I'm using a system that is very similar to yours, but instead of using cancan i've wrote a Module to manage all the logic issues and evaluate the authorizations. It's far from perfect and I will try to learn other methods in the future, but it's working ok for now.
Victor Martins