94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
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,
|
|
}
|
|
};
|
|
}); |