-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
n+1 for side loaded records #83
Comments
I was worried we'd have something like this. Most likely the culprit is in here, where we authorize that you have access to display every related record when using the jsonapi-authorization/lib/jsonapi/authorization/authorizing_processor.rb Lines 340 to 382 in d258f01
Would you be willing to try fixing this somehow? It might very well be that the current approach requires re-thinking — and that is totally fine as well. For context, this was the original issue that prompted authorization of side-loaded resources: #7 — and this PR implemented a first approach to that problem: #10 Of particular note is this comment in #10 by @lime:
...so most likely your issue just highlights that the method got back and bit us 😅 |
@valscion Thanks for your reply and thorough breakdown of the potential problem. I've taken a brief look at the source but honestly I'm not all that familiar with how the library is doing things, and much less familiar with JSONAPI Resources. I'm not sure how much I can contribute to the solution, but I will certainly pitch in to test it extensively. |
Would you happen to have time for me to walk you through the code, for example via a video chat? Would that help? |
I do need to make some time to figure this out since it's blocking currently. Do you have a sense of how complicated the issue is? |
I'm afraid it might be a bit complicated, and likely warrants rethinking include authorization. Before writing any code, we should discuss design of potential solutions first, in order for us not to shoot ourselves in the foot. Try to bear with me as I write up some architectural decisions I've made in the past. As the authorization layer sits on the JR processor layer, we unfortunately have way less information available on the resources and thus have to usually fetch records manually. This is likely the main reason why adding The current approach works by deducing associations from the The reason why we need to do this authorization in the first place, is that I have had a hunch and when looking at JR code, I seem to have found out that include directives haven't gone through the resource association hooks correctly and thus have bypassed our pundit policy scope hooks. It would be amazing if we could:
It would mean that without any hook to include directives, our applications could leak information. On the other hand, if we can show that pundit policy scopes are being used on all levels of the include directive, the current solution might be a huge overkill and an incorrect solution in the first place. It seems that in #7 (comment) I noticed that policy scopes are being bypassed for
...we might be safe again. What we'd need would be tests that verify this functionality. Those tests should happen on the request layer for every operation allowing resource sideloading, like I did in #10 with these request specs:
|
I think this is a bit beyond my scope of understanding for Pundit, JSONAPI Resources and this gem. I may not be able to take the lead on implementing a fix here. |
Thanks for thinking about this and engaging in discussion @adambedford 💞 . I am grateful that you thought about this, and it's OK to admit that this might be too much right now One way to get you unblocked at your project could be to subclass # Work around N+1 problem with `?include=company,company.company-master` queries
# by subclassing jsonapi-authorization processor to skip include authorization completely
#
# https://github.com/venuu/jsonapi-authorization/issues/83#issuecomment-337152268
class CustomAuthorizingProcessorSkippingInclude < JSONAPI::Authorization::AuthorizingProcessor
def authorize_include_item
# no-op
end
end # config/initializers/jsonapi-resources.rb
JSONAPI.configure do |config|
config.default_processor_klass = CustomAuthorizingProcessorSkippingInclude
# ...
end I advise you to double-check that you are not leaking information from your database in your API responses. |
Hi @valscion Thanks for the write up, it was helpful in understanding this issue! Do you still think the best action is to write a test for the following?
|
Great! I'm glad it was helpful
It would indeed be very helpful to verify my hypothesis is correct and we need to add manual authorization for the sideloaded resources case. I'd love to be proven wrong here. I have a feeling that this issue might have been resolved with upcoming |
Could potentially be fixed when cerebris/jsonapi-resources#1164 lands |
Wow, thanks for linking to that PR @Subtletree! It looks really promising indeed |
I'm using JSON API
include
to side load two associations (two levels deep:company,company.company-master
) and I'm seeing an N+1 issue when plugging in Pundit + JSONAPI Athorization into my JSONAPI Resources Processor stack.I've tried explicitly including those two associations in the policy scope with no success, although this shouldn't be required since JSONAPI Resources should be handling this. It does when JSONAPI Authorization isn't involved.
The logs produced:
As you can see, the side loaded records are fetched as normal. However, after that, individual queries are performed, which shouldn't be happening.
This is my policy:
The scope returned should already include the
includes(company: [:company_master])
, and explicitly adding it doesn't resolve the issue.The text was updated successfully, but these errors were encountered: