Carsten Gehling
2008-May-06 07:50 UTC
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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
For those of us too lazy to figure it out, it belongs in the acl_system2 plugin :) On May 6, 3:50 am, Carsten Gehling <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> 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 > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Carsten Gehling
2008-May-06 19:36 UTC
Re: Where should the responsibility for ACL be placed in MVC?
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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Mark Bush
2008-May-07 07:37 UTC
Re: Where should the responsibility for ACL be placed in MVC
Carsten Gehling 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". -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Carsten Gehling
2008-May-07 08:20 UTC
Re: Where should the responsibility for ACL be placed in MVC
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 <filter input params according to white_list> <save meeting model> end This would be the best way, if I also want to make a RESTful controller, right? - Carsten -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
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 Gehling <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> 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 > > <filter input params according to white_list> > <save meeting model> > end > > This would be the best way, if I also want to make a RESTful controller, > right? > > - Carsten > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Carsten Gehling
2008-May-07 13:05 UTC
Re: Where should the responsibility for ACL be placed in MVC
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 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Frederick Cheung
2008-May-07 13:19 UTC
Re: Where should the responsibility for ACL be placed in MVC
On 7 May 2008, at 14:05, Carsten Gehling 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> I didn''t know this aliass_method_chain - nice touch. I will research > this some more. Thank you. > > - Carsten > -- > Posted via http://www.ruby-forum.com/. > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---