-
Notifications
You must be signed in to change notification settings - Fork 60
Make compatible with jsonapi-resources 0.9 #52
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
Conversation
|
Hi, and welcome! Thank you for starting a PR for this. I'm very excited to soon jump to review it! Hopefully it's ok that this is going to take me a few days at least until I can look into this more. I've got a tight schedule at work for a while, and as my wrist is aching again I won't be able to look at this on my freetime anytime soon. I won't forget about this PR, though :). I'll check this out when I've got a good timeslot for this 💞 |
|
Closed and reopened to try to trigger a CI build... wonder what's going on 😕 |
|
This seems to be going to a good direction, thank you! I'm not sure whether we've got a good answer to the backwards compatibility here. The relationship processor hooks have changed a bit, and when we started to authorize for relationship actions we hit these changes, too: #40 (comment) I'd be OK with going by just supporting 0.9 in a future release, as it would make the relationship authorizations cleaner as well. 0.9.0 is out of beta so it's fine if we only target that version, too. Would you be OK with setting this PR up to only support 0.9 and removing the then-unnecessary checks from your changes? |
|
Yes, totally ok with the route of 0.9-only compatibility! Should make the
code a lot cleaner, too! 🙂
…On Sun, Mar 19, 2017 at 2:37 PM Vesa Laakso ***@***.***> wrote:
This seems to be going to a good direction, thank you!
I'm not sure whether we've got a good answer to the backwards
compatibility here. The relationship processor hooks have changed a bit,
and when we started to authorize for relationship actions we hit these
changes, too: #40 (comment)
<#40 (comment)>
I'd be OK with going by just supporting 0.9 in a future release, as it
would make the relationship authorizations cleaner as well. 0.9.0 is out of
beta so it's fine if we only target that version, too.
Would you be OK with setting this PR up to only support 0.9 and removing
the then-unnecessary checks from your changes?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#52 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAWmBstuTcaVNt21pQFuyKfKkRtAOPZMks5rnXXMgaJpZM4MhE-Z>
.
|
|
OK, I have updated the gemspec to require jsonapi-resources 0.9 and updated the code accordingly. I also had to update the remove_to_many_relationship calls to match the new method signature. |
| context 'unauthorized for remove_to_many_relationship' do | ||
| before do | ||
| disallow_operation('remove_to_many_relationship', article, kind_of(Comment), :comments) | ||
| disallow_operation('remove_to_many_relationship', article, kind_of(Comment), "comments") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I wonder whether this change was necessary?
| end | ||
|
|
||
| def authorize_replace_polymorphic_to_one_relationship | ||
| raise NotImplementedError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call with just raising NotImplementedError here.
We'll need to figure out how to authorize for this polymorphic case before shipping v1.0.0 but that might be better to discuss outside of this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think we'd like to skip raising this here and figure out what to do with the polymorphic relationship scenario outside of this PR. This way we wouldn't add too much noise to this upgrade path.
Would you like to remove this callback from the processor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Removed it here 6377da9
|
|
||
| def self.creatable_fields(context) | ||
| super + [:id] | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm what was the reason for this change? Is there a reason why it is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't discover the reason in jsonapi-resources, but there are 22 failures if this is left out. In included_resources_spec, the failures look approximately like this: "Param not allowed", "detail" : "id is not allowed." I can search for more details if you like!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I wonder if it has got to with @thibaudgg's PR #11 and the changes done to the dummy app ArticleResource in https://github.com/venuu/jsonapi-authorization/pull/11/files#diff-cc66704bb355f2769ceb1ed76d5f02b4
I'm not really sure how the self.verify_key and id= methods work, and why exactly they were necessary to have. @thibaudgg do you have any insight to this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I'll have a look next week and give a try to this branch with our app.
Thanks @handlers for all the work on that one! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @thibaudgg! Let us know if you hit roadblocks.
These might be relevant to your testing, if you haven't updated in a while: #53 #40
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm waiting on @thibaudgg to be able to test this and confirm it works nicely :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🆒 thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I launched our test suite on our CI with jsonapi-resource 0.9 and this PR and we get a bunch of errors (unexpected 406 - Not Acceptable responses). It's hard to tell right now if it's because of upgrading to JR 0.9 or this PR specifically.
Sadly I didn't have much time to investigate more this week. I'll try to block an hour next week.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, that 406 error does indeed seem weird. It might very well be because of JR 0.9, too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok turns out that these lines are indeed needed since v0.8.3 of JR as IDs are generated on the client side.
See https://github.com/cerebris/jsonapi-resources/releases/tag/v0.8.3
| source_record, | ||
| related_record, | ||
| params[:relationship_type] | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of looping through all the related_records, we might want to instead change the API of remove_to_many_relationship to take an array of related_records (instead of one at a time).
That way we wouldn't even have to do the if related_resource.empty? check you're doing before calling the authorizer right now, too.
There was a comment #40 (comment) that maybe related to this not being possible before 0.9 version of JR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense to me. I will try!
|
You'll want to change the |
| set_callback :create_to_many_relationships, :before, :authorize_create_to_many_relationships | ||
| set_callback :replace_to_many_relationships, :before, :authorize_replace_to_many_relationships | ||
| set_callback :remove_to_many_relationships, :before, :authorize_remove_to_many_relationships | ||
| set_callback :replace_polymorphic_to_one_relationship, :before, :authorize_replace_polymorphic_to_one_relationship |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is too long and will cause the linter to fail the build. Sorry about that 😥
Maybe write it like like this?
set_callback(
:replace_polymorphic_to_one_relationship,
:before,
:authorize_replace_polymorphic_to_one_relationship
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
|
I've updated the PR to send records to the authorizer as a batch (7280547) instead of iterating over them individually. Travis is also now running successfully :). There is still an open thread related to an update required to make the dummy app's |
|
|
||
| # find_by_keys doesn't raise if no records, so raise explicitly here | ||
| if related_resources.empty? | ||
| fail JSONAPI::Exceptions::RecordNotFound, params[:associated_keys] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this check here? What specs fail if we'd remove this part of the code?
Maybe those tests that would fail have incorrect behaviour which we'd like to change. I don't know, but this seems a bit out of place here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question! If this is removed, one spec failure occurs: when "authorized for remove_to_many_relationship" and "limited by policy scope on comments" it { is_expected.to be_not_found }. The spec expects a 404 if the comments scope (CommentPolicy::Scope) is Comment.none.
With the new code, it instead tries to run remove_from_comments?, which raises NotImplementedError.
1) Relationship operations DELETE /articles/:id/relationships/comments authorized for remove_to_many_relationship limited by policy scope on comments
Failure/Error: raise NotImplementedError
NotImplementedError:
NotImplementedError
# ./spec/dummy/app/policies/article_policy.rb:44:in `remove_from_comments?'
# ./lib/jsonapi/authorization/default_pundit_authorizer.rb:238:in `public_send'
# ./lib/jsonapi/authorization/default_pundit_authorizer.rb:238:in `authorize_relationship_operation'
# ./lib/jsonapi/authorization/default_pundit_authorizer.rb:183:in `remove_to_many_relationship'
# ./lib/jsonapi/authorization/authorizing_processor.rb:201:in `authorize_remove_to_many_relationships'
# ./spec/requests/relationship_operations_spec.rb:275:in `block (3 levels) in <top (required)>'
# ./spec/requests/relationship_operations_spec.rb:302:in `block (5 levels) in <top (required)>'I included the fail to preserve the old 404 behavior. Perhaps we could move that fail to authorize_relationship_operation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I guess we'd really want to test that the DELETE operation authorizes properly, and doesn't use 404 when the comments can't be found.
Can you modify the tests to expect that remove_to_many_relationship authorizer method will be called with the proper arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| last_response | ||
| end | ||
|
|
||
| it { is_expected.not_to be_not_found } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we write this spec as either
it { is_expected.to be_successful }or
it { is_expected.to be_forbidden }like we have done with all the other specs?
If this feels a bit over your head, I could also tackle these at some point in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem! I updated here 3731696. I am glad to keep revising the PR, but if it's easier for you to finish it, that's fine too!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi! I left final review comments for the specs. If these can be addressed, we could merge this PR and fix issues that crop up with JR 0.9 in a future PR
| before do | ||
| allow_operation('remove_to_many_relationship', article, kind_of(Comment), :comments) | ||
| allow_any_instance_of(ArticlePolicy).to receive( | ||
| :remove_from_comments?).and_return(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great if we didn't have to worry about policies in here at all, and could create this spec in terms of only the operations stubbing instead.
Would it be possible to restructure this spec to look something like this?
context 'limited by policy scope on comments' do
let(:comments_scope) { Comment.none }
before do
allow_operation('remove_to_many_relationship', article, [], :comments)
end
it { is_expected.to be_succesful }
endThis would also ensure that the remove_to_many_relationship is indeed called with an empty array instead of any comments.
| [article, comments_to_remove.first, :comments], | ||
| [article, comments_to_remove.second, :comments] | ||
| ]) | ||
| allow_operation('remove_to_many_relationship', article, kind_of(Array), "comments") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we restructure this to test for the actual comments instead of just kind_of(Array)? The kind_of(Array) might be a bit too vague spec and could cause bugs to slip through as it doesn't care about the type of the objects inside the array itself.
Would something like this work?
allow_operation(
'remove_to_many_relationship',
article,
[comments_to_remove.first, comments_to_remove.second],
:comments
)That would be the best. If the specs fail because of this due to some matchers not working correctly, we should fix the matchers instead of trying to work around them by using less specific assertions.
Also, as you can see, let's try to use the symbol version for the relationship name in the assertions (:comments instead of "comments") or otherwise it might result in an inconsistent API with the other authorizers)
| context 'unauthorized for remove_to_many_relationship' do | ||
| before do | ||
| disallow_operation('remove_to_many_relationship', article, kind_of(Comment), :comments) | ||
| disallow_operation('remove_to_many_relationship', article, kind_of(Array), "comments") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing as in https://github.com/venuu/jsonapi-authorization/pull/52/files#r109101102, just that the assertion should be disallow_operation instead of allow_operation
| context 'limited by policy scope on articles' do | ||
| before do | ||
| allow_operation('remove_to_many_relationship', article, kind_of(Comment), :comments) | ||
| allow_operation('remove_to_many_relationship', article, kind_of(Array), :comments) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spec/support/authorization_stubs.rb
Outdated
|
|
||
| allow(AUTHORIZER_CLASS).to receive(:new).with(Hash).and_return(authorizer) | ||
| authorizer | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We hopefully don't need to add this new method here, if we can satisfy the spec in https://github.com/venuu/jsonapi-authorization/pull/52/files#r109100787 with the existing matchers
|
Thanks so much @valscion! I am going to try to update the PR today or tomorrow. |
|
Thank you so much @thibaudgg for testing this out, really appreciate it! We actually just moments ago stumbled upon an issue in JR (it was this one if you're interested) and as it has been fixed in 0.9.0 we'll want to push this PR through if not today, then tomorrow.
We'd actually prefer merge commits over rebasing. We like to keep the history of the conversation in place. |
|
I'll tackle this tomorrow (which in our timezone would be around 16 hours from now). So if you feel like addressing the tests before that, @handlers, feel free to, but if you don't have the time I'll happily plow through them as well and get this PR merged Thank you so much for your efforts here! 💞 |
|
I won't be able to get to this for a while, so feel free to make any
modifications necessary!
…On Tue, Apr 11, 2017 at 11:04 AM Vesa Laakso ***@***.***> wrote:
I'll tackle this tomorrow (which in our timezone would be around 16 hours
from now).
So if you feel like addressing the tests before that, @handlers
<https://github.com/handlers>, feel free to, but if you don't have the
time I'll happily plow through them as well and get this PR merged
|
valscion
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 Thank you!
|
👏 |
Hi! In an effort to make jsonapi-authorization's test suite pass against jsonapi-resources 0.9, this PR does a few things:
:create_to_many_relationship:replace_to_many_relationship:remove_to_many_relationshipbased on whether or notJSONAPI::Processorresponds to the singular or plural version of the method (See Not compatible with v0.9.0 of jsonapi-resources #36).replace_polymorphic_to_one_relationship, which is present in jsonapi-resources 0.9 and 0.8.0.beta1. I don't think this is strictly necessary for 0.9 compatibility but is good to have in my opinion.authorize_remove_to_many_relationshipby updating the logic to find all related records and callauthorizer.remove_to_many_relationshipon each of them.When this branch is run against the suite with jsonapi-resources at 0.8.0.beta1, there are a couple of failures. I am not sure what the backwards compatibility requirements are between point releases of the gem, but I definitely tried to stay somewhat backwards compatible in the conditional callback setting strategy.
I am super new to this project and definitely want to get some experienced 👀 on this! Happy to chop it up into separate PRs and fix stuff up, as this one has a few distinct threads to it.