由 OCR(open-codereview.ai,deepseek-v4-flash)审查驱动修复: - JWT 生产必填、密码 8-72 字节、防枚举;全局 ValidationPipe - classes/dashboard/schedules/students/attendance/archive/exams 越权与 IDOR 修复 - LIKE 通配符转义(14 处);上传 10MB 上限 + MIME 白名单 + 附件 XSS - 集成配置 appSecret AES 加密 + 回填脚本;审计 best-effort;IP 来源防伪造 Reviewed-by: OCR (open-codereview.ai)
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
/// <reference types="node" />
|
||
|
||
import datasource from '../datasource';
|
||
import { encryptSecret, isEncryptedSecret } from '../src/integration/config/secret-crypto';
|
||
import { IntegrationConfigDetail } from '../src/integration/entities/integration-config.entity';
|
||
|
||
/** integration_config_detail.content JSON 中与本次回填相关的结构。 */
|
||
interface StoredConfigContent {
|
||
type?: unknown;
|
||
verify?: unknown;
|
||
config?: Record<string, unknown>;
|
||
}
|
||
|
||
async function main(): Promise<void> {
|
||
// 主动检查加密密钥:缺失时 getEncryptionKey() 会静默使用开发回退密钥,
|
||
// 绝不能用回退密钥加密生产数据,因此未配置时直接报错退出。
|
||
if (!process.env.AI_CONFIG_ENCRYPTION_KEY) {
|
||
throw new Error(
|
||
'AI_CONFIG_ENCRYPTION_KEY 未设置:为避免使用开发回退密钥加密数据,请先配置 AI_CONFIG_ENCRYPTION_KEY 再运行回填脚本',
|
||
);
|
||
}
|
||
|
||
await datasource.initialize();
|
||
console.log('已连接数据库,开始回填第三方集成配置 appSecret 加密...');
|
||
|
||
try {
|
||
const repo = datasource.getRepository(IntegrationConfigDetail);
|
||
const rows = await repo.find();
|
||
let processed = 0;
|
||
|
||
for (const row of rows) {
|
||
if (!row.content) continue;
|
||
|
||
let parsed: StoredConfigContent;
|
||
try {
|
||
parsed = JSON.parse(row.content) as StoredConfigContent;
|
||
} catch {
|
||
continue;
|
||
}
|
||
|
||
const config = parsed.config;
|
||
if (!config || typeof config !== 'object' || Array.isArray(config)) continue;
|
||
|
||
const appSecret = config.appSecret;
|
||
if (typeof appSecret !== 'string' || !appSecret || isEncryptedSecret(appSecret)) continue;
|
||
|
||
config.appSecret = encryptSecret(appSecret);
|
||
row.content = JSON.stringify(parsed);
|
||
await repo.save(row);
|
||
processed += 1;
|
||
}
|
||
|
||
console.log(`回填完成:共处理 ${processed} 行(加密 appSecret)`);
|
||
} finally {
|
||
// 无论成功还是失败都关闭连接池,避免泄漏
|
||
try {
|
||
await datasource.destroy();
|
||
} catch {
|
||
// 销毁失败不影响主流程结果
|
||
}
|
||
}
|
||
}
|
||
|
||
main().catch((error) => {
|
||
console.error('回填失败:', error);
|
||
process.exitCode = 1;
|
||
});
|