File
Blob: src/worker/lib/membership.ts
| 1 | import { and, eq } from "drizzle-orm"; |
| 2 | import type { Context } from "hono"; |
| 3 | |
| 4 | import { memberships } from "@/worker/db/d1/schema"; |
| 5 | import type { Db } from "@/worker/db/d1/client"; |
| 6 | |
| 7 | export 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 | */ |
| 24 | export 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 | } |