[rspec-users] [rails] An authorization question

Andrew Premdas apremdas at gmail.com
Mon Mar 2 09:56:48 EST 2009

Personally I think this should be in the model layer. As you've pointed it
you get alot of repetition if its in the controller layer. But putting
business logic in the controller layer goes against the fundamentals of MVC,
and is a bit of a Rails anti-pattern (fat controller).

So given that the rules should be in the model then the question is which
part of the model should have this responsibility and how do you call it.
Three choices come to mind here

1) Place the rule inside User
2) Place the rule inside the affected model
3) Create a new model(s) to encapsulate this functionality. It might be
helpful to think of this as a service which models can use

1) Pollutes User with additional responsibility, but you can live with this
so long as things remain very simple

2) Isn't DRY if the rules apply to many different models

3) Is more complex

It sounds like you have 1) and should consider moving to 3). However you
might get some change out of improving 1) first if you can, by using
standard refactorings

Have you considered creating a spike and doing a bit of BDD on the spike.
i.e write the stories you want to write, implement simple code for them and
try and work out the interactions you need from there. Even if you don't use
the spike code in your application this might help you get a better set of
features for this piece of functionality, (not tainted by the implementation
of the existing code. These features then can be applied to your legacy
project and perhaps other projects as well.



2009/2/28 Chris Flipse <cflipse at gmail.com>

> On Sat, Feb 28, 2009 at 3:42 PM, Ben Mabey <ben at benmabey.com> wrote:
>> Chris Flipse wrote:
>>> I've actually been okay with it at the unit testing / rspec level -- I've
>>> had it stubbed as you describe for a while.
>>> The pain point came in as I was trying to setup data for Cucumber ...
>>> Which, listening to my tests, tells me that the current structure is bad.  I
>>> was more curious to see how others are handling that sort of situation.
>> If you are seeing state from one scenario bleed over to the next I would
>> suggest something like this in your env.rb:
>> After do
>> User.reset_current
>> end
> Yep got that.  The tests are actually *working*, it's just that the setup
> has gotten painful.
>>> I want to get *away* from the global variable, I'm just not entirely sure
>>> what the target should be.  There doesn't seem to be a whole lot of talk
>>> about actual implementation specifics around model level authorization.
>> I generally have a current_user method defined of my controller to return
>> the logged in user.
> Same.  Authentication was originally generated using acts_as_authenticated,
> so the standard conventions at the controller level are in place.
>> Assuming that your app is only using User.current in your controllers you
>> could try to move towards something like that... If you have models
>> accessing User.current then it truly is being used as a global. :/
> It truly is being used as a global.
>> The user will then have some permissions methods that may take other
>> objects or symbols.  The method will simply return a boolean telling if the
>> user is authorized or not.  That logic usually is based on the role(s) of
>> that user or relationship with the passed in object.  Having this logic in
>> the user could be viewed as a responsibility issue- should the user really
>> be responsible for telling if it is authorized for everything?  In general I
>> do this for most simple cases.  Only when it starts to get complex do I move
>> it out into a Manager-like object.
> Yes!  This is what I was trying (poorly) to get at.
> Responsibility issues might be a large part of why it got factored this way
> to begin with.  The global is bad.  Really bad, which is why I'm trying to
> figure out something that works better.  But I believe it was put in place
> so that a model can be responsible for it's own authorization.  Some of the
> models are used and updated from several different controllers, so any
> authorization logic external to the model would have had to be repeated in
> several different locations.
> The concern with that might be an over-enthusiastic embrace of DRY.
> However some of the authorization stuff is Really Really Important, so
> embedding the authorization logic in the model itself was seen as a way to
> ensure it's not forgotten about.
> Half of my problem right now is that I'm not even sure what *layer* to put
> model specific authentication!  If it's in the controller layer, it's
> repeated logic in every controller that touches the model in question.  If
> it's in the model, the logic is centralized, but now your model needs not
> only to know about Users in general, it needs a specific user.  You have
> less chance of someone doing Something They Shouldn't due to a forgotten
> check in a controller, but the test setup seems to suffer for it.
> One way or the other, the global User.current is going away -- soon.  It's
> just a question of what to replace it with, and where.
> --
> // anything worth taking seriously is worth making fun of
> // http://blog.devcaffeine.com/
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090302/42e3f032/attachment.html>

More information about the rspec-users mailing list