@robelest/convex-auth 0.0.4-preview.32 → 0.0.4-preview.34

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.
Files changed (89) hide show
  1. package/dist/component/_generated/component.d.ts +1611 -2039
  2. package/dist/component/account.js +3 -0
  3. package/dist/component/convex.config.d.ts +2 -2
  4. package/dist/component/factor/device.js +3 -0
  5. package/dist/component/factor/passkey.js +3 -0
  6. package/dist/component/factor/totp.js +3 -0
  7. package/dist/component/group/invite.js +3 -0
  8. package/dist/component/group/member.js +3 -0
  9. package/dist/component/group.js +3 -0
  10. package/dist/component/model.d.ts +342 -30
  11. package/dist/component/model.js +22 -4
  12. package/dist/component/modules.js +24 -21
  13. package/dist/component/public/factors/devices.js +37 -106
  14. package/dist/component/public/factors/passkeys.js +29 -149
  15. package/dist/component/public/factors/totp.js +32 -159
  16. package/dist/component/public/groups/core.js +19 -82
  17. package/dist/component/public/groups/invites.js +15 -104
  18. package/dist/component/public/groups/members.js +26 -149
  19. package/dist/component/public/identity/accounts.js +12 -94
  20. package/dist/component/public/identity/codes.js +13 -73
  21. package/dist/component/public/identity/sessions.js +5 -107
  22. package/dist/component/public/identity/tokens.js +13 -103
  23. package/dist/component/public/identity/users.js +188 -185
  24. package/dist/component/public/identity/verifiers.js +17 -80
  25. package/dist/component/public/security/keys.js +13 -120
  26. package/dist/component/public/security/limits.js +0 -43
  27. package/dist/component/public/sso/audit.js +0 -28
  28. package/dist/component/public/sso/core.js +31 -104
  29. package/dist/component/public/sso/domains.js +0 -71
  30. package/dist/component/public/sso/scim.js +63 -239
  31. package/dist/component/public/sso/secrets.js +0 -30
  32. package/dist/component/public/sso/webhooks.js +23 -128
  33. package/dist/component/rateLimit.js +3 -0
  34. package/dist/component/schema.d.ts +378 -342
  35. package/dist/component/schema.js +11 -1
  36. package/dist/component/session.js +3 -0
  37. package/dist/component/sso/audit.js +3 -0
  38. package/dist/component/sso/connection/domain/verification.js +3 -0
  39. package/dist/component/sso/connection/domain.js +3 -0
  40. package/dist/component/sso/connection/scim/config.js +3 -0
  41. package/dist/component/sso/connection/scim/identity.js +3 -0
  42. package/dist/component/sso/connection/secret.js +3 -0
  43. package/dist/component/sso/connection.js +3 -0
  44. package/dist/component/sso/webhook/delivery.js +3 -0
  45. package/dist/component/sso/webhook/endpoint.js +3 -0
  46. package/dist/component/token/pkce.js +3 -0
  47. package/dist/component/token/refresh.js +3 -0
  48. package/dist/component/token/verification.js +3 -0
  49. package/dist/component/user/email.js +3 -0
  50. package/dist/component/user/key.js +3 -0
  51. package/dist/component/user.js +62 -0
  52. package/dist/core/index.d.ts +131 -28
  53. package/dist/core/index.js +2 -0
  54. package/dist/model.js +391 -0
  55. package/dist/providers/credentials.d.ts +1 -1
  56. package/dist/providers/github.js +6 -0
  57. package/dist/providers/password.js +1 -2
  58. package/dist/server/auth.d.ts +73 -7
  59. package/dist/server/auth.js +4 -1
  60. package/dist/server/context.js +30 -3
  61. package/dist/server/contract.js +42 -42
  62. package/dist/server/core.js +224 -86
  63. package/dist/server/db.js +45 -37
  64. package/dist/server/facade.d.ts +39 -0
  65. package/dist/server/facade.js +16 -0
  66. package/dist/server/index.d.ts +5 -3
  67. package/dist/server/index.js +3 -1
  68. package/dist/server/mounts.d.ts +101 -101
  69. package/dist/server/mutations/credentials/signin.js +3 -7
  70. package/dist/server/mutations/oauth.js +9 -6
  71. package/dist/server/runtime.d.ts +147 -46
  72. package/dist/server/runtime.js +10 -8
  73. package/dist/server/services/group.js +9 -9
  74. package/dist/server/sso/domain.d.ts +1 -1
  75. package/dist/server/sso/domain.js +40 -40
  76. package/dist/server/sso/http.js +18 -18
  77. package/dist/server/sso/oidc.js +1 -1
  78. package/dist/server/sso/policies.js +3 -3
  79. package/dist/server/sso/policy.js +12 -4
  80. package/dist/server/sso/provision.js +9 -9
  81. package/dist/server/sso/validators.js +2 -2
  82. package/dist/server/sso/webhook.js +8 -8
  83. package/dist/server/types.d.ts +185 -124
  84. package/dist/server/types.js +29 -24
  85. package/dist/server/users.js +49 -2
  86. package/dist/server/validators.d.ts +745 -0
  87. package/dist/server/validators.js +60 -0
  88. package/package.json +1 -1
  89. package/dist/component/public.js +0 -22
package/dist/server/db.js CHANGED
@@ -4,85 +4,93 @@ function authDb(ctx, config) {
4
4
  const component = config.component;
5
5
  return {
6
6
  users: {
7
- getById: (userId) => ctx.runQuery(component.public.userGetById, { userId }),
8
- findByVerifiedEmail: (email) => ctx.runQuery(component.public.userFindByVerifiedEmail, { email }),
9
- findByVerifiedPhone: (phone) => ctx.runQuery(component.public.userFindByVerifiedPhone, { phone }),
10
- insert: (data) => ctx.runMutation(component.public.userInsert, { data }),
11
- patch: (userId, data) => ctx.runMutation(component.public.userPatch, {
7
+ getById: (userId) => ctx.runQuery(component.user.get, { id: userId }),
8
+ findByVerifiedEmail: (email) => ctx.runQuery(component.user.get, { verifiedEmail: email }),
9
+ findByVerifiedPhone: (phone) => ctx.runQuery(component.user.get, { verifiedPhone: phone }),
10
+ insert: (data) => ctx.runMutation(component.user.create, { data }),
11
+ patch: (userId, data) => ctx.runMutation(component.user.update, {
12
12
  userId,
13
13
  data
14
14
  }),
15
- upsert: (userId, data) => ctx.runMutation(component.public.userUpsert, {
15
+ upsert: (userId, data) => ctx.runMutation(component.user.upsert, {
16
16
  userId,
17
17
  data
18
18
  })
19
19
  },
20
+ emails: {
21
+ upsert: (args) => ctx.runMutation(component.user.email.upsert, args),
22
+ listByUser: (userId) => ctx.runQuery(component.user.email.list, { userId }),
23
+ findVerified: (email, connectionId) => ctx.runQuery(component.user.email.owner, {
24
+ email,
25
+ connectionId
26
+ })
27
+ },
20
28
  accounts: {
21
- get: (provider, providerAccountId) => ctx.runQuery(component.public.accountGet, {
29
+ get: (provider, providerAccountId) => ctx.runQuery(component.account.get, {
22
30
  provider,
23
31
  providerAccountId
24
32
  }),
25
- getById: (accountId) => ctx.runQuery(component.public.accountGetById, { accountId }),
26
- create: (args) => ctx.runMutation(component.public.accountInsert, args),
27
- patch: (accountId, data) => ctx.runMutation(component.public.accountPatch, {
33
+ getById: (accountId) => ctx.runQuery(component.account.get, { id: accountId }),
34
+ create: (args) => ctx.runMutation(component.account.create, args),
35
+ patch: (accountId, data) => ctx.runMutation(component.account.update, {
28
36
  accountId,
29
37
  data
30
38
  }),
31
- delete: (accountId) => ctx.runMutation(component.public.accountDelete, { accountId })
39
+ delete: (accountId) => ctx.runMutation(component.account.delete, { accountId })
32
40
  },
33
41
  sessions: {
34
- create: (userId, expirationTime) => ctx.runMutation(component.public.sessionCreate, {
42
+ create: (userId, expirationTime) => ctx.runMutation(component.session.create, {
35
43
  userId,
36
44
  expirationTime
37
45
  }),
38
- issue: (args) => ctx.runMutation(component.public.sessionIssue, args),
39
- getById: (sessionId) => ctx.runQuery(component.public.sessionGetById, { sessionId }),
40
- delete: (sessionId) => ctx.runMutation(component.public.sessionDelete, { sessionId }),
41
- listByUser: (userId) => ctx.runQuery(component.public.sessionListByUser, { userId })
46
+ issue: (args) => ctx.runMutation(component.session.issue, args),
47
+ getById: (sessionId) => ctx.runQuery(component.session.get, { sessionId }),
48
+ delete: (sessionId) => ctx.runMutation(component.session.delete, { sessionId }),
49
+ listByUser: (userId) => ctx.runQuery(component.session.list, { userId })
42
50
  },
43
51
  verifiers: {
44
- create: (sessionId, signature) => ctx.runMutation(component.public.verifierCreate, {
52
+ create: (sessionId, signature) => ctx.runMutation(component.token.pkce.create, {
45
53
  sessionId,
46
54
  signature
47
55
  }),
48
- getById: (verifierId) => ctx.runQuery(component.public.verifierGetById, { verifierId }),
49
- getBySignature: (signature) => ctx.runQuery(component.public.verifierGetBySignature, { signature }),
50
- patch: (verifierId, data) => ctx.runMutation(component.public.verifierPatch, {
56
+ getById: (verifierId) => ctx.runQuery(component.token.pkce.get, { id: verifierId }),
57
+ getBySignature: (signature) => ctx.runQuery(component.token.pkce.get, { signature }),
58
+ patch: (verifierId, data) => ctx.runMutation(component.token.pkce.update, {
51
59
  verifierId,
52
60
  data
53
61
  }),
54
- delete: (verifierId) => ctx.runMutation(component.public.verifierDelete, { verifierId })
62
+ delete: (verifierId) => ctx.runMutation(component.token.pkce.delete, { verifierId })
55
63
  },
56
64
  verificationCodes: {
57
- getByAccountId: (accountId) => ctx.runQuery(component.public.verificationCodeGetByAccountId, { accountId }),
58
- getByCode: (code) => ctx.runQuery(component.public.verificationCodeGetByCode, { code }),
59
- create: (args) => ctx.runMutation(component.public.verificationCodeCreate, args),
60
- delete: (verificationCodeId) => ctx.runMutation(component.public.verificationCodeDelete, { verificationCodeId })
65
+ getByAccountId: (accountId) => ctx.runQuery(component.token.verification.get, { accountId }),
66
+ getByCode: (code) => ctx.runQuery(component.token.verification.get, { code }),
67
+ create: (args) => ctx.runMutation(component.token.verification.create, args),
68
+ delete: (verificationCodeId) => ctx.runMutation(component.token.verification.delete, { verificationCodeId })
61
69
  },
62
70
  refreshTokens: {
63
- create: (args) => ctx.runMutation(component.public.refreshTokenCreate, args),
64
- exchange: (args) => ctx.runMutation(component.public.refreshTokenExchange, args),
65
- getById: (refreshTokenId) => ctx.runQuery(component.public.refreshTokenGetById, { refreshTokenId }),
66
- patch: (refreshTokenId, data) => ctx.runMutation(component.public.refreshTokenPatch, {
71
+ create: (args) => ctx.runMutation(component.token.refresh.create, args),
72
+ exchange: (args) => ctx.runMutation(component.token.refresh.exchange, args),
73
+ getById: (refreshTokenId) => ctx.runQuery(component.token.refresh.get, { id: refreshTokenId }),
74
+ patch: (refreshTokenId, data) => ctx.runMutation(component.token.refresh.update, {
67
75
  refreshTokenId,
68
76
  data
69
77
  }),
70
- getChildren: (sessionId, parentRefreshTokenId) => ctx.runQuery(component.public.refreshTokenGetChildren, {
78
+ getChildren: (sessionId, parentRefreshTokenId) => ctx.runQuery(component.token.refresh.listChildren, {
71
79
  sessionId,
72
80
  parentRefreshTokenId
73
81
  }),
74
- listBySession: (sessionId) => ctx.runQuery(component.public.refreshTokenListBySession, { sessionId }),
75
- deleteAll: (sessionId) => ctx.runMutation(component.public.refreshTokenDeleteAll, { sessionId }),
76
- getActive: (sessionId) => ctx.runQuery(component.public.refreshTokenGetActive, { sessionId })
82
+ listBySession: (sessionId) => ctx.runQuery(component.token.refresh.list, { sessionId }),
83
+ deleteAll: (sessionId) => ctx.runMutation(component.token.refresh.delete, { sessionId }),
84
+ getActive: (sessionId) => ctx.runQuery(component.token.refresh.get, { activeForSession: sessionId })
77
85
  },
78
86
  rateLimits: {
79
- get: (identifier) => ctx.runQuery(component.public.rateLimitGet, { identifier }),
80
- create: (args) => ctx.runMutation(component.public.rateLimitCreate, args),
81
- patch: (rateLimitId, data) => ctx.runMutation(component.public.rateLimitPatch, {
87
+ get: (identifier) => ctx.runQuery(component.rateLimit.get, { identifier }),
88
+ create: (args) => ctx.runMutation(component.rateLimit.create, args),
89
+ patch: (rateLimitId, data) => ctx.runMutation(component.rateLimit.update, {
82
90
  rateLimitId,
83
91
  data
84
92
  }),
85
- delete: (rateLimitId) => ctx.runMutation(component.public.rateLimitDelete, { rateLimitId })
93
+ delete: (rateLimitId) => ctx.runMutation(component.rateLimit.delete, { rateLimitId })
86
94
  }
87
95
  };
88
96
  }
@@ -52,6 +52,25 @@ type AuthContext = {
52
52
  groupId: string | null; /** The user's primary role in the active group, or `null`. */
53
53
  role: string | null; /** Resolved grant strings from the user's role definitions. */
54
54
  grants: string[];
55
+ /**
56
+ * Assert the current user holds the given grant(s); throws
57
+ * `ConvexError({ code: "MISSING_GRANTS" })` otherwise. Pass a
58
+ * group-owned document as the second argument to also assert the
59
+ * record belongs to the active group (`code: "FORBIDDEN"` if not).
60
+ *
61
+ * For a boolean check, read `grants` directly:
62
+ * `ctx.auth.grants.includes("issues.read")`.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * ctx.auth.require("members.manage");
67
+ * ctx.auth.require(["issues.edit", "issues.move"]);
68
+ * ctx.auth.require("issues.edit", issueDoc); // group-scoped
69
+ * ```
70
+ */
71
+ require: (grant: string | readonly string[], doc?: {
72
+ groupId?: unknown;
73
+ }) => void;
55
74
  };
56
75
  /**
57
76
  * Nullable auth context returned by `auth.context(ctx, { optional: true })`
@@ -78,6 +97,15 @@ type OptionalAuthContext = {
78
97
  groupId: string | null; /** The user's primary role in the active group, or `null`. */
79
98
  role: string | null; /** Resolved grant strings for the active membership, or `[]`. */
80
99
  grants: string[];
100
+ /**
101
+ * Assert the current user holds the given grant(s); throws when
102
+ * missing (or, with a group-owned `doc`, when it is not in the active
103
+ * group). When unauthenticated this always throws. For a boolean
104
+ * check read `grants` directly.
105
+ */
106
+ require: (grant: string | readonly string[], doc?: {
107
+ groupId?: unknown;
108
+ }) => void;
81
109
  };
82
110
  type AuthContextBase = {
83
111
  getUserIdentity: () => Promise<UserIdentity | null>;
@@ -139,6 +167,17 @@ type AuthContextConfig<TResolve extends Record<string, unknown> = Record<string,
139
167
  * of throwing `NOT_SIGNED_IN`.
140
168
  */
141
169
  optional?: boolean;
170
+ /**
171
+ * Enforce grant(s) inline — equivalent to calling `ctx.auth.require(...)`
172
+ * at the top of every handler built with this customization. Throws
173
+ * `ConvexError({ code: "MISSING_GRANTS" })` when missing.
174
+ */
175
+ require?: string | readonly string[];
176
+ /**
177
+ * Require an active group; throws `ConvexError({ code: "NO_ACTIVE_GROUP" })`
178
+ * when the resolved context has no `groupId`. Reuses the `active` concept.
179
+ */
180
+ active?: true;
142
181
  /**
143
182
  * Attach additional derived fields to the auth context after the base auth
144
183
  * context is resolved.
@@ -19,6 +19,20 @@ function assertAuthResolverContext(ctx) {
19
19
  /**
20
20
  * Resolve the public auth context for a Convex handler context.
21
21
  *
22
+ * Enforce the `require` / `active` builder options against a resolved
23
+ * context. Reuses `ctx.auth.require` for grants so behavior is identical
24
+ * to an inline call.
25
+ *
26
+ * @internal
27
+ */
28
+ function enforceAuthRequirements(resolved, config) {
29
+ if (config?.active === true && resolved.groupId === null) throw new ConvexError({
30
+ code: "NO_ACTIVE_GROUP",
31
+ message: "An active group is required."
32
+ });
33
+ if (config?.require !== void 0) resolved.require(config.require);
34
+ }
35
+ /**
22
36
  * This low-level helper underpins `auth.context(...)`.
23
37
  */
24
38
  async function createPublicAuthContext(auth, ctx, config) {
@@ -27,6 +41,7 @@ async function createPublicAuthContext(auth, ctx, config) {
27
41
  if (config?.optional !== true) throw createNotSignedInError();
28
42
  return createUnauthenticatedAuthContext();
29
43
  }
44
+ enforceAuthRequirements(resolved, config);
30
45
  const extra = config?.resolve ? await config.resolve(ctx, resolved.user, resolved) : {};
31
46
  return {
32
47
  ...resolved,
@@ -55,6 +70,7 @@ function createAuthContextCustomization(auth, config) {
55
70
  args: {}
56
71
  };
57
72
  }
73
+ enforceAuthRequirements(resolved, config);
58
74
  const extra = config?.resolve ? await config.resolve(ctx, resolved.user, resolved) : {};
59
75
  return {
60
76
  ctx: { auth: {
@@ -1,9 +1,11 @@
1
- import { AfterCtx, AuthCallbackContext, AuthCallbackProfile, AuthCallbacks, AuthEvent, BeforeCtx, BeforeEvent, BeforeResult } from "./types.js";
1
+ import { vGroupDoc, vGroupInviteDoc, vGroupMemberDoc, vPaginated, vUserDoc, vUserEmailDoc } from "../component/model.js";
2
+ import { AfterCtx, AuthCallbackContext, AuthCallbackProfile, AuthCallbacks, AuthDataModel, AuthEvent, BeforeCtx, BeforeEvent, BeforeResult, Doc, GenericDoc } from "./types.js";
2
3
  import { AuthConfig, AuthContext, AuthContextConfig, InferAuth, OptionalAuthContext, UserDoc } from "./facade.js";
4
+ import "./identity/convex.js";
3
5
  import { WellKnownEndpoint, WellKnownOptions, WellKnownResponse, wellKnown } from "./wellknown.js";
4
6
  import { HttpAuthContext, HttpAuthContextConfig, OptionalHttpAuthContext } from "./http.js";
7
+ import { AuthExtendValidators, AuthValidators, Group, Membership, Viewer, buildAuthValidators } from "./validators.js";
5
8
  import { AuthApi, AuthApiBase, ConvexAuthResult, InferClientApi, createAuth } from "./auth.js";
6
- import "./identity/convex.js";
7
9
  import { CreateAuthGroupSsoOptions, GroupSsoAccessHandler, GroupSsoAccessInput, GroupSsoAccessPermissions, GroupSsoPermission, GroupSsoResolvedAccessHandler, createAuthGroupSso, scim, sso } from "./mounts.js";
8
10
  import { AuthCookie, AuthCookieConfig, AuthCookies, RefreshResult, ServerOptions, authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./prefetch.js";
9
- export { type AfterCtx, type AuthApi, type AuthApiBase, type AuthCallbackContext, type AuthCallbackProfile, type AuthCallbacks, type AuthConfig, type AuthContext, type AuthContextConfig, type AuthCookie, type AuthCookieConfig, type AuthCookies, type AuthEvent, type BeforeCtx, type BeforeEvent, type BeforeResult, type ConvexAuthResult, type CreateAuthGroupSsoOptions, type GroupSsoAccessHandler, type GroupSsoAccessInput, type GroupSsoAccessPermissions, type GroupSsoPermission, type GroupSsoResolvedAccessHandler, type HttpAuthContext, type HttpAuthContextConfig, type InferAuth, type InferClientApi, type OptionalAuthContext, type OptionalHttpAuthContext, type RefreshResult, type ServerOptions, type UserDoc, type WellKnownEndpoint, type WellKnownOptions, type WellKnownResponse, authCookieNames, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies, wellKnown };
11
+ export { type AfterCtx, type AuthApi, type AuthApiBase, type AuthCallbackContext, type AuthCallbackProfile, type AuthCallbacks, type AuthConfig, type AuthContext, type AuthContextConfig, type AuthCookie, type AuthCookieConfig, type AuthCookies, type AuthDataModel, type AuthEvent, type AuthExtendValidators, type AuthValidators, type BeforeCtx, type BeforeEvent, type BeforeResult, type ConvexAuthResult, type CreateAuthGroupSsoOptions, type Doc, type GenericDoc, type Group, type GroupSsoAccessHandler, type GroupSsoAccessInput, type GroupSsoAccessPermissions, type GroupSsoPermission, type GroupSsoResolvedAccessHandler, type HttpAuthContext, type HttpAuthContextConfig, type InferAuth, type InferClientApi, type Membership, type OptionalAuthContext, type OptionalHttpAuthContext, type RefreshResult, type ServerOptions, type UserDoc, type Viewer, type WellKnownEndpoint, type WellKnownOptions, type WellKnownResponse, authCookieNames, buildAuthValidators, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies, vGroupDoc, vGroupInviteDoc, vGroupMemberDoc, vPaginated, vUserDoc, vUserEmailDoc, wellKnown };
@@ -1,7 +1,9 @@
1
1
  import "./identity/convex.js";
2
+ import { vGroupDoc, vGroupInviteDoc, vGroupMemberDoc, vPaginated, vUserDoc, vUserEmailDoc } from "../component/model.js";
2
3
  import { wellKnown } from "./wellknown.js";
4
+ import { buildAuthValidators } from "./validators.js";
3
5
  import { createAuth } from "./auth.js";
4
6
  import { createAuthGroupSso, scim, sso } from "./mounts.js";
5
7
  import { authCookieNames, parseAuthCookies, serializeAuthCookies, server, shouldProxyAuthAction, structuredAuthCookies } from "./prefetch.js";
6
8
 
7
- export { authCookieNames, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies, wellKnown };
9
+ export { authCookieNames, buildAuthValidators, createAuth, createAuthGroupSso, parseAuthCookies, scim, serializeAuthCookies, server, shouldProxyAuthAction, sso, structuredAuthCookies, vGroupDoc, vGroupInviteDoc, vGroupMemberDoc, vPaginated, vUserDoc, vUserEmailDoc, wellKnown };