Proposal: updateHandler to use findById() + findOneAndUpdate()
See original GitHub issueUsing the recent changes/additions to the middleware, I’ve been able to have my create, list and find endpoints use the authenticated user’s credentials. For example:
create: {
pre: function(payload, request, Log) {
payload.account = request.auth.credentials.account;
return Promise.resolve(payload);
},
},
list: {
pre: function(query, request, Log) {
query.account = request.auth.credentials.account;
return Promise.resolve(query);
},
},
Now I’m working on adding the same functionality to the update endpoint. Currently the update handler simply calls model.findByIdAndUpdate(_id, payload)
. I propose changing this to:
mongooseQuery = model.findById(_id);
mongooseQuery = QueryHelper.createMongooseQuery(model, query, mongooseQuery, Log);
mongooseQuery.findOneAndUpdate(payload)
This way, the document specified by _id will only be found and updated if it also matches any additional constraints in the query.
I have a proof-of-concept implementation at https://github.com/pangeamedia/rest-hapi/commit/fea600d713dce4f59b92bcb2ac7637399039b017#diff-cae92e718d9d94bbd9debab4fbf43095L734 I’ve tested this POC in my app, and it works as expected.
The main difficulty is that the update.pre middleware function currently only returns the payload, but I need it to return the query. For the proof-of-concept, I have update.pre return the query as payload.$query
. This is not ideal, but it maintains backwards compatibility.
Other ideas I had include update.pre returning an object like { payload: payload, query: query }
or an array like [ payload, query ]
, possibly maintaining backwards compatibility in either case by having the update handler introspect the returned value. I don’t know what approach is best.
Thoughts?
Issue Analytics
- State:
- Created 6 years ago
- Comments:9 (9 by maintainers)
I see, it sounds like you’re looking for a method of document specific authorization, which is definitely a feature I would like to add in the near future. Ideally it would perform similar to route specific authorization (most likely utilizing hapi scopes somehow) but on a document level.
I still believe the best way to accomplish the update queries would be through a new
PUT /model
endpoint. That way rather than changing and possibly breaking theupdate: pre
andupdate: post
methods there could be a newupsert: pre
andupsert: post
option that would correctly handle the query. Then you could simply pass{ _id: _id }
as the query and add theaccount
property in theupsert: pre
middleware. Would that work for you?@tamias just pushed an update that includes document-specific authorization.
Also, I provided an example of how to accomplish a task similar to your use-case mentioned in this issue. It takes advantage of the new policies feature. Please see the docs here.