Sequelize: не возвращать пароль

Я использую Sequelize для поиска базы данных для записи пользователя, и я хочу, чтобы поведение модели по умолчанию не возвращало поле password для этой записи. Поле password является хешем, но я все равно не хочу его возвращать.

У меня есть несколько вариантов, которые будут работать, но никто не кажется особенно хорошим:

  • Создайте собственный метод класса findWithoutPassword для модели User и внутри этого метода сделайте User.find с параметром attributes, как показано в Sequelize docs

  • Сделайте обычный User.find и отфильтруйте результаты в контроллере (не рекомендуется)

  • Используйте другую библиотеку для удаления нежелательных атрибутов

Есть ли лучший способ? Лучше всего было бы, если бы был способ указать в определении модели Sequelize, чтобы никогда не возвращать поле password, но я не нашел способа сделать это.

Ответ 1

Я бы предложил переопределить функцию toJSON:

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

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

Или в продолжении v4

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

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

  delete values.password;
  return values;
}

toJSON вызывается, когда данные возвращаются пользователю, поэтому конечные пользователи не будут видеть поле пароля, но оно все равно будет доступно в вашем коде.

Object.assign клонирует возвращенный объект. В противном случае вы полностью удалите свойство из экземпляра.

Ответ 2

Другим способом является добавление области по умолчанию в модель пользователя.

Добавьте это в объект параметров модели

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

Или вы можете создать отдельную область, чтобы использовать ее только в определенных запросах.

Добавьте это в объект параметров модели

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

Затем вы можете использовать его в запросах

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

Ответ 3

Возможно, вы можете просто добавить exclude в свой атрибут, когда вы find, выглядите так:

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

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

Подробнее читайте docs

Ответ 4

Мне нравится использовать комбинацию обоих ответов Павана и объявлять следующее:

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

Это позволяет мне исключить пароль по умолчанию и использовать область withPassword для явного возврата пароля при необходимости, например, при запуске метода входа в систему.

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

Это гарантирует, что пароль не будет возвращен при включении пользователя через указанное поле, например

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

Ответ 5

есть плагин для атрибутов определения, как обсуждалось здесь.

я пошел с переопределением, как указано в принятом ответе, за исключением того, что я назвал исходный toJSON, а не get с this.constructor.super_.prototype.toJSON.apply(this, arguments), как описано в api docs

Ответ 6

Код ниже работал для меня. Мы хотели получить доступ к атрибутам экземпляра во время выполнения, но удалили их перед отправкой данных клиенту.

const Sequelize = require('sequelize')

const sequelize = new Sequelize('postgres://user:[email protected]: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