@robelest/convex-auth 0.0.4-preview.22 → 0.0.4-preview.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -11
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/index.js.map +1 -1
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +36 -39
- package/dist/client/index.js.map +1 -1
- package/dist/component/client/index.d.ts +1 -2
- package/dist/component/index.js +2 -2
- package/dist/component/model.d.ts +9 -9
- package/dist/component/model.d.ts.map +1 -1
- package/dist/component/public/enterprise/audit.d.ts.map +1 -1
- package/dist/component/public/enterprise/audit.js.map +1 -1
- package/dist/component/public/enterprise/core.d.ts.map +1 -1
- package/dist/component/public/enterprise/core.js.map +1 -1
- package/dist/component/public/enterprise/domains.d.ts.map +1 -1
- package/dist/component/public/enterprise/domains.js.map +1 -1
- package/dist/component/public/enterprise/scim.d.ts.map +1 -1
- package/dist/component/public/enterprise/scim.js.map +1 -1
- package/dist/component/public/enterprise/secrets.d.ts.map +1 -1
- package/dist/component/public/enterprise/secrets.js.map +1 -1
- package/dist/component/public/enterprise/webhooks.d.ts.map +1 -1
- package/dist/component/public/enterprise/webhooks.js.map +1 -1
- package/dist/component/public/factors/devices.d.ts.map +1 -1
- package/dist/component/public/factors/devices.js.map +1 -1
- package/dist/component/public/factors/passkeys.d.ts.map +1 -1
- package/dist/component/public/factors/passkeys.js.map +1 -1
- package/dist/component/public/factors/totp.d.ts.map +1 -1
- package/dist/component/public/factors/totp.js.map +1 -1
- package/dist/component/public/groups/core.js.map +1 -1
- package/dist/component/public/groups/invites.d.ts.map +1 -1
- package/dist/component/public/groups/invites.js.map +1 -1
- package/dist/component/public/groups/members.d.ts.map +1 -1
- package/dist/component/public/groups/members.js.map +1 -1
- package/dist/component/public/identity/accounts.d.ts.map +1 -1
- package/dist/component/public/identity/accounts.js.map +1 -1
- package/dist/component/public/identity/codes.d.ts.map +1 -1
- package/dist/component/public/identity/codes.js.map +1 -1
- package/dist/component/public/identity/sessions.d.ts.map +1 -1
- package/dist/component/public/identity/sessions.js.map +1 -1
- package/dist/component/public/identity/tokens.d.ts.map +1 -1
- package/dist/component/public/identity/tokens.js.map +1 -1
- package/dist/component/public/identity/users.d.ts.map +1 -1
- package/dist/component/public/identity/users.js.map +1 -1
- package/dist/component/public/identity/verifiers.d.ts.map +1 -1
- package/dist/component/public/identity/verifiers.js.map +1 -1
- package/dist/component/public/security/keys.d.ts.map +1 -1
- package/dist/component/public/security/keys.js.map +1 -1
- package/dist/component/public/security/limits.d.ts.map +1 -1
- package/dist/component/public/security/limits.js.map +1 -1
- package/dist/component/schema.d.ts +41 -41
- package/dist/component/server/auth.d.ts +127 -130
- package/dist/component/server/auth.d.ts.map +1 -1
- package/dist/component/server/auth.js +100 -64
- package/dist/component/server/auth.js.map +1 -1
- package/dist/component/server/context.js +53 -0
- package/dist/component/server/context.js.map +1 -0
- package/dist/component/server/core.js +113 -250
- package/dist/component/server/core.js.map +1 -1
- package/dist/component/server/crypto.js +25 -7
- package/dist/component/server/crypto.js.map +1 -1
- package/dist/component/server/device.js +59 -16
- package/dist/component/server/device.js.map +1 -1
- package/dist/component/server/enterprise/domain.js +148 -59
- package/dist/component/server/enterprise/domain.js.map +1 -1
- package/dist/component/server/enterprise/http.js +36 -15
- package/dist/component/server/enterprise/http.js.map +1 -1
- package/dist/component/server/enterprise/oidc.js +1 -1
- package/dist/component/server/http.d.ts +85 -0
- package/dist/component/server/http.d.ts.map +1 -0
- package/dist/component/server/http.js +85 -22
- package/dist/component/server/http.js.map +1 -1
- package/dist/component/server/identity.js +5 -2
- package/dist/component/server/identity.js.map +1 -1
- package/dist/component/server/limits.js +21 -30
- package/dist/component/server/limits.js.map +1 -1
- package/dist/component/server/mutations/account.js +12 -10
- package/dist/component/server/mutations/account.js.map +1 -1
- package/dist/component/server/mutations/code.js +5 -2
- package/dist/component/server/mutations/code.js.map +1 -1
- package/dist/component/server/mutations/invalidate.js +1 -1
- package/dist/component/server/mutations/invalidate.js.map +1 -1
- package/dist/component/server/mutations/oauth.js +10 -4
- package/dist/component/server/mutations/oauth.js.map +1 -1
- package/dist/component/server/mutations/refresh.js +2 -2
- package/dist/component/server/mutations/refresh.js.map +1 -1
- package/dist/component/server/mutations/register.js +46 -42
- package/dist/component/server/mutations/register.js.map +1 -1
- package/dist/component/server/mutations/retrieve.js +21 -25
- package/dist/component/server/mutations/retrieve.js.map +1 -1
- package/dist/component/server/mutations/signature.js +10 -4
- package/dist/component/server/mutations/signature.js.map +1 -1
- package/dist/component/server/mutations/signout.js.map +1 -1
- package/dist/component/server/mutations/store.js +9 -24
- package/dist/component/server/mutations/store.js.map +1 -1
- package/dist/component/server/mutations/verifier.js.map +1 -1
- package/dist/component/server/mutations/verify.js +1 -1
- package/dist/component/server/mutations/verify.js.map +1 -1
- package/dist/component/server/oauth.js +53 -16
- package/dist/component/server/oauth.js.map +1 -1
- package/dist/component/server/passkey.js +115 -31
- package/dist/component/server/passkey.js.map +1 -1
- package/dist/component/server/redirects.js +9 -3
- package/dist/component/server/redirects.js.map +1 -1
- package/dist/component/server/refresh.js +10 -7
- package/dist/component/server/refresh.js.map +1 -1
- package/dist/component/server/runtime.d.ts +5 -5
- package/dist/component/server/runtime.js +156 -113
- package/dist/component/server/runtime.js.map +1 -1
- package/dist/component/server/signin.js +34 -10
- package/dist/component/server/signin.js.map +1 -1
- package/dist/component/server/totp.js +79 -19
- package/dist/component/server/totp.js.map +1 -1
- package/dist/component/server/types.d.ts +12 -20
- package/dist/component/server/types.d.ts.map +1 -1
- package/dist/component/server/types.js.map +1 -1
- package/dist/component/server/users.js +6 -3
- package/dist/component/server/users.js.map +1 -1
- package/dist/component/server/utils.js +10 -4
- package/dist/component/server/utils.js.map +1 -1
- package/dist/core/types.d.ts +14 -22
- package/dist/core/types.d.ts.map +1 -1
- package/dist/factors/device.js +8 -9
- package/dist/factors/device.js.map +1 -1
- package/dist/factors/passkey.js +18 -21
- package/dist/factors/passkey.js.map +1 -1
- package/dist/providers/password.js +66 -81
- package/dist/providers/password.js.map +1 -1
- package/dist/runtime/invite.js +2 -8
- package/dist/runtime/invite.js.map +1 -1
- package/dist/server/auth.d.ts +127 -130
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +100 -64
- package/dist/server/auth.js.map +1 -1
- package/dist/server/context.d.ts +1 -0
- package/dist/server/context.js +53 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/core.d.ts +74 -195
- package/dist/server/core.d.ts.map +1 -1
- package/dist/server/core.js +113 -250
- package/dist/server/core.js.map +1 -1
- package/dist/server/crypto.d.ts.map +1 -1
- package/dist/server/crypto.js +25 -7
- package/dist/server/crypto.js.map +1 -1
- package/dist/server/device.js +59 -16
- package/dist/server/device.js.map +1 -1
- package/dist/server/enterprise/domain.d.ts +0 -8
- package/dist/server/enterprise/domain.d.ts.map +1 -1
- package/dist/server/enterprise/domain.js +148 -59
- package/dist/server/enterprise/domain.js.map +1 -1
- package/dist/server/enterprise/http.d.ts.map +1 -1
- package/dist/server/enterprise/http.js +35 -14
- package/dist/server/enterprise/http.js.map +1 -1
- package/dist/server/http.d.ts +81 -3
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +84 -21
- package/dist/server/http.js.map +1 -1
- package/dist/server/identity.js +5 -2
- package/dist/server/identity.js.map +1 -1
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +2 -2
- package/dist/server/limits.js +21 -30
- package/dist/server/limits.js.map +1 -1
- package/dist/server/mounts.d.ts +25 -63
- package/dist/server/mounts.d.ts.map +1 -1
- package/dist/server/mounts.js +46 -107
- package/dist/server/mounts.js.map +1 -1
- package/dist/server/mutations/account.d.ts +8 -9
- package/dist/server/mutations/account.d.ts.map +1 -1
- package/dist/server/mutations/account.js +11 -9
- package/dist/server/mutations/account.js.map +1 -1
- package/dist/server/mutations/code.d.ts +12 -12
- package/dist/server/mutations/code.d.ts.map +1 -1
- package/dist/server/mutations/code.js +5 -2
- package/dist/server/mutations/code.js.map +1 -1
- package/dist/server/mutations/invalidate.d.ts +4 -4
- package/dist/server/mutations/invalidate.d.ts.map +1 -1
- package/dist/server/mutations/invalidate.js.map +1 -1
- package/dist/server/mutations/oauth.d.ts +14 -12
- package/dist/server/mutations/oauth.d.ts.map +1 -1
- package/dist/server/mutations/oauth.js +9 -3
- package/dist/server/mutations/oauth.js.map +1 -1
- package/dist/server/mutations/refresh.d.ts +3 -3
- package/dist/server/mutations/refresh.d.ts.map +1 -1
- package/dist/server/mutations/refresh.js +1 -1
- package/dist/server/mutations/refresh.js.map +1 -1
- package/dist/server/mutations/register.d.ts +11 -11
- package/dist/server/mutations/register.d.ts.map +1 -1
- package/dist/server/mutations/register.js +45 -41
- package/dist/server/mutations/register.js.map +1 -1
- package/dist/server/mutations/retrieve.d.ts +6 -6
- package/dist/server/mutations/retrieve.d.ts.map +1 -1
- package/dist/server/mutations/retrieve.js +20 -24
- package/dist/server/mutations/retrieve.js.map +1 -1
- package/dist/server/mutations/signature.d.ts +6 -7
- package/dist/server/mutations/signature.d.ts.map +1 -1
- package/dist/server/mutations/signature.js +9 -3
- package/dist/server/mutations/signature.js.map +1 -1
- package/dist/server/mutations/signin.d.ts +5 -5
- package/dist/server/mutations/signout.js.map +1 -1
- package/dist/server/mutations/store.d.ts +83 -83
- package/dist/server/mutations/store.js +8 -23
- package/dist/server/mutations/store.js.map +1 -1
- package/dist/server/mutations/verifier.js.map +1 -1
- package/dist/server/mutations/verify.d.ts +7 -7
- package/dist/server/mutations/verify.d.ts.map +1 -1
- package/dist/server/mutations/verify.js.map +1 -1
- package/dist/server/oauth.js +53 -16
- package/dist/server/oauth.js.map +1 -1
- package/dist/server/passkey.d.ts +2 -2
- package/dist/server/passkey.d.ts.map +1 -1
- package/dist/server/passkey.js +114 -30
- package/dist/server/passkey.js.map +1 -1
- package/dist/server/redirects.js +9 -3
- package/dist/server/redirects.js.map +1 -1
- package/dist/server/refresh.js +10 -7
- package/dist/server/refresh.js.map +1 -1
- package/dist/server/runtime.d.ts +11 -11
- package/dist/server/runtime.js +155 -112
- package/dist/server/runtime.js.map +1 -1
- package/dist/server/signin.js +34 -10
- package/dist/server/signin.js.map +1 -1
- package/dist/server/ssr.d.ts.map +1 -1
- package/dist/server/ssr.js +175 -184
- package/dist/server/ssr.js.map +1 -1
- package/dist/server/totp.js +78 -18
- package/dist/server/totp.js.map +1 -1
- package/dist/server/types.d.ts +13 -21
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js.map +1 -1
- package/dist/server/users.js +6 -3
- package/dist/server/users.js.map +1 -1
- package/dist/server/utils.js +10 -4
- package/dist/server/utils.js.map +1 -1
- package/package.json +1 -5
- package/src/authorization/index.ts +1 -1
- package/src/client/core/types.ts +14 -14
- package/src/client/factors/device.ts +10 -12
- package/src/client/factors/passkey.ts +23 -26
- package/src/client/index.ts +54 -64
- package/src/client/runtime/invite.ts +5 -7
- package/src/component/index.ts +9 -3
- package/src/component/public/enterprise/audit.ts +6 -1
- package/src/component/public/enterprise/core.ts +1 -0
- package/src/component/public/enterprise/domains.ts +5 -1
- package/src/component/public/enterprise/scim.ts +1 -0
- package/src/component/public/enterprise/secrets.ts +1 -0
- package/src/component/public/enterprise/webhooks.ts +1 -0
- package/src/component/public/factors/devices.ts +1 -0
- package/src/component/public/factors/passkeys.ts +1 -0
- package/src/component/public/factors/totp.ts +1 -0
- package/src/component/public/groups/core.ts +1 -1
- package/src/component/public/groups/invites.ts +7 -1
- package/src/component/public/groups/members.ts +1 -0
- package/src/component/public/identity/accounts.ts +1 -0
- package/src/component/public/identity/codes.ts +1 -0
- package/src/component/public/identity/sessions.ts +1 -0
- package/src/component/public/identity/tokens.ts +1 -0
- package/src/component/public/identity/users.ts +1 -0
- package/src/component/public/identity/verifiers.ts +1 -0
- package/src/component/public/security/keys.ts +1 -0
- package/src/component/public/security/limits.ts +1 -0
- package/src/providers/password.ts +89 -110
- package/src/server/auth.ts +240 -182
- package/src/server/context.ts +90 -0
- package/src/server/core.ts +195 -286
- package/src/server/crypto.ts +31 -29
- package/src/server/device.ts +65 -32
- package/src/server/enterprise/domain.ts +158 -170
- package/src/server/enterprise/http.ts +46 -39
- package/src/server/http.ts +289 -30
- package/src/server/identity.ts +5 -5
- package/src/server/index.ts +9 -3
- package/src/server/limits.ts +53 -80
- package/src/server/mounts.ts +56 -80
- package/src/server/mutations/account.ts +22 -36
- package/src/server/mutations/code.ts +6 -6
- package/src/server/mutations/invalidate.ts +1 -1
- package/src/server/mutations/oauth.ts +14 -8
- package/src/server/mutations/refresh.ts +5 -4
- package/src/server/mutations/register.ts +87 -132
- package/src/server/mutations/retrieve.ts +44 -44
- package/src/server/mutations/signature.ts +13 -6
- package/src/server/mutations/signout.ts +1 -1
- package/src/server/mutations/store.ts +16 -31
- package/src/server/mutations/verifier.ts +1 -1
- package/src/server/mutations/verify.ts +3 -5
- package/src/server/oauth.ts +60 -69
- package/src/server/passkey.ts +567 -517
- package/src/server/redirects.ts +10 -6
- package/src/server/refresh.ts +14 -18
- package/src/server/runtime.ts +340 -302
- package/src/server/signin.ts +44 -37
- package/src/server/ssr.ts +390 -407
- package/src/server/totp.ts +85 -35
- package/src/server/types.ts +19 -22
- package/src/server/users.ts +7 -6
- package/src/server/utils.ts +10 -12
- package/dist/component/server/authError.js +0 -34
- package/dist/component/server/authError.js.map +0 -1
- package/dist/component/server/errors.d.ts +0 -1
- package/dist/component/server/errors.js +0 -137
- package/dist/component/server/errors.js.map +0 -1
- package/dist/server/authError.d.ts +0 -46
- package/dist/server/authError.d.ts.map +0 -1
- package/dist/server/authError.js +0 -34
- package/dist/server/authError.js.map +0 -1
- package/dist/server/errors.d.ts +0 -177
- package/dist/server/errors.d.ts.map +0 -1
- package/dist/server/errors.js +0 -212
- package/dist/server/errors.js.map +0 -1
- package/src/server/authError.ts +0 -44
- package/src/server/errors.ts +0 -290
package/dist/server/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","names":["result","parseCookies"],"sources":["../../src/server/http.ts"],"sourcesContent":["import {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n httpActionGeneric,\n} from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { parse as parseCookies } from \"cookie\";\n\nimport { isAuthError } from \"./errors\";\nimport { Fx } from \"@robelest/fx\";\n\nimport { AuthError } from \"./authError\";\nimport type { CorsConfig, HttpKeyContext } from \"./types\";\nimport { logError } from \"./utils\";\n\nexport function createHttpAction(auth: {\n key: { verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<any> };\n}) {\n return (\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>,\n options?: {\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = options?.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n return httpActionGeneric(async (genericCtx, request) => {\n return Fx.run(\n Fx.from({\n ok: async () => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return new Response(\n JSON.stringify({\n error: \"Missing or malformed Authorization: Bearer header.\",\n code: \"MISSING_BEARER_TOKEN\",\n }),\n {\n status: 401,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n const rawKey = authHeader.slice(7);\n\n const keyResult = await Fx.run(\n Fx.from({\n ok: () => auth.key.verify(genericCtx, rawKey),\n err: (error) => error,\n }).pipe(\n Fx.fold({\n ok: (result) => ({ ok: true, value: result }) as const,\n err: (error) => ({ ok: false, error }) as const,\n }),\n ),\n );\n\n if (!keyResult.ok) {\n if (isAuthError(keyResult.error)) {\n const { code, message } = keyResult.error.data as {\n code: string;\n message: string;\n };\n return new Response(JSON.stringify({ error: message, code }), {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n throw keyResult.error;\n }\n\n if (\n options?.scope &&\n !keyResult.value.scopes.can(\n options.scope.resource,\n options.scope.action,\n )\n ) {\n return new Response(\n JSON.stringify({\n error: \"This API key does not have the required permissions.\",\n code: \"SCOPE_CHECK_FAILED\",\n }),\n {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n\n const enrichedCtx = Object.assign(genericCtx, {\n key: {\n userId: keyResult.value.userId,\n keyId: keyResult.value.keyId,\n scopes: keyResult.value.scopes,\n },\n });\n const result = await handler(enrichedCtx, request);\n\n if (result instanceof Response) {\n const headers = new Headers(result.headers);\n for (const [k, val] of Object.entries(corsHeaders)) {\n if (!headers.has(k)) headers.set(k, val);\n }\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers,\n });\n }\n\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n return Fx.succeed(\n new Response(\n JSON.stringify({\n error: \"An unexpected error occurred.\",\n code: \"INTERNAL_ERROR\",\n }),\n {\n status: 500,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n ),\n );\n }),\n ),\n );\n });\n };\n}\n\nexport function createHttpRoute(\n wrapAction: ReturnType<typeof createHttpAction>,\n) {\n return (\n http: { route: (config: any) => void },\n routeConfig: {\n path: string;\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>;\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = routeConfig.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n http.route({\n path: routeConfig.path,\n method: \"OPTIONS\",\n handler: httpActionGeneric(async () => {\n return new Response(null, { status: 204, headers: corsHeaders });\n }),\n });\n\n http.route({\n path: routeConfig.path,\n method: routeConfig.method,\n handler: wrapAction(routeConfig.handler, {\n scope: routeConfig.scope,\n cors: routeConfig.cors,\n }),\n });\n };\n}\n\nexport function convertErrorsToResponse(\n errorStatusCode: number,\n action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>,\n) {\n return async (ctx: GenericActionCtx<any>, request: Request) => {\n return Fx.run(\n Fx.from({\n ok: () => action(ctx, request),\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n if (isAuthError(error)) {\n return Fx.succeed(\n new Response(\n JSON.stringify({\n code: error.data.code,\n message: error.data.message,\n }),\n {\n status: errorStatusCode,\n headers: { \"Content-Type\": \"application/json\" },\n },\n ),\n );\n } else if (error instanceof ConvexError) {\n return Fx.succeed(\n new Response(null, {\n status: errorStatusCode,\n statusText:\n typeof error.data === \"string\" ? error.data : \"Error\",\n }),\n );\n } else {\n logError(error);\n return Fx.succeed(\n new Response(null, {\n status: 500,\n statusText: \"Internal Server Error\",\n }),\n );\n }\n }),\n ),\n );\n };\n}\n\nexport function getCookies(\n request: Request,\n): Record<string, string | undefined> {\n return parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n}\n\nexport type SSORuntimeRoute = {\n pathname?: string;\n enterpriseId: string;\n protocol: \"oidc\" | \"saml\" | \"scim\";\n rest: string[];\n};\n\nfunction parseEnterpriseRuntimeRoute(\n pathname: string,\n routeBase: string,\n): SSORuntimeRoute | null {\n const runtimePrefix = `${routeBase}/`;\n const runtimeParts = pathname.startsWith(runtimePrefix)\n ? pathname.slice(runtimePrefix.length).split(\"/\").filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n if (\n runtimeEnterpriseId === undefined ||\n (protocol !== \"oidc\" && protocol !== \"saml\" && protocol !== \"scim\") ||\n rest.length === 0\n ) {\n return null;\n }\n return {\n pathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n };\n}\n\nexport function addOpenIdRoutes(\n http: HttpRouter,\n deps: {\n getIssuer: () => string;\n getJwks: () => string;\n },\n) {\n const cacheControl =\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\";\n\n http.route({\n path: \"/.well-known/openid-configuration\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n const issuer = deps.getIssuer();\n return new Response(\n JSON.stringify({\n issuer,\n jwks_uri: `${issuer}/.well-known/jwks.json`,\n }),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n },\n );\n }),\n });\n\n http.route({\n path: \"/.well-known/jwks.json\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n return new Response(deps.getJwks(), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n });\n }),\n });\n}\n\nexport function addAuthRoutes(\n http: HttpRouter,\n deps: {\n handleSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n handleCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n },\n) {\n http.route({\n pathPrefix: \"/api/auth/signin/\",\n method: \"GET\",\n handler: httpActionGeneric(deps.handleSignIn),\n });\n\n const callbackHandler = httpActionGeneric(deps.handleCallback);\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"GET\",\n handler: callbackHandler,\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"POST\",\n handler: callbackHandler,\n });\n}\n\nexport function addSSORoutes(\n http: HttpRouter,\n deps: {\n routeBase: string;\n convertErrorsToResponse: typeof convertErrorsToResponse;\n handleSamlMetadata: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlAcs: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSlo: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleScimRequest: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n scimError: (status: number, scimType: string, detail: string) => Response;\n },\n) {\n const routePrefix = `${deps.routeBase}/`;\n\n http.route({\n pathPrefix: routePrefix,\n method: \"GET\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route) {\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }\n if (route.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"metadata\") {\n return await deps.handleSamlMetadata(ctx, request, route);\n }\n if (route.rest[0] === \"signin\") {\n return await deps.handleSamlSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route.protocol === \"oidc\" && route.rest.length === 1) {\n if (route.rest[0] === \"signin\") {\n return await deps.handleOidcSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"callback\") {\n return await deps.handleOidcCallback(ctx, request, route);\n }\n }\n if (route.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"POST\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"PUT\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw new AuthError(\n \"INVALID_PARAMETERS\",\n \"Invalid enterprise runtime path.\",\n ).toConvexError();\n }),\n ),\n });\n\n for (const method of [\"PATCH\", \"DELETE\"] as const) {\n http.route({\n pathPrefix: routePrefix,\n method,\n handler: httpActionGeneric(async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route || route.protocol !== \"scim\" || route.rest[0] !== \"v2\") {\n return deps.scimError(404, \"notFound\", \"SCIM resource not found.\");\n }\n return await deps.handleScimRequest(ctx, request);\n }),\n });\n }\n}\n"],"mappings":";;;;;;;;;AAgBA,SAAgB,iBAAiB,MAE9B;AACD,SACE,SAIA,YAIG;EACH,MAAM,aAAa,SAAS,QAAQ,EAAE;EACtC,MAAM,cAAsC;GAC1C,+BAA+B,WAAW,UAAU;GACpD,gCACE,WAAW,WAAW;GACxB,gCACE,WAAW,WAAW;GACzB;AAED,SAAO,kBAAkB,OAAO,YAAY,YAAY;AACtD,UAAO,GAAG,IACR,GAAG,KAAK;IACN,IAAI,YAAY;KACd,MAAM,aAAa,QAAQ,QAAQ,IAAI,gBAAgB;AACvD,SAAI,CAAC,YAAY,WAAW,UAAU,CACpC,QAAO,IAAI,SACT,KAAK,UAAU;MACb,OAAO;MACP,MAAM;MACP,CAAC,EACF;MACE,QAAQ;MACR,SAAS;OACP,GAAG;OACH,gBAAgB;OACjB;MACF,CACF;KAEH,MAAM,SAAS,WAAW,MAAM,EAAE;KAElC,MAAM,YAAY,MAAM,GAAG,IACzB,GAAG,KAAK;MACN,UAAU,KAAK,IAAI,OAAO,YAAY,OAAO;MAC7C,MAAM,UAAU;MACjB,CAAC,CAAC,KACD,GAAG,KAAK;MACN,KAAK,cAAY;OAAE,IAAI;OAAM,OAAOA;OAAQ;MAC5C,MAAM,WAAW;OAAE,IAAI;OAAO;OAAO;MACtC,CAAC,CACH,CACF;AAED,SAAI,CAAC,UAAU,IAAI;AACjB,UAAI,YAAY,UAAU,MAAM,EAAE;OAChC,MAAM,EAAE,MAAM,YAAY,UAAU,MAAM;AAI1C,cAAO,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO;QAAS;QAAM,CAAC,EAAE;QAC5D,QAAQ;QACR,SAAS;SACP,GAAG;SACH,gBAAgB;SACjB;QACF,CAAC;;AAEJ,YAAM,UAAU;;AAGlB,SACE,SAAS,SACT,CAAC,UAAU,MAAM,OAAO,IACtB,QAAQ,MAAM,UACd,QAAQ,MAAM,OACf,CAED,QAAO,IAAI,SACT,KAAK,UAAU;MACb,OAAO;MACP,MAAM;MACP,CAAC,EACF;MACE,QAAQ;MACR,SAAS;OACP,GAAG;OACH,gBAAgB;OACjB;MACF,CACF;KAUH,MAAM,SAAS,MAAM,QAPD,OAAO,OAAO,YAAY,EAC5C,KAAK;MACH,QAAQ,UAAU,MAAM;MACxB,OAAO,UAAU,MAAM;MACvB,QAAQ,UAAU,MAAM;MACzB,EACF,CAAC,EACwC,QAAQ;AAElD,SAAI,kBAAkB,UAAU;MAC9B,MAAM,UAAU,IAAI,QAAQ,OAAO,QAAQ;AAC3C,WAAK,MAAM,CAAC,GAAG,QAAQ,OAAO,QAAQ,YAAY,CAChD,KAAI,CAAC,QAAQ,IAAI,EAAE,CAAE,SAAQ,IAAI,GAAG,IAAI;AAE1C,aAAO,IAAI,SAAS,OAAO,MAAM;OAC/B,QAAQ,OAAO;OACf,YAAY,OAAO;OACnB;OACD,CAAC;;AAGJ,YAAO,IAAI,SAAS,KAAK,UAAU,OAAO,EAAE;MAC1C,QAAQ;MACR,SAAS;OACP,GAAG;OACH,gBAAgB;OACjB;MACF,CAAC;;IAEJ,MAAM,UAAU;IACjB,CAAC,CAAC,KACD,GAAG,SAAS,UAAU;AACpB,aAAS,MAAM;AACf,WAAO,GAAG,QACR,IAAI,SACF,KAAK,UAAU;KACb,OAAO;KACP,MAAM;KACP,CAAC,EACF;KACE,QAAQ;KACR,SAAS;MACP,GAAG;MACH,gBAAgB;MACjB;KACF,CACF,CACF;KACD,CACH,CACF;IACD;;;AAIN,SAAgB,gBACd,YACA;AACA,SACE,MACA,gBAUG;EACH,MAAM,aAAa,YAAY,QAAQ,EAAE;EACzC,MAAM,cAAsC;GAC1C,+BAA+B,WAAW,UAAU;GACpD,gCACE,WAAW,WAAW;GACxB,gCACE,WAAW,WAAW;GACzB;AAED,OAAK,MAAM;GACT,MAAM,YAAY;GAClB,QAAQ;GACR,SAAS,kBAAkB,YAAY;AACrC,WAAO,IAAI,SAAS,MAAM;KAAE,QAAQ;KAAK,SAAS;KAAa,CAAC;KAChE;GACH,CAAC;AAEF,OAAK,MAAM;GACT,MAAM,YAAY;GAClB,QAAQ,YAAY;GACpB,SAAS,WAAW,YAAY,SAAS;IACvC,OAAO,YAAY;IACnB,MAAM,YAAY;IACnB,CAAC;GACH,CAAC;;;AAIN,SAAgB,wBACd,iBACA,QACA;AACA,QAAO,OAAO,KAA4B,YAAqB;AAC7D,SAAO,GAAG,IACR,GAAG,KAAK;GACN,UAAU,OAAO,KAAK,QAAQ;GAC9B,MAAM,UAAU;GACjB,CAAC,CAAC,KACD,GAAG,SAAS,UAAU;AACpB,OAAI,YAAY,MAAM,CACpB,QAAO,GAAG,QACR,IAAI,SACF,KAAK,UAAU;IACb,MAAM,MAAM,KAAK;IACjB,SAAS,MAAM,KAAK;IACrB,CAAC,EACF;IACE,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAChD,CACF,CACF;YACQ,iBAAiB,YAC1B,QAAO,GAAG,QACR,IAAI,SAAS,MAAM;IACjB,QAAQ;IACR,YACE,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;IACjD,CAAC,CACH;QACI;AACL,aAAS,MAAM;AACf,WAAO,GAAG,QACR,IAAI,SAAS,MAAM;KACjB,QAAQ;KACR,YAAY;KACb,CAAC,CACH;;IAEH,CACH,CACF;;;AAIL,SAAgB,WACd,SACoC;AACpC,QAAOC,MAAa,QAAQ,QAAQ,IAAI,SAAS,IAAI,GAAG;;AAU1D,SAAS,4BACP,UACA,WACwB;CACxB,MAAM,gBAAgB,GAAG,UAAU;CAInC,MAAM,CAAC,qBAAqB,UAAU,GAAG,QAHpB,SAAS,WAAW,cAAc,GACnD,SAAS,MAAM,cAAc,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,QAAQ,GAC/D,EAAE;AAEN,KACE,wBAAwB,UACvB,aAAa,UAAU,aAAa,UAAU,aAAa,UAC5D,KAAK,WAAW,EAEhB,QAAO;AAET,QAAO;EACL;EACA,cAAc;EACd;EACA;EACD;;AAGH,SAAgB,gBACd,MACA,MAIA;CACA,MAAM,eACJ;AAEF,MAAK,MAAM;EACT,MAAM;EACN,QAAQ;EACR,SAAS,kBAAkB,YAAY;GACrC,MAAM,SAAS,KAAK,WAAW;AAC/B,UAAO,IAAI,SACT,KAAK,UAAU;IACb;IACA,UAAU,GAAG,OAAO;IACrB,CAAC,EACF;IACE,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,iBAAiB;KAClB;IACF,CACF;IACD;EACH,CAAC;AAEF,MAAK,MAAM;EACT,MAAM;EACN,QAAQ;EACR,SAAS,kBAAkB,YAAY;AACrC,UAAO,IAAI,SAAS,KAAK,SAAS,EAAE;IAClC,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,iBAAiB;KAClB;IACF,CAAC;IACF;EACH,CAAC;;AAGJ,SAAgB,cACd,MACA,MAUA;AACA,MAAK,MAAM;EACT,YAAY;EACZ,QAAQ;EACR,SAAS,kBAAkB,KAAK,aAAa;EAC9C,CAAC;CAEF,MAAM,kBAAkB,kBAAkB,KAAK,eAAe;AAE9D,MAAK,MAAM;EACT,YAAY;EACZ,QAAQ;EACR,SAAS;EACV,CAAC;AAEF,MAAK,MAAM;EACT,YAAY;EACZ,QAAQ;EACR,SAAS;EACV,CAAC;;AAGJ,SAAgB,aACd,MACA,MAuCA;CACA,MAAM,cAAc,GAAG,KAAK,UAAU;AAEtC,MAAK,MAAM;EACT,YAAY;EACZ,QAAQ;EACR,SAAS,kBACP,KAAK,wBAAwB,KAAK,OAAO,KAAK,YAAY;GACxD,MAAM,QAAQ,4BACZ,IAAI,IAAI,QAAQ,IAAI,CAAC,UACrB,KAAK,UACN;AACD,OAAI,CAAC,MACH,OAAM,IAAI,UACR,sBACA,mCACD,CAAC,eAAe;AAEnB,OAAI,MAAM,aAAa,UAAU,MAAM,KAAK,WAAW,GAAG;AACxD,QAAI,MAAM,KAAK,OAAO,WACpB,QAAO,MAAM,KAAK,mBAAmB,KAAK,SAAS,MAAM;AAE3D,QAAI,MAAM,KAAK,OAAO,SACpB,QAAO,MAAM,KAAK,iBAAiB,KAAK,SAAS,MAAM;AAEzD,QAAI,MAAM,KAAK,OAAO,MACpB,QAAO,MAAM,KAAK,cAAc,KAAK,SAAS,MAAM;AAEtD,QAAI,MAAM,KAAK,OAAO,MACpB,QAAO,MAAM,KAAK,cAAc,KAAK,SAAS,MAAM;;AAGxD,OAAI,MAAM,aAAa,UAAU,MAAM,KAAK,WAAW,GAAG;AACxD,QAAI,MAAM,KAAK,OAAO,SACpB,QAAO,MAAM,KAAK,iBAAiB,KAAK,SAAS,MAAM;AAEzD,QAAI,MAAM,KAAK,OAAO,WACpB,QAAO,MAAM,KAAK,mBAAmB,KAAK,SAAS,MAAM;;AAG7D,OAAI,MAAM,aAAa,UAAU,MAAM,KAAK,OAAO,KACjD,QAAO,MAAM,KAAK,kBAAkB,KAAK,QAAQ;AAEnD,SAAM,IAAI,UACR,sBACA,mCACD,CAAC,eAAe;IACjB,CACH;EACF,CAAC;AAEF,MAAK,MAAM;EACT,YAAY;EACZ,QAAQ;EACR,SAAS,kBACP,KAAK,wBAAwB,KAAK,OAAO,KAAK,YAAY;GACxD,MAAM,QAAQ,4BACZ,IAAI,IAAI,QAAQ,IAAI,CAAC,UACrB,KAAK,UACN;AACD,OAAI,OAAO,aAAa,UAAU,MAAM,KAAK,WAAW,GAAG;AACzD,QAAI,MAAM,KAAK,OAAO,MACpB,QAAO,MAAM,KAAK,cAAc,KAAK,SAAS,MAAM;AAEtD,QAAI,MAAM,KAAK,OAAO,MACpB,QAAO,MAAM,KAAK,cAAc,KAAK,SAAS,MAAM;;AAGxD,OAAI,OAAO,aAAa,UAAU,MAAM,KAAK,OAAO,KAClD,QAAO,MAAM,KAAK,kBAAkB,KAAK,QAAQ;AAEnD,SAAM,IAAI,UACR,sBACA,mCACD,CAAC,eAAe;IACjB,CACH;EACF,CAAC;AAEF,MAAK,MAAM;EACT,YAAY;EACZ,QAAQ;EACR,SAAS,kBACP,KAAK,wBAAwB,KAAK,OAAO,KAAK,YAAY;GACxD,MAAM,QAAQ,4BACZ,IAAI,IAAI,QAAQ,IAAI,CAAC,UACrB,KAAK,UACN;AACD,OAAI,OAAO,aAAa,UAAU,MAAM,KAAK,OAAO,KAClD,QAAO,MAAM,KAAK,kBAAkB,KAAK,QAAQ;AAEnD,SAAM,IAAI,UACR,sBACA,mCACD,CAAC,eAAe;IACjB,CACH;EACF,CAAC;AAEF,MAAK,MAAM,UAAU,CAAC,SAAS,SAAS,CACtC,MAAK,MAAM;EACT,YAAY;EACZ;EACA,SAAS,kBAAkB,OAAO,KAAK,YAAY;GACjD,MAAM,QAAQ,4BACZ,IAAI,IAAI,QAAQ,IAAI,CAAC,UACrB,KAAK,UACN;AACD,OAAI,CAAC,SAAS,MAAM,aAAa,UAAU,MAAM,KAAK,OAAO,KAC3D,QAAO,KAAK,UAAU,KAAK,YAAY,2BAA2B;AAEpE,UAAO,MAAM,KAAK,kBAAkB,KAAK,QAAQ;IACjD;EACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"http.js","names":["result","parseCookies"],"sources":["../../src/server/http.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport {\n GenericActionCtx,\n GenericDataModel,\n HttpRouter,\n httpActionGeneric,\n} from \"convex/server\";\nimport { ConvexError } from \"convex/values\";\nimport { parse as parseCookies } from \"cookie\";\n\nimport type {\n AuthContext,\n OptionalAuthContext,\n UserDoc,\n} from \"./auth\";\nimport {\n createUnauthenticatedAuthContext,\n getAuthContextForUser,\n getSessionUserId,\n} from \"./context\";\nimport type { CorsConfig, HttpKeyContext } from \"./types\";\nimport { logError } from \"./utils\";\n\ntype HttpContextAuthLike = {\n user: {\n get: (ctx: any, userId: string) => Promise<UserDoc>;\n getActiveGroup: (\n ctx: any,\n args: { userId: string },\n ) => Promise<string | null>;\n };\n member: {\n inspect: (\n ctx: any,\n args: { userId: string; groupId: string },\n ) => Promise<{\n membership: unknown;\n roleIds: string[];\n grants: string[];\n }>;\n };\n key: {\n verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<{\n userId: string;\n keyId: string;\n scopes: HttpKeyContext[\"key\"][\"scopes\"];\n }>;\n };\n};\n\n/**\n * Auth context returned by `auth.http.context(ctx, request)`.\n *\n * This resolves raw HTTP authentication in two steps:\n * 1. session auth from `ctx.auth.getUserIdentity()`\n * 2. API key auth from `Authorization: Bearer sk_*`\n *\n * The `source` field tells you which authentication path succeeded.\n * When `source === \"key\"`, the verified API key metadata is available on\n * `key`.\n *\n * @example\n * ```ts\n * const authContext = await auth.http.context(ctx, request);\n * if (authContext.source === \"key\") {\n * console.log(authContext.key.keyId);\n * }\n * ```\n */\nexport type HttpAuthContext =\n | (AuthContext & {\n /** The request authenticated through a browser or session token. */\n source: \"session\";\n /** No API key was used for this request. */\n key: null;\n })\n | (AuthContext & {\n /** The request authenticated through an API key. */\n source: \"key\";\n /** Verified API key metadata for the request. */\n key: HttpKeyContext[\"key\"];\n });\n\n/**\n * Nullable HTTP auth context returned by\n * `auth.http.context(ctx, request, { optional: true })`.\n *\n * This preserves a stable auth-shaped object for raw `httpAction` handlers\n * that allow anonymous callers.\n */\nexport type OptionalHttpAuthContext =\n | (OptionalAuthContext & {\n /** No authentication source was resolved. */\n source: null;\n /** No API key metadata is available. */\n key: null;\n })\n | HttpAuthContext;\n\n/**\n * Configuration for {@link createAuth().http.context}.\n *\n * This mirrors {@link AuthContextConfig} for raw HTTP handlers and adds support\n * for enriching mixed session/API-key auth results.\n *\n * @typeParam TResolve - Extra fields returned from `resolve()` and merged into\n * the resolved HTTP auth context.\n *\n * @example\n * ```ts\n * const authContext = await auth.http.context(ctx, request, {\n * resolve: async (_ctx, user, authState) => ({\n * email: user.email,\n * isMachineRequest: authState.source === \"key\",\n * }),\n * });\n * ```\n */\nexport type HttpAuthContextConfig<\n TResolve extends Record<string, unknown> = Record<string, never>,\n> = {\n /**\n * Allow unauthenticated callers and return a null-shaped auth object instead\n * of throwing `NOT_SIGNED_IN`.\n */\n optional?: boolean;\n /**\n * Attach additional derived fields to the resolved HTTP auth context.\n *\n * This callback runs only when authentication succeeds.\n */\n resolve?: (\n ctx: GenericActionCtx<any>,\n user: UserDoc,\n auth: HttpAuthContext,\n ) => Promise<TResolve> | TResolve;\n /**\n * Override or wrap HTTP auth resolution.\n *\n * Return `undefined` to use the built-in session-or-key resolver, `null` for\n * an explicit unauthenticated state, or a fully resolved\n * {@link HttpAuthContext}.\n */\n authResolve?: (\n ctx: GenericActionCtx<any>,\n fallback: () => Promise<HttpAuthContext | null>,\n ) =>\n | Promise<HttpAuthContext | null | undefined>\n | HttpAuthContext\n | null\n | undefined;\n};\n\nfunction createNotSignedInError() {\n return Cv.error({\n code: \"NOT_SIGNED_IN\",\n message: \"Authentication required.\",\n });\n}\n\nasync function getHttpKeyContext(\n auth: HttpContextAuthLike,\n ctx: GenericActionCtx<any>,\n request: Request,\n): Promise<HttpAuthContext | null> {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer sk_\")) {\n return null;\n }\n\n try {\n const verified = await auth.key.verify(ctx, authHeader.slice(7));\n const authContext = await getAuthContextForUser(auth, ctx, verified.userId);\n return {\n ...authContext,\n source: \"key\",\n key: {\n userId: verified.userId,\n keyId: verified.keyId,\n scopes: verified.scopes,\n },\n };\n } catch {\n return null;\n }\n}\n\nasync function resolveHttpAuthContext(\n auth: HttpContextAuthLike,\n ctx: GenericActionCtx<any>,\n request: Request,\n): Promise<HttpAuthContext | null> {\n const sessionUserId = await getSessionUserId(ctx);\n if (sessionUserId !== null) {\n const authContext = await getAuthContextForUser(auth, ctx, sessionUserId);\n return {\n ...authContext,\n source: \"session\",\n key: null,\n };\n }\n\n return await getHttpKeyContext(auth, ctx, request);\n}\n\n/**\n * @internal\n * Create the implementation behind `auth.http.context(...)`.\n */\nexport function createHttpContext(auth: HttpContextAuthLike): {\n <TResolve extends Record<string, unknown> = Record<string, never>>(\n ctx: GenericActionCtx<any>,\n request: Request,\n config: HttpAuthContextConfig<TResolve> & { optional: true },\n ): Promise<OptionalHttpAuthContext & TResolve>;\n <TResolve extends Record<string, unknown> = Record<string, never>>(\n ctx: GenericActionCtx<any>,\n request: Request,\n config?: HttpAuthContextConfig<TResolve>,\n ): Promise<HttpAuthContext & TResolve>;\n} {\n return (async (\n ctx: GenericActionCtx<any>,\n request: Request,\n config?: HttpAuthContextConfig<any>,\n ) => {\n const fallback = () => resolveHttpAuthContext(auth, ctx, request);\n const authOverride = config?.authResolve\n ? await config.authResolve(ctx, fallback)\n : undefined;\n const resolved =\n authOverride === undefined ? await fallback() : authOverride;\n\n if (resolved === null) {\n if (config?.optional !== true) {\n throw createNotSignedInError();\n }\n return {\n ...createUnauthenticatedAuthContext(),\n source: null,\n key: null,\n };\n }\n\n const extra = config?.resolve\n ? await config.resolve(ctx, resolved.user, resolved)\n : {};\n\n return {\n ...resolved,\n ...extra,\n };\n }) as {\n <TResolve extends Record<string, unknown> = Record<string, never>>(\n ctx: GenericActionCtx<any>,\n request: Request,\n config: HttpAuthContextConfig<TResolve> & { optional: true },\n ): Promise<OptionalHttpAuthContext & TResolve>;\n <TResolve extends Record<string, unknown> = Record<string, never>>(\n ctx: GenericActionCtx<any>,\n request: Request,\n config?: HttpAuthContextConfig<TResolve>,\n ): Promise<HttpAuthContext & TResolve>;\n };\n}\n\nexport function createHttpAction(auth: {\n key: { verify: (ctx: GenericActionCtx<any>, rawKey: string) => Promise<any> };\n}) {\n return (\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>,\n options?: {\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = options?.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n return httpActionGeneric(async (genericCtx, request) => {\n return Fx.run(\n Fx.from({\n ok: async () => {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader?.startsWith(\"Bearer \")) {\n return new Response(\n JSON.stringify({\n error: \"Missing or malformed Authorization: Bearer header.\",\n code: \"MISSING_BEARER_TOKEN\",\n }),\n {\n status: 401,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n const rawKey = authHeader.slice(7);\n\n const keyResult = await Fx.run(\n Fx.attempt(\n () => auth.key.verify(genericCtx, rawKey),\n (result) => ({ ok: true, value: result }) as const,\n (error) => ({ ok: false, error }) as const,\n ),\n );\n\n if (!keyResult.ok) {\n if (\n keyResult.error instanceof ConvexError &&\n typeof keyResult.error.data === \"object\" &&\n keyResult.error.data !== null &&\n \"code\" in keyResult.error.data &&\n \"message\" in keyResult.error.data\n ) {\n const { code, message } = keyResult.error.data as {\n code: string;\n message: string;\n };\n return new Response(JSON.stringify({ error: message, code }), {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n throw keyResult.error;\n }\n\n if (\n options?.scope &&\n !keyResult.value.scopes.can(\n options.scope.resource,\n options.scope.action,\n )\n ) {\n return new Response(\n JSON.stringify({\n error: \"This API key does not have the required permissions.\",\n code: \"SCOPE_CHECK_FAILED\",\n }),\n {\n status: 403,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n );\n }\n\n const enrichedCtx = Object.assign(genericCtx, {\n key: {\n userId: keyResult.value.userId,\n keyId: keyResult.value.keyId,\n scopes: keyResult.value.scopes,\n },\n });\n const result = await handler(enrichedCtx, request);\n\n if (result instanceof Response) {\n const headers = new Headers(result.headers);\n for (const [k, val] of Object.entries(corsHeaders)) {\n if (!headers.has(k)) headers.set(k, val);\n }\n return new Response(result.body, {\n status: result.status,\n statusText: result.statusText,\n headers,\n });\n }\n\n return new Response(JSON.stringify(result), {\n status: 200,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n });\n },\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n logError(error);\n return Fx.succeed(\n new Response(\n JSON.stringify({\n error: \"An unexpected error occurred.\",\n code: \"INTERNAL_ERROR\",\n }),\n {\n status: 500,\n headers: {\n ...corsHeaders,\n \"Content-Type\": \"application/json\",\n },\n },\n ),\n );\n }),\n ),\n );\n });\n };\n}\n\nexport function createHttpRoute(\n wrapAction: ReturnType<typeof createHttpAction>,\n) {\n return (\n http: { route: (config: any) => void },\n routeConfig: {\n path: string;\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n handler: (\n ctx: GenericActionCtx<GenericDataModel> & HttpKeyContext,\n request: Request,\n ) => Promise<Response | Record<string, unknown>>;\n scope?: { resource: string; action: string };\n cors?: CorsConfig;\n },\n ) => {\n const corsConfig = routeConfig.cors ?? {};\n const corsHeaders: Record<string, string> = {\n \"Access-Control-Allow-Origin\": corsConfig.origin ?? \"*\",\n \"Access-Control-Allow-Methods\":\n corsConfig.methods ?? \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n \"Access-Control-Allow-Headers\":\n corsConfig.headers ?? \"Content-Type,Authorization\",\n };\n\n http.route({\n path: routeConfig.path,\n method: \"OPTIONS\",\n handler: httpActionGeneric(async () => {\n return new Response(null, { status: 204, headers: corsHeaders });\n }),\n });\n\n http.route({\n path: routeConfig.path,\n method: routeConfig.method,\n handler: wrapAction(routeConfig.handler, {\n scope: routeConfig.scope,\n cors: routeConfig.cors,\n }),\n });\n };\n}\n\nexport function convertErrorsToResponse(\n errorStatusCode: number,\n action: (ctx: GenericActionCtx<any>, request: Request) => Promise<Response>,\n) {\n return async (ctx: GenericActionCtx<any>, request: Request) => {\n return Fx.run(\n Fx.from({\n ok: () => action(ctx, request),\n err: (error) => error,\n }).pipe(\n Fx.recover((error) => {\n if (\n error instanceof ConvexError &&\n typeof error.data === \"object\" &&\n error.data !== null &&\n \"code\" in error.data &&\n \"message\" in error.data\n ) {\n return Fx.succeed(\n new Response(\n JSON.stringify({\n code: error.data.code,\n message: error.data.message,\n }),\n {\n status: errorStatusCode,\n headers: { \"Content-Type\": \"application/json\" },\n },\n ),\n );\n } else if (error instanceof ConvexError) {\n return Fx.succeed(\n new Response(null, {\n status: errorStatusCode,\n statusText:\n typeof error.data === \"string\" ? error.data : \"Error\",\n }),\n );\n } else {\n logError(error);\n return Fx.succeed(\n new Response(null, {\n status: 500,\n statusText: \"Internal Server Error\",\n }),\n );\n }\n }),\n ),\n );\n };\n}\n\nexport function getCookies(\n request: Request,\n): Record<string, string | undefined> {\n return parseCookies(request.headers.get(\"Cookie\") ?? \"\");\n}\n\nexport type SSORuntimeRoute = {\n pathname?: string;\n enterpriseId: string;\n protocol: \"oidc\" | \"saml\" | \"scim\";\n rest: string[];\n};\n\nfunction parseEnterpriseRuntimeRoute(\n pathname: string,\n routeBase: string,\n): SSORuntimeRoute | null {\n const runtimePrefix = `${routeBase}/`;\n const runtimeParts = pathname.startsWith(runtimePrefix)\n ? pathname.slice(runtimePrefix.length).split(\"/\").filter(Boolean)\n : [];\n const [runtimeEnterpriseId, protocol, ...rest] = runtimeParts;\n if (\n runtimeEnterpriseId === undefined ||\n (protocol !== \"oidc\" && protocol !== \"saml\" && protocol !== \"scim\") ||\n rest.length === 0\n ) {\n return null;\n }\n return {\n pathname,\n enterpriseId: runtimeEnterpriseId,\n protocol,\n rest,\n };\n}\n\nexport function addOpenIdRoutes(\n http: HttpRouter,\n deps: {\n getIssuer: () => string;\n getJwks: () => string;\n },\n) {\n const cacheControl =\n \"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400\";\n\n http.route({\n path: \"/.well-known/openid-configuration\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n const issuer = deps.getIssuer();\n return new Response(\n JSON.stringify({\n issuer,\n jwks_uri: `${issuer}/.well-known/jwks.json`,\n }),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n },\n );\n }),\n });\n\n http.route({\n path: \"/.well-known/jwks.json\",\n method: \"GET\",\n handler: httpActionGeneric(async () => {\n return new Response(deps.getJwks(), {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n \"Cache-Control\": cacheControl,\n },\n });\n }),\n });\n}\n\nexport function addAuthRoutes(\n http: HttpRouter,\n deps: {\n handleSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n handleCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n },\n) {\n http.route({\n pathPrefix: \"/api/auth/signin/\",\n method: \"GET\",\n handler: httpActionGeneric(deps.handleSignIn),\n });\n\n const callbackHandler = httpActionGeneric(deps.handleCallback);\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"GET\",\n handler: callbackHandler,\n });\n\n http.route({\n pathPrefix: \"/api/auth/callback/\",\n method: \"POST\",\n handler: callbackHandler,\n });\n}\n\nexport function addSSORoutes(\n http: HttpRouter,\n deps: {\n routeBase: string;\n convertErrorsToResponse: typeof convertErrorsToResponse;\n handleSamlMetadata: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcSignIn: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleOidcCallback: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlAcs: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleSamlSlo: (\n ctx: GenericActionCtx<any>,\n request: Request,\n route: SSORuntimeRoute,\n ) => Promise<Response>;\n handleScimRequest: (\n ctx: GenericActionCtx<any>,\n request: Request,\n ) => Promise<Response>;\n scimError: (status: number, scimType: string, detail: string) => Response;\n },\n) {\n const routePrefix = `${deps.routeBase}/`;\n\n http.route({\n pathPrefix: routePrefix,\n method: \"GET\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }\n if (route.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"metadata\") {\n return await deps.handleSamlMetadata(ctx, request, route);\n }\n if (route.rest[0] === \"signin\") {\n return await deps.handleSamlSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route.protocol === \"oidc\" && route.rest.length === 1) {\n if (route.rest[0] === \"signin\") {\n return await deps.handleOidcSignIn(ctx, request, route);\n }\n if (route.rest[0] === \"callback\") {\n return await deps.handleOidcCallback(ctx, request, route);\n }\n }\n if (route.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"POST\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"saml\" && route.rest.length === 1) {\n if (route.rest[0] === \"acs\") {\n return await deps.handleSamlAcs(ctx, request, route);\n }\n if (route.rest[0] === \"slo\") {\n return await deps.handleSamlSlo(ctx, request, route);\n }\n }\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }),\n ),\n });\n\n http.route({\n pathPrefix: routePrefix,\n method: \"PUT\",\n handler: httpActionGeneric(\n deps.convertErrorsToResponse(400, async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (route?.protocol === \"scim\" && route.rest[0] === \"v2\") {\n return await deps.handleScimRequest(ctx, request);\n }\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"Invalid enterprise runtime path.\",\n });\n }),\n ),\n });\n\n for (const method of [\"PATCH\", \"DELETE\"] as const) {\n http.route({\n pathPrefix: routePrefix,\n method,\n handler: httpActionGeneric(async (ctx, request) => {\n const route = parseEnterpriseRuntimeRoute(\n new URL(request.url).pathname,\n deps.routeBase,\n );\n if (!route || route.protocol !== \"scim\" || route.rest[0] !== \"v2\") {\n return deps.scimError(404, \"notFound\", \"SCIM resource not found.\");\n }\n return await deps.handleScimRequest(ctx, request);\n }),\n });\n }\n}\n"],"mappings":"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"}
|
package/dist/server/identity.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cv } from "@robelest/fx/convex";
|
|
2
2
|
|
|
3
3
|
//#region src/server/identity.ts
|
|
4
4
|
/** @internal */
|
|
5
5
|
function userIdFromIdentitySubject(subject) {
|
|
6
6
|
const [userId, ...rest] = subject.split("|");
|
|
7
|
-
if (typeof userId !== "string" || userId.length === 0 || rest.length === 0 || rest.some((segment) => segment.length === 0)) throw
|
|
7
|
+
if (typeof userId !== "string" || userId.length === 0 || rest.length === 0 || rest.some((segment) => segment.length === 0)) throw Cv.error({
|
|
8
|
+
code: "INTERNAL_ERROR",
|
|
9
|
+
message: "Authenticated identity subject is malformed."
|
|
10
|
+
});
|
|
8
11
|
return userId;
|
|
9
12
|
}
|
|
10
13
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.js","names":[],"sources":["../../src/server/identity.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"identity.js","names":[],"sources":["../../src/server/identity.ts"],"sourcesContent":["import { Cv } from \"@robelest/fx/convex\";\n\n/** @internal */\nexport function userIdFromIdentitySubject(subject: string): string {\n const [userId, ...rest] = subject.split(\"|\");\n if (\n typeof userId !== \"string\" ||\n userId.length === 0 ||\n rest.length === 0 ||\n rest.some((segment) => segment.length === 0)\n ) {\n throw Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"Authenticated identity subject is malformed.\",\n });\n }\n return userId;\n}\n"],"mappings":";;;;AAGA,SAAgB,0BAA0B,SAAyB;CACjE,MAAM,CAAC,QAAQ,GAAG,QAAQ,QAAQ,MAAM,IAAI;AAC5C,KACE,OAAO,WAAW,YAClB,OAAO,WAAW,KAClB,KAAK,WAAW,KAChB,KAAK,MAAM,YAAY,QAAQ,WAAW,EAAE,CAE5C,OAAM,GAAG,MAAM;EACb,MAAM;EACN,SAAS;EACV,CAAC;AAEJ,QAAO"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AuthApi, AuthApiBase, AuthConfig,
|
|
1
|
+
import { AuthApi, AuthApiBase, AuthConfig, AuthContext, AuthContextConfig, ConvexAuthResult, InferAuth, InferClientApi, OptionalAuthContext, UserDoc, createAuth } from "./auth.js";
|
|
2
|
+
import { HttpAuthContext, HttpAuthContextConfig, OptionalHttpAuthContext } from "./http.js";
|
|
2
3
|
import { EnterpriseAdminAuthorizationInput, EnterpriseAdminPermission, EnterpriseAuthorizer, EnterpriseMountOptions, enterprise, scim, sso } from "./mounts.js";
|
|
3
4
|
import { AuthCookie, AuthCookieConfig, AuthCookies, RefreshResult, ServerOptions, authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./ssr.js";
|
|
4
|
-
export { type AuthApi, type AuthApiBase, type AuthConfig, type
|
|
5
|
+
export { type AuthApi, type AuthApiBase, type AuthConfig, type AuthContext, type AuthContextConfig, type AuthCookie, type AuthCookieConfig, type AuthCookies, type ConvexAuthResult, type EnterpriseAdminAuthorizationInput, type EnterpriseAdminPermission, type EnterpriseAuthorizer, type EnterpriseMountOptions, type HttpAuthContext, type HttpAuthContextConfig, type InferAuth, type InferClientApi, type OptionalAuthContext, type OptionalHttpAuthContext, type RefreshResult, type ServerOptions, type UserDoc, authCookieNames, createAuth, enterprise, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies };
|
package/dist/server/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAuth } from "./auth.js";
|
|
2
2
|
import { enterprise, scim, sso } from "./mounts.js";
|
|
3
3
|
import { authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./ssr.js";
|
|
4
4
|
|
|
5
|
-
export {
|
|
5
|
+
export { authCookieNames, createAuth, enterprise, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies };
|
package/dist/server/limits.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { AuthError } from "./authError.js";
|
|
2
|
-
import { errorMessage } from "./utils.js";
|
|
3
1
|
import { authDb } from "./db.js";
|
|
4
2
|
import { Fx } from "@robelest/fx";
|
|
5
3
|
|
|
@@ -16,45 +14,38 @@ const isSignInRateLimited = (ctx, identifier, config) => getRateLimitState(ctx,
|
|
|
16
14
|
* If a record exists, decrement; otherwise create.
|
|
17
15
|
*/
|
|
18
16
|
/** @internal */
|
|
19
|
-
const recordFailedSignIn = (ctx, identifier, config) =>
|
|
20
|
-
|
|
17
|
+
const recordFailedSignIn = (ctx, identifier, config) => Fx.gen(function* () {
|
|
18
|
+
const state = yield* getRateLimitState(ctx, identifier, config);
|
|
19
|
+
if (state !== null) yield* Fx.promise(() => authDb(ctx, config).rateLimits.patch(state.limit._id, {
|
|
21
20
|
attemptsLeft: state.attemptsLeft - 1,
|
|
22
21
|
lastAttemptTime: Date.now()
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
}) : Fx.from({
|
|
26
|
-
ok: () => authDb(ctx, config).rateLimits.create({
|
|
22
|
+
}));
|
|
23
|
+
else yield* Fx.promise(() => authDb(ctx, config).rateLimits.create({
|
|
27
24
|
identifier,
|
|
28
25
|
attemptsLeft: (config.signIn?.maxFailedAttemptsPerHour ?? DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR) - 1,
|
|
29
26
|
lastAttemptTime: Date.now()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
})), Fx.map(() => void 0));
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
33
29
|
/**
|
|
34
30
|
* Reset the rate limit for the given identifier (e.g. after successful sign-in).
|
|
35
31
|
*/
|
|
36
32
|
/** @internal */
|
|
37
|
-
const resetSignInRateLimit = (ctx, identifier, config) =>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
})
|
|
41
|
-
const getRateLimitState = (ctx, identifier, config) => {
|
|
33
|
+
const resetSignInRateLimit = (ctx, identifier, config) => Fx.gen(function* () {
|
|
34
|
+
const state = yield* getRateLimitState(ctx, identifier, config);
|
|
35
|
+
if (state !== null) yield* Fx.promise(() => authDb(ctx, config).rateLimits.delete(state.limit._id));
|
|
36
|
+
});
|
|
37
|
+
const getRateLimitState = (ctx, identifier, config) => Fx.gen(function* () {
|
|
42
38
|
const now = Date.now();
|
|
43
39
|
const maxAttemptsPerHour = config.signIn?.maxFailedAttemptsPerHour ?? DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
limit,
|
|
54
|
-
attemptsLeft: Math.min(maxAttemptsPerHour, limit.attemptsLeft + elapsed * maxAttemptsPerMs)
|
|
55
|
-
};
|
|
56
|
-
}));
|
|
57
|
-
};
|
|
40
|
+
const limit = yield* Fx.promise(() => authDb(ctx, config).rateLimits.get(identifier));
|
|
41
|
+
if (limit === null) return null;
|
|
42
|
+
const elapsed = now - limit.lastAttemptTime;
|
|
43
|
+
const maxAttemptsPerMs = maxAttemptsPerHour / (3600 * 1e3);
|
|
44
|
+
return {
|
|
45
|
+
limit,
|
|
46
|
+
attemptsLeft: Math.min(maxAttemptsPerHour, limit.attemptsLeft + elapsed * maxAttemptsPerMs)
|
|
47
|
+
};
|
|
48
|
+
});
|
|
58
49
|
|
|
59
50
|
//#endregion
|
|
60
51
|
export { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"limits.js","names":[],"sources":["../../src/server/limits.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\
|
|
1
|
+
{"version":3,"file":"limits.js","names":[],"sources":["../../src/server/limits.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { ConvexError } from \"convex/values\";\n\nimport { authDb } from \"./db\";\nimport { Doc, MutationCtx } from \"./types\";\nimport { ConvexAuthConfig } from \"./types\";\n\nconst DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR = 10;\n\n/**\n * Check whether the given identifier is currently rate-limited.\n */\n/** @internal */\nexport const isSignInRateLimited = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<boolean, ConvexError<any>> =>\n getRateLimitState(ctx, identifier, config).pipe(\n Fx.map((state) => state !== null && state.attemptsLeft < 1),\n );\n\n/**\n * Record a failed sign-in attempt for the given identifier.\n *\n * If a record exists, decrement; otherwise create.\n */\n/** @internal */\nexport const recordFailedSignIn = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<void, ConvexError<any>> =>\n Fx.gen(function* () {\n const state = yield* getRateLimitState(ctx, identifier, config);\n if (state !== null) {\n yield* Fx.promise(() =>\n authDb(ctx, config).rateLimits.patch(state.limit._id, {\n attemptsLeft: state.attemptsLeft - 1,\n lastAttemptTime: Date.now(),\n }),\n );\n } else {\n yield* Fx.promise(() =>\n authDb(ctx, config).rateLimits.create({\n identifier,\n attemptsLeft:\n (config.signIn?.maxFailedAttemptsPerHour ??\n DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR) - 1,\n lastAttemptTime: Date.now(),\n }),\n );\n }\n });\n\n/**\n * Reset the rate limit for the given identifier (e.g. after successful sign-in).\n */\n/** @internal */\nexport const resetSignInRateLimit = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<void, ConvexError<any>> =>\n Fx.gen(function* () {\n const state = yield* getRateLimitState(ctx, identifier, config);\n if (state !== null) {\n yield* Fx.promise(() =>\n authDb(ctx, config).rateLimits.delete(state.limit._id),\n );\n }\n });\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\ntype RateLimitState = {\n limit: Doc<\"RateLimit\"> & { attemptsLeft: number; lastAttemptTime: number };\n attemptsLeft: number;\n} | null;\n\nconst getRateLimitState = (\n ctx: MutationCtx,\n identifier: string,\n config: ConvexAuthConfig,\n): Fx<RateLimitState, ConvexError<any>> =>\n Fx.gen(function* () {\n const now = Date.now();\n const maxAttemptsPerHour =\n config.signIn?.maxFailedAttemptsPerHour ??\n DEFAULT_MAX_SIGN_IN_ATTEMPTS_PER_HOUR;\n\n const limit = (yield* Fx.promise(() =>\n authDb(ctx, config).rateLimits.get(identifier),\n )) as\n | (Doc<\"RateLimit\"> & { attemptsLeft: number; lastAttemptTime: number })\n | null;\n if (limit === null) return null;\n const elapsed = now - limit.lastAttemptTime;\n const maxAttemptsPerMs = maxAttemptsPerHour / (60 * 60 * 1000);\n const attemptsLeft = Math.min(\n maxAttemptsPerHour,\n limit.attemptsLeft + elapsed * maxAttemptsPerMs,\n );\n return { limit, attemptsLeft };\n });\n"],"mappings":";;;;AAOA,MAAM,wCAAwC;;;;;AAM9C,MAAa,uBACX,KACA,YACA,WAEA,kBAAkB,KAAK,YAAY,OAAO,CAAC,KACzC,GAAG,KAAK,UAAU,UAAU,QAAQ,MAAM,eAAe,EAAE,CAC5D;;;;;;;AAQH,MAAa,sBACX,KACA,YACA,WAEA,GAAG,IAAI,aAAa;CAClB,MAAM,QAAQ,OAAO,kBAAkB,KAAK,YAAY,OAAO;AAC/D,KAAI,UAAU,KACZ,QAAO,GAAG,cACR,OAAO,KAAK,OAAO,CAAC,WAAW,MAAM,MAAM,MAAM,KAAK;EACpD,cAAc,MAAM,eAAe;EACnC,iBAAiB,KAAK,KAAK;EAC5B,CAAC,CACH;KAED,QAAO,GAAG,cACR,OAAO,KAAK,OAAO,CAAC,WAAW,OAAO;EACpC;EACA,eACG,OAAO,QAAQ,4BACd,yCAAyC;EAC7C,iBAAiB,KAAK,KAAK;EAC5B,CAAC,CACH;EAEH;;;;;AAMJ,MAAa,wBACX,KACA,YACA,WAEA,GAAG,IAAI,aAAa;CAClB,MAAM,QAAQ,OAAO,kBAAkB,KAAK,YAAY,OAAO;AAC/D,KAAI,UAAU,KACZ,QAAO,GAAG,cACR,OAAO,KAAK,OAAO,CAAC,WAAW,OAAO,MAAM,MAAM,IAAI,CACvD;EAEH;AAWJ,MAAM,qBACJ,KACA,YACA,WAEA,GAAG,IAAI,aAAa;CAClB,MAAM,MAAM,KAAK,KAAK;CACtB,MAAM,qBACJ,OAAO,QAAQ,4BACf;CAEF,MAAM,QAAS,OAAO,GAAG,cACvB,OAAO,KAAK,OAAO,CAAC,WAAW,IAAI,WAAW,CAC/C;AAGD,KAAI,UAAU,KAAM,QAAO;CAC3B,MAAM,UAAU,MAAM,MAAM;CAC5B,MAAM,mBAAmB,sBAAsB,OAAU;AAKzD,QAAO;EAAE;EAAO,cAJK,KAAK,IACxB,oBACA,MAAM,eAAe,UAAU,iBAChC;EAC6B;EAC9B"}
|
package/dist/server/mounts.d.ts
CHANGED
|
@@ -36,11 +36,11 @@ type EnterpriseAdminAuthorizationInput = {
|
|
|
36
36
|
/**
|
|
37
37
|
* App-defined authorization hook for mounted enterprise admin APIs.
|
|
38
38
|
*
|
|
39
|
-
* Return `void` (or resolve) to allow the operation, or
|
|
39
|
+
* Return `void` (or resolve) to allow the operation, or throw to deny it.
|
|
40
40
|
*
|
|
41
41
|
* @param ctx - Convex context with `ctx.auth` for identity checks.
|
|
42
42
|
* @param input - The {@link EnterpriseAdminAuthorizationInput} describing who is doing what.
|
|
43
|
-
* @returns `void` to allow
|
|
43
|
+
* @returns `void` to allow; throw to deny.
|
|
44
44
|
*
|
|
45
45
|
* @example
|
|
46
46
|
* ```ts
|
|
@@ -48,16 +48,14 @@ type EnterpriseAdminAuthorizationInput = {
|
|
|
48
48
|
*
|
|
49
49
|
* const authorized: EnterpriseAuthorizer = async (ctx, input) => {
|
|
50
50
|
* const identity = await ctx.auth.getUserIdentity();
|
|
51
|
-
* if (!identity)
|
|
51
|
+
* if (!identity) throw new Error("Forbidden");
|
|
52
52
|
* // Allow all admin ops for the org owner
|
|
53
53
|
* };
|
|
54
54
|
* ```
|
|
55
55
|
*/
|
|
56
56
|
type EnterpriseAuthorizer = (ctx: {
|
|
57
57
|
auth: convex_server0.Auth;
|
|
58
|
-
}, input: EnterpriseAdminAuthorizationInput) => Promise<void
|
|
59
|
-
ok: false;
|
|
60
|
-
}>;
|
|
58
|
+
}, input: EnterpriseAdminAuthorizationInput) => Promise<void>;
|
|
61
59
|
type RoleRef<TRoleId extends string> = {
|
|
62
60
|
id: TRoleId;
|
|
63
61
|
};
|
|
@@ -126,14 +124,14 @@ type EnterpriseMountOptions<TRoleId extends string = string> = {
|
|
|
126
124
|
* @see {@link scim}
|
|
127
125
|
* @see {@link enterprise}
|
|
128
126
|
*/
|
|
129
|
-
declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined = undefined>(auth: Pick<AuthApi<TAuthorization>, "
|
|
127
|
+
declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined = undefined>(auth: Pick<AuthApi<TAuthorization>, "context" | "group" | "member" | "sso">, options?: MountedEnterpriseOptions<AuthRoleId<TAuthorization>>): {
|
|
130
128
|
admin: {
|
|
131
129
|
connection: {
|
|
132
130
|
create: convex_server0.RegisteredMutation<"public", {
|
|
131
|
+
groupId?: string | undefined;
|
|
133
132
|
name?: string | undefined;
|
|
134
133
|
slug?: string | undefined;
|
|
135
134
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
136
|
-
groupId?: string | undefined;
|
|
137
135
|
domain?: string | undefined;
|
|
138
136
|
}, Promise<any>>;
|
|
139
137
|
get: convex_server0.RegisteredQuery<"public", {
|
|
@@ -146,12 +144,12 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
146
144
|
domain: string;
|
|
147
145
|
}, Promise<any>>;
|
|
148
146
|
list: convex_server0.RegisteredQuery<"public", {
|
|
147
|
+
limit?: number | undefined;
|
|
149
148
|
where?: {
|
|
149
|
+
groupId?: string | undefined;
|
|
150
150
|
slug?: string | undefined;
|
|
151
151
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
152
|
-
groupId?: string | undefined;
|
|
153
152
|
} | undefined;
|
|
154
|
-
limit?: number | undefined;
|
|
155
153
|
cursor?: string | null | undefined;
|
|
156
154
|
orderBy?: string | undefined;
|
|
157
155
|
order?: "asc" | "desc" | undefined;
|
|
@@ -164,13 +162,7 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
164
162
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
165
163
|
};
|
|
166
164
|
}, Promise<{
|
|
167
|
-
ok: false;
|
|
168
|
-
code: "NOT_SIGNED_IN" | "FORBIDDEN";
|
|
169
|
-
enterpriseId?: undefined;
|
|
170
|
-
} | {
|
|
171
|
-
ok: true;
|
|
172
165
|
enterpriseId: string;
|
|
173
|
-
code?: undefined;
|
|
174
166
|
}>>;
|
|
175
167
|
delete: convex_server0.RegisteredMutation<"public", {
|
|
176
168
|
enterpriseId: string;
|
|
@@ -194,12 +186,12 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
194
186
|
}, Promise<any>>;
|
|
195
187
|
verification: {
|
|
196
188
|
request: convex_server0.RegisteredMutation<"public", {
|
|
197
|
-
enterpriseId: string;
|
|
198
189
|
domain: string;
|
|
190
|
+
enterpriseId: string;
|
|
199
191
|
}, Promise<any>>;
|
|
200
192
|
confirm: convex_server0.RegisteredAction<"public", {
|
|
201
|
-
enterpriseId: string;
|
|
202
193
|
domain: string;
|
|
194
|
+
enterpriseId: string;
|
|
203
195
|
}, Promise<any>>;
|
|
204
196
|
};
|
|
205
197
|
};
|
|
@@ -263,8 +255,8 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
263
255
|
patch: {
|
|
264
256
|
identity?: {
|
|
265
257
|
accountLinking?: {
|
|
266
|
-
saml?: "verifiedEmail" | "none" | undefined;
|
|
267
258
|
oidc?: "verifiedEmail" | "none" | undefined;
|
|
259
|
+
saml?: "verifiedEmail" | "none" | undefined;
|
|
268
260
|
} | undefined;
|
|
269
261
|
} | undefined;
|
|
270
262
|
provisioning?: {
|
|
@@ -287,9 +279,9 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
287
279
|
};
|
|
288
280
|
audit: {
|
|
289
281
|
list: convex_server0.RegisteredQuery<"public", {
|
|
290
|
-
enterpriseId?: string | undefined;
|
|
291
282
|
groupId?: string | undefined;
|
|
292
283
|
limit?: number | undefined;
|
|
284
|
+
enterpriseId?: string | undefined;
|
|
293
285
|
}, Promise<any>>;
|
|
294
286
|
};
|
|
295
287
|
webhook: {
|
|
@@ -302,21 +294,11 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
302
294
|
endpoint: {
|
|
303
295
|
create: convex_server0.RegisteredMutation<"public", {
|
|
304
296
|
createdByUserId?: string | undefined;
|
|
305
|
-
enterpriseId: string;
|
|
306
297
|
secret: string;
|
|
298
|
+
enterpriseId: string;
|
|
307
299
|
url: string;
|
|
308
300
|
subscriptions: string[];
|
|
309
301
|
}, Promise<{
|
|
310
|
-
ok: false;
|
|
311
|
-
code: "NOT_SIGNED_IN" | "FORBIDDEN";
|
|
312
|
-
_id?: undefined;
|
|
313
|
-
enterpriseId?: undefined;
|
|
314
|
-
url?: undefined;
|
|
315
|
-
subscriptions?: undefined;
|
|
316
|
-
createdByUserId?: undefined;
|
|
317
|
-
status?: undefined;
|
|
318
|
-
failureCount?: undefined;
|
|
319
|
-
} | {
|
|
320
302
|
_id: any;
|
|
321
303
|
enterpriseId: string;
|
|
322
304
|
url: string;
|
|
@@ -324,8 +306,6 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
324
306
|
createdByUserId: string;
|
|
325
307
|
status: string;
|
|
326
308
|
failureCount: number;
|
|
327
|
-
ok?: undefined;
|
|
328
|
-
code?: undefined;
|
|
329
309
|
}>>;
|
|
330
310
|
list: convex_server0.RegisteredQuery<"public", {
|
|
331
311
|
enterpriseId: string;
|
|
@@ -339,8 +319,8 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
339
319
|
client: {
|
|
340
320
|
signIn: convex_server0.RegisteredQuery<"public", {
|
|
341
321
|
email?: string | undefined;
|
|
342
|
-
enterpriseId?: string | undefined;
|
|
343
322
|
domain?: string | undefined;
|
|
323
|
+
enterpriseId?: string | undefined;
|
|
344
324
|
redirectTo?: string | undefined;
|
|
345
325
|
}, Promise<any>>;
|
|
346
326
|
metadata: convex_server0.RegisteredQuery<"public", {
|
|
@@ -380,7 +360,7 @@ declare function sso<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
380
360
|
* @see {@link sso}
|
|
381
361
|
* @see {@link enterprise}
|
|
382
362
|
*/
|
|
383
|
-
declare function scim<TAuthorization extends AuthAuthorizationConfig | undefined = undefined>(auth: Pick<AuthApi<TAuthorization>, "
|
|
363
|
+
declare function scim<TAuthorization extends AuthAuthorizationConfig | undefined = undefined>(auth: Pick<AuthApi<TAuthorization>, "context" | "scim" | "sso">, options?: MountedEnterpriseOptions<AuthRoleId<TAuthorization>>): {
|
|
384
364
|
admin: {
|
|
385
365
|
configure: convex_server0.RegisteredMutation<"public", {
|
|
386
366
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
@@ -430,12 +410,12 @@ declare function scim<TAuthorization extends AuthAuthorizationConfig | undefined
|
|
|
430
410
|
* @see {@link sso}
|
|
431
411
|
* @see {@link scim}
|
|
432
412
|
*/
|
|
433
|
-
declare function enterprise<TAuthorization extends AuthAuthorizationConfig | undefined = undefined>(auth: Pick<AuthApi<TAuthorization>, "
|
|
413
|
+
declare function enterprise<TAuthorization extends AuthAuthorizationConfig | undefined = undefined>(auth: Pick<AuthApi<TAuthorization>, "context" | "group" | "member" | "scim" | "sso">, options: EnterpriseMountOptions<AuthRoleId<TAuthorization>>): {
|
|
434
414
|
createConnection: convex_server0.RegisteredMutation<"public", {
|
|
415
|
+
groupId?: string | undefined;
|
|
435
416
|
name?: string | undefined;
|
|
436
417
|
slug?: string | undefined;
|
|
437
418
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
438
|
-
groupId?: string | undefined;
|
|
439
419
|
domain?: string | undefined;
|
|
440
420
|
}, Promise<any>>;
|
|
441
421
|
getConnection: convex_server0.RegisteredQuery<"public", {
|
|
@@ -448,12 +428,12 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
448
428
|
domain: string;
|
|
449
429
|
}, Promise<any>>;
|
|
450
430
|
listConnections: convex_server0.RegisteredQuery<"public", {
|
|
431
|
+
limit?: number | undefined;
|
|
451
432
|
where?: {
|
|
433
|
+
groupId?: string | undefined;
|
|
452
434
|
slug?: string | undefined;
|
|
453
435
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
454
|
-
groupId?: string | undefined;
|
|
455
436
|
} | undefined;
|
|
456
|
-
limit?: number | undefined;
|
|
457
437
|
cursor?: string | null | undefined;
|
|
458
438
|
orderBy?: string | undefined;
|
|
459
439
|
order?: "asc" | "desc" | undefined;
|
|
@@ -466,13 +446,7 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
466
446
|
status?: "draft" | "active" | "disabled" | undefined;
|
|
467
447
|
};
|
|
468
448
|
}, Promise<{
|
|
469
|
-
ok: false;
|
|
470
|
-
code: "NOT_SIGNED_IN" | "FORBIDDEN";
|
|
471
|
-
enterpriseId?: undefined;
|
|
472
|
-
} | {
|
|
473
|
-
ok: true;
|
|
474
449
|
enterpriseId: string;
|
|
475
|
-
code?: undefined;
|
|
476
450
|
}>>;
|
|
477
451
|
deleteConnection: convex_server0.RegisteredMutation<"public", {
|
|
478
452
|
enterpriseId: string;
|
|
@@ -494,12 +468,12 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
494
468
|
}[];
|
|
495
469
|
}, Promise<any>>;
|
|
496
470
|
requestDomainVerification: convex_server0.RegisteredMutation<"public", {
|
|
497
|
-
enterpriseId: string;
|
|
498
471
|
domain: string;
|
|
472
|
+
enterpriseId: string;
|
|
499
473
|
}, Promise<any>>;
|
|
500
474
|
confirmDomainVerification: convex_server0.RegisteredAction<"public", {
|
|
501
|
-
enterpriseId: string;
|
|
502
475
|
domain: string;
|
|
476
|
+
enterpriseId: string;
|
|
503
477
|
}, Promise<any>>;
|
|
504
478
|
configureOidc: convex_server0.RegisteredMutation<"public", {
|
|
505
479
|
scopes?: string[] | undefined;
|
|
@@ -555,8 +529,8 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
555
529
|
patch: {
|
|
556
530
|
identity?: {
|
|
557
531
|
accountLinking?: {
|
|
558
|
-
saml?: "verifiedEmail" | "none" | undefined;
|
|
559
532
|
oidc?: "verifiedEmail" | "none" | undefined;
|
|
533
|
+
saml?: "verifiedEmail" | "none" | undefined;
|
|
560
534
|
} | undefined;
|
|
561
535
|
} | undefined;
|
|
562
536
|
provisioning?: {
|
|
@@ -577,27 +551,17 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
577
551
|
enterpriseId: string;
|
|
578
552
|
}, Promise<any>>;
|
|
579
553
|
listAudit: convex_server0.RegisteredQuery<"public", {
|
|
580
|
-
enterpriseId?: string | undefined;
|
|
581
554
|
groupId?: string | undefined;
|
|
582
555
|
limit?: number | undefined;
|
|
556
|
+
enterpriseId?: string | undefined;
|
|
583
557
|
}, Promise<any>>;
|
|
584
558
|
createWebhookEndpoint: convex_server0.RegisteredMutation<"public", {
|
|
585
559
|
createdByUserId?: string | undefined;
|
|
586
|
-
enterpriseId: string;
|
|
587
560
|
secret: string;
|
|
561
|
+
enterpriseId: string;
|
|
588
562
|
url: string;
|
|
589
563
|
subscriptions: string[];
|
|
590
564
|
}, Promise<{
|
|
591
|
-
ok: false;
|
|
592
|
-
code: "NOT_SIGNED_IN" | "FORBIDDEN";
|
|
593
|
-
_id?: undefined;
|
|
594
|
-
enterpriseId?: undefined;
|
|
595
|
-
url?: undefined;
|
|
596
|
-
subscriptions?: undefined;
|
|
597
|
-
createdByUserId?: undefined;
|
|
598
|
-
status?: undefined;
|
|
599
|
-
failureCount?: undefined;
|
|
600
|
-
} | {
|
|
601
565
|
_id: any;
|
|
602
566
|
enterpriseId: string;
|
|
603
567
|
url: string;
|
|
@@ -605,8 +569,6 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
605
569
|
createdByUserId: string;
|
|
606
570
|
status: string;
|
|
607
571
|
failureCount: number;
|
|
608
|
-
ok?: undefined;
|
|
609
|
-
code?: undefined;
|
|
610
572
|
}>>;
|
|
611
573
|
listWebhookEndpoints: convex_server0.RegisteredQuery<"public", {
|
|
612
574
|
enterpriseId: string;
|
|
@@ -631,8 +593,8 @@ declare function enterprise<TAuthorization extends AuthAuthorizationConfig | und
|
|
|
631
593
|
}, Promise<any>>;
|
|
632
594
|
signIn: convex_server0.RegisteredQuery<"public", {
|
|
633
595
|
email?: string | undefined;
|
|
634
|
-
enterpriseId?: string | undefined;
|
|
635
596
|
domain?: string | undefined;
|
|
597
|
+
enterpriseId?: string | undefined;
|
|
636
598
|
redirectTo?: string | undefined;
|
|
637
599
|
}, Promise<any>>;
|
|
638
600
|
metadata: convex_server0.RegisteredQuery<"public", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mounts.d.ts","names":[],"sources":["../../src/server/mounts.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"mounts.d.ts","names":[],"sources":["../../src/server/mounts.ts"],"mappings":";;;;;;;;AAgCA;;;;;AAiBA;;;;;;;;KAjBY,yBAAA;;;;AAkDZ;;;KAjCY,iCAAA;EAmCH,2DAjCP,MAAA,UAkCU;EAhCV,UAAA,EAAY,yBAAA,EA8BL;EA5BP,YAAA,WA4BA;EA1BA,OAAA,WA2BA;EAzBA,eAAA;AAAA;;AA0BiB;;;;;;;;;AAEiC;;;;;;;;;;KALxC,oBAAA,IACV,GAAA;EAAO,IAAA,EADuB,cAAA,CACO,IAAA;AAAA,GACrC,KAAA,EAAO,iCAAA,KACJ,OAAA;AAAA,KAEA,OAAA;EAAoC,EAAA,EAAI,OAAA;AAAA;AAAA,KAExC,wBAAA;EACH,KAAA;IACE,UAAA,GAAa,oBAAA;IACb,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAA,CAAQ,OAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;KAwBxB,sBAAA;EACV,KAAA;IACE,UAAA,EAAY,oBAAA;IACZ,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAA,CAAQ,OAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqJpB,GAAA,wBACS,uBAAA,yBAAA,CAEvB,IAAA,EAAM,IAAA,CACJ,OAAA,CAAQ,cAAA,4CAGV,OAAA,GAAU,wBAAA,CAAyB,UAAA,CAAW,cAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkgBhC,IAAA,wBACS,uBAAA,yBAAA,CAEvB,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,cAAA,gCACnB,OAAA,GAAU,wBAAA,CAAyB,UAAA,CAAW,cAAA;;;;;;;;;;;;;;;;AAJhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmFgB,UAAA,wBACS,uBAAA,yBAAA,CAEvB,IAAA,EAAM,IAAA,CACJ,OAAA,CAAQ,cAAA,qDAGV,OAAA,EAAS,sBAAA,CAAuB,UAAA,CAAW,cAAA"}
|