mirror of
https://github.com/hex248/sprint.git
synced 2026-02-08 02:33:01 +00:00
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { LoginRequestSchema } from "@sprint/shared";
|
|
import type { BunRequest } from "bun";
|
|
import { buildAuthCookie, generateToken, verifyPassword } from "../../auth/utils";
|
|
import { createSession, getUserByUsername } from "../../db/queries";
|
|
import { errorResponse, parseJsonBody } from "../../validation";
|
|
|
|
export default async function login(req: BunRequest) {
|
|
if (req.method !== "POST") {
|
|
return errorResponse("method not allowed", "METHOD_NOT_ALLOWED", 405);
|
|
}
|
|
|
|
const parsed = await parseJsonBody(req, LoginRequestSchema);
|
|
if ("error" in parsed) return parsed.error;
|
|
|
|
const { username, password } = parsed.data;
|
|
|
|
const user = await getUserByUsername(username);
|
|
if (!user) {
|
|
return errorResponse("invalid credentials", "INVALID_CREDENTIALS", 401);
|
|
}
|
|
|
|
const ok = await verifyPassword(password, user.passwordHash);
|
|
if (!ok) {
|
|
return errorResponse("invalid credentials", "INVALID_CREDENTIALS", 401);
|
|
}
|
|
|
|
const session = await createSession(user.id);
|
|
if (!session) {
|
|
return errorResponse("failed to create session", "SESSION_ERROR", 500);
|
|
}
|
|
|
|
const token = generateToken(session.id, user.id);
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
user: {
|
|
id: user.id,
|
|
name: user.name,
|
|
username: user.username,
|
|
avatarURL: user.avatarURL,
|
|
iconPreference: user.iconPreference,
|
|
emailVerified: user.emailVerified,
|
|
},
|
|
csrfToken: session.csrfToken,
|
|
}),
|
|
{
|
|
status: 200,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Set-Cookie": buildAuthCookie(token),
|
|
},
|
|
},
|
|
);
|
|
}
|