chore: checkpoint admin restore state
This commit is contained in:
+37
-12
@@ -1,8 +1,28 @@
|
||||
#!/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';
|
||||
import { createLocalUserAuth } from '../server/local-auth.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_*');
|
||||
@@ -30,18 +50,23 @@ if (!password || password !== confirm) {
|
||||
}
|
||||
|
||||
const pool = createDbPool();
|
||||
const auth = createLocalUserAuth(pool);
|
||||
await auth.ensureAdminUser().catch(() => {});
|
||||
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(
|
||||
`INSERT INTO auth_users (username, display_name, role, status, password_hash, balance_cents)
|
||||
VALUES (?, ?, 'admin', 'active', ?, 0)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
display_name = VALUES(display_name),
|
||||
role = VALUES(role),
|
||||
status = VALUES(status),
|
||||
password_hash = VALUES(password_hash)`,
|
||||
[username, username, auth.hashPassword(password)],
|
||||
`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 账号已写入数据库: ${username}`);
|
||||
console.log(`admin 账号密码已更新到 h5_users: ${username}`);
|
||||
await pool.end();
|
||||
|
||||
Reference in New Issue
Block a user