Right now I have a controller for "events" that belong to a specific user. I only want the creator to be able to edit or delete the event. I''ve got the proper foreign keys set up. I''ve finally arrived at the point where I can take baby steps with code, but looks like my first steps are in flagrant violation of the DRY principle. Here''s what I have so far in the "EventsController" and I know it''s ugly (but it works). def update @event = Event.find(params[:id]) if @event.user_id == session[:user] && @event.update_attributes(params[:event]) flash[:notice] = ''Event was successfully updated.'' redirect_to :action => ''show'', :id => @event else flash[:notice] = ''You do not have permission to edit.'' redirect_to :action => ''list'' end end def destroy @event = Event.find(params[:id]) if @event.user_id == session[:user] @event.destroy redirect_to :action => ''list'' flash[:notice] = ''Event was deleted.'' else flash[:notice] = ''You do not own this event.'' redirect_to :action => ''list'' end end What I would like to do is extract the "if @event.user_id =session[:user]" kind of verification from controllers since I can imagine calling this a lot as I add more models with a variety of permissions? Is there a better strategy to approach this? Sam
Jay Levitt
2006-Feb-21 19:34 UTC
[Rails] Re: Abstracting ownership verification out of Controller
On Tue, 21 Feb 2006 22:06:06 +0900, SB wrote:> Right now I have a controller for "events" that belong to a specific > user. I only want the creator to be able to edit or delete the event.Seems like Bill Katz''s brand-new authorization DSL will help you, once somebody writes an implementation including permit_set: http://www.billkatz.com/authorization Jay Levitt
Ezra Zygmuntowicz
2006-Feb-21 20:34 UTC
[Rails] Abstracting ownership verification out of Controller
Sam- Are you storing the whole user object in the session or just the user.id? If you have the whole user object in thereyou can do it like this instead to limit the fin and update to the user who is owner: @event = session[:user].events.find(params[:id]) What that will do is add this to your where clause in :conditions : AND user_id = whatever the session[:user].id is If you dont have the user object in the session and just the id then you can have a method set up that sets the current_user up: def current_user User.find(session[:user]) end And then you would do your Event finder like this: @event = current_user.events.find(params[:id]) Hope that helps -Ezra On Feb 21, 2006, at 5:06 AM, SB wrote:> Right now I have a controller for "events" that belong to a specific > user. I only want the creator to be able to edit or delete the event. > > I''ve got the proper foreign keys set up. > > I''ve finally arrived at the point where I can take baby steps with > code, but looks like my first steps are in flagrant violation of the > DRY principle. > > Here''s what I have so far in the "EventsController" and I know it''s > ugly (but it works). > > > > def update > @event = Event.find(params[:id]) > if @event.user_id == session[:user] && > @event.update_attributes(params[:event]) > flash[:notice] = ''Event was successfully updated.'' > redirect_to :action => ''show'', :id => @event > else > flash[:notice] = ''You do not have permission to edit.'' > redirect_to :action => ''list'' > end > end > > def destroy > @event = Event.find(params[:id]) > if @event.user_id == session[:user] > @event.destroy > redirect_to :action => ''list'' > flash[:notice] = ''Event was deleted.'' > else > flash[:notice] = ''You do not own this event.'' > redirect_to :action => ''list'' > end > end > > > What I would like to do is extract the "if @event.user_id => session[:user]" kind of verification from controllers since I can > imagine calling this a lot as I add more models with a variety of > permissions? > > Is there a better strategy to approach this? > > Sam > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-Ezra Zygmuntowicz Yakima Herald-Republic WebMaster http://yakimaherald.com 509-577-7732 ezra@yakima-herald.com
Francois Beausoleil
2006-Feb-21 22:20 UTC
[Rails] Abstracting ownership verification out of Controller
Hi ! 2006/2/21, Ezra Zygmuntowicz <ezra@yakima-herald.com>:> Are you storing the whole user object in the session or just the > user.id? If you have the whole user object in thereyou can do it like > this instead to limit the fin and update to the user who is owner:This article on my blog might be interesting: http://blog.teksol.info/articles/2005/10/21/model-serialization-in-session Bye ! -- Fran?ois Beausoleil http://blog.teksol.info/
Thank you all for the helpful suggestions, it definitely set me in the right direction. Yes, I did read all the resources suggested and it certainly gives me an indication of what''s ahead. I ended up using "before_filter" to accomplish this. Right now it''s right in the controller but if it crops up in other controllers, I might try to get it into "application.rb". Since I''m building up from scratch, I''d rather keep dependency on libraries and plugins to a minimum since I need to learn rails at the same time rather than rush something out the door or read third party code that''s beyond me. One thing that throws me off with plugins, is that any given plugin might represent a couple styles of coding. This can be confusing for a beginner. Here''s how I rewrote my code: before_filter :verify_permission, :only => [:edit, :update, :destroy] def update if @event.update_attributes(params[:event]) flash[:notice] = ''Event was successfully updated.'' redirect_to :action => ''show'', :id => @event else redirect_to :action => ''list'' end end def destroy @event.destroy redirect_to :action => ''list'' flash[:notice] = ''Event was deleted.'' end private def verify_permission @event = Event.find(params[:id]) if @event.user_id == session[:user] return true else flash[:notice] = ''You do not have permission for this event.'' redirect_to :action => ''list'' end end Basically, I restored "update" and "destroy" to what it was before only taking out "@event = Event.find(params[:id])" since it was now part of "verify_permissions". It gives me a warm feeling to post something on this list before bed and wake up to see responses. Now I know how the shoemaker felt when the elves came to the rescue. And now for another session of solitary Subversion tag... Sam
Bill Katz
2006-Feb-22 07:57 UTC
[Rails] Re: Abstracting ownership verification out of Controller
On 2/21/06, Jay Levitt <jay+news@jay.fm> wrote:> > On Tue, 21 Feb 2006 22:06:06 +0900, SB wrote: > > > Right now I have a controller for "events" that belong to a specific > > user. I only want the creator to be able to edit or delete the event. > > Seems like Bill Katz''s brand-new authorization DSL will help you, once > somebody writes an implementation including permit_set:Actually, the current plugin lets you handle Sam''s case pretty easily, even without permit_set. The permission check would be handled by a user_has_role? method in the Event model class. We hardwire a ''moderator'' role into the Event model. class Event < ActiveRecord::Base def user_has_role?( user, role ) return true if role == ''moderator'' and self.user_id == user.id false end end Then his controller looks like this: class EventController < ApplicationController permit "moderator of :event", :only => [:edit, :update, :destroy] def edit ... end ... end This works because the "event" in the permission expression is checked against @event, any :event hash, and finally, if params[:id] is not nil, it uses Event.find(params[:id]). This is an added convention that facilitates standard use. I''ve just started working with Ezra on refining the authorization DSL, and we may decide to make things more explicit. But right now, the plugin at http://www.billkatz.com/authorization will support authorizations like the above example. -Bill -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060222/4ec47ea0/attachment.html