There are a lot of rails plugins out there that handle user permissions. I'm impressed with the implementation in the hobo gem, but I'm not sure if I can use just this feature and not the other parts. GateKeeper is a really clever implementation, but has some bugs, though it's small enough I could probably fix it myself. Restful_ACL gives you a class method for checking creation, meaning you can't do any checks on the instance in question (not sure if it does scoped finds).
I'd like something that provides a scoped version of ActiveRecord#find which only finds things the current user is allowed to see. This should be robust enough to say, you can only see pictures that are in galleries that are owned by you or one of your friends.
As a bonus, it could prevent creates or updates (in a before_* or validation step) that you don't have the right to perform, including associating your own records with a different user or gallery, or creating such records.
You can do some really complex authorization tricks on the model level with declarative_authorization plugin. Nevertheless, I myself prefer rails-authorization-plugin - with this one you define the roles on the model level (eg. someone is an owner of a resource) and the permissions on the controller level (eg. only the owner of a resource or admin can get the resource). I find this approach much more concise, especially if you are pursuing for a clean REST approach. If you have request like this one:
GET /posts
what you really should return is all posts, not just the posts of the current user. For that purpose you should have a different route:
GET /users/:user_id/posts
where :user_id is set to current user's id. This difference should then be mirrored in the appropriate action:
def index
user = User.find(params[:user_id]) unless params[:user_id].blank?
@posts =
if user
# get all posts of a user
user.posts.all
else
# get all posts
Post.all
end
end
Now, what you really have here are two authorization contexts - "get all posts of a user" and "get all posts" and you usually want to set different permissions for both (eg. "only admins can get all posts" and "only user it self or an admin can get all posts of a user").
I have a gem that's entirely about being able to specify permissions for objects based on their role. You can take a look here: http://github.com/nakajima/roleful/tree/master. It would work well for the sort of before_filter
approach you hinted at.
As for only allowing users to access things with which they have some sort of relationship, I'd think that you're looking at a prime candidate for Rails association proxies. I like Milan Novota's snippet, though I'd modify it slightly:
def index
@posts = user_repo.posts
end
private
def user_repo
# find_by_id is **much** faster than regular find,
# plus it just returns nil when there's no record
if user = User.find_by_id(params[:user_id])
# returns the association proxy
user.posts
else
# returns the class
User
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With