@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,21 @@
|
|
|
1
|
+
import type { Request, Response } from '@octo-cyber/core';
|
|
2
|
+
export declare class LogAnalysisController {
|
|
3
|
+
private get writer();
|
|
4
|
+
private get query();
|
|
5
|
+
/**
|
|
6
|
+
* POST /api/v1/logs
|
|
7
|
+
* 写入一条操作日志(供内部服务或管理员调用)。
|
|
8
|
+
*/
|
|
9
|
+
write(req: Request, res: Response): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* GET /api/v1/logs
|
|
12
|
+
* 查询操作日志列表,支持过滤与分页。
|
|
13
|
+
*/
|
|
14
|
+
findLogs(req: Request, res: Response): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* GET /api/v1/logs/stats
|
|
17
|
+
* 获取日志统计数据(按动作、模块、级别分组 + 近 30 天趋势)。
|
|
18
|
+
*/
|
|
19
|
+
getStats(req: Request, res: Response): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=log-analysis.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/log-analysis.controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAM1D,qBACa,qBAAqB;IAChC,OAAO,KAAK,MAAM,GAEjB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED;;;OAGG;IAEG,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvD;;;OAGG;IAEG,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1D;;;OAGG;IAEG,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3D"}
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.LogAnalysisController = void 0;
|
|
13
|
+
const core_1 = require("@octo-cyber/core");
|
|
14
|
+
const log_writer_service_js_1 = require("../services/log-writer.service.js");
|
|
15
|
+
const log_query_service_js_1 = require("../services/log-query.service.js");
|
|
16
|
+
const log_analysis_schema_js_1 = require("../schemas/log-analysis.schema.js");
|
|
17
|
+
let LogAnalysisController = class LogAnalysisController {
|
|
18
|
+
get writer() {
|
|
19
|
+
return core_1.Container.get(log_writer_service_js_1.LogWriterService);
|
|
20
|
+
}
|
|
21
|
+
get query() {
|
|
22
|
+
return core_1.Container.get(log_query_service_js_1.LogQueryService);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* POST /api/v1/logs
|
|
26
|
+
* 写入一条操作日志(供内部服务或管理员调用)。
|
|
27
|
+
*/
|
|
28
|
+
async write(req, res) {
|
|
29
|
+
const dto = (0, core_1.validateSync)(log_analysis_schema_js_1.WriteLogSchema, req.body);
|
|
30
|
+
const log = await this.writer.write(dto);
|
|
31
|
+
res.status(201).json(core_1.ApiResponse.ok(log, 'Log created'));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* GET /api/v1/logs
|
|
35
|
+
* 查询操作日志列表,支持过滤与分页。
|
|
36
|
+
*/
|
|
37
|
+
async findLogs(req, res) {
|
|
38
|
+
const dto = (0, core_1.validateSync)(log_analysis_schema_js_1.QueryLogSchema, req.query);
|
|
39
|
+
const result = await this.query.findLogs(dto);
|
|
40
|
+
res.json(core_1.ApiResponse.paginated(result.items, result.total, dto.page, dto.pageSize));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* GET /api/v1/logs/stats
|
|
44
|
+
* 获取日志统计数据(按动作、模块、级别分组 + 近 30 天趋势)。
|
|
45
|
+
*/
|
|
46
|
+
async getStats(req, res) {
|
|
47
|
+
const startDate = req.query.startDate ? new Date(req.query.startDate) : undefined;
|
|
48
|
+
const endDate = req.query.endDate ? new Date(req.query.endDate) : undefined;
|
|
49
|
+
const stats = await this.query.getStats(startDate, endDate);
|
|
50
|
+
res.json(core_1.ApiResponse.ok(stats));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
exports.LogAnalysisController = LogAnalysisController;
|
|
54
|
+
__decorate([
|
|
55
|
+
(0, core_1.Post)('/'),
|
|
56
|
+
__metadata("design:type", Function),
|
|
57
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
58
|
+
__metadata("design:returntype", Promise)
|
|
59
|
+
], LogAnalysisController.prototype, "write", null);
|
|
60
|
+
__decorate([
|
|
61
|
+
(0, core_1.Get)('/'),
|
|
62
|
+
__metadata("design:type", Function),
|
|
63
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
64
|
+
__metadata("design:returntype", Promise)
|
|
65
|
+
], LogAnalysisController.prototype, "findLogs", null);
|
|
66
|
+
__decorate([
|
|
67
|
+
(0, core_1.Get)('/stats'),
|
|
68
|
+
__metadata("design:type", Function),
|
|
69
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
70
|
+
__metadata("design:returntype", Promise)
|
|
71
|
+
], LogAnalysisController.prototype, "getStats", null);
|
|
72
|
+
exports.LogAnalysisController = LogAnalysisController = __decorate([
|
|
73
|
+
(0, core_1.Controller)('/api/v1/logs')
|
|
74
|
+
], LogAnalysisController);
|
|
75
|
+
//# sourceMappingURL=log-analysis.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.controller.js","sourceRoot":"","sources":["../../src/controllers/log-analysis.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,2CAA+F;AAC/F,6EAAqE;AACrE,2EAAmE;AACnE,8EAAmF;AAG5E,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAChC,IAAY,MAAM;QAChB,OAAO,gBAAS,CAAC,GAAG,CAAC,wCAAgB,CAAC,CAAC;IACzC,CAAC;IAED,IAAY,KAAK;QACf,OAAO,gBAAS,CAAC,GAAG,CAAC,sCAAe,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,KAAK,CAAC,GAAY,EAAE,GAAa;QACrC,MAAM,GAAG,GAAG,IAAA,mBAAY,EAAC,uCAAc,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAW,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,QAAQ,CAAC,GAAY,EAAE,GAAa;QACxC,MAAM,GAAG,GAAG,IAAA,mBAAY,EAAC,uCAAc,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9C,GAAG,CAAC,IAAI,CAAC,kBAAW,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtF,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,QAAQ,CAAC,GAAY,EAAE,GAAa;QACxC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAmB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5F,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5D,GAAG,CAAC,IAAI,CAAC,kBAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,CAAC;CACF,CAAA;AA1CY,sDAAqB;AAc1B;IADL,IAAA,WAAI,EAAC,GAAG,CAAC;;;;kDAKT;AAOK;IADL,IAAA,UAAG,EAAC,GAAG,CAAC;;;;qDAKR;AAOK;IADL,IAAA,UAAG,EAAC,QAAQ,CAAC;;;;qDAMb;gCAzCU,qBAAqB;IADjC,IAAA,iBAAU,EAAC,cAAc,CAAC;GACd,qBAAqB,CA0CjC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Request, Response } from '@octo-cyber/core';
|
|
2
|
+
export declare class RetentionRuleController {
|
|
3
|
+
private get service();
|
|
4
|
+
/** GET /api/v1/log-retention-rules */
|
|
5
|
+
findAll(_req: Request, res: Response): Promise<void>;
|
|
6
|
+
/** GET /api/v1/log-retention-rules/:id */
|
|
7
|
+
findOne(req: Request, res: Response): Promise<void>;
|
|
8
|
+
/** POST /api/v1/log-retention-rules */
|
|
9
|
+
create(req: Request, res: Response): Promise<void>;
|
|
10
|
+
/** PUT /api/v1/log-retention-rules/:id */
|
|
11
|
+
update(req: Request, res: Response): Promise<void>;
|
|
12
|
+
/** DELETE /api/v1/log-retention-rules/:id */
|
|
13
|
+
remove(req: Request, res: Response): Promise<void>;
|
|
14
|
+
/** POST /api/v1/log-retention-rules/apply — 立即执行一次清理 */
|
|
15
|
+
apply(_req: Request, res: Response): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=retention-rule.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-rule.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/retention-rule.controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAK1D,qBACa,uBAAuB;IAClC,OAAO,KAAK,OAAO,GAElB;IAED,sCAAsC;IAEhC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1D,0CAA0C;IAEpC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IASzD,uCAAuC;IAEjC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD,0CAA0C;IAEpC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxD,6CAA6C;IAEvC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxD,wDAAwD;IAElD,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAIzD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RetentionRuleController = void 0;
|
|
13
|
+
const core_1 = require("@octo-cyber/core");
|
|
14
|
+
const retention_rule_service_js_1 = require("../services/retention-rule.service.js");
|
|
15
|
+
const log_analysis_schema_js_1 = require("../schemas/log-analysis.schema.js");
|
|
16
|
+
let RetentionRuleController = class RetentionRuleController {
|
|
17
|
+
get service() {
|
|
18
|
+
return core_1.Container.get(retention_rule_service_js_1.RetentionRuleService);
|
|
19
|
+
}
|
|
20
|
+
/** GET /api/v1/log-retention-rules */
|
|
21
|
+
async findAll(_req, res) {
|
|
22
|
+
const rules = await this.service.findAll();
|
|
23
|
+
res.json(core_1.ApiResponse.ok(rules));
|
|
24
|
+
}
|
|
25
|
+
/** GET /api/v1/log-retention-rules/:id */
|
|
26
|
+
async findOne(req, res) {
|
|
27
|
+
const rule = await this.service.findById(Number(req.params.id));
|
|
28
|
+
if (!rule) {
|
|
29
|
+
res.status(404).json(core_1.ApiResponse.error('RetentionRule not found', 404));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
res.json(core_1.ApiResponse.ok(rule));
|
|
33
|
+
}
|
|
34
|
+
/** POST /api/v1/log-retention-rules */
|
|
35
|
+
async create(req, res) {
|
|
36
|
+
const dto = (0, core_1.validateSync)(log_analysis_schema_js_1.CreateRetentionRuleSchema, req.body);
|
|
37
|
+
const rule = await this.service.create(dto);
|
|
38
|
+
res.status(201).json(core_1.ApiResponse.ok(rule, 'RetentionRule created'));
|
|
39
|
+
}
|
|
40
|
+
/** PUT /api/v1/log-retention-rules/:id */
|
|
41
|
+
async update(req, res) {
|
|
42
|
+
const dto = (0, core_1.validateSync)(log_analysis_schema_js_1.UpdateRetentionRuleSchema, req.body);
|
|
43
|
+
const rule = await this.service.update(Number(req.params.id), dto);
|
|
44
|
+
res.json(core_1.ApiResponse.ok(rule, 'RetentionRule updated'));
|
|
45
|
+
}
|
|
46
|
+
/** DELETE /api/v1/log-retention-rules/:id */
|
|
47
|
+
async remove(req, res) {
|
|
48
|
+
await this.service.remove(Number(req.params.id));
|
|
49
|
+
res.json(core_1.ApiResponse.ok(null, 'RetentionRule deleted'));
|
|
50
|
+
}
|
|
51
|
+
/** POST /api/v1/log-retention-rules/apply — 立即执行一次清理 */
|
|
52
|
+
async apply(_req, res) {
|
|
53
|
+
const deleted = await this.service.applyRetention();
|
|
54
|
+
res.json(core_1.ApiResponse.ok({ deleted }, `Retention applied, ${deleted} logs removed`));
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.RetentionRuleController = RetentionRuleController;
|
|
58
|
+
__decorate([
|
|
59
|
+
(0, core_1.Get)('/'),
|
|
60
|
+
__metadata("design:type", Function),
|
|
61
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
62
|
+
__metadata("design:returntype", Promise)
|
|
63
|
+
], RetentionRuleController.prototype, "findAll", null);
|
|
64
|
+
__decorate([
|
|
65
|
+
(0, core_1.Get)('/:id'),
|
|
66
|
+
__metadata("design:type", Function),
|
|
67
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
68
|
+
__metadata("design:returntype", Promise)
|
|
69
|
+
], RetentionRuleController.prototype, "findOne", null);
|
|
70
|
+
__decorate([
|
|
71
|
+
(0, core_1.Post)('/'),
|
|
72
|
+
__metadata("design:type", Function),
|
|
73
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
74
|
+
__metadata("design:returntype", Promise)
|
|
75
|
+
], RetentionRuleController.prototype, "create", null);
|
|
76
|
+
__decorate([
|
|
77
|
+
(0, core_1.Put)('/:id'),
|
|
78
|
+
__metadata("design:type", Function),
|
|
79
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
80
|
+
__metadata("design:returntype", Promise)
|
|
81
|
+
], RetentionRuleController.prototype, "update", null);
|
|
82
|
+
__decorate([
|
|
83
|
+
(0, core_1.Delete)('/:id'),
|
|
84
|
+
__metadata("design:type", Function),
|
|
85
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
86
|
+
__metadata("design:returntype", Promise)
|
|
87
|
+
], RetentionRuleController.prototype, "remove", null);
|
|
88
|
+
__decorate([
|
|
89
|
+
(0, core_1.Post)('/apply'),
|
|
90
|
+
__metadata("design:type", Function),
|
|
91
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
92
|
+
__metadata("design:returntype", Promise)
|
|
93
|
+
], RetentionRuleController.prototype, "apply", null);
|
|
94
|
+
exports.RetentionRuleController = RetentionRuleController = __decorate([
|
|
95
|
+
(0, core_1.Controller)('/api/v1/log-retention-rules')
|
|
96
|
+
], RetentionRuleController);
|
|
97
|
+
//# sourceMappingURL=retention-rule.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-rule.controller.js","sourceRoot":"","sources":["../../src/controllers/retention-rule.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { OperationLog, LogLevel, LogAction } from './operation-log.entity.js';
|
|
2
|
+
export { RetentionRule } from './retention-rule.entity.js';
|
|
3
|
+
import { OperationLog } from './operation-log.entity.js';
|
|
4
|
+
import { RetentionRule } from './retention-rule.entity.js';
|
|
5
|
+
export declare const LOG_ANALYSIS_ENTITIES: (typeof OperationLog | typeof RetentionRule)[];
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,eAAO,MAAM,qBAAqB,gDAAgC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LOG_ANALYSIS_ENTITIES = exports.RetentionRule = exports.LogAction = exports.LogLevel = exports.OperationLog = void 0;
|
|
4
|
+
var operation_log_entity_js_1 = require("./operation-log.entity.js");
|
|
5
|
+
Object.defineProperty(exports, "OperationLog", { enumerable: true, get: function () { return operation_log_entity_js_1.OperationLog; } });
|
|
6
|
+
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return operation_log_entity_js_1.LogLevel; } });
|
|
7
|
+
Object.defineProperty(exports, "LogAction", { enumerable: true, get: function () { return operation_log_entity_js_1.LogAction; } });
|
|
8
|
+
var retention_rule_entity_js_1 = require("./retention-rule.entity.js");
|
|
9
|
+
Object.defineProperty(exports, "RetentionRule", { enumerable: true, get: function () { return retention_rule_entity_js_1.RetentionRule; } });
|
|
10
|
+
const operation_log_entity_js_2 = require("./operation-log.entity.js");
|
|
11
|
+
const retention_rule_entity_js_2 = require("./retention-rule.entity.js");
|
|
12
|
+
exports.LOG_ANALYSIS_ENTITIES = [operation_log_entity_js_2.OperationLog, retention_rule_entity_js_2.RetentionRule];
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":";;;AAAA,qEAA8E;AAArE,uHAAA,YAAY,OAAA;AAAE,mHAAA,QAAQ,OAAA;AAAE,oHAAA,SAAS,OAAA;AAC1C,uEAA2D;AAAlD,yHAAA,aAAa,OAAA;AAEtB,uEAAyD;AACzD,yEAA2D;AAE9C,QAAA,qBAAqB,GAAG,CAAC,sCAAY,EAAE,wCAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare enum LogLevel {
|
|
2
|
+
INFO = "INFO",
|
|
3
|
+
WARN = "WARN",
|
|
4
|
+
ERROR = "ERROR"
|
|
5
|
+
}
|
|
6
|
+
export declare enum LogAction {
|
|
7
|
+
CREATE = "CREATE",
|
|
8
|
+
UPDATE = "UPDATE",
|
|
9
|
+
DELETE = "DELETE",
|
|
10
|
+
READ = "READ",
|
|
11
|
+
LOGIN = "LOGIN",
|
|
12
|
+
LOGOUT = "LOGOUT",
|
|
13
|
+
EXPORT = "EXPORT",
|
|
14
|
+
IMPORT = "IMPORT",
|
|
15
|
+
OTHER = "OTHER"
|
|
16
|
+
}
|
|
17
|
+
export declare class OperationLog {
|
|
18
|
+
id: number;
|
|
19
|
+
/** 操作用户 ID,匿名操作为 null */
|
|
20
|
+
userId: number | null;
|
|
21
|
+
/** 操作用户名(快照,避免关联查询) */
|
|
22
|
+
username: string | null;
|
|
23
|
+
/** 操作模块,如 auth / erp / crm */
|
|
24
|
+
module: string;
|
|
25
|
+
/** 操作动作枚举 */
|
|
26
|
+
action: LogAction;
|
|
27
|
+
/** 操作描述(人类可读) */
|
|
28
|
+
description: string;
|
|
29
|
+
/** 请求路径 */
|
|
30
|
+
requestPath: string | null;
|
|
31
|
+
/** HTTP 方法 */
|
|
32
|
+
requestMethod: string | null;
|
|
33
|
+
/** 目标资源 ID */
|
|
34
|
+
resourceId: string | null;
|
|
35
|
+
/** 目标资源类型 */
|
|
36
|
+
resourceType: string | null;
|
|
37
|
+
/** 客户端 IP */
|
|
38
|
+
ip: string | null;
|
|
39
|
+
/** 日志级别 */
|
|
40
|
+
level: LogLevel;
|
|
41
|
+
/** 额外元数据(JSON 字符串) */
|
|
42
|
+
metadata: string | null;
|
|
43
|
+
createdAt: Date;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=operation-log.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-log.entity.d.ts","sourceRoot":"","sources":["../../src/entities/operation-log.entity.ts"],"names":[],"mappings":"AAQA,oBAAY,QAAQ;IAClB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED,oBAAY,SAAS;IACnB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,qBACa,YAAY;IAEvB,EAAE,EAAG,MAAM,CAAC;IAEZ,yBAAyB;IAGzB,MAAM,EAAG,MAAM,GAAG,IAAI,CAAC;IAEvB,uBAAuB;IAEvB,QAAQ,EAAG,MAAM,GAAG,IAAI,CAAC;IAEzB,8BAA8B;IAG9B,MAAM,EAAG,MAAM,CAAC;IAEhB,aAAa;IAGb,MAAM,EAAG,SAAS,CAAC;IAEnB,iBAAiB;IAEjB,WAAW,EAAG,MAAM,CAAC;IAErB,WAAW;IAEX,WAAW,EAAG,MAAM,GAAG,IAAI,CAAC;IAE5B,cAAc;IAEd,aAAa,EAAG,MAAM,GAAG,IAAI,CAAC;IAE9B,cAAc;IAEd,UAAU,EAAG,MAAM,GAAG,IAAI,CAAC;IAE3B,aAAa;IAEb,YAAY,EAAG,MAAM,GAAG,IAAI,CAAC;IAE7B,aAAa;IAEb,EAAE,EAAG,MAAM,GAAG,IAAI,CAAC;IAEnB,WAAW;IAGX,KAAK,EAAG,QAAQ,CAAC;IAEjB,sBAAsB;IAEtB,QAAQ,EAAG,MAAM,GAAG,IAAI,CAAC;IAIzB,SAAS,EAAG,IAAI,CAAC;CAClB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.OperationLog = exports.LogAction = exports.LogLevel = void 0;
|
|
13
|
+
const core_1 = require("@octo-cyber/core");
|
|
14
|
+
var LogLevel;
|
|
15
|
+
(function (LogLevel) {
|
|
16
|
+
LogLevel["INFO"] = "INFO";
|
|
17
|
+
LogLevel["WARN"] = "WARN";
|
|
18
|
+
LogLevel["ERROR"] = "ERROR";
|
|
19
|
+
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
|
20
|
+
var LogAction;
|
|
21
|
+
(function (LogAction) {
|
|
22
|
+
LogAction["CREATE"] = "CREATE";
|
|
23
|
+
LogAction["UPDATE"] = "UPDATE";
|
|
24
|
+
LogAction["DELETE"] = "DELETE";
|
|
25
|
+
LogAction["READ"] = "READ";
|
|
26
|
+
LogAction["LOGIN"] = "LOGIN";
|
|
27
|
+
LogAction["LOGOUT"] = "LOGOUT";
|
|
28
|
+
LogAction["EXPORT"] = "EXPORT";
|
|
29
|
+
LogAction["IMPORT"] = "IMPORT";
|
|
30
|
+
LogAction["OTHER"] = "OTHER";
|
|
31
|
+
})(LogAction || (exports.LogAction = LogAction = {}));
|
|
32
|
+
let OperationLog = class OperationLog {
|
|
33
|
+
id;
|
|
34
|
+
/** 操作用户 ID,匿名操作为 null */
|
|
35
|
+
userId;
|
|
36
|
+
/** 操作用户名(快照,避免关联查询) */
|
|
37
|
+
username;
|
|
38
|
+
/** 操作模块,如 auth / erp / crm */
|
|
39
|
+
module;
|
|
40
|
+
/** 操作动作枚举 */
|
|
41
|
+
action;
|
|
42
|
+
/** 操作描述(人类可读) */
|
|
43
|
+
description;
|
|
44
|
+
/** 请求路径 */
|
|
45
|
+
requestPath;
|
|
46
|
+
/** HTTP 方法 */
|
|
47
|
+
requestMethod;
|
|
48
|
+
/** 目标资源 ID */
|
|
49
|
+
resourceId;
|
|
50
|
+
/** 目标资源类型 */
|
|
51
|
+
resourceType;
|
|
52
|
+
/** 客户端 IP */
|
|
53
|
+
ip;
|
|
54
|
+
/** 日志级别 */
|
|
55
|
+
level;
|
|
56
|
+
/** 额外元数据(JSON 字符串) */
|
|
57
|
+
metadata;
|
|
58
|
+
createdAt;
|
|
59
|
+
};
|
|
60
|
+
exports.OperationLog = OperationLog;
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, core_1.PrimaryGeneratedColumn)(),
|
|
63
|
+
__metadata("design:type", Number)
|
|
64
|
+
], OperationLog.prototype, "id", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
(0, core_1.Index)(),
|
|
67
|
+
(0, core_1.Column)({ type: 'integer', name: 'user_id', nullable: true }),
|
|
68
|
+
__metadata("design:type", Number)
|
|
69
|
+
], OperationLog.prototype, "userId", void 0);
|
|
70
|
+
__decorate([
|
|
71
|
+
(0, core_1.Column)({ type: 'varchar', length: 128, name: 'username', nullable: true }),
|
|
72
|
+
__metadata("design:type", String)
|
|
73
|
+
], OperationLog.prototype, "username", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
(0, core_1.Index)(),
|
|
76
|
+
(0, core_1.Column)({ type: 'varchar', length: 64, name: 'module' }),
|
|
77
|
+
__metadata("design:type", String)
|
|
78
|
+
], OperationLog.prototype, "module", void 0);
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, core_1.Index)(),
|
|
81
|
+
(0, core_1.Column)({ type: 'varchar', length: 32, name: 'action' }),
|
|
82
|
+
__metadata("design:type", String)
|
|
83
|
+
], OperationLog.prototype, "action", void 0);
|
|
84
|
+
__decorate([
|
|
85
|
+
(0, core_1.Column)({ type: 'varchar', length: 512, name: 'description' }),
|
|
86
|
+
__metadata("design:type", String)
|
|
87
|
+
], OperationLog.prototype, "description", void 0);
|
|
88
|
+
__decorate([
|
|
89
|
+
(0, core_1.Column)({ type: 'varchar', length: 512, name: 'request_path', nullable: true }),
|
|
90
|
+
__metadata("design:type", String)
|
|
91
|
+
], OperationLog.prototype, "requestPath", void 0);
|
|
92
|
+
__decorate([
|
|
93
|
+
(0, core_1.Column)({ type: 'varchar', length: 16, name: 'request_method', nullable: true }),
|
|
94
|
+
__metadata("design:type", String)
|
|
95
|
+
], OperationLog.prototype, "requestMethod", void 0);
|
|
96
|
+
__decorate([
|
|
97
|
+
(0, core_1.Column)({ type: 'varchar', length: 256, name: 'resource_id', nullable: true }),
|
|
98
|
+
__metadata("design:type", String)
|
|
99
|
+
], OperationLog.prototype, "resourceId", void 0);
|
|
100
|
+
__decorate([
|
|
101
|
+
(0, core_1.Column)({ type: 'varchar', length: 64, name: 'resource_type', nullable: true }),
|
|
102
|
+
__metadata("design:type", String)
|
|
103
|
+
], OperationLog.prototype, "resourceType", void 0);
|
|
104
|
+
__decorate([
|
|
105
|
+
(0, core_1.Column)({ type: 'varchar', length: 64, name: 'ip', nullable: true }),
|
|
106
|
+
__metadata("design:type", String)
|
|
107
|
+
], OperationLog.prototype, "ip", void 0);
|
|
108
|
+
__decorate([
|
|
109
|
+
(0, core_1.Index)(),
|
|
110
|
+
(0, core_1.Column)({ type: 'varchar', length: 16, name: 'level', default: LogLevel.INFO }),
|
|
111
|
+
__metadata("design:type", String)
|
|
112
|
+
], OperationLog.prototype, "level", void 0);
|
|
113
|
+
__decorate([
|
|
114
|
+
(0, core_1.Column)({ type: 'text', name: 'metadata', nullable: true }),
|
|
115
|
+
__metadata("design:type", String)
|
|
116
|
+
], OperationLog.prototype, "metadata", void 0);
|
|
117
|
+
__decorate([
|
|
118
|
+
(0, core_1.Index)(),
|
|
119
|
+
(0, core_1.CreateDateColumn)({ name: 'created_at' }),
|
|
120
|
+
__metadata("design:type", Date)
|
|
121
|
+
], OperationLog.prototype, "createdAt", void 0);
|
|
122
|
+
exports.OperationLog = OperationLog = __decorate([
|
|
123
|
+
(0, core_1.Entity)('operation_log')
|
|
124
|
+
], OperationLog);
|
|
125
|
+
//# sourceMappingURL=operation-log.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-log.entity.js","sourceRoot":"","sources":["../../src/entities/operation-log.entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** 日志保留规则:超过保留天数的日志会被定期清理 */
|
|
2
|
+
export declare class RetentionRule {
|
|
3
|
+
id: number;
|
|
4
|
+
/** 规则名称 */
|
|
5
|
+
name: string;
|
|
6
|
+
/** 匹配的模块(空表示匹配全部) */
|
|
7
|
+
module: string | null;
|
|
8
|
+
/** 匹配的动作(空表示匹配全部) */
|
|
9
|
+
action: string | null;
|
|
10
|
+
/** 保留天数(0 = 永不删除) */
|
|
11
|
+
retentionDays: number;
|
|
12
|
+
/** 是否启用 */
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
updatedAt: Date;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=retention-rule.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-rule.entity.d.ts","sourceRoot":"","sources":["../../src/entities/retention-rule.entity.ts"],"names":[],"mappings":"AAQA,6BAA6B;AAC7B,qBACa,aAAa;IAExB,EAAE,EAAG,MAAM,CAAC;IAEZ,WAAW;IAEX,IAAI,EAAG,MAAM,CAAC;IAEd,qBAAqB;IAErB,MAAM,EAAG,MAAM,GAAG,IAAI,CAAC;IAEvB,qBAAqB;IAErB,MAAM,EAAG,MAAM,GAAG,IAAI,CAAC;IAEvB,qBAAqB;IAErB,aAAa,EAAG,MAAM,CAAC;IAEvB,WAAW;IAEX,OAAO,EAAG,OAAO,CAAC;IAGlB,SAAS,EAAG,IAAI,CAAC;IAGjB,SAAS,EAAG,IAAI,CAAC;CAClB"}
|
|
@@ -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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RetentionRule = void 0;
|
|
13
|
+
const core_1 = require("@octo-cyber/core");
|
|
14
|
+
/** 日志保留规则:超过保留天数的日志会被定期清理 */
|
|
15
|
+
let RetentionRule = class RetentionRule {
|
|
16
|
+
id;
|
|
17
|
+
/** 规则名称 */
|
|
18
|
+
name;
|
|
19
|
+
/** 匹配的模块(空表示匹配全部) */
|
|
20
|
+
module;
|
|
21
|
+
/** 匹配的动作(空表示匹配全部) */
|
|
22
|
+
action;
|
|
23
|
+
/** 保留天数(0 = 永不删除) */
|
|
24
|
+
retentionDays;
|
|
25
|
+
/** 是否启用 */
|
|
26
|
+
enabled;
|
|
27
|
+
createdAt;
|
|
28
|
+
updatedAt;
|
|
29
|
+
};
|
|
30
|
+
exports.RetentionRule = RetentionRule;
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, core_1.PrimaryGeneratedColumn)(),
|
|
33
|
+
__metadata("design:type", Number)
|
|
34
|
+
], RetentionRule.prototype, "id", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
(0, core_1.Column)({ type: 'varchar', length: 128, name: 'name', unique: true }),
|
|
37
|
+
__metadata("design:type", String)
|
|
38
|
+
], RetentionRule.prototype, "name", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, core_1.Column)({ type: 'varchar', length: 64, name: 'module', nullable: true }),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], RetentionRule.prototype, "module", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, core_1.Column)({ type: 'varchar', length: 32, name: 'action', nullable: true }),
|
|
45
|
+
__metadata("design:type", String)
|
|
46
|
+
], RetentionRule.prototype, "action", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, core_1.Column)({ type: 'integer', name: 'retention_days', default: 90 }),
|
|
49
|
+
__metadata("design:type", Number)
|
|
50
|
+
], RetentionRule.prototype, "retentionDays", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
(0, core_1.Column)({ type: 'boolean', name: 'enabled', default: true }),
|
|
53
|
+
__metadata("design:type", Boolean)
|
|
54
|
+
], RetentionRule.prototype, "enabled", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, core_1.CreateDateColumn)({ name: 'created_at' }),
|
|
57
|
+
__metadata("design:type", Date)
|
|
58
|
+
], RetentionRule.prototype, "createdAt", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, core_1.UpdateDateColumn)({ name: 'updated_at' }),
|
|
61
|
+
__metadata("design:type", Date)
|
|
62
|
+
], RetentionRule.prototype, "updatedAt", void 0);
|
|
63
|
+
exports.RetentionRule = RetentionRule = __decorate([
|
|
64
|
+
(0, core_1.Entity)('log_retention_rule')
|
|
65
|
+
], RetentionRule);
|
|
66
|
+
//# sourceMappingURL=retention-rule.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-rule.entity.js","sourceRoot":"","sources":["../../src/entities/retention-rule.entity.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAM0B;AAE1B,6BAA6B;AAEtB,IAAM,aAAa,GAAnB,MAAM,aAAa;IAExB,EAAE,CAAU;IAEZ,WAAW;IAEX,IAAI,CAAU;IAEd,qBAAqB;IAErB,MAAM,CAAiB;IAEvB,qBAAqB;IAErB,MAAM,CAAiB;IAEvB,qBAAqB;IAErB,aAAa,CAAU;IAEvB,WAAW;IAEX,OAAO,CAAW;IAGlB,SAAS,CAAQ;IAGjB,SAAS,CAAQ;CAClB,CAAA;AA7BY,sCAAa;AAExB;IADC,IAAA,6BAAsB,GAAE;;yCACb;AAIZ;IADC,IAAA,aAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;2CACvD;AAId;IADC,IAAA,aAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;6CACjD;AAIvB;IADC,IAAA,aAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;6CACjD;AAIvB;IADC,IAAA,aAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;oDAC1C;AAIvB;IADC,IAAA,aAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;8CAC1C;AAGlB;IADC,IAAA,uBAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC7B,IAAI;gDAAC;AAGjB;IADC,IAAA,uBAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;8BAC7B,IAAI;gDAAC;wBA5BN,aAAa;IADzB,IAAA,aAAM,EAAC,oBAAoB,CAAC;GAChB,aAAa,CA6BzB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @octo-cyber/log-analysis — Operation log recording, querying, and analysis module.
|
|
3
|
+
*
|
|
4
|
+
* Backend entry point. Do NOT import from this file in front-end code;
|
|
5
|
+
* use the './web' export path instead.
|
|
6
|
+
*/
|
|
7
|
+
export { LogAnalysisModule } from './log-analysis.module.js';
|
|
8
|
+
export { OperationLog, LogLevel, LogAction, RetentionRule, LOG_ANALYSIS_ENTITIES, } from './entities/index.js';
|
|
9
|
+
export { LogWriterService } from './services/log-writer.service.js';
|
|
10
|
+
export { LogQueryService } from './services/log-query.service.js';
|
|
11
|
+
export type { LogQueryResult, LogStats } from './services/log-query.service.js';
|
|
12
|
+
export { RetentionRuleService } from './services/retention-rule.service.js';
|
|
13
|
+
export { LogAnalysisController } from './controllers/log-analysis.controller.js';
|
|
14
|
+
export { RetentionRuleController } from './controllers/retention-rule.controller.js';
|
|
15
|
+
export { WriteLogSchema, QueryLogSchema, CreateRetentionRuleSchema, UpdateRetentionRuleSchema, } from './schemas/log-analysis.schema.js';
|
|
16
|
+
export type { WriteLogDto, QueryLogDto, CreateRetentionRuleDto, UpdateRetentionRuleDto, } from './schemas/log-analysis.schema.js';
|
|
17
|
+
export declare const version = "0.1.0";
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,aAAa,EACb,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAG5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAGrF,OAAO,EACL,cAAc,EACd,cAAc,EACd,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACV,WAAW,EACX,WAAW,EACX,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,kCAAkC,CAAC;AAE1C,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @octo-cyber/log-analysis — Operation log recording, querying, and analysis module.
|
|
4
|
+
*
|
|
5
|
+
* Backend entry point. Do NOT import from this file in front-end code;
|
|
6
|
+
* use the './web' export path instead.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.version = exports.UpdateRetentionRuleSchema = exports.CreateRetentionRuleSchema = exports.QueryLogSchema = exports.WriteLogSchema = exports.RetentionRuleController = exports.LogAnalysisController = exports.RetentionRuleService = exports.LogQueryService = exports.LogWriterService = exports.LOG_ANALYSIS_ENTITIES = exports.RetentionRule = exports.LogAction = exports.LogLevel = exports.OperationLog = exports.LogAnalysisModule = void 0;
|
|
10
|
+
// -- Module --
|
|
11
|
+
var log_analysis_module_js_1 = require("./log-analysis.module.js");
|
|
12
|
+
Object.defineProperty(exports, "LogAnalysisModule", { enumerable: true, get: function () { return log_analysis_module_js_1.LogAnalysisModule; } });
|
|
13
|
+
// -- Entities --
|
|
14
|
+
var index_js_1 = require("./entities/index.js");
|
|
15
|
+
Object.defineProperty(exports, "OperationLog", { enumerable: true, get: function () { return index_js_1.OperationLog; } });
|
|
16
|
+
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return index_js_1.LogLevel; } });
|
|
17
|
+
Object.defineProperty(exports, "LogAction", { enumerable: true, get: function () { return index_js_1.LogAction; } });
|
|
18
|
+
Object.defineProperty(exports, "RetentionRule", { enumerable: true, get: function () { return index_js_1.RetentionRule; } });
|
|
19
|
+
Object.defineProperty(exports, "LOG_ANALYSIS_ENTITIES", { enumerable: true, get: function () { return index_js_1.LOG_ANALYSIS_ENTITIES; } });
|
|
20
|
+
// -- Services (SPI) --
|
|
21
|
+
var log_writer_service_js_1 = require("./services/log-writer.service.js");
|
|
22
|
+
Object.defineProperty(exports, "LogWriterService", { enumerable: true, get: function () { return log_writer_service_js_1.LogWriterService; } });
|
|
23
|
+
var log_query_service_js_1 = require("./services/log-query.service.js");
|
|
24
|
+
Object.defineProperty(exports, "LogQueryService", { enumerable: true, get: function () { return log_query_service_js_1.LogQueryService; } });
|
|
25
|
+
var retention_rule_service_js_1 = require("./services/retention-rule.service.js");
|
|
26
|
+
Object.defineProperty(exports, "RetentionRuleService", { enumerable: true, get: function () { return retention_rule_service_js_1.RetentionRuleService; } });
|
|
27
|
+
// -- Controllers --
|
|
28
|
+
var log_analysis_controller_js_1 = require("./controllers/log-analysis.controller.js");
|
|
29
|
+
Object.defineProperty(exports, "LogAnalysisController", { enumerable: true, get: function () { return log_analysis_controller_js_1.LogAnalysisController; } });
|
|
30
|
+
var retention_rule_controller_js_1 = require("./controllers/retention-rule.controller.js");
|
|
31
|
+
Object.defineProperty(exports, "RetentionRuleController", { enumerable: true, get: function () { return retention_rule_controller_js_1.RetentionRuleController; } });
|
|
32
|
+
// -- Schemas / DTOs --
|
|
33
|
+
var log_analysis_schema_js_1 = require("./schemas/log-analysis.schema.js");
|
|
34
|
+
Object.defineProperty(exports, "WriteLogSchema", { enumerable: true, get: function () { return log_analysis_schema_js_1.WriteLogSchema; } });
|
|
35
|
+
Object.defineProperty(exports, "QueryLogSchema", { enumerable: true, get: function () { return log_analysis_schema_js_1.QueryLogSchema; } });
|
|
36
|
+
Object.defineProperty(exports, "CreateRetentionRuleSchema", { enumerable: true, get: function () { return log_analysis_schema_js_1.CreateRetentionRuleSchema; } });
|
|
37
|
+
Object.defineProperty(exports, "UpdateRetentionRuleSchema", { enumerable: true, get: function () { return log_analysis_schema_js_1.UpdateRetentionRuleSchema; } });
|
|
38
|
+
exports.version = '0.1.0';
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,eAAe;AACf,mEAA6D;AAApD,2HAAA,iBAAiB,OAAA;AAE1B,iBAAiB;AACjB,gDAM6B;AAL3B,wGAAA,YAAY,OAAA;AACZ,oGAAA,QAAQ,OAAA;AACR,qGAAA,SAAS,OAAA;AACT,yGAAA,aAAa,OAAA;AACb,iHAAA,qBAAqB,OAAA;AAGvB,uBAAuB;AACvB,0EAAoE;AAA3D,yHAAA,gBAAgB,OAAA;AACzB,wEAAkE;AAAzD,uHAAA,eAAe,OAAA;AAExB,kFAA4E;AAAnE,iIAAA,oBAAoB,OAAA;AAE7B,oBAAoB;AACpB,uFAAiF;AAAxE,mIAAA,qBAAqB,OAAA;AAC9B,2FAAqF;AAA5E,uIAAA,uBAAuB,OAAA;AAEhC,uBAAuB;AACvB,2EAK0C;AAJxC,wHAAA,cAAc,OAAA;AACd,wHAAA,cAAc,OAAA;AACd,mIAAA,yBAAyB,OAAA;AACzB,mIAAA,yBAAyB,OAAA;AASd,QAAA,OAAO,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IModule, IModuleContext } from '@octo-cyber/core';
|
|
2
|
+
import type { Express } from '@octo-cyber/core';
|
|
3
|
+
/**
|
|
4
|
+
* Log Analysis module — operation log recording, querying, and retention management.
|
|
5
|
+
*
|
|
6
|
+
* Provides:
|
|
7
|
+
* - LogWriterService: other modules call this to record operation logs
|
|
8
|
+
* - Log query with filtering and pagination
|
|
9
|
+
* - Statistical analysis (by action, module, level, daily trend)
|
|
10
|
+
* - Retention rules to auto-clean expired logs
|
|
11
|
+
*/
|
|
12
|
+
export declare class LogAnalysisModule implements IModule {
|
|
13
|
+
readonly name = "log-analysis";
|
|
14
|
+
readonly entities: (typeof import("./entities/operation-log.entity.js").OperationLog | typeof import("./entities/retention-rule.entity.js").RetentionRule)[];
|
|
15
|
+
initialize(_context: IModuleContext): void;
|
|
16
|
+
registerRoutes(app: Express, _context: IModuleContext): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=log-analysis.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-analysis.module.d.ts","sourceRoot":"","sources":["../src/log-analysis.module.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAUhD;;;;;;;;GAQG;AACH,qBAAa,iBAAkB,YAAW,OAAO;IAC/C,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,4IAA8B;IAE/C,UAAU,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAU1C,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;CAc7D"}
|