Mongoose pre method, returns this as empty object

Asked

Viewed 381 times

1

I have the following model, where when registering the user in mongodb , I want him to encrypt the password using bcryptjs, using the Mongoose method UserSchema.pre('save'...

const bcrypt = require('bcryptjs');

module.exports = (app) => {

const mongoose = app.config.banco;

const UserSchema = new mongoose.Schema({

    nome: {
        type: String,
        required: true
    },

    email: {
        type: String,
        required: true
    },

    password: {
        type: String,
        required: true,
        select: false
    },

    criacao: {
        type: Date,
        default: Date.now
    }
});

UserSchema.pre('save', async (next) => {
    console.log(this);
    const hash = await bcrypt.hash(this.password, 10);
    this.password = hash;
    next();
});

const user = mongoose.model('User', UserSchema);
return user;
}

where I have a file in the directory controller to make this registration

module.exports = (app) => {

return {
    async cadastra(req, res) {
        const User = app.models.Usuario;
        const user = await User.create(req.body);
        res.json(user);

 }

 }

only that the method of bcryptjs indicates that the property this.password is undefined where I also put a console.log(this) within the method pre to check which returned, where it is returning empty literal object {}

Error returning in console

 {}
(node:7000) UnhandledPromiseRejectionWarning: Error: Illegal arguments: undefined, number
    at _async (c:\node-api\api-registro\node_modules\bcryptjs\dist\bcrypt.js:214:46)
    at c:\node-api\api-registro\node_modules\bcryptjs\dist\bcrypt.js:223:17

2 answers

1


Change your Arrow Function for a normal function.

An expression Arrow Function has a shorter syntax when compared to a function expression (Function Expression) and doesn’t have his own this, arguments, super or new.target. These function expressions are best applied to functions other than methods, and they cannot be used as constructors (constructors).

Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

UserSchema.pre('save', async function(next){
    console.log(this);
    const hash = await bcrypt.hash(this.password, 10);
    this.password = hash;
    next();
});

0

I don’t know if his friend solved the problem, but in case he didn’t, the problem is

password: {
        type: String,
        required: true,
        select: false
    },

Instead of using the select: false, use select: true

Example:

password: {
        type: String,
        required: true,
        select: true
    },

This mainly serves if you are using code to update and maintain encryption, as in the example:

UserSchema.pre('findOneAndUpdate', async function(next) {
  const userUpdate = await this.model.findOne(this.getQuery());
  userUpdate.password = await bcrypt.hash(userUpdate.password, 10);

  // console.log(userUpdate); // The document that `findOneAndUpdate()` will modify

  userUpdate.save();

  next();
});

If the password is as select: false the object in the database will not be updated. At least that’s how I solved part of my problem.

  • Another detail that I forgot to say: To avoid updating all fields whenever you are going to update, avoid using the http PUT method, instead use PATCH, as it makes it possible to update each field independently, since the PUT method replaces the whole object.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.