import { hashPassword } from '~/server/utils/password'; import { generateVillageForUser } from '~/server/services/villageService'; import { useSession } from 'h3'; const ANONYMOUS_COOKIE_NAME = 'smurf-anonymous-session'; /** * Handles user registration. * * This endpoint has two main flows: * 1. Anonymous User Conversion: If an anonymous session cookie is present, * it finds the anonymous user, updates their details, makes them permanent, * and logs them in, preserving their progress. * 2. Standard Registration: If no anonymous session is found, it creates a * brand new user and a new village for them. * * In both cases, it automatically logs the user in upon successful registration. */ export default defineEventHandler(async (event) => { const { email, password, nickname } = await readBody(event); // --- 1. Input Validation --- if (!email || !password) { throw createError({ statusCode: 400, statusMessage: 'Email and password are required' }); } if (password.length < 8) { throw createError({ statusCode: 400, statusMessage: 'Password must be at least 8 characters long' }); } const normalizedEmail = email.toLowerCase(); // Check if email is already in use by a permanent account const existingPermanentUser = await prisma.user.findFirst({ where: { email: normalizedEmail, isAnonymous: false }, }); if (existingPermanentUser) { throw createError({ statusCode: 409, statusMessage: 'Email already in use' }); } const hashedPassword = await hashPassword(password); let user; // --- 2. Identify User Flow (Anonymous Conversion vs. Standard) --- const anonymousSessionId = getCookie(event, ANONYMOUS_COOKIE_NAME); const anonymousUser = anonymousSessionId ? await prisma.user.findUnique({ where: { anonymousSessionId } }) : null; if (anonymousUser) { // --- Flow A: Convert Anonymous User --- user = await prisma.user.update({ where: { id: anonymousUser.id }, data: { email: normalizedEmail, password: hashedPassword, nickname: nickname || 'New Smurf', isAnonymous: false, // Make the user permanent anonymousSessionId: null, // Invalidate the anonymous session ID }, }); // The village and progress are already associated with this user. // Invalidate the anonymous cookie setCookie(event, ANONYMOUS_COOKIE_NAME, '', { maxAge: -1 }); } else { // --- Flow B: Create New User --- user = await prisma.user.create({ data: { email: normalizedEmail, password: hashedPassword, nickname: nickname || 'New Smurf', isAnonymous: false, }, }); // Generate a new village for the brand new user await generateVillageForUser(user); } // --- 3. Automatically log the user in --- const session = await useSession(event, { password: process.env.SESSION_PASSWORD! }); await session.update({ user: { id: user.id } }); // --- 4. Return DTO --- return { user: { id: user.id, email: user.email, nickname: user.nickname, } }; });