1import type { RequestHandler } from '@sveltejs/kit';
2import type { LoginResponseSuccess, LoginResponseError } from '$lib/types/payloads';
3import db from '$lib/db/db.server';
4import { users } from '$lib/db/schema';
5import { eq } from 'drizzle-orm';
6import { verifyPassword } from '$lib/utils/password';
7import { generateSessionToken, createSession } from '$lib/api/session.server';
8import { setSessionTokenCookie } from '$lib/api/session.cookie';
9
10export const POST: RequestHandler = async ({ request, cookies }) => {
11 console.debug("POST /api/session/login called");
12
13 if (request.method !== 'POST') {
14 return new Response(JSON.stringify({ error: 'Method Not Allowed' } as LoginResponseError), { status: 405 });
15 }
16
17 let body: unknown;
18 try {
19 body = await request.json();
20 } catch (err) {
21 console.debug("Invalid JSON", err);
22 return new Response(JSON.stringify({ error: 'Invalid JSON' } as LoginResponseError), { status: 400 });
23 }
24
25 const { username, password } = body as { username: string, password: string };
26
27 if (typeof username !== 'string' || typeof password !== 'string') {
28 console.debug("Missing or invalid input fields", { username, password });
29 return new Response(JSON.stringify({ error: 'Missing or invalid input fields' } as LoginResponseError), { status: 400 });
30 }
31
32 // Find user by username
33 const user = await db.query.users.findFirst({
34 where: eq(users.nickname, username.trim())
35 });
36
37 if (!user) {
38 console.debug("User not found:", username);
39 return new Response(JSON.stringify({ error: 'Invalid username or password' } as LoginResponseError), { status: 401 });
40 }
41
42 // Verify password
43 try {
44 const isValid = await verifyPassword(password.trim(), user.password);
45 if (!isValid) {
46 console.debug("Invalid password for user:", username);
47 return new Response(JSON.stringify({ error: 'Invalid username or password' } as LoginResponseError), { status: 401 });
48 }
49 } catch (err) {
50 console.debug("Error verifying password", err);
51 return new Response(JSON.stringify({ error: 'Internal Server Error' } as LoginResponseError), { status: 500 });
52 }
53
54 // Generate session token and create session
55 const token = generateSessionToken();
56 const session = await createSession(token, user.id);
57
58 // Update user status to online
59 await db.update(users)
60 .set({
61 status: 'online',
62 lastSeen: Date.now()
63 })
64 .where(eq(users.id, user.id));
65
66 // Set session cookie
67 setSessionTokenCookie({ cookies }, token, session.expiresAt);
68
69 return new Response(JSON.stringify({
70 success: true,
71 user: {
72 id: user.id,
73 nickname: user.nickname,
74 status: 'online',
75 avatarUrl: user.avatarUrl,
76 lastSeen: Date.now()
77 }
78 } as LoginResponseSuccess), {
79 status: 200
80 });
81};