mirror of
https://github.com/ZeroCatDev/ClassworksKV.git
synced 2025-07-01 20:09:23 +00:00
238 lines
5.5 KiB
JavaScript
238 lines
5.5 KiB
JavaScript
import { siteKey } from "../utils/config.js";
|
|
import { PrismaClient } from "@prisma/client";
|
|
import { DecodeAndVerifyPassword, verifySiteKey } from "../utils/crypto.js";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
export const ACCESS_TYPES = {
|
|
PUBLIC: "PUBLIC",
|
|
PROTECTED: "PROTECTED",
|
|
PRIVATE: "PRIVATE",
|
|
};
|
|
|
|
export const checkSiteKey = (req, res, next) => {
|
|
if (!siteKey) {
|
|
return next();
|
|
}
|
|
|
|
const providedKey =
|
|
req.headers["x-site-key"] || req.query.sitekey || req.body?.sitekey;
|
|
|
|
if (!verifySiteKey(providedKey, siteKey)) {
|
|
return res.status(401).json({
|
|
statusCode: 401,
|
|
message: "此服务器已开启站点密钥验证,请提供有效的站点密钥",
|
|
});
|
|
}
|
|
|
|
next();
|
|
};
|
|
|
|
async function getOrCreateDevice(uuid, className) {
|
|
try {
|
|
let device = await prisma.device.findUnique({
|
|
where: { uuid },
|
|
});
|
|
|
|
if (!device) {
|
|
try {
|
|
device = await prisma.device.create({
|
|
data: {
|
|
uuid,
|
|
name: className || null,
|
|
accessType: ACCESS_TYPES.PUBLIC,
|
|
},
|
|
});
|
|
} catch (error) {
|
|
if (error.code === "P2002") {
|
|
device = await prisma.device.findUnique({
|
|
where: { uuid },
|
|
});
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (
|
|
device &&
|
|
!device.password &&
|
|
device.accessType !== ACCESS_TYPES.PUBLIC
|
|
) {
|
|
device = await prisma.device.update({
|
|
where: { uuid },
|
|
data: { accessType: ACCESS_TYPES.PUBLIC },
|
|
});
|
|
}
|
|
|
|
return device;
|
|
} catch (error) {
|
|
console.error("Error in getOrCreateDevice:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
export const deviceInfoMiddleware = async (req, res, next) => {
|
|
const { namespace } = req.params;
|
|
|
|
try {
|
|
const device = await getOrCreateDevice(namespace, req.body?.className);
|
|
res.locals.device = device;
|
|
|
|
next();
|
|
} catch (error) {
|
|
console.error("Auth middleware error:", error);
|
|
res.status(500).json({
|
|
statusCode: 500,
|
|
message: "服务器内部错误",
|
|
});
|
|
}
|
|
};
|
|
export const authMiddleware = async (req, res, next) => {
|
|
const { namespace } = req.params;
|
|
const password =
|
|
req.headers["x-namespace-password"] ||
|
|
req.query.password ||
|
|
req.body?.password;
|
|
|
|
try {
|
|
const device = await getOrCreateDevice(namespace, req.body?.className);
|
|
res.locals.device = device;
|
|
|
|
if (device.password && password !== device.password) {
|
|
return res.status(401).json({
|
|
statusCode: 401,
|
|
message: "设备密码验证失败",
|
|
});
|
|
}
|
|
|
|
next();
|
|
} catch (error) {
|
|
console.error("Auth middleware error:", error);
|
|
res.status(500).json({
|
|
statusCode: 500,
|
|
message: "服务器内部错误",
|
|
});
|
|
}
|
|
};
|
|
|
|
export const readAuthMiddleware = async (req, res, next) => {
|
|
const { namespace } = req.params;
|
|
const password =
|
|
req.headers["x-namespace-password"] ||
|
|
req.query.password ||
|
|
req.body?.password;
|
|
|
|
try {
|
|
const device = await getOrCreateDevice(namespace);
|
|
res.locals.device = device;
|
|
|
|
if (
|
|
[ACCESS_TYPES.PUBLIC, ACCESS_TYPES.PROTECTED].includes(device.accessType)
|
|
) {
|
|
return next();
|
|
}
|
|
|
|
if (
|
|
!device.password ||
|
|
!(await DecodeAndVerifyPassword(password, device.password))
|
|
) {
|
|
return res.status(401).json({
|
|
statusCode: 401,
|
|
message: "设备密码验证失败",
|
|
});
|
|
}
|
|
|
|
next();
|
|
} catch (error) {
|
|
console.error("Read auth middleware error:", error);
|
|
res.status(500).json({
|
|
statusCode: 500,
|
|
message: "服务器内部错误",
|
|
});
|
|
}
|
|
};
|
|
|
|
export const writeAuthMiddleware = async (req, res, next) => {
|
|
const { namespace } = req.params;
|
|
const password =
|
|
req.headers["x-namespace-password"] ||
|
|
req.query.password ||
|
|
req.body?.password;
|
|
|
|
try {
|
|
const device = await getOrCreateDevice(namespace);
|
|
res.locals.device = device;
|
|
|
|
if (device.accessType === ACCESS_TYPES.PUBLIC) {
|
|
return next();
|
|
}
|
|
|
|
if (
|
|
!device.password ||
|
|
!(await DecodeAndVerifyPassword(password, device.password))
|
|
) {
|
|
return res.status(401).json({
|
|
statusCode: 401,
|
|
message: "设备密码验证失败",
|
|
});
|
|
}
|
|
|
|
next();
|
|
} catch (error) {
|
|
console.error("Write auth middleware error:", error);
|
|
res.status(500).json({
|
|
statusCode: 500,
|
|
message: "服务器内部错误",
|
|
});
|
|
}
|
|
};
|
|
|
|
export const removePasswordMiddleware = async (req, res, next) => {
|
|
const { namespace } = req.params;
|
|
const password =
|
|
req.headers["x-namespace-password"] ||
|
|
req.query.password ||
|
|
req.body?.password;
|
|
const providedKey =
|
|
req.headers["x-site-key"] || req.query.sitekey || req.body?.sitekey;
|
|
|
|
try {
|
|
const device = await getOrCreateDevice(namespace);
|
|
res.locals.device = device;
|
|
|
|
if (!verifySiteKey(providedKey, siteKey)) {
|
|
return res.status(401).json({
|
|
statusCode: 401,
|
|
message: "此服务器已开启站点密钥验证,请提供有效的站点密钥",
|
|
});
|
|
}
|
|
|
|
if (
|
|
device.password &&
|
|
!(await DecodeAndVerifyPassword(password, device.password))
|
|
) {
|
|
return res.status(401).json({
|
|
statusCode: 401,
|
|
message: "设备密码验证失败",
|
|
});
|
|
}
|
|
|
|
await prisma.device.update({
|
|
where: { uuid: device.uuid },
|
|
data: {
|
|
password: null,
|
|
accessType: ACCESS_TYPES.PUBLIC,
|
|
},
|
|
});
|
|
|
|
next();
|
|
} catch (error) {
|
|
console.error("Remove password middleware error:", error);
|
|
res.status(500).json({
|
|
statusCode: 500,
|
|
message: "服务器内部错误",
|
|
});
|
|
}
|
|
};
|