Files
cloud-mail/mail-worker/src/security/security.js
2025-06-20 00:52:17 +08:00

156 lines
3.6 KiB
JavaScript

import BizError from '../error/biz-error';
import constant from '../const/constant';
import jwtUtils from '../utils/jwt-utils';
import KvConst from '../const/kv-const';
import dayjs from 'dayjs';
import userService from '../service/user-service';
import permService from '../service/perm-service';
import app from '../hono/hono';
const exclude = [
'/login',
'/register',
'/setting/query',
'/file',
'/webhooks',
'/init'
];
const requirePerms = [
'/email/send',
'/email/delete',
'/account/list',
'/account/delete',
'/account/add',
'/my/delete',
'/role/add',
'/role/list',
'/role/delete',
'/role/tree',
'/role/set',
'/role/setDefault',
'/sys-email/list',
'/sys-email/delete',
'/setting/physicsDeleteAll',
'/setting/setBackground',
'/setting/set',
'/user/delete',
'/user/setPwd',
'/user/setStatus',
'/user/setType',
'/user/list',
'/user/resetSendCount',
'/user/add'
];
const premKey = {
'email:delete': ['/email/delete'],
'email:send': ['/email/send'],
'account:add': ['/account/add'],
'account:query': ['/account/list'],
'account:delete': ['/account/delete'],
'my:delete': ['/my/delete'],
'role:add': ['/role/add'],
'role:set': ['/role/set','/role/setDefault'],
'role:query': ['/role/list', '/role/tree'],
'role:delete': ['/role/delete'],
'user:query': ['/user/list'],
'user:add': ['/user/add'],
'user:reset-send': ['/user/resetSendCount'],
'user:set-pwd': ['/user/setPwd'],
'user:set-status': ['/user/setStatus'],
'user:set-type': ['/user/setType'],
'user:delete': ['/user/delete'],
'sys-email:query': ['/sys-email/list'],
'sys-email:delete': ['/sys-email/delete'],
'setting:query': [],
'setting:set': ['/setting/set', '/setting/setBackground'],
'setting:clean': ['/setting/physicsDeleteAll'],
'analysis:query': ['/analysis/echarts']
};
app.use('*', async (c, next) => {
const path = c.req.path;
if (path.startsWith('/test')) {
return await next();
}
const index = exclude.findIndex(item => {
return path.startsWith(item);
});
if (index > -1) {
return await next();
}
const jwt = c.req.header(constant.TOKEN_HEADER);
const result = await jwtUtils.verifyToken(c, jwt);
if (!result) {
console.error(401,1)
throw new BizError('身份认证失效,请重新登录', 401);
}
const { userId, token } = result;
const authInfo = await c.env.kv.get(KvConst.AUTH_INFO + userId, { type: 'json' });
if (!authInfo) {
console.error(401,2)
throw new BizError('身份认证失效,请重新登录', 401);
}
if (!authInfo.tokens.includes(token)) {
console.error(401,3)
throw new BizError('身份认证失效,请重新登录', 401);
}
const permIndex = requirePerms.findIndex(item => {
return path.startsWith(item);
});
if (permIndex > -1) {
const permKeys = await permService.userPermKeys(c, authInfo.user.userId);
const userPaths = permKeyToPaths(permKeys);
const userPermIndex = userPaths.findIndex(item => {
return path.startsWith(item);
});
if (userPermIndex === -1 && authInfo.user.email !== c.env.admin) {
throw new BizError('权限不足', 403);
}
}
const refreshTime = dayjs(authInfo.refreshTime).startOf('day');
const nowTime = dayjs().startOf('day')
if (!nowTime.isSame(refreshTime)) {
authInfo.refreshTime = dayjs().toISOString();
await userService.updateUserInfo(c, authInfo.user.userId);
await c.env.kv.put(KvConst.AUTH_INFO + userId, JSON.stringify(authInfo), { expirationTtl: constant.TOKEN_EXPIRE });
}
c.set('user',authInfo.user)
return await next();
});
function permKeyToPaths(permKeys) {
const paths = [];
for (const key of permKeys) {
const routeList = premKey[key];
if (routeList && Array.isArray(routeList)) {
paths.push(...routeList);
}
}
return paths;
}