@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.
Files changed (55) hide show
  1. package/dist/controllers/log-analysis.controller.d.ts +21 -0
  2. package/dist/controllers/log-analysis.controller.d.ts.map +1 -0
  3. package/dist/controllers/log-analysis.controller.js +75 -0
  4. package/dist/controllers/log-analysis.controller.js.map +1 -0
  5. package/dist/controllers/retention-rule.controller.d.ts +17 -0
  6. package/dist/controllers/retention-rule.controller.d.ts.map +1 -0
  7. package/dist/controllers/retention-rule.controller.js +97 -0
  8. package/dist/controllers/retention-rule.controller.js.map +1 -0
  9. package/dist/entities/index.d.ts +6 -0
  10. package/dist/entities/index.d.ts.map +1 -0
  11. package/dist/entities/index.js +13 -0
  12. package/dist/entities/index.js.map +1 -0
  13. package/dist/entities/operation-log.entity.d.ts +45 -0
  14. package/dist/entities/operation-log.entity.d.ts.map +1 -0
  15. package/dist/entities/operation-log.entity.js +125 -0
  16. package/dist/entities/operation-log.entity.js.map +1 -0
  17. package/dist/entities/retention-rule.entity.d.ts +17 -0
  18. package/dist/entities/retention-rule.entity.d.ts.map +1 -0
  19. package/dist/entities/retention-rule.entity.js +66 -0
  20. package/dist/entities/retention-rule.entity.js.map +1 -0
  21. package/dist/index.d.ts +18 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +39 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/log-analysis.module.d.ts +18 -0
  26. package/dist/log-analysis.module.d.ts.map +1 -0
  27. package/dist/log-analysis.module.js +41 -0
  28. package/dist/log-analysis.module.js.map +1 -0
  29. package/dist/schemas/log-analysis.schema.d.ts +116 -0
  30. package/dist/schemas/log-analysis.schema.d.ts.map +1 -0
  31. package/dist/schemas/log-analysis.schema.js +42 -0
  32. package/dist/schemas/log-analysis.schema.js.map +1 -0
  33. package/dist/services/log-query.service.d.ts +37 -0
  34. package/dist/services/log-query.service.d.ts.map +1 -0
  35. package/dist/services/log-query.service.js +103 -0
  36. package/dist/services/log-query.service.js.map +1 -0
  37. package/dist/services/log-writer.service.d.ts +20 -0
  38. package/dist/services/log-writer.service.d.ts.map +1 -0
  39. package/dist/services/log-writer.service.js +66 -0
  40. package/dist/services/log-writer.service.js.map +1 -0
  41. package/dist/services/retention-rule.service.d.ts +19 -0
  42. package/dist/services/retention-rule.service.d.ts.map +1 -0
  43. package/dist/services/retention-rule.service.js +110 -0
  44. package/dist/services/retention-rule.service.js.map +1 -0
  45. package/package.json +88 -0
  46. package/web/components/LogsTable.tsx +69 -0
  47. package/web/components/RetentionRulesTab.tsx +187 -0
  48. package/web/components/StatsOverview.tsx +91 -0
  49. package/web/index.ts +27 -0
  50. package/web/manifest.ts +17 -0
  51. package/web/messages/en-US.json +70 -0
  52. package/web/messages/zh-CN.json +70 -0
  53. package/web/pages/LogAnalysisPage.tsx +202 -0
  54. package/web/services/log-analysis-service.ts +68 -0
  55. 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":";;;AAAA,6BAAwB;AACxB,mDAA2D;AAE3D,iBAAiB;AACJ,QAAA,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC9C,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACxC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACjC,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,oBAAS,CAAC;IAC/B,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACvC,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC3C,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC5C,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC1C,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3C,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,OAAC,CAAC,UAAU,CAAC,mBAAQ,CAAC,CAAC,OAAO,CAAC,mBAAQ,CAAC,IAAI,CAAC;IACpD,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAGH,iBAAiB;AACJ,QAAA,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrD,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACrC,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,oBAAS,CAAC,CAAC,QAAQ,EAAE;IAC1C,KAAK,EAAE,OAAC,CAAC,UAAU,CAAC,mBAAQ,CAAC,CAAC,QAAQ,EAAE;IACxC,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACvC,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC3D,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;IACzD,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC9D,CAAC,CAAC;AAGH,iBAAiB;AACJ,QAAA,yBAAyB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAChD,MAAM,EAAE,OAAC,CAAC,UAAU,CAAC,oBAAS,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrD,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IAChD,OAAO,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACnC,CAAC,CAAC;AAGU,QAAA,yBAAyB,GAAG,iCAAyB,CAAC,OAAO,EAAE,CAAC"}
@@ -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":"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"}
@@ -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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"}