views:

181

answers:

2

I want to implement authorization in my Rails application on a model level (not controller), in a similar way that validation on models is done. What is the best way to do this?

If it is implemented in the models itself, the main problem is that the models don't have access to the current user. I've seen solutions like: Thread.current[:user_id] = session[:user_id], but that doesn't seem like a good idea.

I've seen a different approach where variants of the methods like create, find and new are created, accepting an additional parameter for the current user.

Another approach would be to implement all the methods in the User/role class, so for example user.posts.create or user.readable_posts.find would be used instead of Post.create or Post.find.

Which of these approaches would be suggested? Are there any better ways to implement the authorization? Are there any plugins that makes this easier? I need an approach that scales well for multiple roles and models.

A: 

Why would you do this? Isn't controller level identification enough?

if @user.is_able_to_do_this?
  do_this
else
  blah!
end

... and in your model

def is_able_to_do_this
  if self.rights > Constant::Admin_level_whatever
    return true
  end
  return false
end
marcgg
Mainly because I have a fairly complicated permission system, which are more complicated that just can or can't perform an action. For example, certain users should only be able to edit specific attributes of the model.
Ralf
It is also simpler when the same or similar actions on a model is referenced from multiple controllers.
Ralf
Ok, it makes sense. I think in that case that jimmy's answer should be a good option
marcgg
A: 

I would recommend you to look at declarative authorization. It works with both models and controllers.

The way it do what you are asking is having a before_filter in the applicationController that sets Authorization.current_user = current_user where Authorization is a module.

I think that approach is the best one, it keeps the models clean and you don't have to remember to include the user everywhere, but can filter it in the models callback functions instead.

Jimmy Stenke
Using this approach, how are requests from the console (or any other method not going through a controller) handled?
Ralf
I found the answer to my comment, Authorization::Maintenance has functionality specifically for this.At first glance declarative_authorization seemed like it missed some functionality I required, but when I looked deeper I found it to be quite powerful.I like being able to specify all the permissions in a separate file.
Ralf
Yeah, it works quite well with that. Most of the logic is left out of your application. And I like the way that it actually checks if you are permitted to do something instead of listing what a user can do. It feels cleaner.
Jimmy Stenke