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

How to retrieve current logged user from mongoose middlewares? #14530

Open
1 task done
nikzanda opened this issue Apr 22, 2024 · 5 comments
Open
1 task done

How to retrieve current logged user from mongoose middlewares? #14530

nikzanda opened this issue Apr 22, 2024 · 5 comments
Labels
help wanted help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary

Comments

@nikzanda
Copy link

nikzanda commented Apr 22, 2024

Prerequisites

  • I have written a descriptive issue title

Mongoose version

8.3.2

Node.js version

20.10.0

MongoDB version

6.0.2

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

14.3.1

Issue

I need to retrieve the user who made a request to my webApp endpoint in which I run an update on a mongoose model.
I want to use the user's id in a pre('save', ...) in order to save an activity log, or maybe in order to auto update a lastModifiedBy field in each of my collections (least preferred option, and I don't want to set it manually using model.set function).

image

@nikzanda nikzanda added help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary help wanted labels Apr 22, 2024
@humblewolfstudio
Copy link

You should have the userId somewhere in the session right? Are you authenticating the users that request that endpoint?

@nikzanda
Copy link
Author

You should have the userId somewhere in the session right? Are you authenticating the users that request that endpoint?

Yes, I have an express web application and users log in the app by JWT authentication, so I have the userId available in every method in the req variable.

@vkarpov15
Copy link
Collaborator

session is typically used for MongoDB transactions.

The easiest way to pass data to pre('save') middleware is by adding the data to the document's $locals property. That's a property on the document that Mongoose doesn't store in MongoDB and is used for storing ephemeral data for getters, virtuals, middleware, etc.

// In Express route handler:
doc.$locals.userId = req.userId;

// In schema definition:
schema.pre('save', function() {
  this.$locals.userId; // from `req.userId`
});

Does this help?

@nikzanda
Copy link
Author

session is typically used for MongoDB transactions.

The easiest way to pass data to pre('save') middleware is by adding the data to the document's $locals property. That's a property on the document that Mongoose doesn't store in MongoDB and is used for storing ephemeral data for getters, virtuals, middleware, etc.

// In Express route handler:
doc.$locals.userId = req.userId;

// In schema definition:
schema.pre('save', function() {
  this.$locals.userId; // from `req.userId`
});

Does this help?

That's exactly what I was looking for, thanks. The only downside is that I have to set it manually before every save directly on the document: the optimal solution would be to set it automatically one time for every db operation at the beginning of a user's request, for example directly in an express middleware. Is there a way to do so?
Moreover, using $locals does not work with all the functions performed directly on the database eg. updateMany, deleteMany, findOneAndUpdate, updateOne, etc... because there's the need to retrieve the document before. Any ideas on how to manage this use case?

@vkarpov15
Copy link
Collaborator

To automatically make userId accessible from middleware without explicitly passing it every time, you'd something like async local storage.

For queries, you can set the userId as an option and then access it from middleware:

// In Express route handler:
await TestModel.findOne().setOptions({ userId });

// In schema definition:
schema.pre('findOne', function() {
  this.options.userId; // from `req.userId`
});

Are you trying to use Mongoose middleware to implement authorization?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary
Projects
None yet
Development

No branches or pull requests

3 participants