@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/src/server/auth.ts
CHANGED
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { Cv } from "@robelest/fx/convex";
|
|
7
8
|
import type { UserIdentity } from "convex/server";
|
|
8
9
|
import type { GenericId } from "convex/values";
|
|
9
10
|
|
|
10
11
|
import type { AuthApiRefs } from "../client/index";
|
|
12
|
+
import {
|
|
13
|
+
createUnauthenticatedAuthContext,
|
|
14
|
+
getAuthContext as getResolvedAuthContext,
|
|
15
|
+
} from "./context";
|
|
11
16
|
import { Auth as AuthFactory } from "./runtime";
|
|
12
|
-
import { AuthError } from "./authError";
|
|
13
17
|
import type { Doc } from "./types";
|
|
14
18
|
import type {
|
|
15
19
|
AuthAuthorizationConfig,
|
|
@@ -41,7 +45,7 @@ type MemberApiWithAuthorization<
|
|
|
41
45
|
TAuthorization extends AuthAuthorizationConfig | undefined,
|
|
42
46
|
> = Omit<
|
|
43
47
|
ReturnType<typeof AuthFactory>["auth"]["member"],
|
|
44
|
-
"create" | "list" | "update" | "
|
|
48
|
+
"create" | "list" | "update" | "inspect" | "require"
|
|
45
49
|
> & {
|
|
46
50
|
create: (
|
|
47
51
|
ctx: Parameters<
|
|
@@ -54,7 +58,7 @@ type MemberApiWithAuthorization<
|
|
|
54
58
|
status?: string;
|
|
55
59
|
extend?: Record<string, unknown>;
|
|
56
60
|
},
|
|
57
|
-
) => Promise<{
|
|
61
|
+
) => Promise<{ memberId: string }>;
|
|
58
62
|
list: (
|
|
59
63
|
ctx: Parameters<
|
|
60
64
|
ReturnType<typeof AuthFactory>["auth"]["member"]["list"]
|
|
@@ -78,10 +82,21 @@ type MemberApiWithAuthorization<
|
|
|
78
82
|
>[0],
|
|
79
83
|
memberId: string,
|
|
80
84
|
data: Record<string, unknown> & { roleIds?: AuthRoleId<TAuthorization>[] },
|
|
81
|
-
) => Promise<{
|
|
82
|
-
|
|
85
|
+
) => Promise<{ memberId: string }>;
|
|
86
|
+
inspect: (
|
|
83
87
|
ctx: Parameters<
|
|
84
|
-
ReturnType<typeof AuthFactory>["auth"]["member"]["
|
|
88
|
+
ReturnType<typeof AuthFactory>["auth"]["member"]["inspect"]
|
|
89
|
+
>[0],
|
|
90
|
+
opts: {
|
|
91
|
+
userId: string;
|
|
92
|
+
groupId: string;
|
|
93
|
+
ancestry?: boolean;
|
|
94
|
+
maxDepth?: number;
|
|
95
|
+
},
|
|
96
|
+
) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["inspect"]>;
|
|
97
|
+
require: (
|
|
98
|
+
ctx: Parameters<
|
|
99
|
+
ReturnType<typeof AuthFactory>["auth"]["member"]["require"]
|
|
85
100
|
>[0],
|
|
86
101
|
opts: {
|
|
87
102
|
userId: string;
|
|
@@ -91,10 +106,9 @@ type MemberApiWithAuthorization<
|
|
|
91
106
|
grants?: AuthGrant<TAuthorization>[];
|
|
92
107
|
maxDepth?: number;
|
|
93
108
|
},
|
|
94
|
-
) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["
|
|
109
|
+
) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["require"]>;
|
|
95
110
|
};
|
|
96
111
|
|
|
97
|
-
|
|
98
112
|
/**
|
|
99
113
|
* The base auth API surface returned by {@link createAuth}.
|
|
100
114
|
*
|
|
@@ -126,30 +140,40 @@ export type AuthApiBase<
|
|
|
126
140
|
key: ReturnType<typeof AuthFactory>["auth"]["key"];
|
|
127
141
|
http: ReturnType<typeof AuthFactory>["auth"]["http"];
|
|
128
142
|
/**
|
|
129
|
-
* Resolve the current
|
|
143
|
+
* Resolve the current request's auth context. Framework-agnostic — use
|
|
130
144
|
* this in fluent-convex middleware, custom wrappers, or anywhere you
|
|
131
|
-
* need the
|
|
145
|
+
* need the current `{ userId, user, groupId, role, grants }` object.
|
|
132
146
|
*
|
|
133
|
-
*
|
|
147
|
+
* Throws a structured `ConvexError` when unauthenticated by default.
|
|
148
|
+
* Pass `{ optional: true }` to get a null-shaped auth object instead.
|
|
134
149
|
*
|
|
135
150
|
* @param ctx - Convex query, mutation, or action context.
|
|
136
|
-
* @
|
|
151
|
+
* @param config - Optional auth resolution config. Supports `optional`,
|
|
152
|
+
* `resolve`, and `authResolve`.
|
|
153
|
+
* @returns The current auth context.
|
|
137
154
|
*
|
|
138
155
|
* @example fluent-convex middleware
|
|
139
156
|
* ```ts
|
|
140
157
|
* const withAuth = convex.createMiddleware(async (ctx, next) => {
|
|
141
|
-
* return next({ ...ctx, auth: await auth.
|
|
158
|
+
* return next({ ...ctx, auth: await auth.context(ctx) });
|
|
142
159
|
* });
|
|
143
160
|
* ```
|
|
144
161
|
*
|
|
145
162
|
* @example Direct usage in a handler
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
163
|
+
* ```ts
|
|
164
|
+
* const authContext = await auth.context(ctx);
|
|
165
|
+
* const { userId, grants } = authContext;
|
|
166
|
+
* ```
|
|
167
|
+
*
|
|
168
|
+
* @example Optional usage
|
|
169
|
+
* ```ts
|
|
170
|
+
* const authContext = await auth.context(ctx, { optional: true });
|
|
171
|
+
* if (authContext.userId === null) {
|
|
172
|
+
* return null;
|
|
173
|
+
* }
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
context: AuthContextResolver;
|
|
153
177
|
/**
|
|
154
178
|
* Context enrichment for convex-helpers `customQuery` / `customMutation` /
|
|
155
179
|
* `customAction`.
|
|
@@ -158,9 +182,9 @@ export type AuthApiBase<
|
|
|
158
182
|
* and grants, then attaches them to `ctx.auth`. Returns a `Customization`
|
|
159
183
|
* object compatible with convex-helpers' custom function builders.
|
|
160
184
|
*
|
|
161
|
-
* `ctx.auth` is
|
|
162
|
-
*
|
|
163
|
-
*
|
|
185
|
+
* `ctx.auth` is the current request auth context.
|
|
186
|
+
* By default this throws when unauthenticated so handlers can assume
|
|
187
|
+
* `ctx.auth.userId` and `ctx.auth.user` exist.
|
|
164
188
|
*
|
|
165
189
|
* @returns A convex-helpers `Customization` object.
|
|
166
190
|
*
|
|
@@ -182,36 +206,30 @@ export type AuthApiBase<
|
|
|
182
206
|
* export const list = authQuery({
|
|
183
207
|
* args: { workspaceId: v.string() },
|
|
184
208
|
* handler: async (ctx, args) => {
|
|
185
|
-
* if (!ctx.auth) return [];
|
|
186
209
|
* const { userId, groupId, grants } = ctx.auth;
|
|
187
210
|
* // business logic
|
|
188
211
|
* },
|
|
189
212
|
* });
|
|
190
213
|
* ```
|
|
191
214
|
*/
|
|
192
|
-
ctx:
|
|
193
|
-
args: Record<string, never>;
|
|
194
|
-
input: (ctx: any) => Promise<{
|
|
195
|
-
ctx: { auth: AuthResolvedContext | null };
|
|
196
|
-
args: Record<string, never>;
|
|
197
|
-
}>;
|
|
198
|
-
};
|
|
215
|
+
ctx: AuthContextFactory;
|
|
199
216
|
};
|
|
200
217
|
|
|
201
218
|
/**
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
219
|
+
* Current request auth context injected into `ctx.auth` by `auth.ctx()`. This
|
|
220
|
+
* is the authenticated auth shape returned by {@link createAuth().context}.
|
|
221
|
+
* Optional context builders may still surface nullable fields when
|
|
222
|
+
* `optional: true` is used.
|
|
205
223
|
*
|
|
206
|
-
* - `null` when unauthenticated.
|
|
207
224
|
* - `groupId` is `null` when the user has no active group set.
|
|
208
|
-
* - `role`
|
|
225
|
+
* - `role` is `null` when no active group or no membership is resolved.
|
|
226
|
+
* - `grants` is `[]` when no active group or no membership is resolved.
|
|
209
227
|
*
|
|
210
228
|
* @example
|
|
211
229
|
* ```ts
|
|
212
|
-
* import type {
|
|
230
|
+
* import type { AuthContext } from "@robelest/convex-auth/server";
|
|
213
231
|
*
|
|
214
|
-
* const mockAuth:
|
|
232
|
+
* const mockAuth: AuthContext = {
|
|
215
233
|
* userId: "user123" as Id<"User">,
|
|
216
234
|
* user: { _id: "user123", email: "test@example.com" },
|
|
217
235
|
* groupId: "group456",
|
|
@@ -220,7 +238,7 @@ export type AuthApiBase<
|
|
|
220
238
|
* };
|
|
221
239
|
* ```
|
|
222
240
|
*/
|
|
223
|
-
export type
|
|
241
|
+
export type AuthContext = {
|
|
224
242
|
/** The authenticated user's document ID. */
|
|
225
243
|
userId: GenericId<"User">;
|
|
226
244
|
/** The authenticated user's full document. */
|
|
@@ -233,20 +251,84 @@ export type AuthResolvedContext = {
|
|
|
233
251
|
grants: string[];
|
|
234
252
|
};
|
|
235
253
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Nullable auth context returned by `auth.context(ctx, { optional: true })`
|
|
256
|
+
* and injected by `auth.ctx({ optional: true })`.
|
|
257
|
+
*
|
|
258
|
+
* Use this when callers may be unauthenticated but you still want a stable
|
|
259
|
+
* auth-shaped object.
|
|
260
|
+
*
|
|
261
|
+
* - `userId` and `user` are `null` when unauthenticated.
|
|
262
|
+
* - `groupId` and `role` are `null` when no active group is resolved.
|
|
263
|
+
* - `grants` is `[]` when no membership is resolved.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* const authContext = await auth.context(ctx, { optional: true });
|
|
268
|
+
* if (authContext.userId === null) {
|
|
269
|
+
* return null;
|
|
270
|
+
* }
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
export type OptionalAuthContext = {
|
|
274
|
+
/** The authenticated user's document ID, or `null` when unauthenticated. */
|
|
243
275
|
userId: GenericId<"User"> | null;
|
|
276
|
+
/** The authenticated user's full document, or `null` when unauthenticated. */
|
|
244
277
|
user: UserDoc | null;
|
|
278
|
+
/** The user's active group ID, or `null` if none is set. */
|
|
245
279
|
groupId: string | null;
|
|
280
|
+
/** The user's primary role in the active group, or `null`. */
|
|
246
281
|
role: string | null;
|
|
282
|
+
/** Resolved grant strings for the active membership, or `[]`. */
|
|
247
283
|
grants: string[];
|
|
248
284
|
};
|
|
249
285
|
|
|
286
|
+
type AuthContextBase = {
|
|
287
|
+
getUserIdentity: () => Promise<UserIdentity | null>;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
type RequiredAuthContextState = AuthContextBase & AuthContext;
|
|
291
|
+
|
|
292
|
+
type OptionalAuthContextState = AuthContextBase & OptionalAuthContext;
|
|
293
|
+
|
|
294
|
+
type ResolvedAuthContext<TResolve> = AuthContext & TResolve;
|
|
295
|
+
|
|
296
|
+
type ResolvedOptionalAuthContext<TResolve> = OptionalAuthContext & TResolve;
|
|
297
|
+
|
|
298
|
+
type AuthContextResolver = {
|
|
299
|
+
<TResolve extends Record<string, unknown> = Record<string, never>>(
|
|
300
|
+
ctx: any,
|
|
301
|
+
config: AuthContextConfig<TResolve> & { optional: true },
|
|
302
|
+
): Promise<ResolvedOptionalAuthContext<TResolve>>;
|
|
303
|
+
<TResolve extends Record<string, unknown> = Record<string, never>>(
|
|
304
|
+
ctx: any,
|
|
305
|
+
config?: AuthContextConfig<TResolve>,
|
|
306
|
+
): Promise<ResolvedAuthContext<TResolve>>;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
type AuthContextCustomization<TAuth> = {
|
|
310
|
+
args: {};
|
|
311
|
+
input: (
|
|
312
|
+
ctx: any,
|
|
313
|
+
_args: any,
|
|
314
|
+
_extra?: any,
|
|
315
|
+
) => Promise<{
|
|
316
|
+
ctx: {
|
|
317
|
+
auth: TAuth;
|
|
318
|
+
};
|
|
319
|
+
args: {};
|
|
320
|
+
}>;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
type AuthContextFactory = {
|
|
324
|
+
<TResolve extends Record<string, unknown> = Record<string, never>>(
|
|
325
|
+
config: AuthContextConfig<TResolve> & { optional: true },
|
|
326
|
+
): AuthContextCustomization<OptionalAuthContextState & TResolve>;
|
|
327
|
+
<TResolve extends Record<string, unknown> = Record<string, never>>(
|
|
328
|
+
config?: AuthContextConfig<TResolve>,
|
|
329
|
+
): AuthContextCustomization<RequiredAuthContextState & TResolve>;
|
|
330
|
+
};
|
|
331
|
+
|
|
250
332
|
type InternalSsoApi = ReturnType<typeof AuthFactory>["auth"]["sso"];
|
|
251
333
|
|
|
252
334
|
type PublicSsoAdminApi = {
|
|
@@ -262,7 +344,6 @@ type PublicSsoAdminApi = {
|
|
|
262
344
|
isPrimary?: boolean;
|
|
263
345
|
}>,
|
|
264
346
|
) => Promise<{
|
|
265
|
-
ok: true;
|
|
266
347
|
enterpriseId: string;
|
|
267
348
|
domains: Array<{
|
|
268
349
|
domainId: string;
|
|
@@ -277,7 +358,6 @@ type PublicSsoAdminApi = {
|
|
|
277
358
|
ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
|
|
278
359
|
args: { enterpriseId: string; domain: string },
|
|
279
360
|
) => Promise<{
|
|
280
|
-
ok: true;
|
|
281
361
|
enterpriseId: string;
|
|
282
362
|
domain: string;
|
|
283
363
|
requestedAt: number;
|
|
@@ -292,7 +372,6 @@ type PublicSsoAdminApi = {
|
|
|
292
372
|
ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
|
|
293
373
|
args: { enterpriseId: string; domain: string },
|
|
294
374
|
) => Promise<{
|
|
295
|
-
ok: boolean;
|
|
296
375
|
enterpriseId: string;
|
|
297
376
|
domain: string;
|
|
298
377
|
verifiedAt?: number;
|
|
@@ -431,38 +510,54 @@ export type AuthLike = Pick<AuthApiBase, "user" | "member">;
|
|
|
431
510
|
* });
|
|
432
511
|
* ```
|
|
433
512
|
*
|
|
434
|
-
* @see {@link
|
|
513
|
+
* @see {@link AuthContextConfig}
|
|
435
514
|
*/
|
|
436
515
|
|
|
437
516
|
// ---------------------------------------------------------------------------
|
|
438
517
|
// Function builders — shared auth resolution logic
|
|
439
518
|
// ---------------------------------------------------------------------------
|
|
440
519
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
520
|
+
async function resolveConfiguredAuthContext(
|
|
521
|
+
auth: AuthLike,
|
|
522
|
+
ctx: any,
|
|
523
|
+
config?: AuthContextConfig<any>,
|
|
524
|
+
): Promise<AuthContext | null> {
|
|
525
|
+
const fallback = () => getResolvedAuthContext(auth, ctx);
|
|
526
|
+
const authOverride = config?.authResolve
|
|
527
|
+
? await config.authResolve(ctx, fallback)
|
|
528
|
+
: undefined;
|
|
529
|
+
return authOverride === undefined ? await fallback() : authOverride;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function createNotSignedInError() {
|
|
533
|
+
return Cv.error({
|
|
534
|
+
code: "NOT_SIGNED_IN",
|
|
535
|
+
message: "Authentication required.",
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
async function createPublicAuthContext(
|
|
540
|
+
auth: AuthLike,
|
|
541
|
+
ctx: any,
|
|
542
|
+
config?: AuthContextConfig<any>,
|
|
543
|
+
) {
|
|
544
|
+
const resolved = await resolveConfiguredAuthContext(auth, ctx, config);
|
|
545
|
+
|
|
546
|
+
if (resolved === null) {
|
|
547
|
+
if (config?.optional !== true) {
|
|
548
|
+
throw createNotSignedInError();
|
|
463
549
|
}
|
|
550
|
+
return createUnauthenticatedAuthContext();
|
|
464
551
|
}
|
|
465
|
-
|
|
552
|
+
|
|
553
|
+
const extra = config?.resolve
|
|
554
|
+
? await config.resolve(ctx, resolved.user, resolved)
|
|
555
|
+
: {};
|
|
556
|
+
|
|
557
|
+
return {
|
|
558
|
+
...resolved,
|
|
559
|
+
...extra,
|
|
560
|
+
};
|
|
466
561
|
}
|
|
467
562
|
|
|
468
563
|
export function createAuth<
|
|
@@ -504,10 +599,10 @@ export function createAuth<
|
|
|
504
599
|
) => {
|
|
505
600
|
const enterprise = await connectionApi.get(ctx, enterpriseId);
|
|
506
601
|
if (enterprise === null) {
|
|
507
|
-
throw
|
|
508
|
-
"INVALID_PARAMETERS",
|
|
509
|
-
"Enterprise not found.",
|
|
510
|
-
)
|
|
602
|
+
throw Cv.error({
|
|
603
|
+
code: "INVALID_PARAMETERS",
|
|
604
|
+
message: "Enterprise not found.",
|
|
605
|
+
});
|
|
511
606
|
}
|
|
512
607
|
|
|
513
608
|
const normalized = domains.map((entry: (typeof domains)[number]) => ({
|
|
@@ -517,16 +612,16 @@ export function createAuth<
|
|
|
517
612
|
const deduped = new Map<string, (typeof normalized)[number]>();
|
|
518
613
|
for (const entry of normalized) {
|
|
519
614
|
if (entry.domain.length === 0) {
|
|
520
|
-
throw
|
|
521
|
-
"INVALID_PARAMETERS",
|
|
522
|
-
"Domain must not be empty.",
|
|
523
|
-
)
|
|
615
|
+
throw Cv.error({
|
|
616
|
+
code: "INVALID_PARAMETERS",
|
|
617
|
+
message: "Domain must not be empty.",
|
|
618
|
+
});
|
|
524
619
|
}
|
|
525
620
|
if (deduped.has(entry.domain)) {
|
|
526
|
-
throw
|
|
527
|
-
"INVALID_PARAMETERS",
|
|
528
|
-
`Duplicate domain: ${entry.domain}`,
|
|
529
|
-
)
|
|
621
|
+
throw Cv.error({
|
|
622
|
+
code: "INVALID_PARAMETERS",
|
|
623
|
+
message: `Duplicate domain: ${entry.domain}`,
|
|
624
|
+
});
|
|
530
625
|
}
|
|
531
626
|
deduped.set(entry.domain, entry);
|
|
532
627
|
}
|
|
@@ -536,10 +631,10 @@ export function createAuth<
|
|
|
536
631
|
(entry) => entry.isPrimary,
|
|
537
632
|
).length;
|
|
538
633
|
if (primaryCount > 1) {
|
|
539
|
-
throw
|
|
540
|
-
"INVALID_PARAMETERS",
|
|
541
|
-
"Only one primary domain may be set.",
|
|
542
|
-
)
|
|
634
|
+
throw Cv.error({
|
|
635
|
+
code: "INVALID_PARAMETERS",
|
|
636
|
+
message: "Only one primary domain may be set.",
|
|
637
|
+
});
|
|
543
638
|
}
|
|
544
639
|
if (nextDomains.length > 0 && primaryCount === 0) {
|
|
545
640
|
nextDomains[0] = { ...nextDomains[0], isPrimary: true };
|
|
@@ -586,7 +681,6 @@ export function createAuth<
|
|
|
586
681
|
|
|
587
682
|
const updatedDomains = await domainApi.list(ctx, enterpriseId);
|
|
588
683
|
return {
|
|
589
|
-
ok: true as const,
|
|
590
684
|
enterpriseId,
|
|
591
685
|
domains: updatedDomains.map(
|
|
592
686
|
(domain: (typeof updatedDomains)[number]) => ({
|
|
@@ -660,59 +754,72 @@ export function createAuth<
|
|
|
660
754
|
},
|
|
661
755
|
http: authResult.auth.http,
|
|
662
756
|
|
|
663
|
-
|
|
757
|
+
context: ((ctx: any, config?: AuthContextConfig<any>) =>
|
|
758
|
+
createPublicAuthContext(authResult.auth, ctx, config)) as AuthContextResolver,
|
|
664
759
|
|
|
665
|
-
ctx: () =>
|
|
666
|
-
|
|
667
|
-
input: async (ctx: any) => {
|
|
668
|
-
const authCtx = await resolveAuthContext(authResult.auth, ctx);
|
|
669
|
-
return { ctx: { auth: authCtx }, args: {} };
|
|
670
|
-
},
|
|
671
|
-
}),
|
|
760
|
+
ctx: ((config?: AuthContextConfig<any>) =>
|
|
761
|
+
createAuthContextCustomization(authResult.auth, config)) as AuthContextFactory,
|
|
672
762
|
} as unknown as ConvexAuthResult<P, TAuthorization>;
|
|
673
763
|
}
|
|
674
764
|
|
|
675
765
|
// ============================================================================
|
|
676
|
-
//
|
|
766
|
+
// auth.ctx() — ctx enrichment for customQuery / customMutation
|
|
677
767
|
// ============================================================================
|
|
678
768
|
|
|
679
769
|
/**
|
|
680
|
-
* Configuration for {@link
|
|
770
|
+
* Configuration for {@link createAuth().ctx} context enrichment.
|
|
771
|
+
*
|
|
772
|
+
* The same config shape is also used by {@link createAuth().context}.
|
|
681
773
|
*
|
|
682
774
|
* @typeParam TResolve - Extra fields returned from `resolve()` and merged into
|
|
683
775
|
* the resulting `ctx.auth` object.
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* ```ts
|
|
779
|
+
* const authContext = await auth.context(ctx, {
|
|
780
|
+
* resolve: async (_ctx, user, authState) => ({
|
|
781
|
+
* email: user.email,
|
|
782
|
+
* canWrite: authState.grants.includes("posts.write"),
|
|
783
|
+
* }),
|
|
784
|
+
* });
|
|
785
|
+
* ```
|
|
684
786
|
*/
|
|
685
|
-
export type
|
|
787
|
+
export type AuthContextConfig<
|
|
686
788
|
TResolve extends Record<string, unknown> = Record<string, never>,
|
|
687
789
|
> = {
|
|
688
|
-
/**
|
|
790
|
+
/**
|
|
791
|
+
* Allow unauthenticated callers and return a null-shaped auth object instead
|
|
792
|
+
* of throwing `NOT_SIGNED_IN`.
|
|
793
|
+
*/
|
|
689
794
|
optional?: boolean;
|
|
690
795
|
/**
|
|
691
796
|
* Attach additional derived fields to the auth context after the base auth
|
|
692
797
|
* context is resolved.
|
|
798
|
+
*
|
|
799
|
+
* This callback runs only when a user is authenticated.
|
|
693
800
|
*/
|
|
694
801
|
resolve?: (
|
|
695
802
|
ctx: any,
|
|
696
803
|
user: UserDoc,
|
|
697
|
-
auth:
|
|
804
|
+
auth: AuthContext,
|
|
698
805
|
) => Promise<TResolve> | TResolve;
|
|
699
806
|
/**
|
|
700
|
-
* Override or wrap the base auth resolution used by {@link
|
|
807
|
+
* Override or wrap the base auth resolution used by {@link createAuth().ctx}.
|
|
701
808
|
*
|
|
702
809
|
* Return `undefined` to fall back to the built-in resolver,
|
|
703
810
|
* `null` for an explicit unauthenticated state, or an
|
|
704
|
-
* {@link
|
|
811
|
+
* {@link AuthContext} object to provide a pre-resolved auth state.
|
|
705
812
|
* This is useful for tests, proxy auth, impersonation flows, or any
|
|
706
813
|
* environment that needs to inject auth without depending on the standard
|
|
707
814
|
* Convex auth tables.
|
|
708
815
|
*
|
|
709
816
|
* @param ctx - The Convex function context.
|
|
710
|
-
* @param fallback - The built-in auth resolver used by {@link
|
|
817
|
+
* @param fallback - The built-in auth resolver used by {@link createAuth().ctx}.
|
|
711
818
|
* @returns Resolved auth state, `null`, or `undefined` to use the fallback.
|
|
712
819
|
*
|
|
713
820
|
* @example
|
|
714
821
|
* ```ts
|
|
715
|
-
* const authCtx =
|
|
822
|
+
* const authCtx = auth.ctx({
|
|
716
823
|
* authResolve: async (ctx, fallback) => {
|
|
717
824
|
* const injected = getInjectedAuth(ctx);
|
|
718
825
|
* return injected ?? (await fallback());
|
|
@@ -722,12 +829,8 @@ export type AuthCtxConfig<
|
|
|
722
829
|
*/
|
|
723
830
|
authResolve?: (
|
|
724
831
|
ctx: any,
|
|
725
|
-
fallback: () => Promise<
|
|
726
|
-
) =>
|
|
727
|
-
| Promise<AuthResolvedContext | null | undefined>
|
|
728
|
-
| AuthResolvedContext
|
|
729
|
-
| null
|
|
730
|
-
| undefined;
|
|
832
|
+
fallback: () => Promise<AuthContext | null>,
|
|
833
|
+
) => Promise<AuthContext | null | undefined> | AuthContext | null | undefined;
|
|
731
834
|
};
|
|
732
835
|
|
|
733
836
|
/**
|
|
@@ -737,7 +840,6 @@ export type AuthCtxConfig<
|
|
|
737
840
|
* The enriched `ctx.auth` will have `userId: null`, `user: null`,
|
|
738
841
|
* `groupId: null`, `role: null`, and `grants: []` for unauthenticated callers.
|
|
739
842
|
*
|
|
740
|
-
* @param auth - The auth API object returned by {@link createAuth}.
|
|
741
843
|
* @param config - Configuration with `optional: true` and an optional
|
|
742
844
|
* `resolve` callback for attaching extra fields to the auth context.
|
|
743
845
|
* @returns An object with `args` and `input` compatible with Convex
|
|
@@ -745,42 +847,21 @@ export type AuthCtxConfig<
|
|
|
745
847
|
*
|
|
746
848
|
* @example
|
|
747
849
|
* ```ts
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
850
|
+
* const authCtx = auth.ctx({
|
|
851
|
+
* optional: true,
|
|
852
|
+
* resolve: async (_ctx, user) => ({ plan: user.extend?.plan ?? null }),
|
|
853
|
+
* });
|
|
854
|
+
* ```
|
|
753
855
|
*
|
|
754
856
|
* @see {@link createAuth}
|
|
755
857
|
*/
|
|
756
|
-
|
|
757
|
-
TResolve extends Record<string, unknown> = Record<string, never>,
|
|
758
|
-
>(
|
|
759
|
-
auth: AuthLike,
|
|
760
|
-
config: AuthCtxConfig<TResolve> & { optional: true },
|
|
761
|
-
): {
|
|
762
|
-
args: {};
|
|
763
|
-
input: (
|
|
764
|
-
ctx: any,
|
|
765
|
-
_args: any,
|
|
766
|
-
_extra?: any,
|
|
767
|
-
) => Promise<{
|
|
768
|
-
ctx: {
|
|
769
|
-
auth: OptionalAuthCtxState & TResolve;
|
|
770
|
-
};
|
|
771
|
-
args: {};
|
|
772
|
-
}>;
|
|
773
|
-
};
|
|
858
|
+
|
|
774
859
|
/**
|
|
775
860
|
* Create a context enrichment for `customQuery` / `customMutation` — required auth (default).
|
|
776
861
|
*
|
|
777
|
-
* When `optional` is omitted or `false`,
|
|
778
|
-
*
|
|
779
|
-
* no user is signed in the returned `ctx.auth.userId` / `ctx.auth.user` are
|
|
780
|
-
* `null`, `ctx.auth.groupId` / `ctx.auth.role` are `null`, and
|
|
781
|
-
* `ctx.auth.grants` is `[]`.
|
|
862
|
+
* When `optional` is omitted or `false`, unauthenticated requests throw a
|
|
863
|
+
* structured `ConvexError` before your handler runs.
|
|
782
864
|
*
|
|
783
|
-
* @param auth - The auth API object returned by {@link createAuth}.
|
|
784
865
|
* @param config - Optional configuration with a `resolve` callback
|
|
785
866
|
* for attaching extra fields to the auth context.
|
|
786
867
|
* @returns An object with `args` and `input` compatible with Convex
|
|
@@ -788,56 +869,33 @@ export function AuthCtx<
|
|
|
788
869
|
*
|
|
789
870
|
* @example
|
|
790
871
|
* ```ts
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
872
|
+
* const authCtx = auth.ctx({
|
|
873
|
+
* resolve: async (_ctx, user) => ({ email: user.email }),
|
|
874
|
+
* });
|
|
875
|
+
* ```
|
|
795
876
|
*
|
|
796
877
|
* @see {@link createAuth}
|
|
797
878
|
*/
|
|
798
|
-
|
|
799
|
-
TResolve extends Record<string, unknown> = Record<string, never>,
|
|
800
|
-
>(
|
|
879
|
+
function createAuthContextCustomization(
|
|
801
880
|
auth: AuthLike,
|
|
802
|
-
config?:
|
|
803
|
-
)
|
|
804
|
-
args: {};
|
|
805
|
-
input: (
|
|
806
|
-
ctx: any,
|
|
807
|
-
_args: any,
|
|
808
|
-
_extra?: any,
|
|
809
|
-
) => Promise<{
|
|
810
|
-
ctx: {
|
|
811
|
-
auth: RequiredAuthCtxState & TResolve;
|
|
812
|
-
};
|
|
813
|
-
args: {};
|
|
814
|
-
}>;
|
|
815
|
-
};
|
|
816
|
-
// Implementation
|
|
817
|
-
export function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {
|
|
881
|
+
config?: AuthContextConfig<any>,
|
|
882
|
+
) {
|
|
818
883
|
return {
|
|
819
884
|
args: {},
|
|
820
885
|
input: async (ctx: any, _args: any, _extra?: any) => {
|
|
821
886
|
const nativeAuth = ctx.auth;
|
|
822
887
|
const getUserIdentity = nativeAuth.getUserIdentity.bind(nativeAuth);
|
|
823
|
-
const
|
|
824
|
-
|
|
825
|
-
const authOverride = config?.authResolve
|
|
826
|
-
? await config.authResolve(ctx, fallback)
|
|
827
|
-
: undefined;
|
|
828
|
-
const resolved =
|
|
829
|
-
authOverride === undefined ? await fallback() : authOverride;
|
|
888
|
+
const resolved = await resolveConfiguredAuthContext(auth, ctx, config);
|
|
830
889
|
|
|
831
890
|
if (resolved === null) {
|
|
891
|
+
if (config?.optional !== true) {
|
|
892
|
+
throw createNotSignedInError();
|
|
893
|
+
}
|
|
832
894
|
return {
|
|
833
895
|
ctx: {
|
|
834
896
|
auth: {
|
|
835
897
|
getUserIdentity,
|
|
836
|
-
|
|
837
|
-
user: null,
|
|
838
|
-
groupId: null,
|
|
839
|
-
role: null,
|
|
840
|
-
grants: [],
|
|
898
|
+
...createUnauthenticatedAuthContext(),
|
|
841
899
|
},
|
|
842
900
|
},
|
|
843
901
|
args: {},
|
|
@@ -863,21 +921,21 @@ export function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {
|
|
|
863
921
|
}
|
|
864
922
|
|
|
865
923
|
/**
|
|
866
|
-
* Extract the resolved `auth` context type from an
|
|
924
|
+
* Extract the resolved `auth` context type from an `auth.ctx()` customization.
|
|
867
925
|
*
|
|
868
926
|
* Use this to type function parameters or variables that receive the
|
|
869
|
-
* enriched auth context produced by `
|
|
927
|
+
* enriched auth context produced by `auth.ctx()`. The inferred type includes
|
|
870
928
|
* `userId`, `user`, `groupId`, `role`, `grants`, `getUserIdentity`, and any
|
|
871
929
|
* additional fields added by the `resolve` callback. This is the generic
|
|
872
930
|
* utility for reusing the enriched auth shape without manually duplicating
|
|
873
931
|
* conditional auth types.
|
|
874
932
|
*
|
|
875
|
-
* @typeParam T - An `
|
|
933
|
+
* @typeParam T - An `auth.ctx()` return value (must have an `input` method
|
|
876
934
|
* that returns `{ ctx: { auth: ... } }`).
|
|
877
935
|
*
|
|
878
936
|
* @example
|
|
879
937
|
* ```ts
|
|
880
|
-
* const authCtx =
|
|
938
|
+
* const authCtx = auth.ctx({
|
|
881
939
|
* resolve: async (ctx, user) => ({ orgId: user.orgId }),
|
|
882
940
|
* });
|
|
883
941
|
* type Auth = InferAuth<typeof authCtx>;
|