#!/usr/bin/env node import crypto from 'node:crypto'; import readline from 'node:readline/promises'; import { stdin as input, stdout as output } from 'node:process'; import { Algorithm as Argon2Algorithm, hashRawSync as argon2HashRawSync } from '@node-rs/argon2'; import { createDbPool, isDatabaseConfigured } from '../server/db.mjs'; const PASSWORD_ALGORITHM_ARGON2ID = 'argon2id'; const ARGON2_MEMORY = 64 * 1024; const ARGON2_PASSES = 3; const ARGON2_PARALLELISM = 1; const ARGON2_TAG_LENGTH = 32; function createPasswordRecord(password) { const salt = crypto.randomBytes(16).toString('hex'); const passwordHash = argon2HashRawSync(password, { salt: Buffer.from(salt, 'hex'), parallelism: ARGON2_PARALLELISM, outputLen: ARGON2_TAG_LENGTH, memoryCost: ARGON2_MEMORY, timeCost: ARGON2_PASSES, algorithm: Argon2Algorithm.Argon2id, }).toString('hex'); return { salt, passwordHash, passwordAlgorithm: PASSWORD_ALGORITHM_ARGON2ID }; } if (!isDatabaseConfigured()) { console.error('MySQL 未配置,请先设置 DATABASE_URL 或 MYSQL_*'); process.exit(1); } const [usernameArg, passwordArg, confirmArg] = process.argv.slice(2); let username = (usernameArg ?? '').trim(); let password = passwordArg ?? ''; let confirm = confirmArg ?? ''; if (!username || !password || !confirm) { const rl = readline.createInterface({ input, output }); username = username || (await rl.question('admin username [admin]: ')).trim() || 'admin'; password = password || (await rl.question('admin password: ')); confirm = confirm || (await rl.question('confirm password: ')); rl.close(); } else { username = username.trim() || 'admin'; } if (!password || password !== confirm) { console.error('密码为空或两次输入不一致'); process.exit(1); } const pool = createDbPool(); const [rows] = await pool.execute( `SELECT id FROM h5_users WHERE username = ? AND role = 'admin' LIMIT 1`, [username], ); if (!rows.length) { console.error(`未找到共享主用户表中的 admin 账号: ${username}`); await pool.end(); process.exit(1); } const nextPassword = createPasswordRecord(password); await pool.execute( `UPDATE h5_users SET salt = ?, password_hash = ?, password_algorithm = ?, updated_at = ? WHERE id = ?`, [nextPassword.salt, nextPassword.passwordHash, nextPassword.passwordAlgorithm, Date.now(), rows[0].id], ); console.log(`admin 账号密码已更新到 h5_users: ${username}`); await pool.end();