Skip to content
File

Blob: src/worker/lib/membership.ts

typescript40 lines
1import { and, eq } from "drizzle-orm";
2import type { Context } from "hono";
3 
4import { memberships } from "@/worker/db/d1/schema";
5import type { Db } from "@/worker/db/d1/client";
6 
7export async function checkMembership(
8 db: Db,
9 userId: string,
10 workspaceId: string,
11): Promise<typeof memberships.$inferSelect | null> {
12 const result = await db
13 .select()
14 .from(memberships)
15 .where(and(eq(memberships.user_id, userId), eq(memberships.workspace_id, workspaceId)))
16 .get();
17 return result ?? null;
18}
19 
20/**
21 * Check membership and return it, or send a 403 response.
22 * Optionally rejects guests when `rejectGuest` is true.
23 */
24export async function requireMembership(
25 c: Context,
26 db: Db,
27 userId: string,
28 workspaceId: string,
29 rejectGuest?: boolean,
30): Promise<typeof memberships.$inferSelect | Response> {
31 const membership = await checkMembership(db, userId, workspaceId);
32 if (!membership) {
33 return c.json({ error: "forbidden", message: "You are not a member of this workspace" }, 403);
34 }
35 if (rejectGuest && membership.role === "guest") {
36 return c.json({ error: "forbidden", message: "Guests cannot access this resource" }, 403);
37 }
38 return membership;
39}