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