[rspec-users] [rails] An authorization question

Chris Flipse cflipse at gmail.com
Sat Feb 28 17:43:29 EST 2009

On Sat, Feb 28, 2009 at 4:34 PM, Zach Dennis <zach.dennis at gmail.com> wrote:

> Disclaimer, this entire post has to deal with model level
> authorization and a technique I've been using and evolving in Rails
> projects. It has nothing to do with your issue of global state for
> what User is logged in. Onto the fun stuff IMO....

It's actually a lot closer to what I'm trying to get to the bottom of than
the global variable bit is.

> I've been wanting to write a thorough blog post on thoughts and
> reflections on a very related topic, but since you've already kicked
> off the conservation I'll try to add to the discussion. :)
> For nearly a year I've been utilizing the concepts of Roles and also
> Privileges. They are close at heart, but different needs have proven
> both of them to be successful at different times.
> Here's an example of being reliant on a role:
>  # raises if the user cannot fulfill the role
>  supervisor = user.in_role(:supervisor)
>  supervisor.do_supervisory_thing

Okay.  There actually is something fairly close to this.

Take a group blog with an editor/supervisor.  Anyone can write up and draft
a document, but only the supervisor can publish it.

Right now, I do have a User#is_supervisor_of?(group) method.  Good enough

Problem is, where does that check _happen_ ?  At the model level?  Or in the

You can externalize the request in the controller:

  if current_user.is_supervisor_of?( document.group)
    document.published_by = current_user
    # flag some errors

But if it's the sort of action that finds itself in a couple of different
controllers, there's been a worry about repetition -- forgetting logic and
such.  Which is why the code is really more like this:

  # in the model
  def publish!
    if User.current.is_supervisor_of?(group)
      self.published_by = User.current
      self.state = 'published'
      raise NotASupervisorError

Only it's actually a bit worse than that, because I think it's wormed it's
way into the validations...

No controller can forget to check the authorization.  However, it makes
setting up test data -- and even working from the console -- painful.  Among
other things, there a business rule in place that you can't approve your own

> And the supervisor role looks like:
>  class Roles::Supervisor < Roles::Base
>    def do_supervisory_thing
>      # inside the implementation you
>      # can refer to the source of the role
>      # using the method #source
>    end
>  end
> The privilege functionality is similar:
>  # this will raise access denied if user doesn't have the privilege
>  payer = user.with_privilege(:make_payment)
>  payer.pay!(invoice)
> And its implementation looks like:
>  class Privileges::MakePayment < Privileges::Base
>    def pay!(invoice)
>      Payment.create! :invoice => invoice
>    end
>  end
> This abstracts out the behaviour surrounding privileges and roles out
> into their own component. In most cases the methods are very small,
> and they merely create real models, or do other things. The big win
> for me has been that they create a concrete representation of
> something tied to a role or a privilege. I don't know how much more
> intention-revealing I can get. :)
> Right now I am leaving things a little verbose in the controller
> actions, e.g. user.in_role(...) or user.with_privilege(...), but I
> like it because no one has to guess what is being used. The less
> verbose route would be to omit #in_role or #with_privilege and just
> say:
>  user.pay!(invoice)
> The user would be in charge of searching its roles/privileges for one
> that responded to #pay!. I am considering moving to this route, there
> are some edge cases that would need to be solved.
> If you're interested, the roles project is on github:
> http://github.com/zdennis/roles/tree/master
> I just through up a wiki page for using them with Rails if you want to
> test it out: http://wiki.github.com/zdennis/roles/rails

I'll give it a read, see what I can learn

> --
> Zach Dennis
> http://www.continuousthinking.com
> http://www.mutuallyhuman.com
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

// anything worth taking seriously is worth making fun of
// http://blog.devcaffeine.com/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090228/f2651f28/attachment-0001.html>

More information about the rspec-users mailing list