开发者

Ruby on Rails authorization gem to handle the following

Is there an authorization gem in Rails that handles something such as the following:

I have a user that wants to update their own profile. They'll invoke an HTTP POST to something such as http://example/users/:user_id/profile.xml. The problem is, a lot of the code to handle tha开发者_JS百科t has something such as:

if params[:user_id] == current_user.id
  # allow update!
else
  # don't allow update

What authorization gem will allow for abstracting this out so that specifically, that logic can be automagically implied without me having to check it manually in every method that requires it?


Your question involves 2 parts:

  1. Authentication
  2. Authorization

Authentication in this case is basically the concept of allowing users to sign in and sign up to your website. You haven't mentioned this in your question, so maybe you've already implemented it. If you haven't, I'd advise you to look into Devise (here), its really easy to use but also really powerful.

Authorization is specifically what you asked about. That is, once a user is signed in, what privileges does that give him vs someone who's not. Also, what extra privileges do admins have and so on. Like others before me suggested, the best way to do this is to use CanCan (here).

I'm using both of these in the first rails app I've ever made, they are really easy to use.

Also, if you don't want such an extensive solution to authorization like CanCan, you could simply use a before_filter and place your repeated code in there. I used this approach in another application, this post will help you out: (here)


First of all you don't want a gem, you are going to have to write your own code.

that logic can be automagically implied without me having to check it manually in every method that requires it?

That's what before_filters do. You will most likely already have one set up in your application_controller.rb. A before filter will ensure that the authorize method is called before every action that needs it See here unde section 7 Filters for more details on this http://guides.rubyonrails.org/action_controller_overview.html

Lastly, I hope you are not implying that xml post requests to update a profile should not log in! They surely should, http basic authentication will handle this for you.

See here http://api.rubyonrails.org/classes/ActiveResource/Base.html

Also for Rails => v 3.1 http://railscasts.com/episodes/270-authentication-in-rails-3-1

Update

It is clear from the comments below that it is not obvious how the suggestions I have provided help solve you problem

So here is how you could use the above information. A before filter in the application controller will ensure that the current user is ok so you don't need to check your controller params for a user id being == to the current users user id.

Secondly, if you want to know if a user is allowed to do a specific thing then add a method to the user class. something like

def can_do_something?
  #Put your code here to check if something is allowed for this specific user
end

Then instead of

if params[:user_id] == current_user.id
  # allow update!
else
  # don't allow update

You add a validation to the model that you are trying to update (which is probably related to the user in some way) then you need no additional controller code at all above the authorization and authentication checks to deal with this or if that's not a good fit and you really have to put code in your controller then do this

if current_user.can_do_something?
  # allow update!
else
  # don't allow update


Authority

Your basic case would be handled by a simply finding the resource this way:

def update
  # Best practice: only look for resources that belong to this user
  @post = User.posts.find(params[:id])
  ...
end

If you need additional checks, my Authority gem makes it pretty easy. You define who can do what to resources by writing methods like updatable_by? on Authorizer classes and letting your models delegate those questions to the authorizer. That way, models that have the same rules can just use the same authorizer.

In your controllers, you get some nice convenience methods:

class FoosController < ApplicationController

  # Sets up some before_filter checks at the class level. In other words, 
  # if the user can never update any instance of Foo, they'll never even reach
  # the update method
  authorize_actions_for Foo

  ...

 # Before this ever runs, we'll have asked if any Foo is ever `updatable_by?`
 # the current user; if not, they'll see your "access denied" page.
 def update
   # If they got this far, they can at least update **some** Foo instances
   # (though maybe not this one)
   @foo = current_user.foos.find(params[:id]) # this alone handles ownership check

   # Now that we know the specific instance, we can ask whether **this** Foo is
   # `updatable_by?` the user. This shorthand method checks with the authorizer and
   # shows the "access denied" page if the answer is false.
   authorize_action_for(@foo)
   ...
 end  

end

Since you're just writing plain Ruby methods on the authorizers, you can check anything you know how to check in Ruby.

def updatable_by?(user)
  resource.community_owned? && user.points > 20 || user.has_role?(:moderator)
end

See the detailed README for more info.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜