| 29 | * which 404s when unset so a newer image doesn't silently expose drains. |
| 30 | */ |
| 31 | export async function authorizeDrainAccess( |
| 32 | organizationId: string, |
| 33 | options: { requireMutating: boolean } |
| 34 | ): Promise<DrainAccessResult> { |
| 35 | const session = await getSession() |
| 36 | if (!session?.user?.id) { |
| 37 | return { ok: false, response: NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } |
| 38 | } |
| 39 | |
| 40 | const [memberEntry] = await db |
| 41 | .select({ role: member.role }) |
| 42 | .from(member) |
| 43 | .where(and(eq(member.organizationId, organizationId), eq(member.userId, session.user.id))) |
| 44 | .limit(1) |
| 45 | |
| 46 | if (!memberEntry) { |
| 47 | return { |
| 48 | ok: false, |
| 49 | response: NextResponse.json( |
| 50 | { error: 'Forbidden - Not a member of this organization' }, |
| 51 | { status: 403 } |
| 52 | ), |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | if (!isBillingEnabled && !isDataDrainsEnabled) { |
| 57 | return { |
| 58 | ok: false, |
| 59 | response: NextResponse.json( |
| 60 | { error: 'Data Drains are not enabled on this deployment' }, |
| 61 | { status: 404 } |
| 62 | ), |
| 63 | } |
| 64 | } |
| 65 | if (isBillingEnabled) { |
| 66 | const hasEnterprise = await isOrganizationOnEnterprisePlan(organizationId) |
| 67 | if (!hasEnterprise) { |
| 68 | return { |
| 69 | ok: false, |
| 70 | response: NextResponse.json( |
| 71 | { error: 'Data Drains are available on Enterprise plans only' }, |
| 72 | { status: 403 } |
| 73 | ), |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | if (memberEntry.role !== 'owner' && memberEntry.role !== 'admin') { |
| 78 | return { |
| 79 | ok: false, |
| 80 | response: NextResponse.json( |
| 81 | { |
| 82 | error: options.requireMutating |
| 83 | ? 'Forbidden - Only organization owners and admins can manage data drains' |
| 84 | : 'Forbidden - Only organization owners and admins can view data drains', |
| 85 | }, |
| 86 | { status: 403 } |
| 87 | ), |
| 88 | } |