38 lines
2 KiB
TypeScript
38 lines
2 KiB
TypeScript
import { cookies } from "next/headers";
|
|
import PocketBase from "pocketbase";
|
|
import { initialDestination } from "@/lib/auth/access";
|
|
import { authMode, SESSION_COOKIE, userFromRecord } from "@/lib/auth/session";
|
|
import { PB_URL } from "@/lib/pb";
|
|
import { canAccessPath } from "@/lib/auth/path-access";
|
|
|
|
export async function POST(request: Request): Promise<Response> {
|
|
if (authMode() !== "users") return Response.json({ error: "Named login is not enabled" }, { status: 404 });
|
|
let body: Record<string, unknown>;
|
|
try { body = await request.json(); }
|
|
catch { return Response.json({ error: "Enter your email and password" }, { status: 400 }); }
|
|
const email = typeof body.email === "string" ? body.email.trim().toLowerCase() : "";
|
|
const password = typeof body.password === "string" ? body.password : "";
|
|
if (!email || !password) return Response.json({ error: "Enter your email and password" }, { status: 400 });
|
|
|
|
const pb = new PocketBase(PB_URL);
|
|
try {
|
|
const result = await pb.collection("users").authWithPassword(email, password);
|
|
const user = userFromRecord(result.record);
|
|
if (!user) return Response.json({ error: "Invalid email or password" }, { status: 401 });
|
|
(await cookies()).set(SESSION_COOKIE, pb.authStore.token, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === "production",
|
|
sameSite: "lax",
|
|
path: "/",
|
|
maxAge: 5 * 24 * 60 * 60,
|
|
});
|
|
let landing = initialDestination(user);
|
|
if (!user.mustChangePassword && typeof body.redirect === "string" && body.redirect.startsWith("/") && !body.redirect.startsWith("//")) {
|
|
const target = new URL(body.redirect, "http://app.local");
|
|
if (target.origin === "http://app.local" && !target.pathname.startsWith("/api/") && canAccessPath(user, target.pathname)) landing = `${target.pathname}${target.search}${target.hash}`;
|
|
}
|
|
return Response.json({ user: { id: user.id, name: user.name, role: user.role }, landing });
|
|
} catch {
|
|
return Response.json({ error: "Invalid email or password" }, { status: 401 });
|
|
}
|
|
}
|