Sequelize: don't return password

僤鯓⒐⒋嵵緔 提交于 2019-11-28 18:19:56

I would suggest overriding the toJSON function:

sequelize.define('user', attributes, {
  instanceMethods: {
    toJSON: function () {
      var values = Object.assign({}, this.get());

      delete values.password;
      return values;
    }
  }
});

Or in sequelize v4

const User = sequelize.define('user', attributes, {});

User.prototype.toJSON =  function () {
  var values = Object.assign({}, this.get());

  delete values.password;
  return values;
}

toJSON is called when the data is returned to the user, so end users won't see the password field, but it will still be available in your code.

Object.assign clones the returned object - Otherwise you will completely delete the property from the instance.

Another way is to add a default scope to the User model.

Add this in the model's options object

defaultScope: {
  attributes: { exclude: ['password'] },
}

Or you can create a separate scope to use it only in certain queries.

Add this in the model's options object

scopes: {
  withoutPassword: {
    attributes: { exclude: ['password'] },
  }
}

Then you can use it in queries

User.scope('withoutPassword').findAll();

Maybe you can just add exclude at your attribute when you find, look like this:

var User = sequelize.define('user', attributes);

User.findAll({
    attributes: {
        exclude: ['password']
    }
});

Read the docs for more details

I like to use a combination of both of Pawan's answers and declare the following:

defaultScope: {
    attributes: { exclude: ['password'] },
},
scopes: {
    withPassword: {
        attributes: { },
    }
}

This allows me to exclude the password by default and use the withPassword scope to explicitly return the password when needed, such as when running a login method.

userModel.scope('withPassword').findAll()

This ensure that the password is not returned when including the user via a referenced field, e.g.

accountModel.findAll({
    include: [{
        model: userModel,
        as: 'user'
    }]
})

there's a plugin for scoping attributes as discussed here.

i went with the override as mentioned in the accepted answer, except i called the original toJSON rather than get with this.constructor.super_.prototype.toJSON.apply(this, arguments) as described in the api docs

The code below worked for me. We wanted access to the instance attributes at runtime but remove them before sending the data to the client.

const Sequelize = require('sequelize')

const sequelize = new Sequelize('postgres://user:pass@example.com:5432/dbname')

const PROTECTED_ATTRIBUTES = ['password', 'token']

const Model = Sequelize.Model

class User extends Model {
  toJSON () {
    // hide protected fields
    let attributes = Object.assign({}, this.get())
    for (let a of PROTECTED_ATTRIBUTES) {
      delete attributes[a]
    }
    return attributes
  }
}

User.init({
  email: {
    type: Sequelize.STRING,
    unique: true,
    allowNull: false,
    validate: {
      isEmail: true
    }
  },
  password: {
    type: Sequelize.STRING,
    allowNull: false
  },
  token: {
    type: Sequelize.STRING(16),
    unique: true,
    allowNull: false
  },
},
{
  sequelize,
  modelName: 'user'
})

module.exports = User

Github Gist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!