log记录完善

This commit is contained in:
pipipigua 2024-10-31 21:19:37 +08:00
parent e45c367e15
commit 75e663f74e
5 changed files with 95 additions and 44 deletions

View File

@ -46,15 +46,17 @@ const userRole = `
const operationLogs = `
CREATE TABLE IF NOT EXISTS operation_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
username VARCHAR(255),
action VARCHAR(255) NOT NULL COMMENT '操作类型:新增、修改、删除等',
module VARCHAR(255) NOT NULL COMMENT '操作模块:用户管理、角色管理等',
description TEXT COMMENT '操作详细描述',
operator_id INT NOT NULL COMMENT '操作者ID',
operator_name VARCHAR(100) NOT NULL COMMENT '操作者名称',
target_id INT COMMENT '被操作对象ID',
target_type VARCHAR(50) COMMENT '被操作对象类型user, role等',
action VARCHAR(50) NOT NULL COMMENT '操作类型CREATE, UPDATE, DELETE等',
module VARCHAR(50) NOT NULL COMMENT '操作模块:用户管理、角色管理等',
content TEXT COMMENT '操作内容(可以存储详细的修改信息)',
ip VARCHAR(50) COMMENT '操作IP',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表'
FOREIGN KEY (operator_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';
`;
export { operationLogs, role, user, userRole };

View File

@ -7,10 +7,10 @@ import { OkPacket } from 'mysql2';
import { createMathExpr } from "svg-captcha";
import secret from "../config";
import Logger from "../loaders/logger";
import { getOperator } from "../utils/auth";
import { Message } from "../utils/enums";
import { connection } from "../utils/mysql";
import { logOperation, ModuleType, OperationType } from "../utils/operationLog";
const utils = require("@pureadmin/utils");
/** 保存验证码 */
@ -84,11 +84,11 @@ const login = async (req: Request, res: Response) => {
if (data.length === 0) {
// 记录登录失败日志
logOperation({
userId: 0,
username: username,
operatorId: 0, // 改为 operatorId
operatorName: username, // 改为 operatorName
action: OperationType.LOGIN,
module: ModuleType.AUTH,
description: `用户登录失败:用户不存在 (${username})`,
content: `用户登录失败:数据库错误`, // 改为 content
ip: req.ip || ''
});
@ -102,13 +102,13 @@ const login = async (req: Request, res: Response) => {
// 验证密码
const hashedPassword = createHash("md5").update(password).digest("hex");
if (hashedPassword !== user.password) {
// 记录登录失败日志
// 记录用户不存在日志
logOperation({
userId: 0,
username: username,
operatorId: 0,
operatorName: username,
action: OperationType.LOGIN,
module: ModuleType.AUTH,
description: `用户登录失败:密码错误 (${username})`,
content: `用户登录失败:用户不存在`,
ip: req.ip || ''
});
return res.json({
@ -128,11 +128,11 @@ const login = async (req: Request, res: Response) => {
);
// 记录登录成功日志
logOperation({
userId: user.id,
username: user.username,
operatorId: user.id,
operatorName: user.username,
action: OperationType.LOGIN,
module: ModuleType.AUTH,
description: `用户登录成功 (${username})`,
content: `用户登录成功 (${username})`,
ip: req.ip || ''
});
await res.json({
@ -412,6 +412,9 @@ const updateList = async (req: Request, res: Response) => {
const updateFields = [];
const updateValues = [];
// 检查并添加每个可更新字段
if (userData.username) {
updateFields.push("username = ?");
@ -471,16 +474,18 @@ const updateList = async (req: Request, res: Response) => {
data: { message: "更新用户失败" }
});
}
// 直接使用更新的用户信息记录日志
const operator = getOperator(req);
// 记录操作日志
logOperation({
userId: Number(id), // 转换为数字
username: userData.username || userData.name, // 使用更新的用户信息
action: OperationType.UPDATE,
module: ModuleType.USER,
description: `更新用户信息:ID=${id}, 字段:${updateFields.join(', ')}`,
operatorId: operator.id, // 使用 decoded 而不是 operator
operatorName: operator.name, // 使用 decoded 而不是 operator
targetId: Number(id), // 被更新用户的ID
targetType: 'user', // 被操作对象类型
action: OperationType.UPDATE, // 操作类型
module: ModuleType.USER, // 模块
content: `更新用户信息:${JSON.stringify(userData)}`, // 操作内容
ip: req.ip || ''
});
// 如果有角色信息,更新用户角色
if (userData.roles && userData.roles.length > 0) {
// 先删除原有角色
@ -590,6 +595,7 @@ const deleteList = async (req: Request, res: Response) => {
});
});
}
// 记录删除操作日志
// 提交事务
connection.commit(function(err) {
@ -602,11 +608,23 @@ const deleteList = async (req: Request, res: Response) => {
});
});
}
const operator = getOperator(req);
logOperation({
operatorId: operator.id,
operatorName: operator.name,
targetId: Number(id),
targetType: 'user',
action: OperationType.DELETE,
module: ModuleType.USER,
content: `删除用户:${id}`,
ip: req.ip || ''
});
res.json({
success: true,
data: { message: Message[8] }
});
});
});
});
});

View File

@ -4,6 +4,7 @@ import * as dayjs from "dayjs";
import * as multer from "multer";
import config from "./config";
import Logger from "./loaders/logger";
// import { operationLogs, role, user, userRole } from "./models/mysql";
import { importUsersFromLocalExcel } from "./router/excel";
import { getRoleList, getUserList } from "./router/http";
// import { queryTable } from "./utils/mysql";

26
src/utils/auth.ts Normal file
View File

@ -0,0 +1,26 @@
import { Request } from "express";
import * as jwt from "jsonwebtoken";
import secret from "../config";
export interface TokenPayload {
id: number;
username: string;
name: string;
}
// 获取操作者信息
export const getOperator = (req: Request): TokenPayload => {
const authHeader = req.get("Authorization");
if (!authHeader) {
throw new Error("未提供 token");
}
const token = authHeader.replace("Bearer ", "");
const decoded = jwt.verify(token, secret.jwtSecret) as TokenPayload;
return {
id: decoded.id,
username: decoded.username,
name: decoded.name
};
};

View File

@ -1,5 +1,5 @@
import { connection } from "./mysql";
import Logger from "../loaders/logger";
import { connection } from "./mysql";
// 定义操作类型
export enum OperationType {
@ -21,25 +21,29 @@ export enum ModuleType {
// 记录操作日志
export const logOperation = (params: {
userId: number;
username: string;
action: OperationType;
module: ModuleType;
description: string;
ip: string;
operatorId: number; // 操作者ID
operatorName: string; // 操作者名称
targetId?: number; // 被操作对象ID
targetType?: string; // 被操作对象类型
action: OperationType; // 操作类型(使用枚举)
module: ModuleType; // 模块(使用枚举)
content: string; // 操作内容
ip: string; // IP地址
}) => {
const sql = `
INSERT INTO operation_logs
(user_id, username, action, module, description, ip)
VALUES (?, ?, ?, ?, ?, ?)
(operator_id, operator_name, target_id, target_type, action, module, content, ip)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`;
const values = [
params.userId,
params.username,
params.operatorId,
params.operatorName,
params.targetId || null,
params.targetType || null,
params.action,
params.module,
params.description,
params.content,
params.ip
];