Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node / mongoose: getting to request-context in mongoose middleware

I'm using mongoose (on node) and I'm trying to add some additional fields to a model on save by using Mongoose middleware.

I'm taking the often-used case of wanting to add a lastmodifiedsince-date. However, I also want to automatically add the name/profilelink of the user which has done the save.

schema.pre('save', function (next) {
  this.lasteditby=req.user.name; //how to get to 'req'?
  this.lasteditdate = new Date();
  next()
})

I'm using passport - http://passportjs.org/ - which results in req.user being present, req of course being the http-request.

Thanks

EDIT

I've defined pre on an embedded schema, while I'm calling save on that parent of the embedded instance. The solution posted below (passing arg as the first param of save) works on the non-embedded case, but not on mine.

like image 861
Geert-Jan Avatar asked May 07 '12 16:05

Geert-Jan


3 Answers

You can pass data to your Model.save() call which will then be passed to your middleware.

// in your route/controller
var item = new Item();
item.save(req, function() { /*a callback is required when passing args*/ });

// in your model
item.pre('save', function (next, req, callback) {
  console.log(req);
  next(callback);
});

Unfortunately this doesn't work on embedded schemas today (see https://github.com/LearnBoost/mongoose/issues/838). One work around was to attach the property to the parent and then access it within the embedded document:

a = new newModel;
a._saveArg = 'hack';

embedded.pre('save', function (next) {
  console.log(this.parent._saveArg);
  next();
})

If you really need this feature, I would recommend you re-open the issue that I linked to above.

like image 149
Bill Avatar answered Nov 01 '22 22:11

Bill


I know this is really old question, but i am answering it as I spend half a day trying to figure this out. We can pass extra properties as options as following example -

findOneAndUpdate({ '_id': id }, model, { **upsert: true, new: true, customUserId: userId, ipAddress: ipaddress.clientIp** }, function (err, objPersonnel) {

And in pre update and save access as following -

schema.pre('findOneAndUpdate', function (next) {
   // this.options.customUserId,
   // this.options.ipAddress
});

Thanks,

like image 45
daljit Avatar answered Nov 01 '22 22:11

daljit


It can be done with 'request-context'. Step to do:

Install request-context

npm i request-context --save

In your app/server init file:

var express = require('express'),
app = express();
//You awesome code ...
const contextService = require('request-context');
app.use(contextService.middleware('request'));
//Add the middleware 
app.all('*', function(req, res, next) {
  contextService.set('request.req', req);
  next();
})

In you mongoose model:

const contextService = require('request-context');
//Your model define
schema.pre('save', function (next) {
  req = contextService.get('request.req');
  // your awesome code
  next()
})
like image 29
Cong Nguyen Avatar answered Nov 01 '22 21:11

Cong Nguyen