@octo-cyber/log-analysis 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllers/log-analysis.controller.d.ts +21 -0
- package/dist/controllers/log-analysis.controller.d.ts.map +1 -0
- package/dist/controllers/log-analysis.controller.js +75 -0
- package/dist/controllers/log-analysis.controller.js.map +1 -0
- package/dist/controllers/retention-rule.controller.d.ts +17 -0
- package/dist/controllers/retention-rule.controller.d.ts.map +1 -0
- package/dist/controllers/retention-rule.controller.js +97 -0
- package/dist/controllers/retention-rule.controller.js.map +1 -0
- package/dist/entities/index.d.ts +6 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +13 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/operation-log.entity.d.ts +45 -0
- package/dist/entities/operation-log.entity.d.ts.map +1 -0
- package/dist/entities/operation-log.entity.js +125 -0
- package/dist/entities/operation-log.entity.js.map +1 -0
- package/dist/entities/retention-rule.entity.d.ts +17 -0
- package/dist/entities/retention-rule.entity.d.ts.map +1 -0
- package/dist/entities/retention-rule.entity.js +66 -0
- package/dist/entities/retention-rule.entity.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/log-analysis.module.d.ts +18 -0
- package/dist/log-analysis.module.d.ts.map +1 -0
- package/dist/log-analysis.module.js +41 -0
- package/dist/log-analysis.module.js.map +1 -0
- package/dist/schemas/log-analysis.schema.d.ts +116 -0
- package/dist/schemas/log-analysis.schema.d.ts.map +1 -0
- package/dist/schemas/log-analysis.schema.js +42 -0
- package/dist/schemas/log-analysis.schema.js.map +1 -0
- package/dist/services/log-query.service.d.ts +37 -0
- package/dist/services/log-query.service.d.ts.map +1 -0
- package/dist/services/log-query.service.js +103 -0
- package/dist/services/log-query.service.js.map +1 -0
- package/dist/services/log-writer.service.d.ts +20 -0
- package/dist/services/log-writer.service.d.ts.map +1 -0
- package/dist/services/log-writer.service.js +66 -0
- package/dist/services/log-writer.service.js.map +1 -0
- package/dist/services/retention-rule.service.d.ts +19 -0
- package/dist/services/retention-rule.service.d.ts.map +1 -0
- package/dist/services/retention-rule.service.js +110 -0
- package/dist/services/retention-rule.service.js.map +1 -0
- package/package.json +88 -0
- package/web/components/LogsTable.tsx +69 -0
- package/web/components/RetentionRulesTab.tsx +187 -0
- package/web/components/StatsOverview.tsx +91 -0
- package/web/index.ts +27 -0
- package/web/manifest.ts +17 -0
- package/web/messages/en-US.json +70 -0
- package/web/messages/zh-CN.json +70 -0
- package/web/pages/LogAnalysisPage.tsx +202 -0
- package/web/services/log-analysis-service.ts +68 -0
- package/web/types/log-analysis.ts +83 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogAnalysisModule = void 0;
|
|
4
|
+
const core_1 = require("@octo-cyber/core");
|
|
5
|
+
const auth_1 = require("@octo-cyber/auth");
|
|
6
|
+
const index_js_1 = require("./entities/index.js");
|
|
7
|
+
const log_writer_service_js_1 = require("./services/log-writer.service.js");
|
|
8
|
+
const log_query_service_js_1 = require("./services/log-query.service.js");
|
|
9
|
+
const retention_rule_service_js_1 = require("./services/retention-rule.service.js");
|
|
10
|
+
const log_analysis_controller_js_1 = require("./controllers/log-analysis.controller.js");
|
|
11
|
+
const retention_rule_controller_js_1 = require("./controllers/retention-rule.controller.js");
|
|
12
|
+
/**
|
|
13
|
+
* Log Analysis module — operation log recording, querying, and retention management.
|
|
14
|
+
*
|
|
15
|
+
* Provides:
|
|
16
|
+
* - LogWriterService: other modules call this to record operation logs
|
|
17
|
+
* - Log query with filtering and pagination
|
|
18
|
+
* - Statistical analysis (by action, module, level, daily trend)
|
|
19
|
+
* - Retention rules to auto-clean expired logs
|
|
20
|
+
*/
|
|
21
|
+
class LogAnalysisModule {
|
|
22
|
+
name = 'log-analysis';
|
|
23
|
+
entities = [...index_js_1.LOG_ANALYSIS_ENTITIES];
|
|
24
|
+
initialize(_context) {
|
|
25
|
+
const logger = core_1.Container.get(core_1.LoggerService);
|
|
26
|
+
core_1.Container.get(log_writer_service_js_1.LogWriterService).initialize();
|
|
27
|
+
core_1.Container.get(log_query_service_js_1.LogQueryService).initialize();
|
|
28
|
+
core_1.Container.get(retention_rule_service_js_1.RetentionRuleService).initialize();
|
|
29
|
+
logger.info('[LogAnalysisModule] initialized');
|
|
30
|
+
}
|
|
31
|
+
registerRoutes(app, _context) {
|
|
32
|
+
core_1.MenuRegistry.register('log-analysis', [
|
|
33
|
+
{ path: '/log-analysis', titleKey: 'logAnalysis.pages.home' },
|
|
34
|
+
]);
|
|
35
|
+
(0, core_1.registerControllers)(app, [new log_analysis_controller_js_1.LogAnalysisController(), new retention_rule_controller_js_1.RetentionRuleController()], { module: 'log-analysis', middlewares: [(0, auth_1.authMiddleware)()] });
|
|
36
|
+
const logger = core_1.Container.get(core_1.LoggerService);
|
|
37
|
+
logger.info('[LogAnalysisModule] routes registered');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.LogAnalysisModule = LogAnalysisModule;
|
|
41
|
+
//# sourceMappingURL=log-analysis.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.module.js","sourceRoot":"","sources":["../src/log-analysis.module.ts"],"names":[],"mappings":";;;AAAA,2CAK0B;AAG1B,2CAAkD;AAElD,kDAA4D;AAC5D,4EAAoE;AACpE,0EAAkE;AAClE,oFAA4E;AAC5E,yFAAiF;AACjF,6FAAqF;AAErF;;;;;;;;GAQG;AACH,MAAa,iBAAiB;IACnB,IAAI,GAAG,cAAc,CAAC;IACtB,QAAQ,GAAG,CAAC,GAAG,gCAAqB,CAAC,CAAC;IAE/C,UAAU,CAAC,QAAwB;QACjC,MAAM,MAAM,GAAG,gBAAS,CAAC,GAAG,CAAC,oBAAa,CAAC,CAAC;QAE5C,gBAAS,CAAC,GAAG,CAAC,wCAAgB,CAAC,CAAC,UAAU,EAAE,CAAC;QAC7C,gBAAS,CAAC,GAAG,CAAC,sCAAe,CAAC,CAAC,UAAU,EAAE,CAAC;QAC5C,gBAAS,CAAC,GAAG,CAAC,gDAAoB,CAAC,CAAC,UAAU,EAAE,CAAC;QAEjD,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACjD,CAAC;IAED,cAAc,CAAC,GAAY,EAAE,QAAwB;QACnD,mBAAY,CAAC,QAAQ,CAAC,cAAc,EAAE;YACpC,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,wBAAwB,EAAE;SAC9D,CAAC,CAAC;QAEH,IAAA,0BAAmB,EACjB,GAAG,EACH,CAAC,IAAI,kDAAqB,EAAE,EAAE,IAAI,sDAAuB,EAAE,CAAC,EAC5D,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,IAAA,qBAAc,GAAE,CAAC,EAAE,CAC5D,CAAC;QAEF,MAAM,MAAM,GAAG,gBAAS,CAAC,GAAG,CAAC,oBAAa,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;CACF;AA5BD,8CA4BC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { LogLevel, LogAction } from '../entities/index.js';
|
|
3
|
+
export declare const WriteLogSchema: z.ZodObject<{
|
|
4
|
+
userId: z.ZodOptional<z.ZodNumber>;
|
|
5
|
+
username: z.ZodOptional<z.ZodString>;
|
|
6
|
+
module: z.ZodString;
|
|
7
|
+
action: z.ZodNativeEnum<typeof LogAction>;
|
|
8
|
+
description: z.ZodString;
|
|
9
|
+
requestPath: z.ZodOptional<z.ZodString>;
|
|
10
|
+
requestMethod: z.ZodOptional<z.ZodString>;
|
|
11
|
+
resourceId: z.ZodOptional<z.ZodString>;
|
|
12
|
+
resourceType: z.ZodOptional<z.ZodString>;
|
|
13
|
+
ip: z.ZodOptional<z.ZodString>;
|
|
14
|
+
level: z.ZodDefault<z.ZodNativeEnum<typeof LogLevel>>;
|
|
15
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
userId?: number;
|
|
18
|
+
username?: string;
|
|
19
|
+
module?: string;
|
|
20
|
+
action?: LogAction;
|
|
21
|
+
description?: string;
|
|
22
|
+
requestPath?: string;
|
|
23
|
+
requestMethod?: string;
|
|
24
|
+
resourceId?: string;
|
|
25
|
+
resourceType?: string;
|
|
26
|
+
ip?: string;
|
|
27
|
+
level?: LogLevel;
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
29
|
+
}, {
|
|
30
|
+
userId?: number;
|
|
31
|
+
username?: string;
|
|
32
|
+
module?: string;
|
|
33
|
+
action?: LogAction;
|
|
34
|
+
description?: string;
|
|
35
|
+
requestPath?: string;
|
|
36
|
+
requestMethod?: string;
|
|
37
|
+
resourceId?: string;
|
|
38
|
+
resourceType?: string;
|
|
39
|
+
ip?: string;
|
|
40
|
+
level?: LogLevel;
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}>;
|
|
43
|
+
export type WriteLogDto = z.infer<typeof WriteLogSchema>;
|
|
44
|
+
export declare const QueryLogSchema: z.ZodObject<{
|
|
45
|
+
userId: z.ZodOptional<z.ZodNumber>;
|
|
46
|
+
module: z.ZodOptional<z.ZodString>;
|
|
47
|
+
action: z.ZodOptional<z.ZodNativeEnum<typeof LogAction>>;
|
|
48
|
+
level: z.ZodOptional<z.ZodNativeEnum<typeof LogLevel>>;
|
|
49
|
+
keyword: z.ZodOptional<z.ZodString>;
|
|
50
|
+
startDate: z.ZodOptional<z.ZodString>;
|
|
51
|
+
endDate: z.ZodOptional<z.ZodString>;
|
|
52
|
+
page: z.ZodDefault<z.ZodNumber>;
|
|
53
|
+
pageSize: z.ZodDefault<z.ZodNumber>;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
userId?: number;
|
|
56
|
+
module?: string;
|
|
57
|
+
action?: LogAction;
|
|
58
|
+
level?: LogLevel;
|
|
59
|
+
keyword?: string;
|
|
60
|
+
startDate?: string;
|
|
61
|
+
endDate?: string;
|
|
62
|
+
page?: number;
|
|
63
|
+
pageSize?: number;
|
|
64
|
+
}, {
|
|
65
|
+
userId?: number;
|
|
66
|
+
module?: string;
|
|
67
|
+
action?: LogAction;
|
|
68
|
+
level?: LogLevel;
|
|
69
|
+
keyword?: string;
|
|
70
|
+
startDate?: string;
|
|
71
|
+
endDate?: string;
|
|
72
|
+
page?: number;
|
|
73
|
+
pageSize?: number;
|
|
74
|
+
}>;
|
|
75
|
+
export type QueryLogDto = z.infer<typeof QueryLogSchema>;
|
|
76
|
+
export declare const CreateRetentionRuleSchema: z.ZodObject<{
|
|
77
|
+
name: z.ZodString;
|
|
78
|
+
module: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
79
|
+
action: z.ZodOptional<z.ZodNullable<z.ZodNativeEnum<typeof LogAction>>>;
|
|
80
|
+
retentionDays: z.ZodNumber;
|
|
81
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
82
|
+
}, "strip", z.ZodTypeAny, {
|
|
83
|
+
name?: string;
|
|
84
|
+
module?: string;
|
|
85
|
+
action?: LogAction;
|
|
86
|
+
retentionDays?: number;
|
|
87
|
+
enabled?: boolean;
|
|
88
|
+
}, {
|
|
89
|
+
name?: string;
|
|
90
|
+
module?: string;
|
|
91
|
+
action?: LogAction;
|
|
92
|
+
retentionDays?: number;
|
|
93
|
+
enabled?: boolean;
|
|
94
|
+
}>;
|
|
95
|
+
export type CreateRetentionRuleDto = z.infer<typeof CreateRetentionRuleSchema>;
|
|
96
|
+
export declare const UpdateRetentionRuleSchema: z.ZodObject<{
|
|
97
|
+
name: z.ZodOptional<z.ZodString>;
|
|
98
|
+
module: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
99
|
+
action: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodNativeEnum<typeof LogAction>>>>;
|
|
100
|
+
retentionDays: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
enabled: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
102
|
+
}, "strip", z.ZodTypeAny, {
|
|
103
|
+
name?: string;
|
|
104
|
+
module?: string;
|
|
105
|
+
action?: LogAction;
|
|
106
|
+
retentionDays?: number;
|
|
107
|
+
enabled?: boolean;
|
|
108
|
+
}, {
|
|
109
|
+
name?: string;
|
|
110
|
+
module?: string;
|
|
111
|
+
action?: LogAction;
|
|
112
|
+
retentionDays?: number;
|
|
113
|
+
enabled?: boolean;
|
|
114
|
+
}>;
|
|
115
|
+
export type UpdateRetentionRuleDto = z.infer<typeof UpdateRetentionRuleSchema>;
|
|
116
|
+
//# sourceMappingURL=log-analysis.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/log-analysis.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG3D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAazB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAGzD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUzB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAGzD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;EAMpC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE/E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;EAAsC,CAAC;AAC7E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UpdateRetentionRuleSchema = exports.CreateRetentionRuleSchema = exports.QueryLogSchema = exports.WriteLogSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const index_js_1 = require("../entities/index.js");
|
|
6
|
+
// ---- 写入日志 ----
|
|
7
|
+
exports.WriteLogSchema = zod_1.z.object({
|
|
8
|
+
userId: zod_1.z.number().int().positive().optional(),
|
|
9
|
+
username: zod_1.z.string().max(128).optional(),
|
|
10
|
+
module: zod_1.z.string().min(1).max(64),
|
|
11
|
+
action: zod_1.z.nativeEnum(index_js_1.LogAction),
|
|
12
|
+
description: zod_1.z.string().min(1).max(512),
|
|
13
|
+
requestPath: zod_1.z.string().max(512).optional(),
|
|
14
|
+
requestMethod: zod_1.z.string().max(16).optional(),
|
|
15
|
+
resourceId: zod_1.z.string().max(256).optional(),
|
|
16
|
+
resourceType: zod_1.z.string().max(64).optional(),
|
|
17
|
+
ip: zod_1.z.string().max(64).optional(),
|
|
18
|
+
level: zod_1.z.nativeEnum(index_js_1.LogLevel).default(index_js_1.LogLevel.INFO),
|
|
19
|
+
metadata: zod_1.z.record(zod_1.z.unknown()).optional(),
|
|
20
|
+
});
|
|
21
|
+
// ---- 查询日志 ----
|
|
22
|
+
exports.QueryLogSchema = zod_1.z.object({
|
|
23
|
+
userId: zod_1.z.coerce.number().int().positive().optional(),
|
|
24
|
+
module: zod_1.z.string().max(64).optional(),
|
|
25
|
+
action: zod_1.z.nativeEnum(index_js_1.LogAction).optional(),
|
|
26
|
+
level: zod_1.z.nativeEnum(index_js_1.LogLevel).optional(),
|
|
27
|
+
keyword: zod_1.z.string().max(256).optional(),
|
|
28
|
+
startDate: zod_1.z.string().datetime({ offset: true }).optional(),
|
|
29
|
+
endDate: zod_1.z.string().datetime({ offset: true }).optional(),
|
|
30
|
+
page: zod_1.z.coerce.number().int().min(1).default(1),
|
|
31
|
+
pageSize: zod_1.z.coerce.number().int().min(1).max(200).default(20),
|
|
32
|
+
});
|
|
33
|
+
// ---- 保留规则 ----
|
|
34
|
+
exports.CreateRetentionRuleSchema = zod_1.z.object({
|
|
35
|
+
name: zod_1.z.string().min(1).max(128),
|
|
36
|
+
module: zod_1.z.string().max(64).nullable().optional(),
|
|
37
|
+
action: zod_1.z.nativeEnum(index_js_1.LogAction).nullable().optional(),
|
|
38
|
+
retentionDays: zod_1.z.number().int().min(0).max(3650),
|
|
39
|
+
enabled: zod_1.z.boolean().default(true),
|
|
40
|
+
});
|
|
41
|
+
exports.UpdateRetentionRuleSchema = exports.CreateRetentionRuleSchema.partial();
|
|
42
|
+
//# sourceMappingURL=log-analysis.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.schema.js","sourceRoot":"","sources":["../../src/schemas/log-analysis.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { OperationLog } from '../entities/index.js';
|
|
2
|
+
import type { QueryLogDto } from '../schemas/log-analysis.schema.js';
|
|
3
|
+
export interface LogQueryResult {
|
|
4
|
+
items: OperationLog[];
|
|
5
|
+
total: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ActionStat {
|
|
8
|
+
action: string;
|
|
9
|
+
count: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ModuleStat {
|
|
12
|
+
module: string;
|
|
13
|
+
count: number;
|
|
14
|
+
}
|
|
15
|
+
export interface DailyStat {
|
|
16
|
+
date: string;
|
|
17
|
+
count: number;
|
|
18
|
+
}
|
|
19
|
+
export interface LogStats {
|
|
20
|
+
total: number;
|
|
21
|
+
byAction: ActionStat[];
|
|
22
|
+
byModule: ModuleStat[];
|
|
23
|
+
byLevel: {
|
|
24
|
+
level: string;
|
|
25
|
+
count: number;
|
|
26
|
+
}[];
|
|
27
|
+
daily: DailyStat[];
|
|
28
|
+
}
|
|
29
|
+
export declare class LogQueryService {
|
|
30
|
+
private logRepo;
|
|
31
|
+
private initialized;
|
|
32
|
+
initialize(): void;
|
|
33
|
+
private ensureInitialized;
|
|
34
|
+
findLogs(dto: QueryLogDto): Promise<LogQueryResult>;
|
|
35
|
+
getStats(startDate?: Date, endDate?: Date): Promise<LogStats>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=log-query.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-query.service.d.ts","sourceRoot":"","sources":["../../src/services/log-query.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,qBACa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,WAAW,CAAS;IAE5B,UAAU,IAAI,IAAI;IAMlB,OAAO,CAAC,iBAAiB;IAMnB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCnD,QAAQ,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC;CAiDpE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.LogQueryService = void 0;
|
|
10
|
+
const core_1 = require("@octo-cyber/core");
|
|
11
|
+
const index_js_1 = require("../entities/index.js");
|
|
12
|
+
let LogQueryService = class LogQueryService {
|
|
13
|
+
logRepo;
|
|
14
|
+
initialized = false;
|
|
15
|
+
initialize() {
|
|
16
|
+
const db = core_1.Container.get(core_1.DatabaseService);
|
|
17
|
+
this.logRepo = db.getRepository(index_js_1.OperationLog);
|
|
18
|
+
this.initialized = true;
|
|
19
|
+
}
|
|
20
|
+
ensureInitialized() {
|
|
21
|
+
if (!this.initialized) {
|
|
22
|
+
this.initialize();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async findLogs(dto) {
|
|
26
|
+
this.ensureInitialized();
|
|
27
|
+
const { page, pageSize } = dto;
|
|
28
|
+
const qb = this.logRepo.createQueryBuilder('log').orderBy('log.createdAt', 'DESC');
|
|
29
|
+
if (dto.userId !== undefined) {
|
|
30
|
+
qb.andWhere('log.user_id = :userId', { userId: dto.userId });
|
|
31
|
+
}
|
|
32
|
+
if (dto.module) {
|
|
33
|
+
qb.andWhere('log.module = :module', { module: dto.module });
|
|
34
|
+
}
|
|
35
|
+
if (dto.action) {
|
|
36
|
+
qb.andWhere('log.action = :action', { action: dto.action });
|
|
37
|
+
}
|
|
38
|
+
if (dto.level) {
|
|
39
|
+
qb.andWhere('log.level = :level', { level: dto.level });
|
|
40
|
+
}
|
|
41
|
+
if (dto.keyword) {
|
|
42
|
+
qb.andWhere('log.description LIKE :keyword', { keyword: `%${dto.keyword}%` });
|
|
43
|
+
}
|
|
44
|
+
if (dto.startDate) {
|
|
45
|
+
qb.andWhere('log.created_at >= :startDate', { startDate: new Date(dto.startDate) });
|
|
46
|
+
}
|
|
47
|
+
if (dto.endDate) {
|
|
48
|
+
qb.andWhere('log.created_at <= :endDate', { endDate: new Date(dto.endDate) });
|
|
49
|
+
}
|
|
50
|
+
qb.skip((page - 1) * pageSize).take(pageSize);
|
|
51
|
+
const [items, total] = await qb.getManyAndCount();
|
|
52
|
+
return { items, total };
|
|
53
|
+
}
|
|
54
|
+
async getStats(startDate, endDate) {
|
|
55
|
+
this.ensureInitialized();
|
|
56
|
+
const buildBase = () => {
|
|
57
|
+
const qb = this.logRepo.createQueryBuilder('log');
|
|
58
|
+
if (startDate)
|
|
59
|
+
qb.andWhere('log.created_at >= :startDate', { startDate });
|
|
60
|
+
if (endDate)
|
|
61
|
+
qb.andWhere('log.created_at <= :endDate', { endDate });
|
|
62
|
+
return qb;
|
|
63
|
+
};
|
|
64
|
+
const [totalResult, byAction, byModule, byLevel, daily] = await Promise.all([
|
|
65
|
+
buildBase().getCount(),
|
|
66
|
+
buildBase()
|
|
67
|
+
.select('log.action', 'action')
|
|
68
|
+
.addSelect('COUNT(*)', 'count')
|
|
69
|
+
.groupBy('log.action')
|
|
70
|
+
.orderBy('count', 'DESC')
|
|
71
|
+
.getRawMany(),
|
|
72
|
+
buildBase()
|
|
73
|
+
.select('log.module', 'module')
|
|
74
|
+
.addSelect('COUNT(*)', 'count')
|
|
75
|
+
.groupBy('log.module')
|
|
76
|
+
.orderBy('count', 'DESC')
|
|
77
|
+
.getRawMany(),
|
|
78
|
+
buildBase()
|
|
79
|
+
.select('log.level', 'level')
|
|
80
|
+
.addSelect('COUNT(*)', 'count')
|
|
81
|
+
.groupBy('log.level')
|
|
82
|
+
.getRawMany(),
|
|
83
|
+
buildBase()
|
|
84
|
+
.select("strftime('%Y-%m-%d', log.created_at)", 'date')
|
|
85
|
+
.addSelect('COUNT(*)', 'count')
|
|
86
|
+
.groupBy('date')
|
|
87
|
+
.orderBy('date', 'ASC')
|
|
88
|
+
.getRawMany(),
|
|
89
|
+
]);
|
|
90
|
+
return {
|
|
91
|
+
total: totalResult,
|
|
92
|
+
byAction: byAction.map(r => ({ action: r.action, count: Number(r.count) })),
|
|
93
|
+
byModule: byModule.map(r => ({ module: r.module, count: Number(r.count) })),
|
|
94
|
+
byLevel: byLevel.map(r => ({ level: r.level, count: Number(r.count) })),
|
|
95
|
+
daily: daily.map(r => ({ date: r.date, count: Number(r.count) })),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
exports.LogQueryService = LogQueryService;
|
|
100
|
+
exports.LogQueryService = LogQueryService = __decorate([
|
|
101
|
+
(0, core_1.Service)()
|
|
102
|
+
], LogQueryService);
|
|
103
|
+
//# sourceMappingURL=log-query.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-query.service.js","sourceRoot":"","sources":["../../src/services/log-query.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAuE;AAEvE,mDAAoD;AAgC7C,IAAM,eAAe,GAArB,MAAM,eAAe;IAClB,OAAO,CAA4B;IACnC,WAAW,GAAG,KAAK,CAAC;IAE5B,UAAU;QACR,MAAM,EAAE,GAAG,gBAAS,CAAC,GAAG,CAAC,sBAAe,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,uBAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,GAAgB;QAC7B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAEnF,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,EAAE,CAAC,QAAQ,CAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,EAAE,CAAC,QAAQ,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,EAAE,CAAC,QAAQ,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,EAAE,CAAC,QAAQ,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,EAAE,CAAC,QAAQ,CAAC,+BAA+B,EAAE,EAAE,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAClB,EAAE,CAAC,QAAQ,CAAC,8BAA8B,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,EAAE,CAAC,QAAQ,CAAC,4BAA4B,EAAE,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAE9C,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,eAAe,EAAE,CAAC;QAClD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAgB,EAAE,OAAc;QAC7C,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,MAAM,SAAS,GAAG,GAAG,EAAE;YACrB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,SAAS;gBAAE,EAAE,CAAC,QAAQ,CAAC,8BAA8B,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;YAC1E,IAAI,OAAO;gBAAE,EAAE,CAAC,QAAQ,CAAC,4BAA4B,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;YACpE,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QAEF,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1E,SAAS,EAAE,CAAC,QAAQ,EAAE;YAEtB,SAAS,EAAE;iBACR,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC;iBAC9B,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;iBAC9B,OAAO,CAAC,YAAY,CAAC;iBACrB,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;iBACxB,UAAU,EAAqC;YAElD,SAAS,EAAE;iBACR,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC;iBAC9B,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;iBAC9B,OAAO,CAAC,YAAY,CAAC;iBACrB,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;iBACxB,UAAU,EAAqC;YAElD,SAAS,EAAE;iBACR,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC;iBAC5B,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;iBAC9B,OAAO,CAAC,WAAW,CAAC;iBACpB,UAAU,EAAoC;YAEjD,SAAS,EAAE;iBACR,MAAM,CAAC,sCAAsC,EAAE,MAAM,CAAC;iBACtD,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC;iBAC9B,OAAO,CAAC,MAAM,CAAC;iBACf,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;iBACtB,UAAU,EAAmC;SACjD,CAAC,CAAC;QAEH,OAAO;YACL,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3E,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3E,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SAClE,CAAC;IACJ,CAAC;CACF,CAAA;AAnGY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,cAAO,GAAE;GACG,eAAe,CAmG3B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OperationLog, LogAction } from '../entities/index.js';
|
|
2
|
+
import type { WriteLogDto } from '../schemas/log-analysis.schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* 操作日志写入服务。
|
|
5
|
+
* 其他模块通过 Container.get(LogWriterService).write(...) 来记录操作日志。
|
|
6
|
+
*/
|
|
7
|
+
export declare class LogWriterService {
|
|
8
|
+
private logRepo;
|
|
9
|
+
private initialized;
|
|
10
|
+
initialize(): void;
|
|
11
|
+
private ensureInitialized;
|
|
12
|
+
write(dto: WriteLogDto): Promise<OperationLog>;
|
|
13
|
+
/** 快捷方法:记录 INFO 级别操作 */
|
|
14
|
+
info(module: string, action: LogAction, description: string, extra?: Partial<WriteLogDto>): Promise<void>;
|
|
15
|
+
/** 快捷方法:记录 WARN 级别操作 */
|
|
16
|
+
warn(module: string, action: LogAction, description: string, extra?: Partial<WriteLogDto>): Promise<void>;
|
|
17
|
+
/** 快捷方法:记录 ERROR 级别操作 */
|
|
18
|
+
error(module: string, action: LogAction, description: string, extra?: Partial<WriteLogDto>): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=log-writer.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-writer.service.d.ts","sourceRoot":"","sources":["../../src/services/log-writer.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAY,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAErE;;;GAGG;AACH,qBACa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,WAAW,CAAS;IAE5B,UAAU,IAAI,IAAI;IAMlB,OAAO,CAAC,iBAAiB;IAMnB,KAAK,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAqBpD,wBAAwB;IAClB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/G,wBAAwB;IAClB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/G,yBAAyB;IACnB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAKjH"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.LogWriterService = void 0;
|
|
10
|
+
const core_1 = require("@octo-cyber/core");
|
|
11
|
+
const index_js_1 = require("../entities/index.js");
|
|
12
|
+
/**
|
|
13
|
+
* 操作日志写入服务。
|
|
14
|
+
* 其他模块通过 Container.get(LogWriterService).write(...) 来记录操作日志。
|
|
15
|
+
*/
|
|
16
|
+
let LogWriterService = class LogWriterService {
|
|
17
|
+
logRepo;
|
|
18
|
+
initialized = false;
|
|
19
|
+
initialize() {
|
|
20
|
+
const db = core_1.Container.get(core_1.DatabaseService);
|
|
21
|
+
this.logRepo = db.getRepository(index_js_1.OperationLog);
|
|
22
|
+
this.initialized = true;
|
|
23
|
+
}
|
|
24
|
+
ensureInitialized() {
|
|
25
|
+
if (!this.initialized) {
|
|
26
|
+
this.initialize();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async write(dto) {
|
|
30
|
+
this.ensureInitialized();
|
|
31
|
+
const log = this.logRepo.create({
|
|
32
|
+
userId: dto.userId ?? null,
|
|
33
|
+
username: dto.username ?? null,
|
|
34
|
+
module: dto.module,
|
|
35
|
+
action: dto.action,
|
|
36
|
+
description: dto.description,
|
|
37
|
+
requestPath: dto.requestPath ?? null,
|
|
38
|
+
requestMethod: dto.requestMethod ?? null,
|
|
39
|
+
resourceId: dto.resourceId ?? null,
|
|
40
|
+
resourceType: dto.resourceType ?? null,
|
|
41
|
+
ip: dto.ip ?? null,
|
|
42
|
+
level: dto.level ?? index_js_1.LogLevel.INFO,
|
|
43
|
+
metadata: dto.metadata ? JSON.stringify(dto.metadata) : null,
|
|
44
|
+
});
|
|
45
|
+
return this.logRepo.save(log);
|
|
46
|
+
}
|
|
47
|
+
/** 快捷方法:记录 INFO 级别操作 */
|
|
48
|
+
async info(module, action, description, extra) {
|
|
49
|
+
await this.write({ module, action, description, level: index_js_1.LogLevel.INFO, ...extra });
|
|
50
|
+
}
|
|
51
|
+
/** 快捷方法:记录 WARN 级别操作 */
|
|
52
|
+
async warn(module, action, description, extra) {
|
|
53
|
+
await this.write({ module, action, description, level: index_js_1.LogLevel.WARN, ...extra });
|
|
54
|
+
}
|
|
55
|
+
/** 快捷方法:记录 ERROR 级别操作 */
|
|
56
|
+
async error(module, action, description, extra) {
|
|
57
|
+
const logger = core_1.Container.get(core_1.LoggerService);
|
|
58
|
+
logger.error(`[OperationLog] ${module}/${action}: ${description}`);
|
|
59
|
+
await this.write({ module, action, description, level: index_js_1.LogLevel.ERROR, ...extra });
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
exports.LogWriterService = LogWriterService;
|
|
63
|
+
exports.LogWriterService = LogWriterService = __decorate([
|
|
64
|
+
(0, core_1.Service)()
|
|
65
|
+
], LogWriterService);
|
|
66
|
+
//# sourceMappingURL=log-writer.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-writer.service.js","sourceRoot":"","sources":["../../src/services/log-writer.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAsF;AAEtF,mDAAyE;AAGzE;;;GAGG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IACnB,OAAO,CAA4B;IACnC,WAAW,GAAG,KAAK,CAAC;IAE5B,UAAU;QACR,MAAM,EAAE,GAAG,gBAAS,CAAC,GAAG,CAAC,sBAAe,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,uBAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAgB;QAC1B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI;YAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;YAC9B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,IAAI;YACpC,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,IAAI;YACxC,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,IAAI;YAClC,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,IAAI;YACtC,EAAE,EAAE,GAAG,CAAC,EAAE,IAAI,IAAI;YAClB,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,mBAAQ,CAAC,IAAI;YACjC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;SAC7D,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,wBAAwB;IACxB,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAiB,EAAE,WAAmB,EAAE,KAA4B;QAC7F,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAQ,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,wBAAwB;IACxB,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAiB,EAAE,WAAmB,EAAE,KAA4B;QAC7F,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAQ,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,yBAAyB;IACzB,KAAK,CAAC,KAAK,CAAC,MAAc,EAAE,MAAiB,EAAE,WAAmB,EAAE,KAA4B;QAC9F,MAAM,MAAM,GAAG,gBAAS,CAAC,GAAG,CAAC,oBAAa,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,kBAAkB,MAAM,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC,CAAC;QACnE,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAQ,CAAC,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IACrF,CAAC;CACF,CAAA;AArDY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,cAAO,GAAE;GACG,gBAAgB,CAqD5B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { RetentionRule } from '../entities/index.js';
|
|
2
|
+
import type { CreateRetentionRuleDto, UpdateRetentionRuleDto } from '../schemas/log-analysis.schema.js';
|
|
3
|
+
export declare class RetentionRuleService {
|
|
4
|
+
private ruleRepo;
|
|
5
|
+
private logRepo;
|
|
6
|
+
private initialized;
|
|
7
|
+
initialize(): void;
|
|
8
|
+
private ensureInitialized;
|
|
9
|
+
findAll(): Promise<RetentionRule[]>;
|
|
10
|
+
findById(id: number): Promise<RetentionRule | null>;
|
|
11
|
+
create(dto: CreateRetentionRuleDto): Promise<RetentionRule>;
|
|
12
|
+
update(id: number, dto: UpdateRetentionRuleDto): Promise<RetentionRule>;
|
|
13
|
+
remove(id: number): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* 执行清理:按所有启用规则删除超期日志,返回总删除条数。
|
|
16
|
+
*/
|
|
17
|
+
applyRetention(): Promise<number>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=retention-rule.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-rule.service.d.ts","sourceRoot":"","sources":["../../src/services/retention-rule.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAExG,qBACa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,WAAW,CAAS;IAE5B,UAAU,IAAI,IAAI;IAOlB,OAAO,CAAC,iBAAiB;IAMnB,OAAO,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAKnC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAKnD,MAAM,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC;IAgB3D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,aAAa,CAAC;IAcvE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;CAkCxC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RetentionRuleService = void 0;
|
|
10
|
+
const core_1 = require("@octo-cyber/core");
|
|
11
|
+
const index_js_1 = require("../entities/index.js");
|
|
12
|
+
const operation_log_entity_js_1 = require("../entities/operation-log.entity.js");
|
|
13
|
+
let RetentionRuleService = class RetentionRuleService {
|
|
14
|
+
ruleRepo;
|
|
15
|
+
logRepo;
|
|
16
|
+
initialized = false;
|
|
17
|
+
initialize() {
|
|
18
|
+
const db = core_1.Container.get(core_1.DatabaseService);
|
|
19
|
+
this.ruleRepo = db.getRepository(index_js_1.RetentionRule);
|
|
20
|
+
this.logRepo = db.getRepository(operation_log_entity_js_1.OperationLog);
|
|
21
|
+
this.initialized = true;
|
|
22
|
+
}
|
|
23
|
+
ensureInitialized() {
|
|
24
|
+
if (!this.initialized) {
|
|
25
|
+
this.initialize();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async findAll() {
|
|
29
|
+
this.ensureInitialized();
|
|
30
|
+
return this.ruleRepo.find({ order: { id: 'ASC' } });
|
|
31
|
+
}
|
|
32
|
+
async findById(id) {
|
|
33
|
+
this.ensureInitialized();
|
|
34
|
+
return this.ruleRepo.findOneBy({ id });
|
|
35
|
+
}
|
|
36
|
+
async create(dto) {
|
|
37
|
+
this.ensureInitialized();
|
|
38
|
+
const existing = await this.ruleRepo.findOneBy({ name: dto.name });
|
|
39
|
+
if (existing) {
|
|
40
|
+
throw core_1.AppError.badRequest(`Retention rule '${dto.name}' already exists`);
|
|
41
|
+
}
|
|
42
|
+
const rule = this.ruleRepo.create({
|
|
43
|
+
name: dto.name,
|
|
44
|
+
module: dto.module ?? null,
|
|
45
|
+
action: dto.action ?? null,
|
|
46
|
+
retentionDays: dto.retentionDays,
|
|
47
|
+
enabled: dto.enabled ?? true,
|
|
48
|
+
});
|
|
49
|
+
return this.ruleRepo.save(rule);
|
|
50
|
+
}
|
|
51
|
+
async update(id, dto) {
|
|
52
|
+
this.ensureInitialized();
|
|
53
|
+
const rule = await this.ruleRepo.findOneBy({ id });
|
|
54
|
+
if (!rule)
|
|
55
|
+
throw core_1.AppError.notFound(`RetentionRule #${id} not found`);
|
|
56
|
+
if (dto.name !== undefined)
|
|
57
|
+
rule.name = dto.name;
|
|
58
|
+
if (dto.module !== undefined)
|
|
59
|
+
rule.module = dto.module ?? null;
|
|
60
|
+
if (dto.action !== undefined)
|
|
61
|
+
rule.action = dto.action ?? null;
|
|
62
|
+
if (dto.retentionDays !== undefined)
|
|
63
|
+
rule.retentionDays = dto.retentionDays;
|
|
64
|
+
if (dto.enabled !== undefined)
|
|
65
|
+
rule.enabled = dto.enabled;
|
|
66
|
+
return this.ruleRepo.save(rule);
|
|
67
|
+
}
|
|
68
|
+
async remove(id) {
|
|
69
|
+
this.ensureInitialized();
|
|
70
|
+
const rule = await this.ruleRepo.findOneBy({ id });
|
|
71
|
+
if (!rule)
|
|
72
|
+
throw core_1.AppError.notFound(`RetentionRule #${id} not found`);
|
|
73
|
+
await this.ruleRepo.remove(rule);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 执行清理:按所有启用规则删除超期日志,返回总删除条数。
|
|
77
|
+
*/
|
|
78
|
+
async applyRetention() {
|
|
79
|
+
this.ensureInitialized();
|
|
80
|
+
const logger = core_1.Container.get(core_1.LoggerService);
|
|
81
|
+
const rules = await this.ruleRepo.findBy({ enabled: true });
|
|
82
|
+
let totalDeleted = 0;
|
|
83
|
+
for (const rule of rules) {
|
|
84
|
+
if (rule.retentionDays === 0)
|
|
85
|
+
continue;
|
|
86
|
+
const cutoff = new Date();
|
|
87
|
+
cutoff.setDate(cutoff.getDate() - rule.retentionDays);
|
|
88
|
+
const qb = this.logRepo.createQueryBuilder('log')
|
|
89
|
+
.where('log.created_at < :cutoff', { cutoff });
|
|
90
|
+
if (rule.module) {
|
|
91
|
+
qb.andWhere('log.module = :module', { module: rule.module });
|
|
92
|
+
}
|
|
93
|
+
if (rule.action) {
|
|
94
|
+
qb.andWhere('log.action = :action', { action: rule.action });
|
|
95
|
+
}
|
|
96
|
+
const { affected } = await qb.delete().from(operation_log_entity_js_1.OperationLog).execute();
|
|
97
|
+
const count = affected ?? 0;
|
|
98
|
+
totalDeleted += count;
|
|
99
|
+
if (count > 0) {
|
|
100
|
+
logger.info(`[RetentionRule] Rule '${rule.name}' deleted ${count} logs older than ${rule.retentionDays} days`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return totalDeleted;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
exports.RetentionRuleService = RetentionRuleService;
|
|
107
|
+
exports.RetentionRuleService = RetentionRuleService = __decorate([
|
|
108
|
+
(0, core_1.Service)()
|
|
109
|
+
], RetentionRuleService);
|
|
110
|
+
//# sourceMappingURL=retention-rule.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-rule.service.js","sourceRoot":"","sources":["../../src/services/retention-rule.service.ts"],"names":[],"mappings":"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"}
|