# Permission System with groups, roles and users

**URL:** <https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060>\
**Category:** Rails\
**Created:** [July 14, 2008, 9:17pm UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060 "2008-07-14T21:17:50Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 14, 2008, 9:17pm UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/1 "2008-07-14T21:17:50Z")

</div>

Hi there,

i have a serious problem here.  
Let me explain my situation:

I have 3 Models: Group, Role, User  
Pretty self explaining. Every group has multiple roles (every group  
can define it’s own roles. some have 3, some have 14 and so on…) and  
every role has many users through a join table.

Every group has some features like a public forum, a calender, public  
and private news and so on.  
I need to define Rules / Permissions like “roles which are allowed to  
post in the public forum”, “roles which are allowed to create new  
events in the calender”…  
The Group admin can select 1-n roles which are allowed to do these  
actions.  
But how do i model these relations. I try to find a “good” design for  
this since a few days now and didn’t find a answer. It would be  
possible to create a field for every “option” inside the groups table  
which stores a comma seperated list of roles… if you know what i  
mean. but this seems kind of “messy” to me.

there has to be an “intelligent”, dynamic, RoR like way to handle  
this.

Any suggestions are welcome!

Thanks in advance,

Pascal

---

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 15, 2008, 12:25am UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/2 "2008-07-15T00:25:58Z")

</div>

i tried to use the “method\_missing” for my problem.

i created the following:  
table “group\_options” with key:string  
it contains every option like “create\_events\_roles” as the key

table “group\_options\_relations” with group\_option\_id:integer  
role\_id:integer group\_id:integer  
it is the join table for the role and the group\_option

i added the following method to my group model:

def method\_missing(m, _args, &block)  
 @option = GroupOption.find\_by\_key(m.to\_s) ||  
GroupOption.find\_by\_key(m.to\_s.match(/(\w_)?=/)[1])  
if @option  
if args.size != 0

GroupOptionsRelation.find\_all\_by\_group\_option\_id\_and\_group\_id(@option.id,  
self.id).each do |go|  
go.destroy  
end  
args.first.each do |a|  
GroupOptionsRelation.create(:group\_option\_id =\>  
@option.id, :role\_id =\> a.to\_i, :group\_id =\> self.id)  
end  
else  
return  
GroupOptionsRelation.find\_all\_by\_group\_option\_id\_and\_group\_id(@option.id,  
self.id)  
end  
else  
super  
end  
end

it “does” something that i “could” use. but it doesn’t “feel” right…  
?\> g = Group.find(4)  
=\> #\<Group id: 4, title: “Test Group”\>

> > g.create\_events\_roles  
> > =\> [#\<GroupOptionsRelation id: 2, role\_id: 5, group\_option\_id: 1,  
> > created\_at: “2008-07-15 00:15:15”, updated\_at: “2008-07-15 00:15:15”,  
> > group\_id: 4\>, #\<GroupOptionsRelation id: 3, role\_id: 12,  
> > group\_option\_id: 1, created\_at: “2008-07-15 00:15:15”, updated\_at:  
> > “2008-07-15 00:15:15”, group\_id: 4\>, #\<GroupOptionsRelation id: 4,  
> > role\_id: 19, group\_option\_id: 1, created\_at: “2008-07-15 00:15:15”,  
> > updated\_at: “2008-07-15 00:15:15”, group\_id: 4\>]
> 
> > g.create\_events\_roles [4,2]  
> > =\> [4, 2]
> 
> > g.create\_events\_roles  
> > =\> [#\<GroupOptionsRelation id: 5, role\_id: 4, group\_option\_id: 1,  
> > created\_at: “2008-07-15 00:22:20”, updated\_at: “2008-07-15 00:22:20”,  
> > group\_id: 4\>, #\<GroupOptionsRelation id: 6, role\_id: 2,  
> > group\_option\_id: 1, created\_at: “2008-07-15 00:22:20”, updated\_at:  
> > “2008-07-15 00:22:20”, group\_id: 4\>]

hmmmm  
any ideas how to clean this up? Go a “better” way?

thanks in advance,

Pascal

---

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 15, 2008, 3:53am UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/3 "2008-07-15T03:53:04Z")

</div>

Yeah the original rails recipes book covers this topic in the exact  
manner  
you specify.

---

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 15, 2008, 2:32am UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/4 "2008-07-15T02:32:35Z")

</div>

i’ve seen solutions that define a role has\_many permissions, where the  
permissions attributes include a controller+action (eg ‘comments’  
‘new’),  
and then implement it as a before\_filter in the controllers or site-  
wide in application.rb

try googling “rails acl”

linoj

---

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 15, 2008, 5:14pm UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/5 "2008-07-15T17:14:38Z")

</div>

i think i’ll try a different way.  
i’am going to “tag” my roles with something like acts\_as\_taggable.  
if a role is tagged with “may\_create\_events” the user of this role  
“may create events” 🙂  
hope this works

---

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 15, 2008, 11:40am UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/6 "2008-07-15T11:40:39Z")

</div>

@linoj: the acl plugins only cover one dimension. the role. like  
access\_control :new =\> ‘admin | moderator’  
but i need to add the group as another dimension. for example, every  
group has a calender and role “maintainer” of group 1 may edit the  
calender of group 1 but not the one from group 3. The Acl system just  
says “you are a maintainer, you can use the new action!” but it should  
say something like “you are not a maintainer of group 3, go away!!”

@Brian H.: glad i own the rails recipes in the original and the new  
version, but, i can’t find a topic describing my problem. Which one  
did you mean?

---

<div class="post-metadata">

**Author:** ![Pascal\_F](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3da27b/32.png) [@Pascal\_F](https://www.ruby-forum.com/u/Pascal_F)\
**Post date:** [July 15, 2008, 8:59pm UTC](https://www.ruby-forum.com/t/permission-system-with-groups-roles-and-users/143060/7 "2008-07-15T20:59:09Z")

</div>

Pascal F. wrote:

> Hi there,
> 
> i have a serious problem here.  
> Let me explain my situation:
> 
> I have 3 Models: Group, Role, User  
> Pretty self explaining. Every group has multiple roles (every group  
> can define it’s own roles. some have 3, some have 14 and so on…) and  
> every role has many users through a join table.

One way to model this is defining a “context” model, that way a user  
has each role in a particular context, and you have an active context  
in each session that filters the available roles for the current user.  
The downside is that in some situations you might have to hardcode the  
current context (depending on what each view shows).

The advantage is that permissions are defined just one time if they  
are the same

Example:

Roles\_Users table has user\_id, role\_id, context\_id, context\_value  
fields  
John has role Administrator in Group1  
Rachel has role Moderator in Group1  
John has role Moderator in Group2  
Robert has role in Group2  
Robert has role in Group1

If you only have to discriminate by group, then you don’t need  
context\_id, just the value.

Then:

Administrators can Delete Posts  
Moderators can Edit Posts  
Users can Create Posts  
Users can Edit Posts (if they created it)

So, in your controller, to decide if you need to display the “Delete  
Post” link in you post list, you need to verify that the current user  
is an administrator AND the “current” group is Group1.

I hope that makes sense.

Lucas.
