2026-08-17 12:25:42 +08:00
|
|
|
|
'use strict';
|
|
|
|
|
|
|
2026-10-14 10:22:53 +08:00
|
|
|
|
// 初始管理员账号。
|
|
|
|
|
|
// 口令:下方内置 bcrypt 哈希仅为**开发/演示**默认值(对应公开弱口令,仅供本机初始化)。
|
|
|
|
|
|
// 正式初始化(生产等)时应通过环境变量 ADMIN_INIT_PASSWORD 注入真实口令 ——
|
|
|
|
|
|
// 本文件⛔不落盘任何明文口令(铁律 25)。
|
2026-08-17 12:25:42 +08:00
|
|
|
|
module.exports = {
|
|
|
|
|
|
up: async (queryInterface, Sequelize) => {
|
|
|
|
|
|
const now = new Date();
|
2026-10-14 10:22:53 +08:00
|
|
|
|
const row = {
|
|
|
|
|
|
role: 'admin',
|
|
|
|
|
|
name_cn: '系统管理员',
|
|
|
|
|
|
name_en: 'Administrator',
|
|
|
|
|
|
gender: null,
|
|
|
|
|
|
phone: null,
|
|
|
|
|
|
email: 'admin@competition.com',
|
|
|
|
|
|
id_number: '000000000000000000',
|
|
|
|
|
|
password: '$2b$10$Nc6PCJItIwuOzpM22dTiAezB.jZMI8mzkCbg3oRZkAWx.QaI4co9.',
|
|
|
|
|
|
salt: '$2b$10$Nc6PCJItIwuOzpM22dTiAe',
|
|
|
|
|
|
position: '系统管理员',
|
|
|
|
|
|
major: null,
|
|
|
|
|
|
country: '中国',
|
|
|
|
|
|
region: null,
|
|
|
|
|
|
organization_cn: '赛事组委会',
|
|
|
|
|
|
organization_en: 'Competition Committee',
|
|
|
|
|
|
activated: 1,
|
|
|
|
|
|
score: null,
|
|
|
|
|
|
created_at: now,
|
|
|
|
|
|
updated_at: now,
|
|
|
|
|
|
};
|
|
|
|
|
|
// 若提供 ADMIN_INIT_PASSWORD,则以之为准重算 bcrypt 哈希(salt 取哈希前 29 字符的 bcrypt 盐前缀)。
|
|
|
|
|
|
const initPwd = process.env.ADMIN_INIT_PASSWORD;
|
|
|
|
|
|
if (initPwd) {
|
|
|
|
|
|
const hash = require('bcrypt').hashSync(String(initPwd), 10);
|
|
|
|
|
|
row.password = hash;
|
|
|
|
|
|
row.salt = hash.slice(0, 29);
|
|
|
|
|
|
}
|
|
|
|
|
|
await queryInterface.bulkInsert('accounts', [row], {});
|
2026-08-17 12:25:42 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
down: async (queryInterface, Sequelize) => {
|
|
|
|
|
|
await queryInterface.bulkDelete('accounts', {
|
|
|
|
|
|
id_number: '000000000000000000',
|
|
|
|
|
|
}, {});
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|