create-dp-koa 1.1.2 → 1.1.4
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/package.json +1 -1
- package/template/.cursor/rules/00-backend-core.skill.md +1 -1
- package/template/.cursor/rules/01-backend-skill-router.skill.md +8 -2
- package/template/.cursor/rules/10-backend-api.skill.md +8 -0
- package/template/.cursor/rules/11-backend-controller-recipes.skill.md +12 -9
- package/template/.cursor/rules/21-backend-service.skill.md +14 -0
- package/template/.cursor/rules/30-backend-validation.skill.md +1 -1
- package/template/.cursor/rules/40-backend-error-logging.skill.md +9 -5
- package/template/.cursor/rules/50-backend-bootstrap-lifecycle.skill.md +4 -4
- package/template/.cursor/rules/60-backend-router-registration.skill.md +16 -6
- package/template/.cursor/rules/70-backend-middleware.skill.md +2 -2
- package/template/.cursor/rules/80-backend-utils-and-libs.skill.md +71 -14
- package/template/.cursor/rules/85-backend-plugins.rule.md +4 -4
- package/template/.cursor/rules/90-backend-testing.skill.md +26 -0
- package/template/.cursor/rules/README.md +2 -2
- package/template/.trae/skills/11-backend-controller-recipes.skill.md +12 -9
- package/template/.trae/skills/21-backend-service.skill.md +15 -1
- package/template/.trae/skills/40-backend-error-logging.skill.md +9 -5
- package/template/.trae/skills/80-backend-utils-and-libs.skill.md +77 -8
- package/template/.trae/skills/90-backend-testing.skill.md +26 -0
- package/template/scripts/sync-template.mjs +20 -0
- package/template/src/app.ts +1 -2
- package/template/src/{framework/plugins → plugins}/registry.ts +2 -2
- package/template/src/plugins/weboffice/http/routes.ts +1 -1
- package/template/src/plugins/weboffice/index.ts +3 -3
- package/template/src/plugins/weboffice/services/webofficeCallback.service.ts +3 -4
- package/template/src/types/ctxState.ts +9 -0
- package/template/src/utils/testDataInitializer.ts +1 -1
- package/template/tsconfig.json +6 -0
- package/template/src/annotations/decorators/ConfigManagement.ts +0 -9
- package/template/src/annotations/decorators/DistributedTracing.ts +0 -9
- package/template/src/annotations/decorators/EnterprisePerformance.ts +0 -9
- package/template/src/annotations/decorators/PerformanceMonitor.ts +0 -32
- package/template/src/annotations/decorators/SecurityAudit.ts +0 -9
- package/template/src/annotations/index.ts +0 -50
- package/template/src/annotations/processors/ConfigManagementProcessor.ts +0 -369
- package/template/src/annotations/processors/DistributedTracingProcessor.ts +0 -288
- package/template/src/annotations/processors/EnterprisePerformanceProcessor.ts +0 -189
- package/template/src/annotations/processors/PerformanceMonitorProcessor.ts +0 -101
- package/template/src/annotations/processors/SecurityAuditProcessor.ts +0 -345
- package/template/src/annotations/processors/SwaggerProcessor.ts +0 -612
- package/template/src/annotations/processors/index.ts +0 -10
- package/template/src/examples/InterceptorExampleRunner.ts +0 -284
- package/template/src/examples/ServiceInterceptorExample.ts +0 -214
- package/template/src/examples/cacheExamples.ts +0 -155
- package/template/src/framework/decorator/controller.ts +0 -311
- package/template/src/framework/decorator/processor/AnnotationDecorators.ts +0 -100
- package/template/src/framework/decorator/processor/AnnotationProcessor.ts +0 -160
- package/template/src/framework/decorator/processor/AnnotationProcessorConfig.ts +0 -45
- package/template/src/framework/decorator/processor/AnnotationRegistry.ts +0 -117
- package/template/src/framework/decorator/processor/AnnotationSystemInitializer.ts +0 -95
- package/template/src/framework/decorator/processor/ProcessorManager.ts +0 -76
- package/template/src/framework/decorator/processor/processors/CustomProcessors.ts +0 -126
- package/template/src/framework/decorator/processor/processors/DefaultProcessors.ts +0 -207
- package/template/src/framework/decorator/refactored/DecoratorFactory.ts +0 -99
- package/template/src/framework/decorator/refactored/DecoratorMetadataManager.ts +0 -125
- package/template/src/framework/decorator/refactored/DecoratorValidator.ts +0 -128
- package/template/src/framework/decorator/refactored/TypeSafeDecorators.ts +0 -139
- package/template/src/framework/decorator/refactored/index.ts +0 -98
- package/template/src/framework/decorator/swagger.ts +0 -150
- package/template/src/framework/interceptors/AdvancedServiceCallInterceptor.ts +0 -375
- package/template/src/framework/interceptors/ServiceCallInterceptor.ts +0 -348
- package/template/src/framework/interceptors/index.ts +0 -19
- package/template/src/framework/plugins/types.ts +0 -15
- package/template/src/framework/types/ServiceResult.ts +0 -151
- package/template/src/framework/types/index.ts +0 -16
- package/template/src/framework/utils/CacheManager.ts +0 -430
- package/template/src/framework/utils/CacheService.ts +0 -248
- package/template/src/framework/utils/DtoValidator.ts +0 -164
- package/template/src/framework/utils/MigrationHelper.ts +0 -179
- package/template/src/framework/utils/MigrationManager.ts +0 -256
- package/template/src/framework/utils/NewRouter.ts +0 -207
- package/template/src/framework/utils/TransactionManager.ts +0 -172
- package/template/src/framework/utils/bootstrap.ts +0 -445
- package/template/src/framework/utils/cache.ts +0 -269
- package/template/src/framework/utils/databaseConfig.ts +0 -148
- package/template/src/framework/utils/db.ts +0 -39
- package/template/src/framework/utils/dbMonitor.ts +0 -106
- package/template/src/framework/utils/function.ts +0 -61
- package/template/src/framework/utils/gracefulShutdown.ts +0 -131
- package/template/src/framework/utils/logger.ts +0 -388
- package/template/src/framework/utils/metrics.ts +0 -182
- package/template/src/framework/utils/router.ts +0 -417
- package/template/src/framework/utils/swagger.ts +0 -184
- package/template/src/framework/utils/testDb.ts +0 -19
- package/template/src/framework/utils/token.ts +0 -23
- package/template/src/framework/utils/transform.ts +0 -17
- package/template/src/libs/aokEmailSender.ts +0 -42
- package/template/src/libs/captcha.ts +0 -37
- package/template/src/libs/cos.ts +0 -45
- package/template/src/libs/mCache.ts +0 -7
- package/template/src/libs/serviceValidate.ts +0 -3
- package/template/src/libs/tecentSms.ts +0 -51
- package/template/src/middlewares/a.middleware.ts +0 -6
- package/template/src/middlewares/error.middleware.ts +0 -14
- package/template/src/middlewares/logging.middleware.ts +0 -187
- package/template/src/middlewares/static.middleware.ts +0 -79
- package/template/src/middlewares/swagger.middleware.ts +0 -70
- package/template/src/middlewares/token.middleware.ts +0 -32
- package/template/src/migrations/1700000000000-InitialDatabaseStructure.ts +0 -172
- package/template/src/migrations/index.ts +0 -6
- package/template/src/repository/base/BaseRepository.ts +0 -124
- package/template/src/repository/interfaces/IBaseRepository.ts +0 -67
- package/template/src/service/base.service.ts +0 -116
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 企业级性能监控注解处理器
|
|
3
|
-
* 提供详细的性能指标、监控和告警
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Context } from 'koa';
|
|
7
|
-
import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
|
|
8
|
-
import { logger } from '@src/framework/utils/logger';
|
|
9
|
-
|
|
10
|
-
export interface PerformanceMetrics {
|
|
11
|
-
executionTime: number;
|
|
12
|
-
memoryUsage: {
|
|
13
|
-
rss: number;
|
|
14
|
-
heapUsed: number;
|
|
15
|
-
heapTotal: number;
|
|
16
|
-
external: number;
|
|
17
|
-
};
|
|
18
|
-
cpuUsage?: number;
|
|
19
|
-
requestSize?: number;
|
|
20
|
-
responseSize?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface PerformanceConfig {
|
|
24
|
-
maxExecutionTime?: number;
|
|
25
|
-
maxMemoryUsage?: number;
|
|
26
|
-
enableMetrics?: boolean;
|
|
27
|
-
enableAlerts?: boolean;
|
|
28
|
-
alertThresholds?: {
|
|
29
|
-
executionTime?: number;
|
|
30
|
-
memoryUsage?: number;
|
|
31
|
-
errorRate?: number;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class EnterprisePerformanceProcessor implements AnnotationProcessor {
|
|
36
|
-
readonly name = 'EnterprisePerformance';
|
|
37
|
-
readonly priority = 1; // 最高优先级
|
|
38
|
-
|
|
39
|
-
private metrics: Map<string, PerformanceMetrics[]> = new Map();
|
|
40
|
-
private alertThresholds: Map<string, PerformanceConfig> = new Map();
|
|
41
|
-
|
|
42
|
-
async process(
|
|
43
|
-
ctx: Context,
|
|
44
|
-
controller: any,
|
|
45
|
-
methodName: string,
|
|
46
|
-
annotationData: PerformanceConfig,
|
|
47
|
-
callParams: any[]
|
|
48
|
-
): Promise<boolean> {
|
|
49
|
-
const startTime = process.hrtime.bigint();
|
|
50
|
-
const startMemory = process.memoryUsage();
|
|
51
|
-
const startCpu = process.cpuUsage();
|
|
52
|
-
|
|
53
|
-
// 存储性能监控数据
|
|
54
|
-
ctx.state.performanceMonitor = {
|
|
55
|
-
startTime,
|
|
56
|
-
startMemory,
|
|
57
|
-
startCpu,
|
|
58
|
-
methodName: `${controller.constructor.name}.${methodName}`,
|
|
59
|
-
config: annotationData || {},
|
|
60
|
-
requestSize: ctx.request.length || 0
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// 记录开始时间
|
|
64
|
-
logger.info(`[${this.name}] 开始性能监控: ${controller.constructor.name}.${methodName}`);
|
|
65
|
-
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async postProcess(
|
|
70
|
-
ctx: Context,
|
|
71
|
-
controller: any,
|
|
72
|
-
methodName: string,
|
|
73
|
-
response: any
|
|
74
|
-
): Promise<void> {
|
|
75
|
-
const monitor = ctx.state.performanceMonitor;
|
|
76
|
-
if (!monitor) return;
|
|
77
|
-
|
|
78
|
-
const endTime = process.hrtime.bigint();
|
|
79
|
-
const endMemory = process.memoryUsage();
|
|
80
|
-
const endCpu = process.cpuUsage();
|
|
81
|
-
|
|
82
|
-
// 计算性能指标
|
|
83
|
-
const executionTime = Number(endTime - monitor.startTime) / 1000000; // 毫秒
|
|
84
|
-
const memoryDelta = {
|
|
85
|
-
rss: endMemory.rss - monitor.startMemory.rss,
|
|
86
|
-
heapUsed: endMemory.heapUsed - monitor.startMemory.heapUsed,
|
|
87
|
-
heapTotal: endMemory.heapTotal - monitor.startMemory.heapTotal,
|
|
88
|
-
external: endMemory.external - monitor.startMemory.external
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const cpuDelta = {
|
|
92
|
-
user: endCpu.user - monitor.startCpu.user,
|
|
93
|
-
system: endCpu.system - monitor.startCpu.system
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const metrics: PerformanceMetrics = {
|
|
97
|
-
executionTime,
|
|
98
|
-
memoryUsage: memoryDelta,
|
|
99
|
-
cpuUsage: (cpuDelta.user + cpuDelta.system) / 1000000, // 微秒转毫秒
|
|
100
|
-
requestSize: monitor.requestSize,
|
|
101
|
-
responseSize: JSON.stringify(response).length
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// 存储指标
|
|
105
|
-
this.storeMetrics(monitor.methodName, metrics);
|
|
106
|
-
|
|
107
|
-
// 检查告警阈值
|
|
108
|
-
this.checkAlerts(monitor.methodName, metrics, monitor.config);
|
|
109
|
-
|
|
110
|
-
// 记录性能日志
|
|
111
|
-
logger.info(`[${this.name}] 性能指标: ${monitor.methodName}`, {
|
|
112
|
-
executionTime: `${executionTime.toFixed(2)}ms`,
|
|
113
|
-
memoryUsage: `${(memoryDelta.heapUsed / 1024 / 1024).toFixed(2)}MB`,
|
|
114
|
-
cpuUsage: `${metrics.cpuUsage?.toFixed(2)}ms`,
|
|
115
|
-
requestSize: `${metrics.requestSize}B`,
|
|
116
|
-
responseSize: `${metrics.responseSize}B`
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// 清理上下文
|
|
120
|
-
delete ctx.state.performanceMonitor;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private storeMetrics(methodName: string, metrics: PerformanceMetrics): void {
|
|
124
|
-
if (!this.metrics.has(methodName)) {
|
|
125
|
-
this.metrics.set(methodName, []);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const methodMetrics = this.metrics.get(methodName)!;
|
|
129
|
-
methodMetrics.push(metrics);
|
|
130
|
-
|
|
131
|
-
// 只保留最近100条记录
|
|
132
|
-
if (methodMetrics.length > 100) {
|
|
133
|
-
methodMetrics.shift();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private checkAlerts(methodName: string, metrics: PerformanceMetrics, config: PerformanceConfig): void {
|
|
138
|
-
const thresholds = config.alertThresholds || {};
|
|
139
|
-
|
|
140
|
-
// 执行时间告警
|
|
141
|
-
if (thresholds.executionTime && metrics.executionTime > thresholds.executionTime) {
|
|
142
|
-
logger.warn(`[${this.name}] ⚠️ 执行时间告警: ${methodName}`, {
|
|
143
|
-
executionTime: `${metrics.executionTime.toFixed(2)}ms`,
|
|
144
|
-
threshold: `${thresholds.executionTime}ms`
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// 内存使用告警
|
|
149
|
-
if (thresholds.memoryUsage && Math.abs(metrics.memoryUsage.heapUsed) > thresholds.memoryUsage * 1024 * 1024) {
|
|
150
|
-
logger.warn(`[${this.name}] ⚠️ 内存使用告警: ${methodName}`, {
|
|
151
|
-
memoryUsage: `${(metrics.memoryUsage.heapUsed / 1024 / 1024).toFixed(2)}MB`,
|
|
152
|
-
threshold: `${thresholds.memoryUsage}MB`
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* 获取性能统计
|
|
159
|
-
*/
|
|
160
|
-
getPerformanceStats(methodName?: string): any {
|
|
161
|
-
if (methodName) {
|
|
162
|
-
const metrics = this.metrics.get(methodName) || [];
|
|
163
|
-
return this.calculateStats(metrics);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const allStats: any = {};
|
|
167
|
-
this.metrics.forEach((metrics, name) => {
|
|
168
|
-
allStats[name] = this.calculateStats(metrics);
|
|
169
|
-
});
|
|
170
|
-
return allStats;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
private calculateStats(metrics: PerformanceMetrics[]): any {
|
|
174
|
-
if (metrics.length === 0) return null;
|
|
175
|
-
|
|
176
|
-
const executionTimes = metrics.map(m => m.executionTime);
|
|
177
|
-
const memoryUsages = metrics.map(m => m.memoryUsage.heapUsed);
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
count: metrics.length,
|
|
181
|
-
avgExecutionTime: executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length,
|
|
182
|
-
maxExecutionTime: Math.max(...executionTimes),
|
|
183
|
-
minExecutionTime: Math.min(...executionTimes),
|
|
184
|
-
avgMemoryUsage: memoryUsages.reduce((a, b) => a + b, 0) / memoryUsages.length,
|
|
185
|
-
maxMemoryUsage: Math.max(...memoryUsages),
|
|
186
|
-
minMemoryUsage: Math.min(...memoryUsages)
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { Context } from 'koa';
|
|
2
|
-
import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
|
|
3
|
-
import { isDebug } from '@src/framework/utils/function';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 性能监控注解处理器
|
|
7
|
-
* 监控方法执行时间、内存使用等性能指标
|
|
8
|
-
*/
|
|
9
|
-
export class PerformanceMonitorProcessor implements AnnotationProcessor {
|
|
10
|
-
readonly name = 'PerformanceMonitor';
|
|
11
|
-
readonly priority = 8; // 高优先级,在日志记录之前执行
|
|
12
|
-
|
|
13
|
-
async process(
|
|
14
|
-
ctx: Context,
|
|
15
|
-
controller: any,
|
|
16
|
-
methodName: string,
|
|
17
|
-
annotationData: any,
|
|
18
|
-
callParams: any[]
|
|
19
|
-
): Promise<boolean> {
|
|
20
|
-
const startTime = process.hrtime.bigint();
|
|
21
|
-
const startMemory = process.memoryUsage();
|
|
22
|
-
|
|
23
|
-
// 只在调试模式下输出详细日志
|
|
24
|
-
if (isDebug()) {
|
|
25
|
-
console.log(`[${this.name}] 开始性能监控: ${controller.constructor.name}.${methodName}`);
|
|
26
|
-
console.log(`[${this.name}] 配置参数:`, annotationData);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// 将性能监控数据存储到上下文中
|
|
30
|
-
ctx.state.performanceMonitor = {
|
|
31
|
-
startTime,
|
|
32
|
-
startMemory,
|
|
33
|
-
methodName: `${controller.constructor.name}.${methodName}`,
|
|
34
|
-
config: annotationData || {}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 后置处理方法
|
|
42
|
-
* 在控制器方法执行完成后自动调用
|
|
43
|
-
*/
|
|
44
|
-
async postProcess(
|
|
45
|
-
ctx: Context,
|
|
46
|
-
controller: any,
|
|
47
|
-
methodName: string,
|
|
48
|
-
response: any
|
|
49
|
-
): Promise<void> {
|
|
50
|
-
this.logPerformance(ctx);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* 记录性能监控结果
|
|
55
|
-
*/
|
|
56
|
-
private logPerformance(ctx: Context): void {
|
|
57
|
-
const monitor = ctx.state.performanceMonitor;
|
|
58
|
-
if (!monitor) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const endTime = process.hrtime.bigint();
|
|
63
|
-
const endMemory = process.memoryUsage();
|
|
64
|
-
|
|
65
|
-
// 计算执行时间(纳秒转毫秒)
|
|
66
|
-
const executionTime = Number(endTime - monitor.startTime) / 1000000;
|
|
67
|
-
|
|
68
|
-
// 计算内存使用变化
|
|
69
|
-
const memoryDelta = {
|
|
70
|
-
rss: endMemory.rss - monitor.startMemory.rss,
|
|
71
|
-
heapUsed: endMemory.heapUsed - monitor.startMemory.heapUsed,
|
|
72
|
-
heapTotal: endMemory.heapTotal - monitor.startMemory.heapTotal,
|
|
73
|
-
external: endMemory.external - monitor.startMemory.external
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// 只在调试模式下输出详细日志
|
|
77
|
-
if (isDebug()) {
|
|
78
|
-
console.log(`[PerformanceMonitor] 性能监控结果: ${monitor.methodName}`);
|
|
79
|
-
console.log(`[PerformanceMonitor] 执行时间: ${executionTime.toFixed(2)}ms`);
|
|
80
|
-
console.log(`[PerformanceMonitor] 内存使用变化:`, {
|
|
81
|
-
rss: `${(memoryDelta.rss / 1024 / 1024).toFixed(2)}MB`,
|
|
82
|
-
heapUsed: `${(memoryDelta.heapUsed / 1024 / 1024).toFixed(2)}MB`,
|
|
83
|
-
heapTotal: `${(memoryDelta.heapTotal / 1024 / 1024).toFixed(2)}MB`,
|
|
84
|
-
external: `${(memoryDelta.external / 1024 / 1024).toFixed(2)}MB`
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 性能警告(始终输出)
|
|
89
|
-
const config = monitor.config;
|
|
90
|
-
if (config.maxExecutionTime && executionTime > config.maxExecutionTime) {
|
|
91
|
-
console.warn(`[PerformanceMonitor] ⚠️ 执行时间超过阈值: ${executionTime.toFixed(2)}ms > ${config.maxExecutionTime}ms`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (config.maxMemoryUsage && Math.abs(memoryDelta.heapUsed) > config.maxMemoryUsage * 1024 * 1024) {
|
|
95
|
-
console.warn(`[PerformanceMonitor] ⚠️ 内存使用变化过大: ${(memoryDelta.heapUsed / 1024 / 1024).toFixed(2)}MB`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 清理上下文
|
|
99
|
-
delete ctx.state.performanceMonitor;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 企业级安全审计注解处理器
|
|
3
|
-
* 提供安全事件记录、审计日志和合规性检查
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Context } from 'koa';
|
|
7
|
-
import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
|
|
8
|
-
import { logger } from '@src/framework/utils/logger';
|
|
9
|
-
|
|
10
|
-
export interface SecurityAuditConfig {
|
|
11
|
-
enableAudit?: boolean;
|
|
12
|
-
logLevel?: 'info' | 'warn' | 'error';
|
|
13
|
-
includeRequestData?: boolean;
|
|
14
|
-
includeResponseData?: boolean;
|
|
15
|
-
sensitiveFields?: string[];
|
|
16
|
-
complianceMode?: 'GDPR' | 'SOX' | 'HIPAA' | 'PCI-DSS';
|
|
17
|
-
retentionDays?: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface SecurityEvent {
|
|
21
|
-
timestamp: string;
|
|
22
|
-
userId?: string;
|
|
23
|
-
sessionId?: string;
|
|
24
|
-
ipAddress: string;
|
|
25
|
-
userAgent: string;
|
|
26
|
-
method: string;
|
|
27
|
-
url: string;
|
|
28
|
-
controller: string;
|
|
29
|
-
action: string;
|
|
30
|
-
requestData?: any;
|
|
31
|
-
responseData?: any;
|
|
32
|
-
securityLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
|
|
33
|
-
eventType: 'AUTHENTICATION' | 'AUTHORIZATION' | 'DATA_ACCESS' | 'DATA_MODIFICATION' | 'SYSTEM_ACCESS';
|
|
34
|
-
riskScore: number;
|
|
35
|
-
complianceFlags: string[];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export class SecurityAuditProcessor implements AnnotationProcessor {
|
|
39
|
-
readonly name = 'SecurityAudit';
|
|
40
|
-
readonly priority = 2; // 高优先级
|
|
41
|
-
|
|
42
|
-
private auditLog: SecurityEvent[] = [];
|
|
43
|
-
private complianceRules: Map<string, any> = new Map();
|
|
44
|
-
|
|
45
|
-
constructor() {
|
|
46
|
-
this.initializeComplianceRules();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async process(
|
|
50
|
-
ctx: Context,
|
|
51
|
-
controller: any,
|
|
52
|
-
methodName: string,
|
|
53
|
-
annotationData: SecurityAuditConfig,
|
|
54
|
-
callParams: any[]
|
|
55
|
-
): Promise<boolean> {
|
|
56
|
-
if (!annotationData?.enableAudit) return true;
|
|
57
|
-
|
|
58
|
-
const config = annotationData;
|
|
59
|
-
|
|
60
|
-
// 创建安全事件
|
|
61
|
-
const securityEvent: SecurityEvent = {
|
|
62
|
-
timestamp: new Date().toISOString(),
|
|
63
|
-
userId: ctx.state.user?.id,
|
|
64
|
-
sessionId: ctx.state.sessionId,
|
|
65
|
-
ipAddress: ctx.ip || ctx.request.ip,
|
|
66
|
-
userAgent: ctx.get('User-Agent') || '',
|
|
67
|
-
method: ctx.method,
|
|
68
|
-
url: ctx.url,
|
|
69
|
-
controller: controller.constructor.name,
|
|
70
|
-
action: methodName,
|
|
71
|
-
securityLevel: this.determineSecurityLevel(controller, methodName),
|
|
72
|
-
eventType: this.determineEventType(controller, methodName),
|
|
73
|
-
riskScore: this.calculateRiskScore(ctx, controller, methodName),
|
|
74
|
-
complianceFlags: this.checkCompliance(ctx, config)
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// 添加请求数据(如果配置允许)
|
|
78
|
-
if (config.includeRequestData) {
|
|
79
|
-
securityEvent.requestData = this.sanitizeData(ctx.request.body, config.sensitiveFields);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// 存储事件
|
|
83
|
-
this.auditLog.push(securityEvent);
|
|
84
|
-
|
|
85
|
-
// 记录审计日志
|
|
86
|
-
this.logSecurityEvent(securityEvent, config.logLevel || 'info');
|
|
87
|
-
|
|
88
|
-
// 检查高风险操作
|
|
89
|
-
if (securityEvent.riskScore > 7) {
|
|
90
|
-
this.handleHighRiskEvent(securityEvent);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async postProcess(
|
|
97
|
-
ctx: Context,
|
|
98
|
-
controller: any,
|
|
99
|
-
methodName: string,
|
|
100
|
-
response: any
|
|
101
|
-
): Promise<void> {
|
|
102
|
-
// 更新最后的安全事件
|
|
103
|
-
const lastEvent = this.auditLog[this.auditLog.length - 1];
|
|
104
|
-
if (lastEvent && lastEvent.controller === controller.constructor.name && lastEvent.action === methodName) {
|
|
105
|
-
lastEvent.responseData = this.sanitizeData(response, []);
|
|
106
|
-
|
|
107
|
-
// 检查响应中的敏感数据泄露
|
|
108
|
-
this.checkDataLeakage(lastEvent);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
private determineSecurityLevel(controller: any, methodName: string): SecurityEvent['securityLevel'] {
|
|
113
|
-
const controllerName = controller.constructor.name.toLowerCase();
|
|
114
|
-
const method = methodName.toLowerCase();
|
|
115
|
-
|
|
116
|
-
// 高风险操作
|
|
117
|
-
if (method.includes('delete') || method.includes('remove') || method.includes('destroy')) {
|
|
118
|
-
return 'CRITICAL';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// 中等风险操作
|
|
122
|
-
if (method.includes('update') || method.includes('modify') || method.includes('change')) {
|
|
123
|
-
return 'HIGH';
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// 低风险操作
|
|
127
|
-
if (method.includes('get') || method.includes('list') || method.includes('find')) {
|
|
128
|
-
return 'LOW';
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return 'MEDIUM';
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
private determineEventType(controller: any, methodName: string): SecurityEvent['eventType'] {
|
|
135
|
-
const controllerName = controller.constructor.name.toLowerCase();
|
|
136
|
-
const method = methodName.toLowerCase();
|
|
137
|
-
|
|
138
|
-
if (controllerName.includes('auth') || controllerName.includes('login')) {
|
|
139
|
-
return 'AUTHENTICATION';
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (method.includes('create') || method.includes('update') || method.includes('delete')) {
|
|
143
|
-
return 'DATA_MODIFICATION';
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (method.includes('get') || method.includes('list') || method.includes('find')) {
|
|
147
|
-
return 'DATA_ACCESS';
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return 'SYSTEM_ACCESS';
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private calculateRiskScore(ctx: Context, controller: any, methodName: string): number {
|
|
154
|
-
let score = 0;
|
|
155
|
-
|
|
156
|
-
// 基于HTTP方法
|
|
157
|
-
switch (ctx.method) {
|
|
158
|
-
case 'DELETE': score += 4; break;
|
|
159
|
-
case 'PUT': score += 3; break;
|
|
160
|
-
case 'POST': score += 2; break;
|
|
161
|
-
case 'GET': score += 1; break;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 基于用户权限
|
|
165
|
-
if (!ctx.state.user) score += 3;
|
|
166
|
-
if (!ctx.state.user?.isAdmin) score += 1;
|
|
167
|
-
|
|
168
|
-
// 基于IP地址
|
|
169
|
-
if (this.isSuspiciousIP(ctx.ip)) score += 2;
|
|
170
|
-
|
|
171
|
-
// 基于时间
|
|
172
|
-
if (this.isOffHours()) score += 1;
|
|
173
|
-
|
|
174
|
-
return Math.min(score, 10);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
private checkCompliance(ctx: Context, config: SecurityAuditConfig): string[] {
|
|
178
|
-
const flags: string[] = [];
|
|
179
|
-
|
|
180
|
-
if (config.complianceMode) {
|
|
181
|
-
const rules = this.complianceRules.get(config.complianceMode);
|
|
182
|
-
if (rules) {
|
|
183
|
-
// GDPR 检查
|
|
184
|
-
if (config.complianceMode === 'GDPR') {
|
|
185
|
-
if (this.containsPersonalData(ctx.request.body)) {
|
|
186
|
-
flags.push('GDPR_PERSONAL_DATA');
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// SOX 检查
|
|
191
|
-
if (config.complianceMode === 'SOX') {
|
|
192
|
-
if (this.isFinancialData(ctx.request.body)) {
|
|
193
|
-
flags.push('SOX_FINANCIAL_DATA');
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return flags;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private sanitizeData(data: any, sensitiveFields: string[] = []): any {
|
|
203
|
-
if (!data || typeof data !== 'object') return data;
|
|
204
|
-
|
|
205
|
-
const sanitized = { ...data };
|
|
206
|
-
|
|
207
|
-
// 移除敏感字段
|
|
208
|
-
sensitiveFields.forEach(field => {
|
|
209
|
-
if (sanitized[field]) {
|
|
210
|
-
sanitized[field] = '[REDACTED]';
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// 移除密码字段
|
|
215
|
-
if (sanitized.password) {
|
|
216
|
-
sanitized.password = '[REDACTED]';
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return sanitized;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
private logSecurityEvent(event: SecurityEvent, level: string): void {
|
|
223
|
-
const logData = {
|
|
224
|
-
securityEvent: event,
|
|
225
|
-
message: `Security audit: ${event.eventType} - ${event.controller}.${event.action}`,
|
|
226
|
-
riskScore: event.riskScore,
|
|
227
|
-
complianceFlags: event.complianceFlags
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
switch (level) {
|
|
231
|
-
case 'error':
|
|
232
|
-
logger.error(`[SecurityAudit] ${logData.message}`, undefined, logData);
|
|
233
|
-
break;
|
|
234
|
-
case 'warn':
|
|
235
|
-
logger.warn(`[SecurityAudit] ${logData.message}`, logData);
|
|
236
|
-
break;
|
|
237
|
-
default:
|
|
238
|
-
logger.info(`[SecurityAudit] ${logData.message}`, logData);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
private handleHighRiskEvent(event: SecurityEvent): void {
|
|
243
|
-
logger.error(`[SecurityAudit] 高风险安全事件`, undefined, {
|
|
244
|
-
event,
|
|
245
|
-
alert: 'HIGH_RISK_SECURITY_EVENT',
|
|
246
|
-
timestamp: new Date().toISOString()
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
// 这里可以集成外部安全系统
|
|
250
|
-
// 例如:发送到 SIEM 系统、触发告警等
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
private checkDataLeakage(event: SecurityEvent): void {
|
|
254
|
-
if (event.responseData && typeof event.responseData === 'object') {
|
|
255
|
-
const responseStr = JSON.stringify(event.responseData);
|
|
256
|
-
|
|
257
|
-
// 检查是否包含敏感信息
|
|
258
|
-
const sensitivePatterns = [
|
|
259
|
-
/password/i,
|
|
260
|
-
/ssn/i,
|
|
261
|
-
/credit.*card/i,
|
|
262
|
-
/social.*security/i
|
|
263
|
-
];
|
|
264
|
-
|
|
265
|
-
sensitivePatterns.forEach(pattern => {
|
|
266
|
-
if (pattern.test(responseStr)) {
|
|
267
|
-
logger.error(`[SecurityAudit] 潜在数据泄露`, undefined, {
|
|
268
|
-
event,
|
|
269
|
-
pattern: pattern.toString(),
|
|
270
|
-
alert: 'POTENTIAL_DATA_LEAKAGE'
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
private initializeComplianceRules(): void {
|
|
278
|
-
this.complianceRules.set('GDPR', {
|
|
279
|
-
personalDataFields: ['email', 'phone', 'address', 'name', 'ssn'],
|
|
280
|
-
retentionPeriod: 365
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
this.complianceRules.set('SOX', {
|
|
284
|
-
financialDataFields: ['amount', 'transaction', 'payment', 'invoice'],
|
|
285
|
-
auditTrail: true
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
this.complianceRules.set('HIPAA', {
|
|
289
|
-
healthDataFields: ['medical', 'health', 'diagnosis', 'treatment'],
|
|
290
|
-
encryptionRequired: true
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
private containsPersonalData(data: any): boolean {
|
|
295
|
-
const personalFields = ['email', 'phone', 'address', 'name', 'ssn'];
|
|
296
|
-
return personalFields.some(field =>
|
|
297
|
-
data && typeof data === 'object' && data[field]
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
private isFinancialData(data: any): boolean {
|
|
302
|
-
const financialFields = ['amount', 'transaction', 'payment', 'invoice'];
|
|
303
|
-
return financialFields.some(field =>
|
|
304
|
-
data && typeof data === 'object' && data[field]
|
|
305
|
-
);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
private isSuspiciousIP(ip: string): boolean {
|
|
309
|
-
// 简单的可疑IP检查
|
|
310
|
-
const suspiciousRanges = ['192.168.', '10.', '172.'];
|
|
311
|
-
return suspiciousRanges.some(range => ip.startsWith(range));
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
private isOffHours(): boolean {
|
|
315
|
-
const hour = new Date().getHours();
|
|
316
|
-
return hour < 6 || hour > 22;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* 获取审计日志
|
|
321
|
-
*/
|
|
322
|
-
getAuditLog(filter?: Partial<SecurityEvent>): SecurityEvent[] {
|
|
323
|
-
if (!filter) return [...this.auditLog];
|
|
324
|
-
|
|
325
|
-
return this.auditLog.filter(event => {
|
|
326
|
-
return Object.keys(filter).every(key =>
|
|
327
|
-
event[key as keyof SecurityEvent] === filter[key as keyof SecurityEvent]
|
|
328
|
-
);
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
* 清理过期日志
|
|
334
|
-
*/
|
|
335
|
-
cleanupExpiredLogs(retentionDays: number = 90): void {
|
|
336
|
-
const cutoffDate = new Date();
|
|
337
|
-
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
|
|
338
|
-
|
|
339
|
-
this.auditLog = this.auditLog.filter(event =>
|
|
340
|
-
new Date(event.timestamp) > cutoffDate
|
|
341
|
-
);
|
|
342
|
-
|
|
343
|
-
logger.info(`[SecurityAudit] 清理过期日志完成,保留 ${this.auditLog.length} 条记录`);
|
|
344
|
-
}
|
|
345
|
-
}
|