Closed Matthijsy closed 5 years ago
When you're accessing something plural, like in your case "addresses", jsnonapi-authorization
should call addresses#index?
and also make the returned addresses records go through your policy scope.
Could you tell me a bit more about what you see happening?
I have a user which has many addresses, I defined all the policy methods of addresses as false (for debugging). When I do a request to /addresses I get 403. However when I do /users/1/addresses I get the list of addresses. Do I need to include some mixin? I have included JSONAPI::Authorization::PunditScopedResource
When looking in the authorizer class I see some difference between /resource/:id/relationship and /resource?include=relationship. Is this maybe cause by that? Because when i do /user?include=addresses I do get a 403.
Reference: https://github.com/venuu/jsonapi-authorization/blob/master/lib/jsonapi/authorization/default_pundit_authorizer.rb#L80 https://github.com/venuu/jsonapi-authorization/blob/master/lib/jsonapi/authorization/default_pundit_authorizer.rb#L226
Hmm yeah, PunditScopedResource
should be enough to make it go through your policy scope:
Have you perhaps overridden the definition for records_for
in your UserResource
or somewhere else?
The specs here:
Should say that jsonapi-authorization
does apply the policy scope:
As otherwise the spec would've returned 3 comments instead of only 1:
Now I see why it is not working. It is not calling AddressPolicy#index?
but it's calling AddressPolicy::Scope#resolve
. So I need to create a scope resolve method for the relationship. Is this the inteded behaviour?
Hmm... when viewing related resources, we do not call RelatedRecordPolicy#index?
at all here:
That might be a bug. I wonder if we have the information in that place to figure out which related resource class we're trying to look at? The method should pass related_record_class:
keyword argument to the authorizer if possible, and then that should be used to call:
def show_related_resources(source_record:, related_record_class:)
::Pundit.authorize(user, source_record, 'show?')
::Pundit.authorize(user, related_record_class, 'index?')
end
Now I see why it is not working. It is not calling
AddressPolicy#index?
but it's callingAddressPolicy::Scope#resolve
. So I need to create a scope resolve method for the relationship. Is this the inteded behaviour?
Yes, you should create a scope resolve method for the relationship. I think it should've errored out if you didn't have one defined? Or maybe you have some base class that defines an "all results are OK" scope resolver?
Yes we have an base Scope which returns all the records. It would be great if for related resources it will call the related record policy index? as well (as you mentioned 2 comments above). For now I will work with the Scope.resolve
Yeah sounds like a plan 😊
Hi,
I just found out that when accessing the relationships of a model (for example /users/1/addresses) with a has_many relationship only the
model#show?
policy is checked. I would expect that also the relationship policy is checked (in my exampleaddresses#show?
). What is the reason that this doesn't happen? Is this an error or is this intended?In my user addresses example I cannot forbid a user to get addresses of all the other users without forbidding all users to see another user. This is not what I want. How can I make this happen?