Forum: Ruby on Rails Abstracting ownership verification out of Controller

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
SB (Guest)
on 2006-02-21 15:09
(Received via mailing list)
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 L. (Guest)
on 2006-02-21 21:35
(Received via mailing list)
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 K.'s brand-new authorization DSL will help you, once
somebody writes an implementation including permit_set:

http://www.billkatz.com/authorization

Jay L.
Ezra Z. (Guest)
on 2006-02-21 22:37
(Received via mailing list)
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:

> ugly (but it works).
>       flash[:notice] = 'You do not have permission to edit.'
>     else
>
> Is there a better strategy to approach this?
>
> Sam
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>

-Ezra Z.
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
removed_email_address@domain.invalid
Francois B. (Guest)
on 2006-02-22 00:22
(Received via mailing list)
Hi !

2006/2/21, Ezra Z. <removed_email_address@domain.invalid>:
>         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-...

Bye !
SB (Guest)
on 2006-02-22 06:56
(Received via mailing list)
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 K. (Guest)
on 2006-02-22 09:58
(Received via mailing list)
On 2/21/06, Jay L. <removed_email_address@domain.invalid> 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 K.'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
This topic is locked and can not be replied to.