Files
memind_adm/scripts/init-admin.mjs
2026-06-30 20:26:33 +08:00

73 lines
2.4 KiB
JavaScript

#!/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();