( request: Request, )
| 72 | * the return value means no admin read can accidentally become subject-scoped. |
| 73 | */ |
| 74 | const authorizeTenant = ( |
| 75 | request: Request, |
| 76 | ): Effect.Effect< |
| 77 | string, |
| 78 | AdminUsersUnauthorized | AdminUsersForbidden, |
| 79 | WorkOSClient | ApiKeyService | UserStoreService |
| 80 | > => |
| 81 | Effect.gen(function* () { |
| 82 | // (1) The bearer path. `resolveBearerAuth` (not `resolveApiKeyPrincipal`, |
| 83 | // which rejects org keys for the product plane) is what distinguishes an |
| 84 | // org key from a user key. |
| 85 | const bearer = yield* resolveBearerAuth(request).pipe( |
| 86 | // Every rejected-credential and infra failure collapses to one refusal: |
| 87 | // this plane must not report whether a key exists, belongs to another |
| 88 | // org, or merely lacks privilege. |
| 89 | Effect.catchCause(() => Effect.succeed(null)), |
| 90 | ); |
| 91 | if (bearer !== null) { |
| 92 | if (isPlatformAuth(bearer)) return bearer.organizationId; |
| 93 | // A user-scoped key authenticated fine but names one member; the platform |
| 94 | // plane has no honest way to serve it. |
| 95 | return yield* new AdminUsersForbidden(); |
| 96 | } |
| 97 | |
| 98 | // (2) The session path: a live admin membership in the selected org. |
| 99 | const workos = yield* WorkOSClient; |
| 100 | const session = yield* workos |
| 101 | .authenticateRequest(request) |
| 102 | .pipe(Effect.catchCause(() => Effect.succeed(null))); |
| 103 | if (!session) return yield* new AdminUsersUnauthorized(); |
| 104 | |
| 105 | const selector = orgSelectorFromRequest(request) ?? session.organizationId; |
| 106 | if (!selector) return yield* new AdminUsersForbidden(); |
| 107 | // Re-checks live membership, so the org selector header can only ever name |
| 108 | // an org the caller already belongs to. |
| 109 | const org = yield* authorizeOrganizationSelector(session.userId, selector).pipe( |
| 110 | Effect.catchCause(() => Effect.succeed(null)), |
| 111 | ); |
| 112 | if (!org) return yield* new AdminUsersForbidden(); |
| 113 | |
| 114 | const membership = yield* workos |
| 115 | .getUserOrgMembership(org.id, session.userId) |
| 116 | .pipe(Effect.catchCause(() => Effect.succeed(null))); |
| 117 | // A pending admin invite is not an active admin — require both. |
| 118 | if (!membership || membership.status !== "active" || membership.role?.slug !== "admin") { |
| 119 | return yield* new AdminUsersForbidden(); |
| 120 | } |
| 121 | return org.id; |
| 122 | }); |
| 123 | |
| 124 | /** |
| 125 | * How many user-detail reads run at once. Matches the account plane's own |
no test coverage detected