Files
competition-website/database/seeders/002-seed-admin.js
qubiaobiao ae436c01ca fix(auth): seeder 002 改种 admins + 默认口令守卫补 'admin'(候选⑳/㉑)
候选⑳:002-seed-admin.js 原 bulkInsert 到 accounts 表(row 含 role/name_cn/salt
等列),但登录链路读 admins 表(service/auth.js:101 findAdmin() → model/admin.js:49
tableName='admins')⇒ 原写法属死写入,种下的行永不被登录读取。改为写入 admins 并按
其真实列契约(id/username/password/created_at/updated_at)重写 row;down() 同步改
bulkDelete('admins', {username:'admin'})。前置已全仓 grep 确认 accounts.role='admin'
零消费点(后端 4 处 Account 用法均按 id_number/uid 定位;role==='admin' 5 处判定全
作用于 JWT payload / 前端本地态)。

候选㉑:DEFAULT_ADMIN_PASSWORDS 原为 ['admin123','admin123456'],不含 'admin',而
schema.sql 建库路径的初始口令恰为 admin ⇒ 生产未改密时该口令可绕过 4005 守卫
(verifyPassword 兼容 SHA256 ⇒ 可直接登录)。已补入 'admin'。结构性缺口(口令字面
判据 ⇒ 未枚举的默认口令均绕过)未消除,登记为 BACKLOG 候选㉒。

同源引用同步(就地更正、零删除):schema.sql:213-218 注释、docs/modules.md:581
注释(含行号引用 378→387)。

验证:node --check 通过;R111 判别力自证 22/22 PASS + 4 项变异全红;
verify_no_secrets HIGH 0 / CAND 2(与基线一致 ⇒ 零新增);verify_tautology_guard
PASS;verify_constant_shape_guard PASS。
2026-10-14 10:47:51 +08:00

42 lines
2.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
// 初始管理员账号。
// 口令:下方内置 bcrypt 哈希仅为**开发/演示**默认值(对应公开弱口令,仅供本机初始化)。
// 正式初始化(生产等)时应通过环境变量 ADMIN_INIT_PASSWORD 注入真实口令 ——
// 本文件⛔不落盘任何明文口令(铁律 25)。
//
// ⚠️ 【R111 更正 · 实测】本 seeder 原先 `bulkInsert` 到 **`accounts`** 表(row 含
// role/name_cn/salt/id_number 等列);但登录链路读的是 **`admins`** 表
// (`service/auth.js:101 findAdmin()` → `model/admin.js:49 tableName='admins'`)
// ⇒ 原写法属**死写入**(种下的那行永远不会被登录读取)。
// 已改为写入 `admins`,并按该表真实列契约(`id/username/password/created_at/updated_at`,
// 见 `database/migrations/002-create-admins.js:17-46` 与 `database/schema.sql:20-29`)重写 row。
// 详见 `.workbuddy/memory/BACKLOG.md` 候选⑳。
module.exports = {
up: async (queryInterface, Sequelize) => {
const now = new Date();
// `admins` 表列契约:id(自增主键,勿传)/ username / password / created_at / updated_at。
// ⛔ 该表**无** salt / role / name_cn / id_number / activated / score 等列。
const row = {
username: 'admin',
// bcrypt(cost=10) 哈希 = 开发默认弱口令(公开值,仅供本机初始化;生产须经 ADMIN_INIT_PASSWORD 覆盖)。
// 60 字符 < `admins.password VARCHAR(100)` ⇒ 列宽容得下。
password: '$2b$10$Nc6PCJItIwuOzpM22dTiAezB.jZMI8mzkCbg3oRZkAWx.QaI4co9.',
created_at: now,
updated_at: now,
};
// 若提供 ADMIN_INIT_PASSWORD,则以之为准重算 bcrypt 哈希(明文只经过程环境,⛔ 不落盘)。
const initPwd = process.env.ADMIN_INIT_PASSWORD;
if (initPwd) {
row.password = require('bcrypt').hashSync(String(initPwd), 10);
}
await queryInterface.bulkInsert('admins', [row], {});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete('admins', {
username: 'admin',
}, {});
},
};