import { NextRequest, NextResponse } from 'next/server'; import { cookies } from 'next/headers'; import { db } from '@/lib/db'; // Reserved subdomains that cannot be used const RESERVED_SUBDOMAINS = [ 'www', 'app', 'api', 'admin', 'mail', 'email', 'ftp', 'smtp', 'pop', 'imap', 'dns', 'ns1', 'ns2', 'blog', 'shop', 'store', 'help', 'support', 'dashboard', 'login', 'signup', 'auth', 'cdn', 'static', 'assets', 'dev', 'staging', 'test', 'demo', 'beta', 'alpha' ]; // Validate subdomain format function isValidSubdomain(subdomain: string): { valid: boolean; error?: string } { if (!subdomain) { return { valid: false, error: 'Subdomain is required' }; } // Must be lowercase if (subdomain !== subdomain.toLowerCase()) { return { valid: false, error: 'Subdomain must be lowercase' }; } // Length check if (subdomain.length < 3 || subdomain.length > 30) { return { valid: false, error: 'Subdomain must be 3-30 characters' }; } // Alphanumeric and hyphens only, no leading/trailing hyphens if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(subdomain)) { return { valid: false, error: 'Only lowercase letters, numbers, and hyphens allowed' }; } // No consecutive hyphens if (/--/.test(subdomain)) { return { valid: false, error: 'No consecutive hyphens allowed' }; } // Check reserved if (RESERVED_SUBDOMAINS.includes(subdomain)) { return { valid: false, error: 'This subdomain is reserved' }; } return { valid: true }; } // GET /api/user/subdomain - Get current subdomain export async function GET() { try { const userId = cookies().get('userId')?.value; if (!userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const user = await db.user.findUnique({ where: { id: userId }, select: { subdomain: true }, }); if (!user) { return NextResponse.json({ error: 'User not found' }, { status: 404 }); } return NextResponse.json({ subdomain: user.subdomain }); } catch (error) { console.error('Error fetching subdomain:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } } // POST /api/user/subdomain - Set subdomain export async function POST(request: NextRequest) { try { const userId = cookies().get('userId')?.value; if (!userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const body = await request.json(); const subdomain = body.subdomain?.trim().toLowerCase(); // Validate const validation = isValidSubdomain(subdomain); if (!validation.valid) { return NextResponse.json({ error: validation.error }, { status: 400 }); } // Check if already taken by another user const existing = await db.user.findFirst({ where: { subdomain, NOT: { id: userId }, }, }); if (existing) { return NextResponse.json({ error: 'This subdomain is already taken' }, { status: 409 }); } // Update user try { const updatedUser = await db.user.update({ where: { id: userId }, data: { subdomain }, select: { subdomain: true } // Only select needed fields }); return NextResponse.json({ success: true, subdomain: updatedUser.subdomain, url: `https://${updatedUser.subdomain}.qrmaster.net` }); } catch (error: any) { if (error.code === 'P2025') { return NextResponse.json({ error: 'User not found' }, { status: 404 }); } throw error; } } catch (error) { console.error('Error setting subdomain:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } } // DELETE /api/user/subdomain - Remove subdomain export async function DELETE() { try { const userId = cookies().get('userId')?.value; if (!userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } await db.user.update({ where: { id: userId }, data: { subdomain: null }, }); return NextResponse.json({ success: true }); } catch (error) { console.error('Error removing subdomain:', error); return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); } }