mirror of
https://github.com/pure-admin/pure-admin-backend.git
synced 2025-04-24 23:37:17 +08:00
log记录完善
This commit is contained in:
parent
e45c367e15
commit
75e663f74e
@ -44,17 +44,19 @@ const userRole = `
|
|||||||
|
|
||||||
/** 创建操作日志表 */
|
/** 创建操作日志表 */
|
||||||
const operationLogs = `
|
const operationLogs = `
|
||||||
CREATE TABLE IF NOT EXISTS operation_logs (
|
CREATE TABLE IF NOT EXISTS operation_logs (
|
||||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
user_id INT NOT NULL,
|
operator_id INT NOT NULL COMMENT '操作者ID',
|
||||||
username VARCHAR(255),
|
operator_name VARCHAR(100) NOT NULL COMMENT '操作者名称',
|
||||||
action VARCHAR(255) NOT NULL COMMENT '操作类型:新增、修改、删除等',
|
target_id INT COMMENT '被操作对象ID',
|
||||||
module VARCHAR(255) NOT NULL COMMENT '操作模块:用户管理、角色管理等',
|
target_type VARCHAR(50) COMMENT '被操作对象类型(如:user, role等)',
|
||||||
description TEXT COMMENT '操作详细描述',
|
action VARCHAR(50) NOT NULL COMMENT '操作类型:CREATE, UPDATE, DELETE等',
|
||||||
|
module VARCHAR(50) NOT NULL COMMENT '操作模块:用户管理、角色管理等',
|
||||||
|
content TEXT COMMENT '操作内容(可以存储详细的修改信息)',
|
||||||
ip VARCHAR(50) COMMENT '操作IP',
|
ip VARCHAR(50) COMMENT '操作IP',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
FOREIGN KEY (operator_id) REFERENCES users(id)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表'
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export { operationLogs, role, user, userRole };
|
export { operationLogs, role, user, userRole };
|
||||||
|
@ -7,10 +7,10 @@ import { OkPacket } from 'mysql2';
|
|||||||
import { createMathExpr } from "svg-captcha";
|
import { createMathExpr } from "svg-captcha";
|
||||||
import secret from "../config";
|
import secret from "../config";
|
||||||
import Logger from "../loaders/logger";
|
import Logger from "../loaders/logger";
|
||||||
|
import { getOperator } from "../utils/auth";
|
||||||
import { Message } from "../utils/enums";
|
import { Message } from "../utils/enums";
|
||||||
import { connection } from "../utils/mysql";
|
import { connection } from "../utils/mysql";
|
||||||
import { logOperation, ModuleType, OperationType } from "../utils/operationLog";
|
import { logOperation, ModuleType, OperationType } from "../utils/operationLog";
|
||||||
|
|
||||||
const utils = require("@pureadmin/utils");
|
const utils = require("@pureadmin/utils");
|
||||||
|
|
||||||
/** 保存验证码 */
|
/** 保存验证码 */
|
||||||
@ -84,11 +84,11 @@ const login = async (req: Request, res: Response) => {
|
|||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
// 记录登录失败日志
|
// 记录登录失败日志
|
||||||
logOperation({
|
logOperation({
|
||||||
userId: 0,
|
operatorId: 0, // 改为 operatorId
|
||||||
username: username,
|
operatorName: username, // 改为 operatorName
|
||||||
action: OperationType.LOGIN,
|
action: OperationType.LOGIN,
|
||||||
module: ModuleType.AUTH,
|
module: ModuleType.AUTH,
|
||||||
description: `用户登录失败:用户不存在 (${username})`,
|
content: `用户登录失败:数据库错误`, // 改为 content
|
||||||
ip: req.ip || ''
|
ip: req.ip || ''
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -102,15 +102,15 @@ const login = async (req: Request, res: Response) => {
|
|||||||
// 验证密码
|
// 验证密码
|
||||||
const hashedPassword = createHash("md5").update(password).digest("hex");
|
const hashedPassword = createHash("md5").update(password).digest("hex");
|
||||||
if (hashedPassword !== user.password) {
|
if (hashedPassword !== user.password) {
|
||||||
// 记录登录失败日志
|
// 记录用户不存在日志
|
||||||
logOperation({
|
logOperation({
|
||||||
userId: 0,
|
operatorId: 0,
|
||||||
username: username,
|
operatorName: username,
|
||||||
action: OperationType.LOGIN,
|
action: OperationType.LOGIN,
|
||||||
module: ModuleType.AUTH,
|
module: ModuleType.AUTH,
|
||||||
description: `用户登录失败:密码错误 (${username})`,
|
content: `用户登录失败:用户不存在`,
|
||||||
ip: req.ip || ''
|
ip: req.ip || ''
|
||||||
});
|
});
|
||||||
return res.json({
|
return res.json({
|
||||||
success: false,
|
success: false,
|
||||||
data: { message: "密码错误" }
|
data: { message: "密码错误" }
|
||||||
@ -128,11 +128,11 @@ const login = async (req: Request, res: Response) => {
|
|||||||
);
|
);
|
||||||
// 记录登录成功日志
|
// 记录登录成功日志
|
||||||
logOperation({
|
logOperation({
|
||||||
userId: user.id,
|
operatorId: user.id,
|
||||||
username: user.username,
|
operatorName: user.username,
|
||||||
action: OperationType.LOGIN,
|
action: OperationType.LOGIN,
|
||||||
module: ModuleType.AUTH,
|
module: ModuleType.AUTH,
|
||||||
description: `用户登录成功 (${username})`,
|
content: `用户登录成功 (${username})`,
|
||||||
ip: req.ip || ''
|
ip: req.ip || ''
|
||||||
});
|
});
|
||||||
await res.json({
|
await res.json({
|
||||||
@ -411,7 +411,10 @@ const updateList = async (req: Request, res: Response) => {
|
|||||||
// 构建更新字段
|
// 构建更新字段
|
||||||
const updateFields = [];
|
const updateFields = [];
|
||||||
const updateValues = [];
|
const updateValues = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 检查并添加每个可更新字段
|
// 检查并添加每个可更新字段
|
||||||
if (userData.username) {
|
if (userData.username) {
|
||||||
updateFields.push("username = ?");
|
updateFields.push("username = ?");
|
||||||
@ -471,16 +474,18 @@ const updateList = async (req: Request, res: Response) => {
|
|||||||
data: { message: "更新用户失败" }
|
data: { message: "更新用户失败" }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 直接使用更新的用户信息记录日志
|
const operator = getOperator(req);
|
||||||
|
// 记录操作日志
|
||||||
logOperation({
|
logOperation({
|
||||||
userId: Number(id), // 转换为数字
|
operatorId: operator.id, // 使用 decoded 而不是 operator
|
||||||
username: userData.username || userData.name, // 使用更新的用户信息
|
operatorName: operator.name, // 使用 decoded 而不是 operator
|
||||||
action: OperationType.UPDATE,
|
targetId: Number(id), // 被更新用户的ID
|
||||||
module: ModuleType.USER,
|
targetType: 'user', // 被操作对象类型
|
||||||
description: `更新用户信息:ID=${id}, 字段:${updateFields.join(', ')}`,
|
action: OperationType.UPDATE, // 操作类型
|
||||||
|
module: ModuleType.USER, // 模块
|
||||||
|
content: `更新用户信息:${JSON.stringify(userData)}`, // 操作内容
|
||||||
ip: req.ip || ''
|
ip: req.ip || ''
|
||||||
});
|
});
|
||||||
|
|
||||||
// 如果有角色信息,更新用户角色
|
// 如果有角色信息,更新用户角色
|
||||||
if (userData.roles && userData.roles.length > 0) {
|
if (userData.roles && userData.roles.length > 0) {
|
||||||
// 先删除原有角色
|
// 先删除原有角色
|
||||||
@ -590,6 +595,7 @@ const deleteList = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 记录删除操作日志
|
||||||
|
|
||||||
// 提交事务
|
// 提交事务
|
||||||
connection.commit(function(err) {
|
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({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
data: { message: Message[8] }
|
data: { message: Message[8] }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4,6 +4,7 @@ import * as dayjs from "dayjs";
|
|||||||
import * as multer from "multer";
|
import * as multer from "multer";
|
||||||
import config from "./config";
|
import config from "./config";
|
||||||
import Logger from "./loaders/logger";
|
import Logger from "./loaders/logger";
|
||||||
|
// import { operationLogs, role, user, userRole } from "./models/mysql";
|
||||||
import { importUsersFromLocalExcel } from "./router/excel";
|
import { importUsersFromLocalExcel } from "./router/excel";
|
||||||
import { getRoleList, getUserList } from "./router/http";
|
import { getRoleList, getUserList } from "./router/http";
|
||||||
// import { queryTable } from "./utils/mysql";
|
// import { queryTable } from "./utils/mysql";
|
||||||
|
26
src/utils/auth.ts
Normal file
26
src/utils/auth.ts
Normal 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
|
||||||
|
};
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
import { connection } from "./mysql";
|
|
||||||
import Logger from "../loaders/logger";
|
import Logger from "../loaders/logger";
|
||||||
|
import { connection } from "./mysql";
|
||||||
|
|
||||||
// 定义操作类型
|
// 定义操作类型
|
||||||
export enum OperationType {
|
export enum OperationType {
|
||||||
@ -21,25 +21,29 @@ export enum ModuleType {
|
|||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
export const logOperation = (params: {
|
export const logOperation = (params: {
|
||||||
userId: number;
|
operatorId: number; // 操作者ID
|
||||||
username: string;
|
operatorName: string; // 操作者名称
|
||||||
action: OperationType;
|
targetId?: number; // 被操作对象ID
|
||||||
module: ModuleType;
|
targetType?: string; // 被操作对象类型
|
||||||
description: string;
|
action: OperationType; // 操作类型(使用枚举)
|
||||||
ip: string;
|
module: ModuleType; // 模块(使用枚举)
|
||||||
|
content: string; // 操作内容
|
||||||
|
ip: string; // IP地址
|
||||||
}) => {
|
}) => {
|
||||||
const sql = `
|
const sql = `
|
||||||
INSERT INTO operation_logs
|
INSERT INTO operation_logs
|
||||||
(user_id, username, action, module, description, ip)
|
(operator_id, operator_name, target_id, target_type, action, module, content, ip)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const values = [
|
const values = [
|
||||||
params.userId,
|
params.operatorId,
|
||||||
params.username,
|
params.operatorName,
|
||||||
|
params.targetId || null,
|
||||||
|
params.targetType || null,
|
||||||
params.action,
|
params.action,
|
||||||
params.module,
|
params.module,
|
||||||
params.description,
|
params.content,
|
||||||
params.ip
|
params.ip
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user