'use strict'; /** * 后端运维脚本共用:数据库连接配置解析(**唯一入口**) * ============================================================ * * 为什么单独成文件 * ------------------------------------------------------------ * 任何"需要连库"的运维脚本(弱口令扫描 / 口令策略接口验证 / 后续新增)都必须 * 用同一套优先级与同一条凭据纪律。各自实现必然漂移 —— 例如某处"缺口令时兜底成 * 空串"就能静默连上无口令的库,而另一处明确失败,两者行为不一致却都"看起来正常"。 * * 读取优先级(与 scripts/_creds.py 完全同源) * ------------------------------------------------------------ * 1. 环境变量 DB_HOST / DB_PORT / DB_USER / DB_PASSWORD / DB_NAME(CI / 服务器注入优先) * 2. 仓库根 `scripts/.creds.local.json`(本机开发,已被 .gitignore 排除) * 3. 明确失败 —— ⛔ **刻意不提供明文兜底**:口令为空时直接抛错, * 绝不静默尝试空口令连库(那会掩盖"凭据没注入"这一真实故障)。 * * ⚠️ Python 侧对应实现见 `scripts/_creds.py`,两侧口径必须一致; * 如需增删键,**两边同时改**。 * * @returns {{host: string, port: number, user: string, password: string, database: string}} */ const fs = require('fs'); const path = require('path'); function loadDbConfig() { const env = process.env; let local = {}; // backend/scripts/ → 仓库根/scripts/.creds.local.json const localFile = path.join(__dirname, '..', '..', 'scripts', '.creds.local.json'); try { local = JSON.parse(fs.readFileSync(localFile, 'utf8')); } catch (e) { // 文件不存在是允许的(走环境变量);但**损坏**必须报错,不静默降级 if (e.code !== 'ENOENT') { throw new Error(`凭据文件解析失败 ${localFile}: ${e.message}`); } } const cfg = { host: env.DB_HOST || local.db_host || '127.0.0.1', port: parseInt(env.DB_PORT || local.db_port || 3306, 10), user: env.DB_USER || local.db_user || 'root', password: env.DB_PASSWORD || local.db_password || '', database: env.DB_NAME || local.db_name || 'competition_db', }; if (!cfg.password) { throw new Error( '未取到数据库口令。请任选其一:\n' + ' ① 设置环境变量 DB_PASSWORD\n' + ' ② 创建 scripts/.creds.local.json(形如 {"db_password":"..."})\n' + '⛔ 本模块刻意不提供明文兜底:缺凭据时明确失败,不静默连库。' ); } return cfg; } module.exports = { loadDbConfig };