node.js - NODE / UPDATE / API / SEQUELIZE:UnhandledPromiseRejectionWarning:TypeError:无法读取null的属性“电子邮件”
问题描述
编辑: 问题正是在身份验证中(实际上它工作正常,但是,令牌指的是数据库中旧用户的 ID):
const { email, oldPassword } = req.body;
const user = await User.findByPk(req.userId);
if (email !== user.email) {
const userExists = await User.findOne({ where: { email } });
if (userExists) {
return res.status(400).send({ error: 'User already exists.' });
}
}
可能,在我手动更改数据库后,令牌无法识别这一点。(我也设置了 7 天的有效期)
编辑 /\
错误:
Executing (default): SELECT "id", "name", "email", "password_hash", "provider", "created_at" AS "createdAt", "updated_at" AS "updatedAt" FROM "users" AS "User" WHERE "User"."id" = 7;
(node:1616) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'email' of null
at update (C:\Project\src\app\controllers\UserController.js:56:24)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1616) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate
the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1616) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
PS:
WHERE "User"."id" = 7;
(在这种情况下,用户数据库中的 ID 为 = 1)
这条线代表:
at update (C:\Project\src\app\controllers\UserController.js:56:24)
UserController 上的这部分代码:
if (email !== user.email) { // <<<---- Here
const userExists = await User.findOne({ where: { email } });
if (userExists) {
return res.status(400).send({ error: 'User already exists.' });
}
}
理解问题:
我正在 Node.js 中创建一个 API,我正在尝试进行用户更新
我正在使用Docker在数据库中使用sequelize(PostgreSQL)(我自己作为初学者,我考虑过Docker/Database/Sequelize有问题的可能性,因为我创建了10个假用户并将其插入到数据库中,之后,我删除了所有(手动,在 Postbird 上),当然第一个新的 user_ID 会变成,例如 11)。然后,我创建了一个新的数据库,并使用 id1 正常创建了用户。
我认为用户只有在通过以下身份验证时才能更新他的信息:(
routes.use(authMiddleware);
在 ./src/routes.js 中)
- 我没有把我做的身份验证放在这里,我相信它是 100% 工作的。
这是项目的架构:
./src/routes.js
import { Router } from 'express';
import UserController from './app/controllers/UserController';
import authMiddleware from './app/middlwares/auth';
const routes = new Router();
routes.use(authMiddleware);
routes.put('/users', UserController.update);
export default routes;
.src/app/controllers/UserController.js
import User from '../models/User';
class UserController {
async update(req, res) {
const { email, oldPassword } = req.body;
const user = await User.findByPk(req.userId);
if (email !== user.email) {
const userExists = await User.findOne({ where: { email } });
if (userExists) {
return res.status(400).send({ error: 'User already exists.' });
}
}
if (oldPassword && !(await user.checkPassword(oldPassword))) {
return res.status(401).json({ error: 'Password does not match' });
}
const { id, name, provider } = await user.update(req.body);
return res.json({
id,
name,
email,
provider,
});
}
}
export default new UserController();
./src/app/models/User.js
import Sequelize, { Model } from 'sequelize';
import bcrypt from 'bcryptjs';
class User extends Model {
static init(sequelize) {
super.init(
{
name: Sequelize.STRING,
email: Sequelize.STRING,
password: Sequelize.VIRTUAL,
password_hash: Sequelize.STRING,
provider: Sequelize.BOOLEAN,
},
{
sequelize,
}
);
this.addHook('beforeSave', async (user) => {
if (user.password) {
user.password_hash = await bcrypt.hash(user.password, 8);
}
});
return this;
}
checkPassword(password) {
return bcrypt.compare(password, this.password_hash);
}
}
export default User;
./src/database/migrations/number-create-users.js
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
allowNulll: false,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNulll: false,
},
email: {
type: Sequelize.STRING,
allowNulll: false,
unique: true,
},
password_hash: {
type: Sequelize.STRING,
allowNulll: false,
},
provider: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNulll: false,
},
created_at: {
type: Sequelize.DATE,
allowNulll: false,
},
updated_at: {
type: Sequelize.DATE,
allowNulll: false,
},
});
},
down: async (queryInterface) => {
await queryInterface.dropTable('users');
},
};
HTTP/PUT JSON 数据:
{
"name": "user000",
"email": "email000@domain.com.br",
"oldPassword": "password000",
"password": "123456",
"confirmPassword": "123456"
}
考虑到用户已经通过身份验证。
解决方案
问题可能是以下查询未找到用户。因此user
可能是 undefined
。你确定这条线是正确的吗?
const user = await User.findByPk(req.userId);
并且userId
不应该在请求的正文中或在params
?IE:
const user = await User.findByPk(req.params.userId);
如果用户 ID 在参数中,我认为您还需要将您的更新route
为:
routes.put('/users/:userId', UserController.update);
此外,我认为将异步内容包装到 try catch 块中是一种很好的做法。像这样的东西:
try {
const user = await User.findByPk(req.params.userId);
} catch (err) {
console.log(err)
}
推荐阅读
- python - 重新定位当前使用 Tkinter 网格定位的棋盘游戏
- git - 有没有什么方法可以让多个设备(人)在数据块中同时在不同的分支中工作?
- r - 在 Rmarkdown 中打印树时出现奇怪的字符
- postgresql - 使用 AWS/RDS `pg_read_server_files role to COPY`运行 IHP 作业
- c# - 仅当我将 Console.WriteLine 放入 Getter 时才会触发事件
- c - 将 8 位有符号整数转换为无符号整数,然后再转换为 int32
- php - Laravel 数据库连接问题
- sql - 动态查询 - 每周更新 - Oracle SQL
- powershell - 如何使用 PowerShell 远程访问受密码保护的服务器
- java - Sceneform上的自定义PlanedDetector无需重复