session.ts
Raw
1import { ADMIN_USERNAME } from "../constants.ts";
2import { db } from "../db";
3
4export interface SessionUser {
5 id: number;
6 username: string;
7 isAdmin: boolean;
8 avatar_version: number;
9 git_name: string | null;
10 git_email: string | null;
11}
12
13export async function resolveSession(
14 cookie: string | undefined,
15): Promise<SessionUser | null> {
16 if (!cookie) return null;
17 const now = new Date().toISOString();
18 const session = await db
19 .selectFrom("sessions")
20 .innerJoin("users", "users.id", "sessions.user_id")
21 .select([
22 "users.id",
23 "users.username",
24 "users.avatar_version",
25 "users.git_name",
26 "users.git_email",
27 "sessions.expires_at",
28 ])
29 .where("sessions.id", "=", cookie)
30 .where("sessions.expires_at", ">", now)
31 .executeTakeFirst();
32 if (!session) return null;
33 return {
34 id: session.id,
35 username: session.username,
36 isAdmin: session.username === ADMIN_USERNAME,
37 avatar_version: session.avatar_version,
38 git_name: session.git_name,
39 git_email: session.git_email,
40 };
41}
42
43export function requireAuth(user: SessionUser | null): Response | null {
44 if (!user) {
45 return new Response(null, {
46 status: 302,
47 headers: { Location: "/login" },
48 });
49 }
50 return null;
51}
52
53export function requireAdmin(user: SessionUser | null): Response | null {
54 if (!user) {
55 return new Response(null, {
56 status: 302,
57 headers: { Location: "/login" },
58 });
59 }
60 if (!user.isAdmin) {
61 return new Response("Forbidden", {
62 status: 403,
63 headers: { "Content-Type": "text/plain; charset=utf-8" },
64 });
65 }
66 return null;
67}
68