# Where should the responsibility for ACL be placed in MVC?

**URL:** <https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774>\
**Category:** Rails\
**Created:** [May 6, 2008, 9:50am UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774 "2008-05-06T09:50:07Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 6, 2008, 9:50am UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/1 "2008-05-06T09:50:07Z")

</div>

I am rebuilding one of my favorite intranet apps in Rails. I use a lot  
of access control - not just on model-level, but down to specific fields  
inside one model.

For example:

User A is allowed to modify the field “Meeting.modulex”, because he is  
member of a certain group  
User B is not allowed to modify the same field.

Three things sping into my mind at this:

a) The standard CRUD setup actually uses the view to dictate, which  
fields, a user may edit (which of course could be compromised)

b) The model validation scheme only cares about filling the fields with  
valid values

c) There is a convention saying that the controller should be “thin”,  
and the model “fat”

I am very much in doubt, where i should place my Access control. On one  
hand it is easier to put it into the controller, since it sometimes  
spans multiple models. On the other hand, this isn’t very DRY.

I am interested in hearing how other users have tackled this problem.

- Carsten

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 6, 2008, 4:21pm UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/2 "2008-05-06T16:21:05Z")

</div>

For those of us too lazy to figure it out, it belongs in the  
acl\_system2 plugin 🙂

On May 6, 3:50 am, Carsten G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 7, 2008, 9:37am UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/3 "2008-05-07T09:37:50Z")

</div>

Carsten G. wrote:

> a) The standard CRUD setup actually uses the view to dictate, which  
> fields, a user may edit (which of course could be compromised)

The view shouldn’t contain any business logic. It is just there to  
create something visual for the user. The controller should setup any  
state for the view to use to decide what to render and, hence,  
potentially restrict what a user can see. It is also up to the  
controller to decide what to accept from a user (say from submitting a  
form).

> c) There is a convention saying that the controller should be “thin”,  
> and the model “fat”

If it makes sense to a model to restrict operations based on another  
model, then that logic is fine in the model, however users are generally  
only relevant in the context of a controller. If you are operating in  
the console, for example, you will not necessarily have a user defined  
and you then wouldn’t want convoluted code in the model to handle this.  
Let the model just get on with the job of being a model.

The controller is the place where you can determine users and so seems a  
very natural place to put access limitations. After all, you are really  
wanting to limit what users of the application can do, not what users of  
the model can do (having direct access to the model probably means  
having direct access to the database and you lose your access control  
anyway).

What I do is create a set of predicates in the application controller  
(possibly in a module that can be mixed in) so that code becomes more  
readable. For example, using a before\_filter to always ensure you have  
a @user instance variable, then have an admin? method which checks for  
@user having admin rights, then in your controller you can use “if  
admin?” where necessary.

Then, if you want to use any of these predicates in a view, “export”  
them as helpers using “helper\_method”.

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 7, 2008, 10:20am UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/4 "2008-05-07T10:20:15Z")

</div>

Brilliant explanation Mark! Thank you so much for that. 🙂

I had serverly misunderstood where the model’s responsibilites stop and  
the controller’s start, but your arguments make it logical.

If I have a model like this:

## Meeting

id  
date  
from  
to  
subject  
show\_on\_screen \*

- This atribute may only be written if user has the role “secretary”

What is best practice for this? Would you make one “update” controller  
method like this:

def update  
white\_list = [‘id’, ‘date’, ‘from’, ‘to’, ‘subject’]  
if @user.secretary?  
white\_list \<\< ‘show\_on\_screen’  
end

 end

This would be the best way, if I also want to make a RESTful controller,  
right?

- Carsten

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 7, 2008, 2:36pm UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/5 "2008-05-07T14:36:55Z")

</div>

The approach that we’d typically take would be to only render the  
input field for the secretary. That could mean either:

- Views for Users in the secretary role have some conditional logic  
that renders the ‘show\_on\_screen’ field
- A unique view specifically tasked for ‘show\_on\_screen’ is created  
and only Users in the secretary role are given access

In either case, the #update action can remain the same.

Obviously that approach is not bulletproof. Someone who _really_  
wants to set the value could find a way to hack an http request with  
the appropriate attributes. If you want to lock it down even tighter,  
you could work along the lines of creating a method to update the  
attributes that takes roles into account, and then invoke that method  
from the controller (where the user is in context as Mark explains  
above). It probably makes sense to wrap the method in using  
alias\_method\_chain:

class Meeting  
def update\_attributes\_with\_role(role, attributes={})  
attributes.each\_pair{|attr, val| attributes.delete(:attr)  
unless …authorized…}  
update\_attributes\_without\_role attributes  
end  
alias\_method\_chain :update\_attributes, :role  
…

end

On May 7, 4:20 am, Carsten G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 6, 2008, 9:36pm UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/6 "2008-05-06T21:36:50Z")

</div>

AndyV wrote:

> For those of us too lazy to figure it out, it belongs in the  
> acl\_system2 plugin 🙂

I took a look at acl\_system2. If I understand it correctly, it creates  
access-control on the controller. Thereby signifying, that  
access-limitation to specific model-fields should be placed in the  
controller.

Is this the common-way approach?

- Carsten

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 7, 2008, 3:21pm UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/7 "2008-05-07T15:21:13Z")

</div>

On 7 May 2008, at 14:05, Carsten G. wrote:

> Andy: My intial concern _was_ exactly that I wanted to guard against  
> phony HTML-forms, where the user has added the extra field himself. So  
> just rendering the view without “show\_on\_screen” attribute would not  
> be  
> enough IMHO.

Do you want attr\_protected ?

Fred

---

<div class="post-metadata">

**Author:** ![tuktuk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/77aa72/32.png) [@tuktuk](https://www.ruby-forum.com/u/tuktuk)\
**Post date:** [May 7, 2008, 3:05pm UTC](https://www.ruby-forum.com/t/where-should-the-responsibility-for-acl-be-placed-in-mvc/136774/8 "2008-05-07T15:05:59Z")

</div>

Andy: My intial concern _was_ exactly that I wanted to guard against  
phony HTML-forms, where the user has added the extra field himself. So  
just rendering the view without “show\_on\_screen” attribute would not be  
enough IMHO.

I didn’t know this aliass\_method\_chain - nice touch. I will research  
this some more. Thank you.

- Carsten
