@robelest/convex-auth 0.0.4-preview.21 → 0.0.4-preview.23
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/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/convex.config.d.ts +2 -2
- package/dist/component/convex.config.d.ts.map +1 -1
- package/dist/component/model.d.ts +5 -5
- 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 +39 -39
- package/dist/component/server/auth.d.ts +95 -52
- package/dist/component/server/auth.d.ts.map +1 -1
- package/dist/component/server/auth.js +63 -43
- package/dist/component/server/auth.js.map +1 -1
- package/dist/component/server/core.js +116 -235
- 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 +58 -15
- 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.js +26 -21
- 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 +3 -3
- package/dist/component/server/runtime.d.ts.map +1 -1
- package/dist/component/server/runtime.js +62 -20
- 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 +95 -52
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +63 -43
- package/dist/server/auth.js.map +1 -1
- package/dist/server/core.d.ts +71 -159
- package/dist/server/core.d.ts.map +1 -1
- package/dist/server/core.js +116 -235
- 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 +58 -15
- 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 +2 -2
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +25 -20
- 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 +2 -2
- package/dist/server/limits.js +21 -30
- package/dist/server/limits.js.map +1 -1
- package/dist/server/mounts.d.ts +26 -64
- package/dist/server/mounts.d.ts.map +1 -1
- package/dist/server/mounts.js +45 -106
- 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 +13 -13
- 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 +12 -10
- 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/signin.d.ts.map +1 -1
- package/dist/server/mutations/signout.js.map +1 -1
- package/dist/server/mutations/store.d.ts +97 -97
- package/dist/server/mutations/store.d.ts.map +1 -1
- 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 +10 -10
- 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 +14 -14
- package/dist/server/runtime.d.ts.map +1 -1
- package/dist/server/runtime.js +61 -19
- 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 +2 -6
- package/src/authorization/index.ts +1 -1
- package/src/cli/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 +1 -0
- 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 +177 -111
- package/src/server/core.ts +197 -233
- 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 +36 -30
- package/src/server/identity.ts +5 -5
- package/src/server/index.ts +2 -0
- package/src/server/limits.ts +53 -80
- package/src/server/mounts.ts +47 -74
- 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 +70 -55
- 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,13 +4,12 @@
|
|
|
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";
|
|
11
12
|
import { Auth as AuthFactory } from "./runtime";
|
|
12
|
-
import { Fx } from "@robelest/fx";
|
|
13
|
-
import { AuthError } from "./authError";
|
|
14
13
|
import type { Doc } from "./types";
|
|
15
14
|
import type {
|
|
16
15
|
AuthAuthorizationConfig,
|
|
@@ -35,11 +34,14 @@ import type {
|
|
|
35
34
|
*/
|
|
36
35
|
export type AuthConfig = Omit<ConvexAuthConfig, "component">;
|
|
37
36
|
|
|
37
|
+
/** Canonical user document type exposed by Convex Auth. */
|
|
38
|
+
export type UserDoc = Doc<"User">;
|
|
39
|
+
|
|
38
40
|
type MemberApiWithAuthorization<
|
|
39
41
|
TAuthorization extends AuthAuthorizationConfig | undefined,
|
|
40
42
|
> = Omit<
|
|
41
43
|
ReturnType<typeof AuthFactory>["auth"]["member"],
|
|
42
|
-
"create" | "list" | "update" | "
|
|
44
|
+
"create" | "list" | "update" | "inspect" | "require"
|
|
43
45
|
> & {
|
|
44
46
|
create: (
|
|
45
47
|
ctx: Parameters<
|
|
@@ -52,7 +54,7 @@ type MemberApiWithAuthorization<
|
|
|
52
54
|
status?: string;
|
|
53
55
|
extend?: Record<string, unknown>;
|
|
54
56
|
},
|
|
55
|
-
) => Promise<{
|
|
57
|
+
) => Promise<{ memberId: string }>;
|
|
56
58
|
list: (
|
|
57
59
|
ctx: Parameters<
|
|
58
60
|
ReturnType<typeof AuthFactory>["auth"]["member"]["list"]
|
|
@@ -76,10 +78,21 @@ type MemberApiWithAuthorization<
|
|
|
76
78
|
>[0],
|
|
77
79
|
memberId: string,
|
|
78
80
|
data: Record<string, unknown> & { roleIds?: AuthRoleId<TAuthorization>[] },
|
|
79
|
-
) => Promise<{
|
|
80
|
-
|
|
81
|
+
) => Promise<{ memberId: string }>;
|
|
82
|
+
inspect: (
|
|
81
83
|
ctx: Parameters<
|
|
82
|
-
ReturnType<typeof AuthFactory>["auth"]["member"]["
|
|
84
|
+
ReturnType<typeof AuthFactory>["auth"]["member"]["inspect"]
|
|
85
|
+
>[0],
|
|
86
|
+
opts: {
|
|
87
|
+
userId: string;
|
|
88
|
+
groupId: string;
|
|
89
|
+
ancestry?: boolean;
|
|
90
|
+
maxDepth?: number;
|
|
91
|
+
},
|
|
92
|
+
) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["inspect"]>;
|
|
93
|
+
require: (
|
|
94
|
+
ctx: Parameters<
|
|
95
|
+
ReturnType<typeof AuthFactory>["auth"]["member"]["require"]
|
|
83
96
|
>[0],
|
|
84
97
|
opts: {
|
|
85
98
|
userId: string;
|
|
@@ -89,10 +102,9 @@ type MemberApiWithAuthorization<
|
|
|
89
102
|
grants?: AuthGrant<TAuthorization>[];
|
|
90
103
|
maxDepth?: number;
|
|
91
104
|
},
|
|
92
|
-
) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["
|
|
105
|
+
) => ReturnType<ReturnType<typeof AuthFactory>["auth"]["member"]["require"]>;
|
|
93
106
|
};
|
|
94
107
|
|
|
95
|
-
|
|
96
108
|
/**
|
|
97
109
|
* The base auth API surface returned by {@link createAuth}.
|
|
98
110
|
*
|
|
@@ -124,30 +136,29 @@ export type AuthApiBase<
|
|
|
124
136
|
key: ReturnType<typeof AuthFactory>["auth"]["key"];
|
|
125
137
|
http: ReturnType<typeof AuthFactory>["auth"]["http"];
|
|
126
138
|
/**
|
|
127
|
-
* Resolve the current
|
|
139
|
+
* Resolve the current request's auth context. Framework-agnostic — use
|
|
128
140
|
* this in fluent-convex middleware, custom wrappers, or anywhere you
|
|
129
|
-
* need the
|
|
141
|
+
* need the current `{ userId, user, groupId, role, grants }` object.
|
|
130
142
|
*
|
|
131
|
-
*
|
|
143
|
+
* Throws a structured `ConvexError` when unauthenticated.
|
|
132
144
|
*
|
|
133
145
|
* @param ctx - Convex query, mutation, or action context.
|
|
134
|
-
* @returns The
|
|
146
|
+
* @returns The current auth context.
|
|
135
147
|
*
|
|
136
148
|
* @example fluent-convex middleware
|
|
137
149
|
* ```ts
|
|
138
150
|
* const withAuth = convex.createMiddleware(async (ctx, next) => {
|
|
139
|
-
* return next({ ...ctx, auth: await auth.
|
|
151
|
+
* return next({ ...ctx, auth: await auth.context(ctx) });
|
|
140
152
|
* });
|
|
141
153
|
* ```
|
|
142
154
|
*
|
|
143
155
|
* @example Direct usage in a handler
|
|
144
156
|
* ```ts
|
|
145
|
-
* const
|
|
146
|
-
*
|
|
147
|
-
* const { userId, grants } = resolved;
|
|
157
|
+
* const authContext = await auth.context(ctx);
|
|
158
|
+
* const { userId, grants } = authContext;
|
|
148
159
|
* ```
|
|
149
160
|
*/
|
|
150
|
-
|
|
161
|
+
context: (ctx: any) => Promise<AuthContext>;
|
|
151
162
|
/**
|
|
152
163
|
* Context enrichment for convex-helpers `customQuery` / `customMutation` /
|
|
153
164
|
* `customAction`.
|
|
@@ -156,9 +167,9 @@ export type AuthApiBase<
|
|
|
156
167
|
* and grants, then attaches them to `ctx.auth`. Returns a `Customization`
|
|
157
168
|
* object compatible with convex-helpers' custom function builders.
|
|
158
169
|
*
|
|
159
|
-
* `ctx.auth` is
|
|
160
|
-
*
|
|
161
|
-
*
|
|
170
|
+
* `ctx.auth` is the current request auth context.
|
|
171
|
+
* By default this throws when unauthenticated so handlers can assume
|
|
172
|
+
* `ctx.auth.userId` and `ctx.auth.user` exist.
|
|
162
173
|
*
|
|
163
174
|
* @returns A convex-helpers `Customization` object.
|
|
164
175
|
*
|
|
@@ -180,7 +191,6 @@ export type AuthApiBase<
|
|
|
180
191
|
* export const list = authQuery({
|
|
181
192
|
* args: { workspaceId: v.string() },
|
|
182
193
|
* handler: async (ctx, args) => {
|
|
183
|
-
* if (!ctx.auth) return [];
|
|
184
194
|
* const { userId, groupId, grants } = ctx.auth;
|
|
185
195
|
* // business logic
|
|
186
196
|
* },
|
|
@@ -190,24 +200,40 @@ export type AuthApiBase<
|
|
|
190
200
|
ctx: () => {
|
|
191
201
|
args: Record<string, never>;
|
|
192
202
|
input: (ctx: any) => Promise<{
|
|
193
|
-
ctx: { auth:
|
|
203
|
+
ctx: { auth: AuthContext };
|
|
194
204
|
args: Record<string, never>;
|
|
195
205
|
}>;
|
|
196
206
|
};
|
|
197
207
|
};
|
|
198
208
|
|
|
199
209
|
/**
|
|
200
|
-
*
|
|
210
|
+
* Current request auth context injected into `ctx.auth` by `auth.ctx()` and
|
|
211
|
+
* {@link AuthCtx}. This is the authenticated auth shape returned by
|
|
212
|
+
* {@link createAuth().context}. Optional context builders may still surface
|
|
213
|
+
* nullable fields when `optional: true` is used.
|
|
201
214
|
*
|
|
202
|
-
* - `null` when unauthenticated.
|
|
203
215
|
* - `groupId` is `null` when the user has no active group set.
|
|
204
|
-
* - `role`
|
|
216
|
+
* - `role` is `null` when no active group or no membership is resolved.
|
|
217
|
+
* - `grants` is `[]` when no active group or no membership is resolved.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* import type { AuthContext } from "@robelest/convex-auth/server";
|
|
222
|
+
*
|
|
223
|
+
* const mockAuth: AuthContext = {
|
|
224
|
+
* userId: "user123" as Id<"User">,
|
|
225
|
+
* user: { _id: "user123", email: "test@example.com" },
|
|
226
|
+
* groupId: "group456",
|
|
227
|
+
* role: "admin",
|
|
228
|
+
* grants: ["read", "write"],
|
|
229
|
+
* };
|
|
230
|
+
* ```
|
|
205
231
|
*/
|
|
206
|
-
export type
|
|
232
|
+
export type AuthContext = {
|
|
207
233
|
/** The authenticated user's document ID. */
|
|
208
|
-
userId:
|
|
234
|
+
userId: GenericId<"User">;
|
|
209
235
|
/** The authenticated user's full document. */
|
|
210
|
-
user:
|
|
236
|
+
user: UserDoc;
|
|
211
237
|
/** The user's active group ID, or `null` if none set. */
|
|
212
238
|
groupId: string | null;
|
|
213
239
|
/** The user's primary role in the active group, or `null`. */
|
|
@@ -216,6 +242,20 @@ export type AuthResolvedContext = {
|
|
|
216
242
|
grants: string[];
|
|
217
243
|
};
|
|
218
244
|
|
|
245
|
+
type AuthCtxBase = {
|
|
246
|
+
getUserIdentity: () => Promise<UserIdentity | null>;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
type RequiredAuthCtxState = AuthCtxBase & AuthContext;
|
|
250
|
+
|
|
251
|
+
type OptionalAuthCtxState = AuthCtxBase & {
|
|
252
|
+
userId: GenericId<"User"> | null;
|
|
253
|
+
user: UserDoc | null;
|
|
254
|
+
groupId: string | null;
|
|
255
|
+
role: string | null;
|
|
256
|
+
grants: string[];
|
|
257
|
+
};
|
|
258
|
+
|
|
219
259
|
type InternalSsoApi = ReturnType<typeof AuthFactory>["auth"]["sso"];
|
|
220
260
|
|
|
221
261
|
type PublicSsoAdminApi = {
|
|
@@ -231,7 +271,6 @@ type PublicSsoAdminApi = {
|
|
|
231
271
|
isPrimary?: boolean;
|
|
232
272
|
}>,
|
|
233
273
|
) => Promise<{
|
|
234
|
-
ok: true;
|
|
235
274
|
enterpriseId: string;
|
|
236
275
|
domains: Array<{
|
|
237
276
|
domainId: string;
|
|
@@ -246,7 +285,6 @@ type PublicSsoAdminApi = {
|
|
|
246
285
|
ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
|
|
247
286
|
args: { enterpriseId: string; domain: string },
|
|
248
287
|
) => Promise<{
|
|
249
|
-
ok: true;
|
|
250
288
|
enterpriseId: string;
|
|
251
289
|
domain: string;
|
|
252
290
|
requestedAt: number;
|
|
@@ -261,7 +299,6 @@ type PublicSsoAdminApi = {
|
|
|
261
299
|
ctx: Parameters<InternalSsoApi["connection"]["create"]>[0],
|
|
262
300
|
args: { enterpriseId: string; domain: string },
|
|
263
301
|
) => Promise<{
|
|
264
|
-
ok: boolean;
|
|
265
302
|
enterpriseId: string;
|
|
266
303
|
domain: string;
|
|
267
304
|
verifiedAt?: number;
|
|
@@ -370,7 +407,7 @@ export type InferClientApi<T> =
|
|
|
370
407
|
: AuthApiRefs;
|
|
371
408
|
|
|
372
409
|
/** @internal */
|
|
373
|
-
export type AuthLike = Pick<AuthApiBase, "user">;
|
|
410
|
+
export type AuthLike = Pick<AuthApiBase, "user" | "member">;
|
|
374
411
|
|
|
375
412
|
// ============================================================================
|
|
376
413
|
// Auth setup APIs
|
|
@@ -415,9 +452,12 @@ export type AuthLike = Pick<AuthApiBase, "user">;
|
|
|
415
452
|
* 1. `user.id(ctx)` → userId or null (exit early)
|
|
416
453
|
* 2. `user.get(ctx, userId)` → user doc (cached per-execution)
|
|
417
454
|
* 3. `user.getActiveGroup(ctx, { userId })` → groupId or null
|
|
418
|
-
* 4. If groupId → `member.
|
|
455
|
+
* 4. If groupId → `member.inspect(ctx, { userId, groupId })` → role + grants
|
|
419
456
|
*/
|
|
420
|
-
async function
|
|
457
|
+
async function getAuthContext(
|
|
458
|
+
auth: AuthLike,
|
|
459
|
+
ctx: any,
|
|
460
|
+
): Promise<AuthContext | null> {
|
|
421
461
|
const userId = await auth.user.id(ctx);
|
|
422
462
|
if (!userId) return null;
|
|
423
463
|
const user = await auth.user.get(ctx, userId);
|
|
@@ -425,7 +465,7 @@ async function resolveAuthContext(auth: any, ctx: any) {
|
|
|
425
465
|
let role: string | null = null;
|
|
426
466
|
let grants: string[] = [];
|
|
427
467
|
if (groupId) {
|
|
428
|
-
const resolved = await auth.member.
|
|
468
|
+
const resolved = await auth.member.inspect(ctx, { userId, groupId });
|
|
429
469
|
if (resolved.membership) {
|
|
430
470
|
role = resolved.roleIds[0] ?? null;
|
|
431
471
|
grants = resolved.grants;
|
|
@@ -473,10 +513,10 @@ export function createAuth<
|
|
|
473
513
|
) => {
|
|
474
514
|
const enterprise = await connectionApi.get(ctx, enterpriseId);
|
|
475
515
|
if (enterprise === null) {
|
|
476
|
-
throw
|
|
477
|
-
"INVALID_PARAMETERS",
|
|
478
|
-
"Enterprise not found.",
|
|
479
|
-
)
|
|
516
|
+
throw Cv.error({
|
|
517
|
+
code: "INVALID_PARAMETERS",
|
|
518
|
+
message: "Enterprise not found.",
|
|
519
|
+
});
|
|
480
520
|
}
|
|
481
521
|
|
|
482
522
|
const normalized = domains.map((entry: (typeof domains)[number]) => ({
|
|
@@ -486,16 +526,16 @@ export function createAuth<
|
|
|
486
526
|
const deduped = new Map<string, (typeof normalized)[number]>();
|
|
487
527
|
for (const entry of normalized) {
|
|
488
528
|
if (entry.domain.length === 0) {
|
|
489
|
-
throw
|
|
490
|
-
"INVALID_PARAMETERS",
|
|
491
|
-
"Domain must not be empty.",
|
|
492
|
-
)
|
|
529
|
+
throw Cv.error({
|
|
530
|
+
code: "INVALID_PARAMETERS",
|
|
531
|
+
message: "Domain must not be empty.",
|
|
532
|
+
});
|
|
493
533
|
}
|
|
494
534
|
if (deduped.has(entry.domain)) {
|
|
495
|
-
throw
|
|
496
|
-
"INVALID_PARAMETERS",
|
|
497
|
-
`Duplicate domain: ${entry.domain}`,
|
|
498
|
-
)
|
|
535
|
+
throw Cv.error({
|
|
536
|
+
code: "INVALID_PARAMETERS",
|
|
537
|
+
message: `Duplicate domain: ${entry.domain}`,
|
|
538
|
+
});
|
|
499
539
|
}
|
|
500
540
|
deduped.set(entry.domain, entry);
|
|
501
541
|
}
|
|
@@ -505,10 +545,10 @@ export function createAuth<
|
|
|
505
545
|
(entry) => entry.isPrimary,
|
|
506
546
|
).length;
|
|
507
547
|
if (primaryCount > 1) {
|
|
508
|
-
throw
|
|
509
|
-
"INVALID_PARAMETERS",
|
|
510
|
-
"Only one primary domain may be set.",
|
|
511
|
-
)
|
|
548
|
+
throw Cv.error({
|
|
549
|
+
code: "INVALID_PARAMETERS",
|
|
550
|
+
message: "Only one primary domain may be set.",
|
|
551
|
+
});
|
|
512
552
|
}
|
|
513
553
|
if (nextDomains.length > 0 && primaryCount === 0) {
|
|
514
554
|
nextDomains[0] = { ...nextDomains[0], isPrimary: true };
|
|
@@ -555,7 +595,6 @@ export function createAuth<
|
|
|
555
595
|
|
|
556
596
|
const updatedDomains = await domainApi.list(ctx, enterpriseId);
|
|
557
597
|
return {
|
|
558
|
-
ok: true as const,
|
|
559
598
|
enterpriseId,
|
|
560
599
|
domains: updatedDomains.map(
|
|
561
600
|
(domain: (typeof updatedDomains)[number]) => ({
|
|
@@ -629,12 +668,27 @@ export function createAuth<
|
|
|
629
668
|
},
|
|
630
669
|
http: authResult.auth.http,
|
|
631
670
|
|
|
632
|
-
|
|
671
|
+
context: async (ctx: any) => {
|
|
672
|
+
const authContext = await getAuthContext(authResult.auth, ctx);
|
|
673
|
+
if (authContext === null) {
|
|
674
|
+
throw Cv.error({
|
|
675
|
+
code: "NOT_SIGNED_IN",
|
|
676
|
+
message: "Authentication required.",
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
return authContext;
|
|
680
|
+
},
|
|
633
681
|
|
|
634
682
|
ctx: () => ({
|
|
635
683
|
args: {},
|
|
636
684
|
input: async (ctx: any) => {
|
|
637
|
-
const authCtx = await
|
|
685
|
+
const authCtx = await getAuthContext(authResult.auth, ctx);
|
|
686
|
+
if (authCtx === null) {
|
|
687
|
+
throw Cv.error({
|
|
688
|
+
code: "NOT_SIGNED_IN",
|
|
689
|
+
message: "Authentication required.",
|
|
690
|
+
});
|
|
691
|
+
}
|
|
638
692
|
return { ctx: { auth: authCtx }, args: {} };
|
|
639
693
|
},
|
|
640
694
|
}),
|
|
@@ -645,9 +699,6 @@ export function createAuth<
|
|
|
645
699
|
// AuthCtx — ctx enrichment for customQuery / customMutation
|
|
646
700
|
// ============================================================================
|
|
647
701
|
|
|
648
|
-
/** Canonical user document type exposed by Convex Auth. */
|
|
649
|
-
export type UserDoc = Doc<"User">;
|
|
650
|
-
|
|
651
702
|
/**
|
|
652
703
|
* Configuration for {@link AuthCtx} context enrichment.
|
|
653
704
|
*
|
|
@@ -660,17 +711,50 @@ export type AuthCtxConfig<
|
|
|
660
711
|
/** Allow unauthenticated callers and return `userId: null` / `user: null`. */
|
|
661
712
|
optional?: boolean;
|
|
662
713
|
/**
|
|
663
|
-
* Attach additional derived fields to the auth context after the
|
|
714
|
+
* Attach additional derived fields to the auth context after the base auth
|
|
715
|
+
* context is resolved.
|
|
664
716
|
*/
|
|
665
|
-
resolve?: (
|
|
717
|
+
resolve?: (
|
|
718
|
+
ctx: any,
|
|
719
|
+
user: UserDoc,
|
|
720
|
+
auth: AuthContext,
|
|
721
|
+
) => Promise<TResolve> | TResolve;
|
|
722
|
+
/**
|
|
723
|
+
* Override or wrap the base auth resolution used by {@link AuthCtx}.
|
|
724
|
+
*
|
|
725
|
+
* Return `undefined` to fall back to the built-in resolver,
|
|
726
|
+
* `null` for an explicit unauthenticated state, or an
|
|
727
|
+
* {@link AuthContext} object to provide a pre-resolved auth state.
|
|
728
|
+
* This is useful for tests, proxy auth, impersonation flows, or any
|
|
729
|
+
* environment that needs to inject auth without depending on the standard
|
|
730
|
+
* Convex auth tables.
|
|
731
|
+
*
|
|
732
|
+
* @param ctx - The Convex function context.
|
|
733
|
+
* @param fallback - The built-in auth resolver used by {@link AuthCtx}.
|
|
734
|
+
* @returns Resolved auth state, `null`, or `undefined` to use the fallback.
|
|
735
|
+
*
|
|
736
|
+
* @example
|
|
737
|
+
* ```ts
|
|
738
|
+
* const authCtx = AuthCtx(auth, {
|
|
739
|
+
* authResolve: async (ctx, fallback) => {
|
|
740
|
+
* const injected = getInjectedAuth(ctx);
|
|
741
|
+
* return injected ?? (await fallback());
|
|
742
|
+
* },
|
|
743
|
+
* });
|
|
744
|
+
* ```
|
|
745
|
+
*/
|
|
746
|
+
authResolve?: (
|
|
747
|
+
ctx: any,
|
|
748
|
+
fallback: () => Promise<AuthContext | null>,
|
|
749
|
+
) => Promise<AuthContext | null | undefined> | AuthContext | null | undefined;
|
|
666
750
|
};
|
|
667
751
|
|
|
668
752
|
/**
|
|
669
753
|
* Create a context enrichment for `customQuery` / `customMutation` — optional auth.
|
|
670
754
|
*
|
|
671
755
|
* When `optional: true` is set, unauthenticated requests are allowed.
|
|
672
|
-
* The enriched `ctx.auth` will have `userId: null
|
|
673
|
-
* for unauthenticated callers.
|
|
756
|
+
* The enriched `ctx.auth` will have `userId: null`, `user: null`,
|
|
757
|
+
* `groupId: null`, `role: null`, and `grants: []` for unauthenticated callers.
|
|
674
758
|
*
|
|
675
759
|
* @param auth - The auth API object returned by {@link createAuth}.
|
|
676
760
|
* @param config - Configuration with `optional: true` and an optional
|
|
@@ -701,11 +785,7 @@ export function AuthCtx<
|
|
|
701
785
|
_extra?: any,
|
|
702
786
|
) => Promise<{
|
|
703
787
|
ctx: {
|
|
704
|
-
auth:
|
|
705
|
-
getUserIdentity: () => Promise<UserIdentity | null>;
|
|
706
|
-
userId: GenericId<"User"> | null;
|
|
707
|
-
user: UserDoc | null;
|
|
708
|
-
} & TResolve;
|
|
788
|
+
auth: OptionalAuthCtxState & TResolve;
|
|
709
789
|
};
|
|
710
790
|
args: {};
|
|
711
791
|
}>;
|
|
@@ -713,10 +793,8 @@ export function AuthCtx<
|
|
|
713
793
|
/**
|
|
714
794
|
* Create a context enrichment for `customQuery` / `customMutation` — required auth (default).
|
|
715
795
|
*
|
|
716
|
-
* When `optional` is omitted or `false`,
|
|
717
|
-
*
|
|
718
|
-
* no user is signed in the returned `ctx.auth.userId` and `ctx.auth.user` are
|
|
719
|
-
* `null`.
|
|
796
|
+
* When `optional` is omitted or `false`, unauthenticated requests throw a
|
|
797
|
+
* structured `ConvexError` before your handler runs.
|
|
720
798
|
*
|
|
721
799
|
* @param auth - The auth API object returned by {@link createAuth}.
|
|
722
800
|
* @param config - Optional configuration with a `resolve` callback
|
|
@@ -746,11 +824,7 @@ export function AuthCtx<
|
|
|
746
824
|
_extra?: any,
|
|
747
825
|
) => Promise<{
|
|
748
826
|
ctx: {
|
|
749
|
-
auth:
|
|
750
|
-
getUserIdentity: () => Promise<UserIdentity | null>;
|
|
751
|
-
userId: GenericId<"User">;
|
|
752
|
-
user: UserDoc;
|
|
753
|
-
} & TResolve;
|
|
827
|
+
auth: RequiredAuthCtxState & TResolve;
|
|
754
828
|
};
|
|
755
829
|
args: {};
|
|
756
830
|
}>;
|
|
@@ -761,39 +835,31 @@ export function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {
|
|
|
761
835
|
args: {},
|
|
762
836
|
input: async (ctx: any, _args: any, _extra?: any) => {
|
|
763
837
|
const nativeAuth = ctx.auth;
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
const userId = await auth.user.id(ctx);
|
|
781
|
-
if (!userId) {
|
|
782
|
-
return null;
|
|
783
|
-
}
|
|
784
|
-
const user = await auth.user.get(ctx, userId);
|
|
785
|
-
return { userId, user };
|
|
786
|
-
},
|
|
787
|
-
}),
|
|
788
|
-
);
|
|
789
|
-
|
|
790
|
-
if (userContext === null) {
|
|
838
|
+
const getUserIdentity = nativeAuth.getUserIdentity.bind(nativeAuth);
|
|
839
|
+
const fallback = () => getAuthContext(auth, ctx);
|
|
840
|
+
|
|
841
|
+
const authOverride = config?.authResolve
|
|
842
|
+
? await config.authResolve(ctx, fallback)
|
|
843
|
+
: undefined;
|
|
844
|
+
const resolved =
|
|
845
|
+
authOverride === undefined ? await fallback() : authOverride;
|
|
846
|
+
|
|
847
|
+
if (resolved === null) {
|
|
848
|
+
if (config?.optional !== true) {
|
|
849
|
+
throw Cv.error({
|
|
850
|
+
code: "NOT_SIGNED_IN",
|
|
851
|
+
message: "Authentication required.",
|
|
852
|
+
});
|
|
853
|
+
}
|
|
791
854
|
return {
|
|
792
855
|
ctx: {
|
|
793
856
|
auth: {
|
|
794
|
-
getUserIdentity
|
|
857
|
+
getUserIdentity,
|
|
795
858
|
userId: null,
|
|
796
859
|
user: null,
|
|
860
|
+
groupId: null,
|
|
861
|
+
role: null,
|
|
862
|
+
grants: [],
|
|
797
863
|
},
|
|
798
864
|
},
|
|
799
865
|
args: {},
|
|
@@ -801,15 +867,14 @@ export function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {
|
|
|
801
867
|
}
|
|
802
868
|
|
|
803
869
|
const extra = config?.resolve
|
|
804
|
-
? await config.resolve(ctx,
|
|
870
|
+
? await config.resolve(ctx, resolved.user, resolved)
|
|
805
871
|
: {};
|
|
806
872
|
|
|
807
873
|
return {
|
|
808
874
|
ctx: {
|
|
809
875
|
auth: {
|
|
810
|
-
getUserIdentity
|
|
811
|
-
|
|
812
|
-
user: userContext.user,
|
|
876
|
+
getUserIdentity,
|
|
877
|
+
...resolved,
|
|
813
878
|
...extra,
|
|
814
879
|
},
|
|
815
880
|
},
|
|
@@ -824,9 +889,10 @@ export function AuthCtx(auth: AuthLike, config?: AuthCtxConfig<any>) {
|
|
|
824
889
|
*
|
|
825
890
|
* Use this to type function parameters or variables that receive the
|
|
826
891
|
* enriched auth context produced by `AuthCtx`. The inferred type includes
|
|
827
|
-
* `userId`, `user`, `getUserIdentity`, and any
|
|
828
|
-
* by the `resolve` callback. This is the generic
|
|
829
|
-
* enriched auth shape without manually duplicating
|
|
892
|
+
* `userId`, `user`, `groupId`, `role`, `grants`, `getUserIdentity`, and any
|
|
893
|
+
* additional fields added by the `resolve` callback. This is the generic
|
|
894
|
+
* utility for reusing the enriched auth shape without manually duplicating
|
|
895
|
+
* conditional auth types.
|
|
830
896
|
*
|
|
831
897
|
* @typeParam T - An `AuthCtx` return value (must have an `input` method
|
|
832
898
|
* that returns `{ ctx: { auth: ... } }`).
|