mirror of
https://github.com/ZeroCatDev/ClassworksKV.git
synced 2025-12-07 21:13:10 +00:00
feat: 添加设备信息提取功能,增强 UUID 认证中间件的错误处理
This commit is contained in:
parent
4ff64ad514
commit
4ae023afb0
@ -93,7 +93,22 @@ export const uuidAuth = async (req, res, next) => {
|
|||||||
next(error);
|
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
|
* 从请求中提取UUID
|
||||||
*/
|
*/
|
||||||
|
|||||||
231
routes/device.js
231
routes/device.js
@ -1,6 +1,6 @@
|
|||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
const router = Router();
|
const router = Router();
|
||||||
import { uuidAuth } from "../middleware/uuidAuth.js";
|
import { uuidAuth, extractDeviceInfo } from "../middleware/uuidAuth.js";
|
||||||
import { PrismaClient } from "@prisma/client";
|
import { PrismaClient } from "@prisma/client";
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
import errors from "../utils/errors.js";
|
import errors from "../utils/errors.js";
|
||||||
@ -131,21 +131,21 @@ router.get(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
id: device.id,
|
id: device.id,
|
||||||
uuid: device.uuid,
|
uuid: device.uuid,
|
||||||
name: device.name,
|
name: device.name,
|
||||||
hasPassword: !!device.password,
|
hasPassword: !!device.password,
|
||||||
passwordHint: device.passwordHint,
|
passwordHint: device.passwordHint,
|
||||||
createdAt: device.createdAt,
|
createdAt: device.createdAt,
|
||||||
account: device.account ? {
|
account: device.account ? {
|
||||||
id: device.account.id,
|
id: device.account.id,
|
||||||
name: device.account.name,
|
name: device.account.name,
|
||||||
email: device.account.email,
|
email: device.account.email,
|
||||||
avatarUrl: device.account.avatarUrl,
|
avatarUrl: device.account.avatarUrl,
|
||||||
} : null,
|
} : null,
|
||||||
isBoundToAccount: !!device.account,
|
isBoundToAccount: !!device.account,
|
||||||
namespace: device.namespace,
|
namespace: device.namespace,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);/**
|
);/**
|
||||||
* PUT /devices/:uuid/name
|
* PUT /devices/:uuid/name
|
||||||
@ -153,7 +153,7 @@ router.get(
|
|||||||
*/
|
*/
|
||||||
router.put(
|
router.put(
|
||||||
"/:uuid/name",
|
"/:uuid/name",
|
||||||
uuidAuth,
|
extractDeviceInfo,
|
||||||
errors.catchAsync(async (req, res, next) => {
|
errors.catchAsync(async (req, res, next) => {
|
||||||
const { name } = req.body;
|
const { name } = req.body;
|
||||||
const device = res.locals.device;
|
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
|
* GET /devices/online
|
||||||
@ -408,3 +213,5 @@ router.get(
|
|||||||
res.json({ success: true, devices });
|
res.json({ success: true, devices });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export default router;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user