-
Notifications
You must be signed in to change notification settings - Fork 60
Description
UPDATE on 2016-10-29:
The approach I want to take on authorizing relationships relies on always using a whitelist instead of blacklist. This means that:
- There won't be a generic
allow_relationship?method that would handle all relationships. - Using
update?after trying to set a foreign key won't work, as it is a blacklist approach.
So even at the cost of some policies becoming huge, I want to keep each method as small and unambiguous as possible. That means methods named like this:
class CommentPolicy
def allow_relationship_article?(article)
# ...
end
endI haven't yet made up my mind on which side of the association the authorization should happen, but I'd like that choice to be abstracted away from the AuthorizingProcessor. It could live inside DefaultPunditAuthorizer, if it would make sense, or we could come up with a new place for that logic to live in.
See my comment about this for more details, and to continue the discussion.
Open this to read the old proposal that kicked off the conversation
For a create request that looks like this:
{
"data": {
"id": "post-1",
"type": "posts",
"relationships": {
"author": {
"data": {
"id": "user-1", "type": "user"
}
},
"comments": {
"data": [
{ "id": "comment-1", "type": "comments" },
{ "id": "comment-2", "type": "comments" }
]
},
"tags": {
"data": [
{ "id": "tag-1", "type": "tags" },
{ "id": "tag-2", "type": "tags" }
]
}
}
}
}We authorize with these methods:
PostPolicy.new(post_1, current_user).create?PostPolicy.new(post_1, current_user).associate_with_author(user_1)?PostPolicy.new(post_1, current_user).associate_with_comments([comment_1, comment_2])?PostPolicy.new(post_1, current_user).associate_with_tags([tag_1, tag_2])?
For this request, no matter if it's an update or a create call, we are able to only use PostPolicy to authorize for every association.
I can't see there being any other way as we _cannot_ change the UserPolicy#associate_with_comments call to these without a huge scope creep:
CommentPolicy.new(comment_1, user).associate_with_post(post_1)?CommentPolicy.new(comment_2, user).associate_with_post(post_1)?
Who knows, the Comment resource might even call that association with a completely different name than post underneath!
If that request would be an update request, it would only change the PostPolicy#create? call to be PostPolicy#update? and the association checks would remain the same.
I know this goes against Pundit architecture, but I can't really see there being any other way because we aren't able to call post_1.author = author_1 nor post_1.comments = [comment_1, comment_2] before authorizing as it would implicitly save the association immediately. So we aren't able to just use the post_1.author value in PostPolicy#update? to check for authorization, as it isn't set yet.
-
has_oneassociation reference — When are objects saved? (Ruby on Rails Guides)When you assign an object to a
has_oneassociation, that object is automatically saved (in order to update its foreign key). In addition, any object being replaced is also automatically saved, because its foreign key will change too. -
has_manyassociation reference — When are objects saved? (Ruby on Rails Guides)When you assign an object to a
has_manyassociation, that object is automatically saved (in order to update its foreign key). If you assign multiple objects in one statement, then they are all saved.