From 4ae023afb0239c1e8d33be6ca91f13f04ef65497 Mon Sep 17 00:00:00 2001 From: Sunwuyuan Date: Sun, 16 Nov 2025 14:46:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=8F=90=E5=8F=96=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=20UUID=20=E8=AE=A4=E8=AF=81=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E4=BB=B6=E7=9A=84=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware/uuidAuth.js | 15 +++ routes/device.js | 231 ++++------------------------------------- 2 files changed, 34 insertions(+), 212 deletions(-) diff --git a/middleware/uuidAuth.js b/middleware/uuidAuth.js index bc6aef5..7ccaeaf 100644 --- a/middleware/uuidAuth.js +++ b/middleware/uuidAuth.js @@ -93,7 +93,22 @@ export const uuidAuth = async (req, res, next) => { next(error); } }; +export const extractDeviceInfo = async (req,res,next) => { + var uuid= extractUuid(req); + if (!uuid) { + throw errors.createError(400, "需要提供设备UUID"); + } + const device = await prisma.device.findUnique({ + where: { uuid }, + }); + if (!device) { + throw errors.createError(404, "设备不存在"); + } + res.locals.device = device; + res.locals.deviceId = device.id; + next(); +} /** * 从请求中提取UUID */ diff --git a/routes/device.js b/routes/device.js index efda58d..c6d09d6 100644 --- a/routes/device.js +++ b/routes/device.js @@ -1,6 +1,6 @@ import { Router } from "express"; const router = Router(); -import { uuidAuth } from "../middleware/uuidAuth.js"; +import { uuidAuth, extractDeviceInfo } from "../middleware/uuidAuth.js"; import { PrismaClient } from "@prisma/client"; import crypto from "crypto"; import errors from "../utils/errors.js"; @@ -131,21 +131,21 @@ router.get( } return res.json({ - id: device.id, - uuid: device.uuid, - name: device.name, - hasPassword: !!device.password, - passwordHint: device.passwordHint, - createdAt: device.createdAt, - account: device.account ? { - id: device.account.id, - name: device.account.name, - email: device.account.email, - avatarUrl: device.account.avatarUrl, - } : null, - isBoundToAccount: !!device.account, - namespace: device.namespace, - }); + id: device.id, + uuid: device.uuid, + name: device.name, + hasPassword: !!device.password, + passwordHint: device.passwordHint, + createdAt: device.createdAt, + account: device.account ? { + id: device.account.id, + name: device.account.name, + email: device.account.email, + avatarUrl: device.account.avatarUrl, + } : null, + isBoundToAccount: !!device.account, + namespace: device.namespace, + }); }) );/** * PUT /devices/:uuid/name @@ -153,7 +153,7 @@ router.get( */ router.put( "/:uuid/name", - uuidAuth, + extractDeviceInfo, errors.catchAsync(async (req, res, next) => { const { name } = req.body; const device = res.locals.device; @@ -180,202 +180,7 @@ router.put( }) ); -/** - * POST /devices/:uuid/password - * 初次设置设备密码 (无需认证,仅当设备未设置密码时) - */ -router.post( - "/:uuid/password", - errors.catchAsync(async (req, res, next) => { - const { uuid } = req.params; - const newPassword = req.query.newPassword || req.body.newPassword; - if (!newPassword) { - return next(errors.createError(400, "新密码是必需的")); - } - - // 查找设备 - const device = await prisma.device.findUnique({ - where: { uuid }, - }); - - if (!device) { - return next(errors.createError(404, "设备不存在")); - } - - // 只有在设备未设置密码时才允许无认证设置 - if (device.password) { - return next(errors.createError(403, "设备已设置密码,请使用修改密码接口")); - } - - const hashedPassword = await hashPassword(newPassword); - - await prisma.device.update({ - where: { id: device.id }, - data: { - password: hashedPassword, - }, - }); - - return res.json({ - success: true, - message: "密码设置成功", - }); - }) -); - -/** - * PUT /devices/:uuid/password - * 修改设备密码 (需要UUID认证和当前密码验证,账户拥有者除外) - */ -router.put( - "/:uuid/password", - uuidAuth, - errors.catchAsync(async (req, res, next) => { - const currentPassword = req.query.currentPassword; - const newPassword = req.query.newPassword || req.body.newPassword; - const passwordHint = req.query.passwordHint || req.body.passwordHint; - const device = res.locals.device; - const isAccountOwner = res.locals.isAccountOwner; - - if (!newPassword) { - return next(errors.createError(400, "新密码是必需的")); - } - - // 如果是账户拥有者,无需验证当前密码 - if (!isAccountOwner) { - if (!device.password) { - return next(errors.createError(400, "设备未设置密码,请使用设置密码接口")); - } - - if (!currentPassword) { - return next(errors.createError(400, "当前密码是必需的")); - } - - // 验证当前密码 - const isCurrentPasswordValid = await verifyDevicePassword(currentPassword, device.password); - if (!isCurrentPasswordValid) { - return next(errors.createError(401, "当前密码错误")); - } - } - - const hashedNewPassword = await hashPassword(newPassword); - - await prisma.device.update({ - where: { id: device.id }, - data: { - password: hashedNewPassword, - passwordHint: passwordHint !== undefined ? passwordHint : device.passwordHint, - }, - }); - - return res.json({ - success: true, - message: "密码修改成功", - }); - }) -); - -/** - * PUT /devices/:uuid/password-hint - * 设置密码提示 (需要UUID认证) - */ -router.put( - "/:uuid/password-hint", - uuidAuth, - errors.catchAsync(async (req, res, next) => { - const { passwordHint } = req.body; - const device = res.locals.device; - - await prisma.device.update({ - where: { id: device.id }, - data: { passwordHint: passwordHint || null }, - }); - - return res.json({ - success: true, - message: "密码提示设置成功", - passwordHint: passwordHint || null, - }); - }) -); - -/** - * GET /devices/:uuid/password-hint - * 获取设备密码提示 (无需认证) - */ -router.get( - "/:uuid/password-hint", - errors.catchAsync(async (req, res, next) => { - const { uuid } = req.params; - - const device = await prisma.device.findUnique({ - where: { uuid }, - select: { - passwordHint: true, - }, - }); - - if (!device) { - return next(errors.createError(404, "设备不存在")); - } - - return res.json({ - success: true, - passwordHint: device.passwordHint || null, - }); - }) -); - -/** - * DELETE /devices/:uuid/password - * 删除设备密码 (需要UUID认证和密码验证,账户拥有者除外) - */ -router.delete( - "/:uuid/password", - uuidAuth, - errors.catchAsync(async (req, res, next) => { - const password = req.query.password; - const device = res.locals.device; - const isAccountOwner = res.locals.isAccountOwner; - - if (!device.password) { - return next(errors.createError(400, "设备未设置密码")); - } - - // 如果不是账户拥有者,需要验证密码 - if (!isAccountOwner) { - if (!password) { - return next(errors.createError(400, "密码是必需的")); - } - - // 验证密码 - const isPasswordValid = await verifyDevicePassword(password, device.password); - if (!isPasswordValid) { - return next(errors.createError(401, "密码错误")); - } - } - - try { - await prisma.device.update({ - where: { id: device.id }, - data: { - password: null, - passwordHint: null, - }, - }); - - return res.json({ - success: true, - message: "密码删除成功", - }); - } catch (error) { - throw error; - } - }) -); - -export default router; /** * GET /devices/online @@ -408,3 +213,5 @@ router.get( res.json({ success: true, devices }); }) ); + +export default router;