new-site/api/src/create-admin.ts
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

56 lines
1.6 KiB
TypeScript

/**
* Create an admin user for the dashboard.
*
* Usage:
* npx tsx src/create-admin.ts <username> <password> [display_name] [email]
*
* Example:
* npx tsx src/create-admin.ts justin MySecurePass123 "Justin" "justin@performancewest.net"
*
* Requires DATABASE_URL environment variable.
*/
import bcrypt from "bcryptjs";
import pg from "pg";
async function main() {
const [, , username, password, displayName, email] = process.argv;
if (!username || !password) {
console.error("Usage: npx tsx src/create-admin.ts <username> <password> [display_name] [email]");
process.exit(1);
}
const dbUrl = process.env.DATABASE_URL;
if (!dbUrl) {
console.error("DATABASE_URL environment variable is required.");
process.exit(1);
}
const pool = new pg.Pool({ connectionString: dbUrl });
try {
// Hash password with bcrypt (12 rounds)
const hash = await bcrypt.hash(password, 12);
const result = await pool.query(
`INSERT INTO admin_users (username, password_hash, display_name, email)
VALUES ($1, $2, $3, $4)
ON CONFLICT (username) DO UPDATE SET
password_hash = $2, display_name = $3, email = $4, active = TRUE
RETURNING id, username`,
[username.toLowerCase().trim(), hash, displayName || username, email || null],
);
const user = result.rows[0];
console.log(`Admin user created/updated: ${user.username} (id: ${user.id})`);
console.log(`Login at: https://performancewest.net/admin`);
} catch (err) {
console.error("Failed to create admin user:", err);
process.exit(1);
} finally {
await pool.end();
}
}
main();