88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
/**
|
||
* Startup configuration validator.
|
||
*
|
||
* Validates critical config items before server start.
|
||
* All issues are warnings in staging — only COOKIE_ENCRYPTION_KEY missing
|
||
* and admin password using defaults will be flagged.
|
||
*/
|
||
import config from '../config';
|
||
|
||
interface ValidationError {
|
||
key: string;
|
||
message: string;
|
||
severity: 'error' | 'warn';
|
||
}
|
||
|
||
export function validateConfig(): ValidationError[] {
|
||
const errors: ValidationError[] = [];
|
||
const isProd = config.nodeEnv === 'production';
|
||
|
||
// ─── JWT Secret ───
|
||
const DEFAULT_JWT_SECRETS = [
|
||
'cloudsearch-jwt-secret-dev',
|
||
'your-super-secret-jwt-key-change-me',
|
||
'',
|
||
];
|
||
if (DEFAULT_JWT_SECRETS.includes(config.jwtSecret)) {
|
||
errors.push({
|
||
key: 'JWT_SECRET',
|
||
message: '使用了默认 JWT Secret,生产部署前应修改(openssl rand -hex 32)',
|
||
severity: isProd ? 'warn' : 'warn',
|
||
});
|
||
}
|
||
|
||
// ─── Admin Password ───
|
||
const weakPasswords = ['admin123', 'admin', 'password', '123456', ''];
|
||
if (weakPasswords.includes(config.adminPassword)) {
|
||
errors.push({
|
||
key: 'ADMIN_PASSWORD',
|
||
message: `使用了默认管理员密码,生产部署前应设置强密码`,
|
||
severity: isProd ? 'warn' : 'warn',
|
||
});
|
||
}
|
||
|
||
// ─── Cookie Encryption ───
|
||
// Key is auto-generated and persisted to encryption.key if COOKIE_ENCRYPTION_KEY is not set
|
||
|
||
// ─── Port conflict check (best-effort) ───
|
||
if (config.port < 1024 && (process as any).getuid?.() !== 0) {
|
||
errors.push({
|
||
key: 'PORT',
|
||
message: `端口 ${config.port} 需要 root 权限(<1024),建议使用 9527 或更高端口`,
|
||
severity: 'warn',
|
||
});
|
||
}
|
||
|
||
return errors;
|
||
}
|
||
|
||
/**
|
||
* Print validation results and return whether startup should proceed.
|
||
* Returns false only if 'error' severity issues found in production.
|
||
* In staging, warnings are printed but startup continues.
|
||
*/
|
||
export function checkStartup(): boolean {
|
||
const errors = validateConfig();
|
||
const isProd = config.nodeEnv === 'production';
|
||
|
||
if (errors.length === 0) {
|
||
console.log('[Config] ✅ 所有配置检查通过');
|
||
return true;
|
||
}
|
||
|
||
console.log('[Config] ── 配置检查结果 ──');
|
||
for (const err of errors) {
|
||
const prefix = err.severity === 'error' ? '❌' : '⚠️';
|
||
console.log(`[Config] ${prefix} [${err.severity.toUpperCase()}] ${err.key}: ${err.message}`);
|
||
}
|
||
|
||
const criticalErrors = errors.filter(e => e.severity === 'error');
|
||
if (criticalErrors.length > 0 && isProd) {
|
||
console.error('[Config] 🛑 生产环境存在严重配置错误,拒绝启动。请修复后重试。');
|
||
return false;
|
||
}
|
||
|
||
console.log(`[Config] ✅ 继续启动(${errors.length} 个警告)`);
|
||
return true;
|
||
}
|