import { Request, Response } from 'express'; import bcrypt from 'bcryptjs'; import jwt from 'jsonwebtoken'; import { prisma } from '../config/database'; import { logger } from '../utils/logger'; import { createAuditLog } from '../utils/audit'; export const adminController = { // 管理员登录 async login(req: Request, res: Response): Promise { try { const { username, password } = req.body; // 验证管理员凭据 const admin = await prisma.user.findFirst({ where: { username, isAdmin: true } }); if (!admin) { // 记录管理员登录失败审计日志 await createAuditLog({ userId: null, action: 'ADMIN_LOGIN_FAILED', resource: 'ADMIN', details: JSON.stringify({ username, reason: '管理员不存在' }), ipAddress: req.ip ?? null, userAgent: req.get('User-Agent') ?? null }); res.status(401).json({ success: false, message: '管理员凭据无效' }); return; } // 验证密码 const isValidPassword = await bcrypt.compare(password, admin.password); if (!isValidPassword) { // 记录管理员登录失败审计日志 await createAuditLog({ userId: admin.id, action: 'ADMIN_LOGIN_FAILED', resource: 'ADMIN', details: JSON.stringify({ username, reason: '密码错误' }), ipAddress: req.ip ?? null, userAgent: req.get('User-Agent') ?? null }); res.status(401).json({ success: false, message: '管理员凭据无效' }); return; } // 生成JWT token const token = jwt.sign( { userId: admin.id, username: admin.username, role: admin.isAdmin ? 'admin' : 'user' }, "pandora", { expiresIn: '24h' } ); // 创建审计日志 await createAuditLog({ userId: admin.id, action: 'ADMIN_LOGIN', resource: 'ADMIN', details: { username: admin.username }, ipAddress: req.ip ?? null, userAgent: req.get('User-Agent') ?? null }); res.json({ success: true, message: '管理员登录成功', token, admin: { id: admin.id, username: admin.username, role: admin.isAdmin ? 'admin' : 'user' } }); } catch (error) { logger.error('Admin login error:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }, // 获取统计数据 async getStats(req: Request, res: Response): Promise { try { // 获取用户总数 const totalUsers = await prisma.user.count({ where: { isAdmin: false } }); // 获取账号总数 const totalAccounts = await prisma.websiteAccount.count(); // 获取今日访问数(基于会话) const today = new Date(); today.setHours(0, 0, 0, 0); const todayVisits = await prisma.session.count({ where: { createdAt: { gte: today } } }); // 获取系统告警数(基于审计日志中的错误) const alerts = await prisma.auditLog.count({ where: { action: { contains: 'ERROR' }, createdAt: { gte: new Date(Date.now() - 24 * 60 * 60 * 1000) // 最近24小时 } } }); console.log('统计数据:', { totalUsers, totalAccounts, todayVisits, alerts }); res.json({ success: true, data: { totalUsers, totalAccounts, todayVisits, alerts } }); } catch (error) { logger.error('Get stats error:', error); res.status(500).json({ success: false, message: '获取统计数据失败' }); } }, // 获取最近活动 async getRecentActivities(req: Request, res: Response): Promise { try { const activities = await prisma.auditLog.findMany({ take: 10, orderBy: { createdAt: 'desc' }, include: { user: { select: { id: true, username: true } } } }); const formattedActivities = activities.map((activity: any) => { let description = ''; if (activity.action === 'USER_LOGIN_FAILED' || activity.action === 'ADMIN_LOGIN_FAILED') { // 解析失败原因 let reason = '登录失败'; let username = '未知用户'; if (activity.details) { try { const details = JSON.parse(activity.details); reason = details.reason || '登录失败'; username = details.username || '未知用户'; } catch (e) { console.error('解析活动详情失败:', e); } } description = `${username} ${reason}`; } else if (activity.user) { description = `${activity.user.username} ${activity.action}`; } else { description = `系统 ${activity.action}`; } return { id: activity.id, description, time: activity.createdAt, details: activity.details, ipAddress: activity.ipAddress, userAgent: activity.userAgent, action: activity.action }; }); console.log('最近活动:', formattedActivities); res.json({ success: true, data: { activities: formattedActivities } }); } catch (error) { logger.error('Get recent activities error:', error); res.status(500).json({ success: false, message: '获取最近活动失败' }); } } };