import { PrismaClient as PrismaClientAuth } from '../node_modules/.prisma/client-auth'; import bcrypt from 'bcryptjs'; import * as dotenv from 'dotenv'; // Load environment variables dotenv.config({ path: '.env' }); const prisma = new PrismaClientAuth({ datasourceUrl: process.env.DATABASE_URL_AUTH, }); async function setupAuth() { try { console.log('Setting up authentication tables and admin user...\n'); // Create tables using raw SQL (Prisma doesn't support CREATE TABLE in migrations easily) console.log('Creating users table...'); await prisma.$executeRawUnsafe(` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, name VARCHAR(255), password_hash VARCHAR(255) NOT NULL, is_admin BOOLEAN DEFAULT FALSE, is_active BOOLEAN DEFAULT TRUE, has_write_access BOOLEAN DEFAULT FALSE, email_verified BOOLEAN DEFAULT FALSE, email_confirmation_token VARCHAR(255) UNIQUE, email_confirmation_token_expiry TIMESTAMP, password_reset_token VARCHAR(255) UNIQUE, password_reset_token_expiry TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); `); // Add missing columns if table already exists with old schema console.log('Adding missing columns if needed...'); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS is_admin BOOLEAN DEFAULT FALSE;`); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS has_write_access BOOLEAN DEFAULT FALSE;`); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified BOOLEAN DEFAULT FALSE;`); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_confirmation_token VARCHAR(255);`); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_confirmation_token_expiry TIMESTAMP;`); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_token VARCHAR(255);`); await prisma.$executeRawUnsafe(`ALTER TABLE users ADD COLUMN IF NOT EXISTS password_reset_token_expiry TIMESTAMP;`); // Add unique constraints if they don't exist await prisma.$executeRawUnsafe(`CREATE UNIQUE INDEX IF NOT EXISTS users_email_confirmation_token_key ON users(email_confirmation_token) WHERE email_confirmation_token IS NOT NULL;`); await prisma.$executeRawUnsafe(`CREATE UNIQUE INDEX IF NOT EXISTS users_password_reset_token_key ON users(password_reset_token) WHERE password_reset_token IS NOT NULL;`); console.log('Creating pending_identifications table...'); await prisma.$executeRawUnsafe(` CREATE TABLE IF NOT EXISTS pending_identifications ( id SERIAL PRIMARY KEY, face_id INTEGER NOT NULL, user_id INTEGER NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, middle_name VARCHAR(255), maiden_name VARCHAR(255), date_of_birth DATE, status VARCHAR(50) DEFAULT 'pending', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -- Note: face_id references faces in punimtag database, but we can't use foreign key across databases ); `); console.log('Creating indexes...'); await prisma.$executeRawUnsafe(`CREATE INDEX IF NOT EXISTS idx_pending_identifications_face_id ON pending_identifications(face_id);`); await prisma.$executeRawUnsafe(`CREATE INDEX IF NOT EXISTS idx_pending_identifications_user_id ON pending_identifications(user_id);`); await prisma.$executeRawUnsafe(`CREATE INDEX IF NOT EXISTS idx_pending_identifications_status ON pending_identifications(status);`); // Check if admin user already exists const existingAdmin = await prisma.user.findUnique({ where: { email: 'admin@admin.com' }, }); if (existingAdmin) { console.log('Admin user already exists. Updating password...'); const passwordHash = await bcrypt.hash('admin', 10); await prisma.user.update({ where: { email: 'admin@admin.com' }, data: { passwordHash, isAdmin: true, hasWriteAccess: true, emailVerified: true, isActive: true, }, }); console.log('✅ Admin user password updated (admin@admin.com / admin)'); } else { console.log('Creating admin user...'); const passwordHash = await bcrypt.hash('admin', 10); await prisma.user.create({ data: { email: 'admin@admin.com', name: 'Admin', passwordHash, isAdmin: true, hasWriteAccess: true, emailVerified: true, isActive: true, }, }); console.log('✅ Admin user created (admin@admin.com / admin)'); } console.log('\n✅ Setup complete!'); console.log('\nAdmin credentials:'); console.log(' Email: admin@admin.com'); console.log(' Password: admin'); console.log('\nNote: Make sure to grant appropriate database permissions:'); console.log(' - Regular users: INSERT on pending_identifications'); console.log(' - Admin: UPDATE on pending_identifications (for approval)'); } catch (error: any) { console.error('Error setting up authentication:', error); if (error.message.includes('permission denied')) { console.error('\n⚠️ Permission denied. You may need to:'); console.error(' 1. Run this script with a user that has CREATE TABLE permissions'); console.error(' 2. Or manually create the tables using create_auth_tables.sql'); } throw error; } finally { await prisma.$disconnect(); } } setupAuth();