#!/usr/bin/env node /** * Script to create an admin user * Usage: npm run create-admin * or: npx tsx src/scripts/create-admin.ts */ import { PrismaClient } from '@prisma/client'; import * as readline from 'readline'; import { hashPassword, validatePasswordStrength } from '../utils/password'; const prisma = new PrismaClient(); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); function question(query: string): Promise { return new Promise((resolve) => { rl.question(query, resolve); }); } async function createAdmin() { try { console.log('\n🌿 Basil Recipe Manager - Create Admin User\n'); // Get email const email = await question('Email address: '); if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { console.error('āŒ Invalid email address'); process.exit(1); } // Check if user already exists const existingUser = await prisma.user.findUnique({ where: { email: email.toLowerCase() }, }); if (existingUser) { console.error('āŒ User with this email already exists'); if (existingUser.role === 'ADMIN') { console.log('ā„¹ļø This user is already an admin'); } else { const upgrade = await question('Would you like to upgrade this user to admin? (yes/no): '); if (upgrade.toLowerCase() === 'yes' || upgrade.toLowerCase() === 'y') { await prisma.user.update({ where: { id: existingUser.id }, data: { role: 'ADMIN' }, }); console.log('āœ… User upgraded to admin successfully'); } } process.exit(0); } // Get name const name = await question('Full name (optional): '); // Get password const password = await question('Password (min 8 chars, uppercase, lowercase, number): '); // Validate password const passwordValidation = validatePasswordStrength(password); if (!passwordValidation.valid) { console.error('āŒ Password does not meet requirements:'); passwordValidation.errors.forEach((error) => { console.error(` - ${error}`); }); process.exit(1); } // Confirm password const passwordConfirm = await question('Confirm password: '); if (password !== passwordConfirm) { console.error('āŒ Passwords do not match'); process.exit(1); } // Hash password console.log('\nšŸ” Hashing password...'); const passwordHash = await hashPassword(password); // Create admin user console.log('šŸ‘¤ Creating admin user...'); const admin = await prisma.user.create({ data: { email: email.toLowerCase(), name: name || undefined, passwordHash, role: 'ADMIN', provider: 'local', emailVerified: true, // Auto-verify admin users emailVerifiedAt: new Date(), }, }); console.log('\nāœ… Admin user created successfully!'); console.log('\nUser details:'); console.log(` ID: ${admin.id}`); console.log(` Email: ${admin.email}`); console.log(` Name: ${admin.name || 'N/A'}`); console.log(` Role: ${admin.role}`); console.log(` Email Verified: ${admin.emailVerified}`); console.log(` Created: ${admin.createdAt.toISOString()}`); console.log('\nšŸ”‘ You can now log in with this email and password\n'); } catch (error) { console.error('\nāŒ Error creating admin user:', error); process.exit(1); } finally { rl.close(); await prisma.$disconnect(); } } createAdmin();