Where should the responsibility for ACL be placed in MVC?

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

For those of us too lazy to figure it out, it belongs in the acl_system2 plugin :slight_smile:

AndyV wrote:

For those of us too lazy to figure it out, it belongs in the acl_system2 plugin :slight_smile:

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

Brilliant explanation Mark! Thank you so much for that. :slight_smile:

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

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

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

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