整理代码结构

This commit is contained in:
Baobhan Sith
2025-06-01 15:31:06 +08:00
parent 3d16613194
commit 33422a215c
39 changed files with 37 additions and 37 deletions
@@ -0,0 +1,142 @@
import { Database } from 'sqlite3';
import { getDbInstance, runDb, getDb as getDbRow, allDb } from '../database/connection';
import { AuditLogEntry, AuditLogActionType } from '../types/audit.types';
type DbAuditLogRow = AuditLogEntry;
export class AuditLogRepository {
/**
* 添加一条审计日志记录。
* @param actionType 操作类型。
* @param details 可选的详细信息(对象或字符串)。
*/
async addLog(actionType: AuditLogActionType, details?: Record<string, any> | string | null): Promise<void> {
const timestamp = Math.floor(Date.now() / 1000);
let detailsString: string | null = null;
if (details) {
try {
detailsString = typeof details === 'string' ? details : JSON.stringify(details);
} catch (error: any) {
console.error(`[审计日志] 序列化操作 ${actionType} 的详情失败:`, error.message);
detailsString = JSON.stringify({ error: 'Failed to stringify details', originalDetails: String(details) }); // Ensure originalDetails is stringifiable
}
}
const sql = 'INSERT INTO audit_logs (timestamp, action_type, details) VALUES (?, ?, ?)';
const params = [timestamp, actionType, detailsString];
try {
const db = await getDbInstance();
await runDb(db, sql, params);
// --- 添加日志清理逻辑 ---
await this.cleanupOldLogs(db);
// --- 清理逻辑结束 ---
} catch (err: any) {
console.error(`[审计日志] 添加操作 ${actionType} 的日志条目时出错: ${err.message}`);
// 决定日志记录失败是应该抛出错误还是仅记录日志
}
}
/**
* 清理旧的审计日志,保持最多 MAX_LOG_ENTRIES 条记录。
* @param db - 数据库实例。
*/
private async cleanupOldLogs(db: Database): Promise<void> {
const MAX_LOG_ENTRIES = 50000; // 设置最大日志条数
const countSql = 'SELECT COUNT(*) as total FROM audit_logs';
const deleteSql = `
DELETE FROM audit_logs
WHERE id IN (
SELECT id
FROM audit_logs
ORDER BY timestamp ASC
LIMIT ?
)
`; // 假设有自增的 id 列,并且 timestamp 能准确反映顺序
try {
const countRow = await getDbRow<{ total: number }>(db, countSql);
const total = countRow?.total ?? 0;
if (total > MAX_LOG_ENTRIES) {
const logsToDelete = total - MAX_LOG_ENTRIES;
console.log(`[审计日志] 日志数量 (${total}) 超过限制 (${MAX_LOG_ENTRIES})。正在删除 ${logsToDelete} 条最旧的记录。`);
await runDb(db, deleteSql, [logsToDelete]);
}
} catch (err: any) {
console.error(`[审计日志] 日志清理过程中出错: ${err.message}`);
// 清理失败不应阻止主日志记录流程,仅记录错误。
}
}
/**
* 获取审计日志列表(支持分页和基本过滤)。
* @param limit 每页数量。
* @param offset 偏移量。
* @param actionType 可选的操作类型过滤。
* @param startDate 可选的开始时间戳(秒)。
* @param endDate 可选的结束时间戳(秒)。
* @param searchTerm 可选的搜索关键词(模糊匹配 details)。
*/
async getLogs(
limit: number = 50,
offset: number = 0,
actionType?: AuditLogActionType,
startDate?: number,
endDate?: number,
searchTerm?: string // 添加 searchTerm 参数
): Promise<{ logs: AuditLogEntry[], total: number }> {
let baseSql = 'SELECT * FROM audit_logs';
let countSql = 'SELECT COUNT(*) as total FROM audit_logs';
const whereClauses: string[] = [];
const params: (string | number)[] = [];
const countParams: (string | number)[] = [];
if (actionType) {
whereClauses.push('action_type = ?');
params.push(actionType);
countParams.push(actionType);
}
// 添加 searchTerm 的过滤逻辑
if (searchTerm) {
// 搜索 details 字段,使用 LIKE 进行模糊匹配
whereClauses.push('details LIKE ?');
const searchTermLike = `%${searchTerm}%`;
params.push(searchTermLike);
countParams.push(searchTermLike);
}
if (whereClauses.length > 0) {
const whereSql = ` WHERE ${whereClauses.join(' AND ')}`;
baseSql += whereSql;
countSql += whereSql;
}
baseSql += ' ORDER BY timestamp DESC LIMIT ? OFFSET ?';
params.push(limit, offset);
try {
const db = await getDbInstance();
const countRow = await getDbRow<{ total: number }>(db, countSql, countParams);
const total = countRow?.total ?? 0;
const logs = await allDb<DbAuditLogRow>(db, baseSql, params);
return { logs, total };
} catch (err: any) {
console.error(`获取审计日志时出错:`, err.message);
throw new Error(`获取审计日志时出错: ${err.message}`);
}
}
}