25 lines
1.2 KiB
TypeScript
25 lines
1.2 KiB
TypeScript
// API route: POST /api/login. Validates the body with the SAME schema the form
|
|
// uses on the client, then checks the password hash and starts a session.
|
|
import { verifyCsrf, verifyPassword, logIn, type Context } from "@wrnexus/core";
|
|
import { getDb } from "@wrnexus/db";
|
|
import { parseBody } from "@wrnexus/validation";
|
|
import login from "../schemas/login.ts";
|
|
import { GetUserByEmail } from "../db/queries.gen.ts";
|
|
|
|
export async function POST(ctx: Context): Promise<Response> {
|
|
if (!verifyCsrf(ctx)) return new Response("Invalid CSRF token", { status: 403 });
|
|
|
|
const result = await parseBody(login, ctx.req);
|
|
if (!result.ok) return result.response; // 400 { ok:false, errors }
|
|
|
|
const { email, password } = result.value as { email: string; password: string };
|
|
const user = await GetUserByEmail(getDb(), { email });
|
|
if (!user || !(await verifyPassword(password, user.passwordHash))) {
|
|
return Response.json({ ok: false, error: "Invalid email or password" }, { status: 401 });
|
|
}
|
|
|
|
// Store only safe fields in the session — never the password hash.
|
|
logIn(ctx, { id: user.id, email: user.email, name: user.name });
|
|
return Response.json({ ok: true, user: { id: user.id, email: user.email, name: user.name } });
|
|
}
|