Sequelize class 方法工作正常但实例方法不起作用
Sequelize class method works fine but instance method is not working
我已经在Sequelize中定义了一个用户模型,还为它定义了一个自定义的class方法和一个实例方法。我在登录 api 中调用了这两种方法(效果很好)。问题是 class 方法完美运行,但实例方法导致错误,我无法识别我的代码有什么问题。请帮忙。
这是我的用户模型及其方法:
const Sequelize = require("sequelize");
const sequelize = require("../db/db.config");
const bcrypt = require("bcryptjs");
const _ = require("lodash");
const jwt = require("jsonwebtoken");
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
first_name: {
type: Sequelize.STRING(50),
allowNull: false,
},
last_name: {
type: Sequelize.STRING(50),
allowNull: false,
},
email: {
type: Sequelize.STRING(50),
allowNull: false,
validate: {
isEmail: true,
},
},
password: {
type: Sequelize.STRING(100),
allowNull: false,
},
});
User.prototype.testMethod = function () {
console.log("THIS IS A TEST");
};
User.beforeCreate(async (user, options) => {
const hashedPassword = await bcrypt.hash(user.password, 10);
user.password = hashedPassword;
});
User.findByEmailAndPassword = async function (inputEmail, inputPassword) {
try {
const user = await User.findOne({ where: { email: inputEmail } });
if (user === null) {
return null;
}
const passwordMatch = await bcrypt.compare(inputPassword, user.password);
if (!passwordMatch) {
return null;
}
return _.pick(user, "id", "first_name", "last_name", "email");
} catch (error) {
console.log("FIND BY EMAIL AND PASSWORD ERROR: ", error);
}
};
module.exports = User;
这是我的登录路由器:
const express = require("express");
const router = express.Router();
const User = require("../models/user.model");
router.post("/api/login", async (req, res) => {
try {
const user = await User.findByEmailAndPassword(
req.body.email,
req.body.password
);
console.log("USER: ", user);
await user.testMethod();
if (!user) {
return res.status(400).send({
errorMessage: "Username and password combination is not correct!",
});
}
return res.status(200).send(user);
} catch (error) {
res.status(400).send({ errorMessage: error });
}
});
module.exports = router;
谢谢。
首先,您遇到问题的原因是 findByEmailAndPassword
是 return 从 _.pick
中获取常规对象,并且您正在为 Sequelize
定义实例方法实例。此实例方法可以在 Sequelize
实例而不是常规对象上调用。
但是,你的目标是
What I'm trying to do here is to avoid sending user password in my response body.
defaultScope
非常适合这个用例。它允许您在模型上定义一些重复的选项。
您可以将用户模型定义为
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
...
}, {
defaultScope: {
attributes: {
exclude: ['password']
}
}
});
在模型上定义 defaultScope
,这将默认应用于许多 Sequelize
函数。
Scopes apply to .find, .findAll, .count, .update, .increment and .destroy.
我也测试过它也适用于.findByPk
,.findOne
.
那么,如何使用...
调用常规 Sequelize findOne
函数。
const user = User.findOne({
where: {
email: req.body.email,
password: req.body.password
}
});
默认情况下,由于应用了 defaultScope
,因此不会 return password
响应。
在某些需要return password
的情况下,使用unscoped
禁用defaultScope
。
// This will return `password` in response.
User.unscoped().fineOne(...)
我已经在Sequelize中定义了一个用户模型,还为它定义了一个自定义的class方法和一个实例方法。我在登录 api 中调用了这两种方法(效果很好)。问题是 class 方法完美运行,但实例方法导致错误,我无法识别我的代码有什么问题。请帮忙。
这是我的用户模型及其方法:
const Sequelize = require("sequelize");
const sequelize = require("../db/db.config");
const bcrypt = require("bcryptjs");
const _ = require("lodash");
const jwt = require("jsonwebtoken");
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
first_name: {
type: Sequelize.STRING(50),
allowNull: false,
},
last_name: {
type: Sequelize.STRING(50),
allowNull: false,
},
email: {
type: Sequelize.STRING(50),
allowNull: false,
validate: {
isEmail: true,
},
},
password: {
type: Sequelize.STRING(100),
allowNull: false,
},
});
User.prototype.testMethod = function () {
console.log("THIS IS A TEST");
};
User.beforeCreate(async (user, options) => {
const hashedPassword = await bcrypt.hash(user.password, 10);
user.password = hashedPassword;
});
User.findByEmailAndPassword = async function (inputEmail, inputPassword) {
try {
const user = await User.findOne({ where: { email: inputEmail } });
if (user === null) {
return null;
}
const passwordMatch = await bcrypt.compare(inputPassword, user.password);
if (!passwordMatch) {
return null;
}
return _.pick(user, "id", "first_name", "last_name", "email");
} catch (error) {
console.log("FIND BY EMAIL AND PASSWORD ERROR: ", error);
}
};
module.exports = User;
这是我的登录路由器:
const express = require("express");
const router = express.Router();
const User = require("../models/user.model");
router.post("/api/login", async (req, res) => {
try {
const user = await User.findByEmailAndPassword(
req.body.email,
req.body.password
);
console.log("USER: ", user);
await user.testMethod();
if (!user) {
return res.status(400).send({
errorMessage: "Username and password combination is not correct!",
});
}
return res.status(200).send(user);
} catch (error) {
res.status(400).send({ errorMessage: error });
}
});
module.exports = router;
谢谢。
首先,您遇到问题的原因是 findByEmailAndPassword
是 return 从 _.pick
中获取常规对象,并且您正在为 Sequelize
定义实例方法实例。此实例方法可以在 Sequelize
实例而不是常规对象上调用。
但是,你的目标是
What I'm trying to do here is to avoid sending user password in my response body.
defaultScope
非常适合这个用例。它允许您在模型上定义一些重复的选项。
您可以将用户模型定义为
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
...
}, {
defaultScope: {
attributes: {
exclude: ['password']
}
}
});
在模型上定义 defaultScope
,这将默认应用于许多 Sequelize
函数。
Scopes apply to .find, .findAll, .count, .update, .increment and .destroy.
我也测试过它也适用于.findByPk
,.findOne
.
那么,如何使用...
调用常规 Sequelize findOne
函数。
const user = User.findOne({
where: {
email: req.body.email,
password: req.body.password
}
});
默认情况下,由于应用了 defaultScope
,因此不会 return password
响应。
在某些需要return password
的情况下,使用unscoped
禁用defaultScope
。
// This will return `password` in response.
User.unscoped().fineOne(...)