import { NextRequest, NextResponse } from 'next/server'; import { Pool } from 'pg'; const pool = new Pool({ connectionString: process.env.DATABASE_URL, ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, }); export default async function handler(req: NextRequest) { if (req.method !== 'POST') { return new NextResponse(JSON.stringify({ error: 'Method not allowed' }), { status: 405, headers: { 'Content-Type': 'application/json' }, }); } const client = await pool.connect(); try { console.log('Setting up user authentication schema...'); // Check if users table already exists const tableCheck = await client.query(` SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'users' ); `); if (tableCheck.rows[0].exists) { return new NextResponse(JSON.stringify({ success: true, message: 'User authentication schema already exists', already_setup: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); } // Create tables one by one await client.query(` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, first_name VARCHAR(50), last_name VARCHAR(50), avatar_url TEXT, is_active BOOLEAN DEFAULT true, email_verified BOOLEAN DEFAULT false, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP WITH TIME ZONE ); `); await client.query(` CREATE TABLE IF NOT EXISTS roles ( id SERIAL PRIMARY KEY, name VARCHAR(50) UNIQUE NOT NULL, description TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); `); await client.query(` CREATE TABLE IF NOT EXISTS user_roles ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, role_id INTEGER REFERENCES roles(id) ON DELETE CASCADE, assigned_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, assigned_by INTEGER REFERENCES users(id), UNIQUE(user_id, role_id) ); `); await client.query(` CREATE TABLE IF NOT EXISTS permissions ( id SERIAL PRIMARY KEY, name VARCHAR(100) UNIQUE NOT NULL, description TEXT, resource VARCHAR(50), action VARCHAR(50), created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); `); await client.query(` CREATE TABLE IF NOT EXISTS role_permissions ( id SERIAL PRIMARY KEY, role_id INTEGER REFERENCES roles(id) ON DELETE CASCADE, permission_id INTEGER REFERENCES permissions(id) ON DELETE CASCADE, UNIQUE(role_id, permission_id) ); `); await client.query(` CREATE TABLE IF NOT EXISTS user_sessions ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, token_hash VARCHAR(255) NOT NULL, expires_at TIMESTAMP WITH TIME ZONE NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, last_used TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, user_agent TEXT, ip_address INET ); `); // Insert default roles await client.query(` INSERT INTO roles (name, description) VALUES ('user', 'Standard user with basic permissions'), ('admin', 'Administrator with full system access') ON CONFLICT (name) DO NOTHING; `); // Insert basic permissions const permissions = [ ['cards.read', 'View cards'], ['collections.manage', 'Manage collections'], ['decks.manage', 'Manage decks'], ['admin.access', 'Access admin panel'] ]; for (const [name, description] of permissions) { await client.query(` INSERT INTO permissions (name, description) VALUES ($1, $2) ON CONFLICT (name) DO NOTHING; `, [name, description]); } // Assign permissions to roles await client.query(` INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r, permissions p WHERE r.name = 'user' AND p.name IN ('cards.read', 'collections.manage', 'decks.manage') ON CONFLICT (role_id, permission_id) DO NOTHING; `); await client.query(` INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r, permissions p WHERE r.name = 'admin' ON CONFLICT (role_id, permission_id) DO NOTHING; `); // Create indexes await client.query(` CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON user_roles(user_id); `); console.log('✅ User authentication schema setup completed!'); return new NextResponse(JSON.stringify({ success: true, message: 'User authentication schema setup completed successfully' }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); } catch (error) { console.error('Schema setup failed:', error); return new NextResponse(JSON.stringify({ success: false, error: 'Schema setup failed', details: (error as Error).message }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } finally { client.release(); } }