Skip to content
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

PUT model/{id} (updateAttributes) implicitly invokes findById & access hook #2255

Closed
shaharz opened this issue Apr 25, 2016 · 14 comments
Closed

Comments

@shaharz
Copy link

shaharz commented Apr 25, 2016

I believe this is a similar issue to #2064. According to the docs, updateAttributes doesn't trigger the 'access' hook. However, when you PUT model/{id} there is an implicit findById call in model.js that does trigger it. As a result, PUT model/{id} might fail even though they're not looking to access the result, only in update attributes.

In addition, none of the remote hooks have been called at this point so there's no context to the operation hook to help make an intelligent decision as to whether to let the request go through or not.

Relevant stack trace:

at Function.findById (/app/user/node_modules/loopback-datasource-juggler/lib/dao.js:1134:10)
at Function.ModelCtor.sharedCtor (/app/user/node_modules/loopback/lib/model.js:160:19)
at SharedMethod.invoke (/app/user/node_modules/strong-remoting/lib/shared-method.js:252:25)
at HttpContext.invoke (/app/user/node_modules/strong-remoting/lib/http-context.js:384:12)
at restPrototypeMethodHandler (/app/user/node_modules/strong-remoting/lib/rest-adapter.js:427:9)
@superkhau superkhau self-assigned this May 2, 2016
@superkhau
Copy link
Contributor

superkhau commented May 3, 2016

Can you provide a sample repo for me to reproduce the issue on my end?

@superkhau
Copy link
Contributor

As a result, PUT model/{id} might fail even though they're not looking to access the result, only in update attributes.

@shaharz What do you mean might fail? If you are not accessing the result, it should be passed through as though you didn't add the hook.

It sounds like you're saying the problem is sending a PUT request triggers the access hook when it shouldn't.

@Amir-61 @bajtos I remember one of you guys working on refactoring the PUT feature. What is the expected behaviour with regard to what hooks get triggered for a PUT request? The docs specify before save, after save, loaded and persisted which seem to make sense to me.

/cc @raymondfeng

@Amir-61
Copy link
Contributor

Amir-61 commented May 3, 2016

According to the docs, updateAttributes doesn't trigger the 'access' hook.

That's right!

The docs specify before save, after save, loaded and persisted which seem to make sense to me.

Yes you are right for the code please see here... The following hooks are triggered by this order:'before save', 'persist', 'loaded' and 'after save'...

when you PUT model/{id} there is an implicit findById call in model.js that does trigger it

AFAICT updateAttributes does not call findById...

@shaharz
Copy link
Author

shaharz commented May 3, 2016

I later noticed the following under 'access':

Prototype methods don't trigger the access hook because the hook was already triggered by the method that loaded the model instance from the database.

For example, when you call a prototype method via the REST API, two model calls are made: static findById() (that triggers the "access" hook) and then the prototype method as requested.

So in fact it is documented, but my point regarding the lack of context in the hook still stands.

@superkhau
Copy link
Contributor

superkhau commented May 3, 2016

So in fact it is documented, but my point regarding the lack of context in the hook still stands.

@shaharz So is this a feature request to get access to context in the op hook then?

@shaharz
Copy link
Author

shaharz commented May 3, 2016

When I say context I don't mean the Loopback context, but the broad sense of the word. Suppose I I have a remote hook beforeRemote('**'), it will fire after the operation hook, if at all. As someone else said on #2064, "from the description of the beforeRemote hook I would expect that that hook is triggered before anything else happens.".

Since that's not the case, the choice is basically to either give up the access hook altogether or use middleware (that is guaranteed to fire before the hook).

If this is still unclear I can put together a minimal case to illustrate the problem.

@superkhau
Copy link
Contributor

If this is still unclear I can put together a minimal case to illustrate the problem.

This would definitely help. See https://github.com/strongloop/loopback/wiki/Reporting-issues#bug-report

@shaharz
Copy link
Author

shaharz commented May 3, 2016

@superkhau
Copy link
Contributor

@shaharz In your example, I can't reproduce it properly. beforeRemote gets called first and access is never called (opposite of what you describe in the readme).

@superkhau
Copy link
Contributor

Actually I could use your example after modifying a few things. However, the result I get is remote hook first, then access, which seems correct. What are you expecting to happen?

@shaharz
Copy link
Author

shaharz commented May 7, 2016

@superkhau I pushed npm-shrinkwrap.json to make sure we're running the same version. Also fixed formatting in the README. What you're saying is correct for PUT /Tests/ (beforeRemote then access) but not for PUT /Tests/1 (access only).

@bajtos
Copy link
Member

bajtos commented May 9, 2016

Hello, as for the "access" hook: the way how this hook is designed, it should be called whenever any model instance(s) are accessed. This way it's possible to implement custom access control by registering "access" hook observer.

We are discussing with @Amir-61 that we should eventually implement a static version of updateAttributes that would not load the instance, i.e. something like MyModel.patchById(id, data). However, such method will still invoke the "access" hook.

When I say context I don't mean the Loopback context, but the broad sense of the word. Suppose I I have a remote hook beforeRemote('**'), it will fire after the operation hook, if at all. As someone else said on #2064, "from the description of the beforeRemote hook I would expect that that hook is triggered before anything else happens.".

Since that's not the case, the choice is basically to either give up the access hook altogether or use middleware (that is guaranteed to fire before the hook).

If I understand your comments posted later, then you are looking for a remoting hook that would be called before sharedCtor is invoked, but that would include all context information for the prototype method. Is that correct assessment?

@shaharz
Copy link
Author

shaharz commented May 9, 2016

Yes, I was expecting the remote hook to be called before sharedCtor. As to whether it's this hook or a different/new one, I defer to your expertise!

@superkhau
Copy link
Contributor

Escalating to feature. Thanks for the input everyone.

@superkhau superkhau added feature and removed triaging labels May 9, 2016
@superkhau superkhau removed their assignment May 9, 2016
@stale stale bot added the stale label Aug 23, 2017
@stale stale bot closed this as completed Sep 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants