question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: updateHandler to use findById() + findOneAndUpdate()

See original GitHub issue

Using 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:closed
  • Created 6 years ago
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
JKHeadleycommented, Sep 6, 2017

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 the update: pre and update: post methods there could be a new upsert: pre and upsert: post option that would correctly handle the query. Then you could simply pass { _id: _id } as the query and add the account property in the upsert: pre middleware. Would that work for you?

0reactions
JKHeadleycommented, Oct 10, 2017

@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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Use `findOneAndUpdate()` in Mongoose
As the name implies, findOneAndUpdate() finds the first document that matches a given filter , applies an update , and returns the document....
Read more >
db.collection.findOneAndUpdate() — MongoDB Manual
The selection criteria for the update. The same query selectors as in the find() method are available. To update the first document returned...
Read more >
Mongoose: findOneAndUpdate doesn't return updated ...
Why this happens? The default is to return the original, unaltered document. If you want the new, updated document to be returned you...
Read more >
09 - Perform New Updates Using model.findOneAndUpdate
Mongoose has some methods findOneAndUpdate() and findByIdAndUpdate() that allow us to update records in one step.
Read more >
pre, post middleware are not executed on findByIdAndUpdate
AFAIK, the only way to get the hooks to execute is to use separate find() and save() calls as mentioned above.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found