馃 distributed transcription service
thistle.dunkirk.sh
1// Helper functions for route authentication and error handling
2
3import db from "../db/schema";
4import type { User } from "./auth";
5import { getSessionFromRequest, getUserBySession } from "./auth";
6import { AuthErrors } from "./errors";
7
8export interface AuthenticatedRequest extends Request {
9 user: User;
10}
11
12export function requireAuth(req: Request): User {
13 const sessionId = getSessionFromRequest(req);
14 if (!sessionId) {
15 throw AuthErrors.required();
16 }
17
18 const user = getUserBySession(sessionId);
19 if (!user) {
20 throw AuthErrors.invalidSession();
21 }
22
23 return user;
24}
25
26export function requireAdmin(req: Request): User {
27 const user = requireAuth(req);
28
29 if (user.role !== "admin") {
30 throw AuthErrors.adminRequired();
31 }
32
33 return user;
34}
35
36export function hasActiveSubscription(userId: number): boolean {
37 const subscription = db
38 .query<{ status: string }, [number]>(
39 "SELECT status FROM subscriptions WHERE user_id = ? AND status IN ('active', 'trialing', 'past_due') ORDER BY created_at DESC LIMIT 1",
40 )
41 .get(userId);
42
43 return !!subscription;
44}
45
46export function requireSubscription(req: Request): User {
47 const user = requireAuth(req);
48
49 // Admins bypass subscription requirement
50 if (user.role === "admin") {
51 return user;
52 }
53
54 if (!hasActiveSubscription(user.id)) {
55 throw AuthErrors.subscriptionRequired();
56 }
57
58 return user;
59}