73 lines
2.1 KiB
JavaScript
73 lines
2.1 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Create or update an admin user.
|
|
*
|
|
* Usage:
|
|
* node scripts/create-admin.js <username> <password>
|
|
*
|
|
* If the username already exists, the password is updated (upsert).
|
|
* Run this directly on the server after deployment.
|
|
*
|
|
* Example:
|
|
* node scripts/create-admin.js raine supersecretpassword
|
|
*/
|
|
|
|
import bcrypt from 'bcryptjs';
|
|
import Database from 'better-sqlite3';
|
|
import { randomBytes } from 'crypto';
|
|
import { config } from 'dotenv';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname, join } from 'path';
|
|
|
|
// Load .env from project root
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
config({ path: join(__dirname, '..', '.env') });
|
|
|
|
const [,, username, password] = process.argv;
|
|
|
|
if (!username || !password) {
|
|
console.error('Usage: node scripts/create-admin.js <username> <password>');
|
|
process.exit(1);
|
|
}
|
|
|
|
if (username.length < 2 || username.length > 32) {
|
|
console.error('Username must be between 2 and 32 characters.');
|
|
process.exit(1);
|
|
}
|
|
|
|
if (password.length < 8) {
|
|
console.error('Password must be at least 8 characters.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const dbPath = process.env.DATABASE_URL ?? './dev.db';
|
|
const db = new Database(dbPath);
|
|
db.pragma('journal_mode = WAL');
|
|
db.pragma('foreign_keys = ON');
|
|
|
|
// Ensure the admins table exists (safe to run before full app init)
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS admins (
|
|
id TEXT PRIMARY KEY,
|
|
username TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
created_at TEXT NOT NULL
|
|
);
|
|
`);
|
|
|
|
const existing = db.prepare(`SELECT id FROM admins WHERE username = ?`).get(username);
|
|
const hash = bcrypt.hashSync(password, 12);
|
|
const now = new Date().toISOString();
|
|
|
|
if (existing) {
|
|
db.prepare(`UPDATE admins SET password_hash = ? WHERE username = ?`).run(hash, username);
|
|
console.log(`✓ Password updated for admin: ${username}`);
|
|
} else {
|
|
const id = randomBytes(8).toString('hex');
|
|
db.prepare(`INSERT INTO admins (id, username, password_hash, created_at) VALUES (?, ?, ?, ?)`)
|
|
.run(id, username, hash, now);
|
|
console.log(`✓ Admin created: ${username}`);
|
|
}
|
|
|
|
db.close();
|