1
0
mirror of https://github.com/ZeroCatDev/ClassworksKV.git synced 2025-07-02 12:59:22 +00:00

120 lines
3.4 KiB
JavaScript

import { siteKey } from "../config.js";
import AppError from "../utils/errors.js";
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export const ACCESS_TYPES = {
NO_PASSWORD_WRITABLE: 'NO_PASSWORD_WRITABLE',
NO_PASSWORD_READABLE: 'NO_PASSWORD_READABLE',
NO_PASSWORD_UNREADABLE: 'NO_PASSWORD_UNREADABLE'
};
export const checkSiteKey = (req, res, next) => {
const providedKey = req.headers['x-site-key'];
if (!siteKey) {
return next();
}
if (!providedKey || providedKey !== siteKey) {
const error = AppError.createError(
AppError.HTTP_STATUS.UNAUTHORIZED,
"此服务器已开启站点密钥验证,请在请求头中添加 x-site-key 以继续访问"
);
return res.status(error.statusCode).json(error);
}
next();
};
async function getOrCreateDevice(uuid, className) {
let device = await prisma.device.findUnique({
where: { uuid }
});
if (!device) {
device = await prisma.device.create({
data: {
uuid,
name: className || null,
accessType: ACCESS_TYPES.NO_PASSWORD_WRITABLE
}
});
}
return device;
}
async function validatePassword(device, password) {
if (!device.password) return true;
return device.password === password;
}
export const authMiddleware = async (req, res, next) => {
const { namespace } = req.params;
const { password } = req.body;
try {
const device = await getOrCreateDevice(namespace, req.body.className);
req.device = device;
if (device.password && !await validatePassword(device, password)) {
return res.status(401).json({ error: 'Invalid password' });
}
next();
} catch (error) {
console.error('Auth middleware error:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
export const readAuthMiddleware = async (req, res, next) => {
const { namespace } = req.params;
try {
const device = await getOrCreateDevice(namespace);
req.device = device;
if (device.accessType === ACCESS_TYPES.NO_PASSWORD_UNREADABLE) {
return res.status(403).json({ error: 'Device is not readable' });
}
if (device.accessType === ACCESS_TYPES.NO_PASSWORD_READABLE) {
return next();
}
if (device.password) {
const { password } = req.body;
if (!await validatePassword(device, password)) {
return res.status(401).json({ error: 'Invalid password' });
}
}
next();
} catch (error) {
console.error('Read auth middleware error:', error);
res.status(500).json({ error: 'Internal server error' });
}
};
export const writeAuthMiddleware = async (req, res, next) => {
const { namespace } = req.params;
try {
const device = await getOrCreateDevice(namespace);
req.device = device;
if (device.password) {
const { password } = req.body;
if (!await validatePassword(device, password)) {
return res.status(401).json({ error: 'Invalid password' });
}
}
next();
} catch (error) {
console.error('Write auth middleware error:', error);
res.status(500).json({ error: 'Internal server error' });
}
};