diff --git a/back/api/log.ts b/back/api/log.ts index 020d572e..13f94dec 100644 --- a/back/api/log.ts +++ b/back/api/log.ts @@ -8,8 +8,12 @@ import { readDirs, removeAnsi, rmPath, + IFile, } from '../config/util'; import LogService from '../services/log'; +import CronService from '../services/cron'; +import { UserRole } from '../data/user'; +import { Crontab } from '../data/cron'; const route = Router(); const blacklist = ['.tmp']; @@ -20,6 +24,39 @@ export default (app: Router) => { const logger: Logger = Container.get('logger'); try { const result = await readDirs(config.logPath, config.logPath, blacklist); + + // Filter logs based on user permissions + if (req.user?.role !== UserRole.admin && req.user?.userId) { + const cronService = Container.get(CronService); + const { data: userCrons } = await cronService.crontabs({ + searchValue: '', + page: '0', + size: '0', + sorter: '', + filters: '', + queryString: '', + userId: req.user.userId, + }); + + // Build a set of log paths that the user has access to + const allowedLogPaths = new Set( + userCrons + .filter((cron: Crontab) => cron.log_name && cron.log_name !== '/dev/null') + .map((cron: Crontab) => cron.log_name) + ); + + // Filter the result to only include logs the user owns + const filteredResult = (result as IFile[]).filter((item: IFile) => + item.type === 'directory' && (allowedLogPaths.has(item.title) || allowedLogPaths.has(`${item.title}/`)) + ); + + res.send({ + code: 200, + data: filteredResult, + }); + return; + } + res.send({ code: 200, data: result, @@ -45,6 +82,35 @@ export default (app: Router) => { message: '暂无权限', }); } + + // Check if user has permission to view this log + if (req.user?.role !== UserRole.admin && req.user?.userId) { + const cronService = Container.get(CronService); + const { data: userCrons } = await cronService.crontabs({ + searchValue: '', + page: '0', + size: '0', + sorter: '', + filters: '', + queryString: '', + userId: req.user.userId, + }); + + const logPath = (req.query.path as string) || ''; + const hasAccess = userCrons.some((cron: Crontab) => + cron.log_name && + cron.log_name !== '/dev/null' && + (logPath.startsWith(cron.log_name) || cron.log_name.startsWith(logPath)) + ); + + if (!hasAccess) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + } + const content = await getFileContentByName(finalPath); res.send({ code: 200, data: removeAnsi(content) }); } catch (e) { @@ -68,6 +134,35 @@ export default (app: Router) => { message: '暂无权限', }); } + + // Check if user has permission to view this log + if (req.user?.role !== UserRole.admin && req.user?.userId) { + const cronService = Container.get(CronService); + const { data: userCrons } = await cronService.crontabs({ + searchValue: '', + page: '0', + size: '0', + sorter: '', + filters: '', + queryString: '', + userId: req.user.userId, + }); + + const logPath = (req.query.path as string) || ''; + const hasAccess = userCrons.some((cron: Crontab) => + cron.log_name && + cron.log_name !== '/dev/null' && + (logPath.startsWith(cron.log_name) || cron.log_name.startsWith(logPath)) + ); + + if (!hasAccess) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + } + const content = await getFileContentByName(finalPath); res.send({ code: 200, data: content }); } catch (e) { @@ -99,6 +194,34 @@ export default (app: Router) => { message: '暂无权限', }); } + + // Check if user has permission to delete this log + if (req.user?.role !== UserRole.admin && req.user?.userId) { + const cronService = Container.get(CronService); + const { data: userCrons } = await cronService.crontabs({ + searchValue: '', + page: '0', + size: '0', + sorter: '', + filters: '', + queryString: '', + userId: req.user.userId, + }); + + const hasAccess = userCrons.some((cron: Crontab) => + cron.log_name && + cron.log_name !== '/dev/null' && + (path.startsWith(cron.log_name) || cron.log_name.startsWith(path)) + ); + + if (!hasAccess) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + } + await rmPath(finalPath); res.send({ code: 200 }); } catch (e) { @@ -129,6 +252,34 @@ export default (app: Router) => { message: '暂无权限', }); } + + // Check if user has permission to download this log + if (req.user?.role !== UserRole.admin && req.user?.userId) { + const cronService = Container.get(CronService); + const { data: userCrons } = await cronService.crontabs({ + searchValue: '', + page: '0', + size: '0', + sorter: '', + filters: '', + queryString: '', + userId: req.user.userId, + }); + + const hasAccess = userCrons.some((cron: Crontab) => + cron.log_name && + cron.log_name !== '/dev/null' && + (path.startsWith(cron.log_name) || cron.log_name.startsWith(path)) + ); + + if (!hasAccess) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + } + return res.download(filePath, filename, (err) => { if (err) { return next(err); diff --git a/back/api/system.ts b/back/api/system.ts index 8074e6ff..dbde7abd 100644 --- a/back/api/system.ts +++ b/back/api/system.ts @@ -14,6 +14,7 @@ import { } from '../config/util'; import dayjs from 'dayjs'; import multer from 'multer'; +import { UserRole } from '../data/user'; const route = Router(); const storage = multer.diskStorage({ @@ -357,6 +358,14 @@ export default (app: Router) => { }), async (req: Request, res: Response, next: NextFunction) => { try { + // Only admin can view system logs + if (req.user?.role !== UserRole.admin) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + const systemService = Container.get(SystemService); await systemService.getSystemLog( res, @@ -375,6 +384,14 @@ export default (app: Router) => { '/log', async (req: Request, res: Response, next: NextFunction) => { try { + // Only admin can delete system logs + if (req.user?.role !== UserRole.admin) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + const systemService = Container.get(SystemService); await systemService.deleteSystemLog(); res.send({ code: 200 }); diff --git a/back/api/user.ts b/back/api/user.ts index b50c5492..d57824e6 100644 --- a/back/api/user.ts +++ b/back/api/user.ts @@ -9,6 +9,7 @@ import { v4 as uuidV4 } from 'uuid'; import rateLimit from 'express-rate-limit'; import config from '../config'; import { isDemoEnv } from '../config/util'; +import { UserRole } from '../data/user'; const route = Router(); const storage = multer.diskStorage({ @@ -179,6 +180,14 @@ export default (app: Router) => { async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { + // Only admin can view login logs + if (req.user?.role !== UserRole.admin) { + return res.send({ + code: 403, + message: '暂无权限', + }); + } + const userService = Container.get(UserService); const data = await userService.getLoginLog(); res.send({ code: 200, data });