@robelest/convex-auth 0.0.4-preview.2 → 0.0.4-preview.21
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 +67 -26
- package/dist/authorization/index.d.ts +63 -0
- package/dist/authorization/index.d.ts.map +1 -0
- package/dist/authorization/index.js +63 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/bin.js +6185 -0
- package/dist/client/core/types.d.ts +20 -0
- package/dist/client/core/types.d.ts.map +1 -0
- package/dist/client/index.d.ts +2 -299
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +407 -534
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +42 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +2546 -90
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/client/core/types.d.ts +2 -0
- package/dist/component/client/index.d.ts +2 -0
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/functions.d.ts +11 -9
- package/dist/component/functions.d.ts.map +1 -1
- package/dist/component/functions.js.map +1 -1
- package/dist/component/index.d.ts +7 -11
- package/dist/component/index.js +2 -3
- package/dist/component/model.d.ts +153 -0
- package/dist/component/model.d.ts.map +1 -0
- package/dist/component/model.js +349 -0
- package/dist/component/model.js.map +1 -0
- package/dist/component/providers/anonymous.d.ts +54 -0
- package/dist/component/providers/anonymous.d.ts.map +1 -0
- package/dist/component/providers/credentials.d.ts +5 -5
- package/dist/component/providers/credentials.d.ts.map +1 -1
- package/dist/component/providers/device.d.ts +67 -0
- package/dist/component/providers/device.d.ts.map +1 -0
- package/dist/component/providers/email.d.ts +62 -0
- package/dist/component/providers/email.d.ts.map +1 -0
- package/dist/component/providers/oauth.d.ts.map +1 -1
- package/dist/component/providers/oauth.js.map +1 -1
- package/dist/component/providers/passkey.d.ts +57 -0
- package/dist/component/providers/passkey.d.ts.map +1 -0
- package/dist/component/providers/password.d.ts +88 -0
- package/dist/component/providers/password.d.ts.map +1 -0
- package/dist/component/providers/phone.d.ts +48 -0
- package/dist/component/providers/phone.d.ts.map +1 -0
- package/dist/component/providers/sso.d.ts +50 -0
- package/dist/component/providers/sso.d.ts.map +1 -0
- package/dist/component/providers/totp.d.ts +45 -0
- package/dist/component/providers/totp.d.ts.map +1 -0
- package/dist/component/public/enterprise/audit.d.ts +73 -0
- package/dist/component/public/enterprise/audit.d.ts.map +1 -0
- package/dist/component/public/enterprise/audit.js +108 -0
- package/dist/component/public/enterprise/audit.js.map +1 -0
- package/dist/component/public/enterprise/core.d.ts +176 -0
- package/dist/component/public/enterprise/core.d.ts.map +1 -0
- package/dist/component/public/enterprise/core.js +292 -0
- package/dist/component/public/enterprise/core.js.map +1 -0
- package/dist/component/public/enterprise/domains.d.ts +174 -0
- package/dist/component/public/enterprise/domains.d.ts.map +1 -0
- package/dist/component/public/enterprise/domains.js +271 -0
- package/dist/component/public/enterprise/domains.js.map +1 -0
- package/dist/component/public/enterprise/scim.d.ts +245 -0
- package/dist/component/public/enterprise/scim.d.ts.map +1 -0
- package/dist/component/public/enterprise/scim.js +344 -0
- package/dist/component/public/enterprise/scim.js.map +1 -0
- package/dist/component/public/enterprise/secrets.d.ts +78 -0
- package/dist/component/public/enterprise/secrets.d.ts.map +1 -0
- package/dist/component/public/enterprise/secrets.js +118 -0
- package/dist/component/public/enterprise/secrets.js.map +1 -0
- package/dist/component/public/enterprise/webhooks.d.ts +211 -0
- package/dist/component/public/enterprise/webhooks.d.ts.map +1 -0
- package/dist/component/public/enterprise/webhooks.js +300 -0
- package/dist/component/public/enterprise/webhooks.js.map +1 -0
- package/dist/component/public/factors/devices.d.ts +157 -0
- package/dist/component/public/factors/devices.d.ts.map +1 -0
- package/dist/component/public/factors/devices.js +216 -0
- package/dist/component/public/factors/devices.js.map +1 -0
- package/dist/component/public/factors/passkeys.d.ts +175 -0
- package/dist/component/public/factors/passkeys.d.ts.map +1 -0
- package/dist/component/public/factors/passkeys.js +238 -0
- package/dist/component/public/factors/passkeys.js.map +1 -0
- package/dist/component/public/factors/totp.d.ts +189 -0
- package/dist/component/public/factors/totp.d.ts.map +1 -0
- package/dist/component/public/factors/totp.js +254 -0
- package/dist/component/public/factors/totp.js.map +1 -0
- package/dist/component/public/groups/core.d.ts +137 -0
- package/dist/component/public/groups/core.d.ts.map +1 -0
- package/dist/component/public/groups/core.js +321 -0
- package/dist/component/public/groups/core.js.map +1 -0
- package/dist/component/public/groups/invites.d.ts +217 -0
- package/dist/component/public/groups/invites.d.ts.map +1 -0
- package/dist/component/public/groups/invites.js +457 -0
- package/dist/component/public/groups/invites.js.map +1 -0
- package/dist/component/public/groups/members.d.ts +204 -0
- package/dist/component/public/groups/members.d.ts.map +1 -0
- package/dist/component/public/groups/members.js +355 -0
- package/dist/component/public/groups/members.js.map +1 -0
- package/dist/component/public/identity/accounts.d.ts +147 -0
- package/dist/component/public/identity/accounts.d.ts.map +1 -0
- package/dist/component/public/identity/accounts.js +200 -0
- package/dist/component/public/identity/accounts.js.map +1 -0
- package/dist/component/public/identity/codes.d.ts +104 -0
- package/dist/component/public/identity/codes.d.ts.map +1 -0
- package/dist/component/public/identity/codes.js +140 -0
- package/dist/component/public/identity/codes.js.map +1 -0
- package/dist/component/public/identity/sessions.d.ts +128 -0
- package/dist/component/public/identity/sessions.d.ts.map +1 -0
- package/dist/component/public/identity/sessions.js +192 -0
- package/dist/component/public/identity/sessions.js.map +1 -0
- package/dist/component/public/identity/tokens.d.ts +169 -0
- package/dist/component/public/identity/tokens.d.ts.map +1 -0
- package/dist/component/public/identity/tokens.js +227 -0
- package/dist/component/public/identity/tokens.js.map +1 -0
- package/dist/component/public/identity/users.d.ts +212 -0
- package/dist/component/public/identity/users.d.ts.map +1 -0
- package/dist/component/public/identity/users.js +311 -0
- package/dist/component/public/identity/users.js.map +1 -0
- package/dist/component/public/identity/verifiers.d.ts +116 -0
- package/dist/component/public/identity/verifiers.d.ts.map +1 -0
- package/dist/component/public/identity/verifiers.js +154 -0
- package/dist/component/public/identity/verifiers.js.map +1 -0
- package/dist/component/public/security/keys.d.ts +209 -0
- package/dist/component/public/security/keys.d.ts.map +1 -0
- package/dist/component/public/security/keys.js +319 -0
- package/dist/component/public/security/keys.js.map +1 -0
- package/dist/component/public/security/limits.d.ts +114 -0
- package/dist/component/public/security/limits.d.ts.map +1 -0
- package/dist/component/public/security/limits.js +169 -0
- package/dist/component/public/security/limits.js.map +1 -0
- package/dist/component/public.d.ts +24 -271
- package/dist/component/public.d.ts.map +1 -1
- package/dist/component/public.js +21 -1229
- package/dist/component/schema.d.ts +473 -110
- package/dist/component/schema.js +162 -73
- package/dist/component/schema.js.map +1 -1
- package/dist/component/server/auth.d.ts +318 -373
- package/dist/component/server/auth.d.ts.map +1 -1
- package/dist/component/server/auth.js +204 -123
- package/dist/component/server/auth.js.map +1 -1
- package/dist/component/server/authError.js +34 -0
- package/dist/component/server/authError.js.map +1 -0
- package/dist/component/server/{providers.js → config.js} +43 -12
- package/dist/component/server/config.js.map +1 -0
- package/dist/component/server/cookies.js +3 -0
- package/dist/component/server/cookies.js.map +1 -1
- package/dist/component/server/core.js +713 -0
- package/dist/component/server/core.js.map +1 -0
- package/dist/component/server/crypto.js +38 -0
- package/dist/component/server/crypto.js.map +1 -0
- package/dist/component/server/{implementation/db.js → db.js} +2 -1
- package/dist/component/server/db.js.map +1 -0
- package/dist/component/server/device.js +109 -0
- package/dist/component/server/device.js.map +1 -0
- package/dist/component/server/enterprise/config.js +46 -0
- package/dist/component/server/enterprise/config.js.map +1 -0
- package/dist/component/server/enterprise/domain.js +885 -0
- package/dist/component/server/enterprise/domain.js.map +1 -0
- package/dist/component/server/enterprise/http.js +766 -0
- package/dist/component/server/enterprise/http.js.map +1 -0
- package/dist/component/server/enterprise/oidc.js +248 -0
- package/dist/component/server/enterprise/oidc.js.map +1 -0
- package/dist/component/server/enterprise/policy.js +85 -0
- package/dist/component/server/enterprise/policy.js.map +1 -0
- package/dist/component/server/enterprise/saml.js +338 -0
- package/dist/component/server/enterprise/saml.js.map +1 -0
- package/dist/component/server/enterprise/scim.js +97 -0
- package/dist/component/server/enterprise/scim.js.map +1 -0
- package/dist/component/server/enterprise/shared.js +51 -0
- package/dist/component/server/enterprise/shared.js.map +1 -0
- package/dist/component/server/errors.d.ts +1 -0
- package/dist/component/server/errors.js +24 -16
- package/dist/component/server/errors.js.map +1 -1
- package/dist/component/server/http.js +288 -0
- package/dist/component/server/http.js.map +1 -0
- package/dist/component/server/identity.js +13 -0
- package/dist/component/server/identity.js.map +1 -0
- package/dist/{server/implementation → component/server}/keys.js +9 -31
- package/dist/component/server/keys.js.map +1 -0
- package/dist/component/server/limits.js +61 -0
- package/dist/component/server/limits.js.map +1 -0
- package/dist/component/server/mutations/account.js +44 -0
- package/dist/component/server/mutations/account.js.map +1 -0
- package/dist/component/server/{implementation/mutations → mutations}/code.js +7 -4
- package/dist/component/server/mutations/code.js.map +1 -0
- package/dist/component/server/mutations/invalidate.js +32 -0
- package/dist/component/server/mutations/invalidate.js.map +1 -0
- package/dist/component/server/mutations/oauth.js +110 -0
- package/dist/component/server/mutations/oauth.js.map +1 -0
- package/dist/component/server/mutations/refresh.js +119 -0
- package/dist/component/server/mutations/refresh.js.map +1 -0
- package/dist/component/server/mutations/register.js +83 -0
- package/dist/component/server/mutations/register.js.map +1 -0
- package/dist/component/server/mutations/retrieve.js +65 -0
- package/dist/component/server/mutations/retrieve.js.map +1 -0
- package/dist/component/server/mutations/signature.js +32 -0
- package/dist/component/server/mutations/signature.js.map +1 -0
- package/dist/component/server/{implementation/mutations → mutations}/signin.js +2 -2
- package/dist/component/server/mutations/signin.js.map +1 -0
- package/dist/component/server/mutations/signout.js +27 -0
- package/dist/component/server/mutations/signout.js.map +1 -0
- package/dist/component/server/mutations/store/refs.js +15 -0
- package/dist/component/server/mutations/store/refs.js.map +1 -0
- package/dist/component/server/mutations/store.js +85 -0
- package/dist/component/server/mutations/store.js.map +1 -0
- package/dist/component/server/mutations/verifier.js +18 -0
- package/dist/component/server/mutations/verifier.js.map +1 -0
- package/dist/component/server/mutations/verify.js +98 -0
- package/dist/component/server/mutations/verify.js.map +1 -0
- package/dist/component/server/oauth.js +106 -60
- package/dist/component/server/oauth.js.map +1 -1
- package/dist/component/server/passkey.js +328 -0
- package/dist/component/server/passkey.js.map +1 -0
- package/dist/{server/implementation → component/server}/redirects.js +13 -11
- package/dist/component/server/redirects.js.map +1 -0
- package/dist/component/server/refresh.js +96 -0
- package/dist/component/server/refresh.js.map +1 -0
- package/dist/component/server/runtime.d.ts +136 -0
- package/dist/component/server/runtime.d.ts.map +1 -0
- package/dist/component/server/runtime.js +413 -0
- package/dist/component/server/runtime.js.map +1 -0
- package/dist/{server/implementation → component/server}/sessions.js +14 -8
- package/dist/component/server/sessions.js.map +1 -0
- package/dist/component/server/signin.js +201 -0
- package/dist/component/server/signin.js.map +1 -0
- package/dist/component/server/tokens.js +17 -0
- package/dist/component/server/tokens.js.map +1 -0
- package/dist/component/server/totp.js +148 -0
- package/dist/component/server/totp.js.map +1 -0
- package/dist/component/server/types.d.ts +387 -298
- package/dist/component/server/types.d.ts.map +1 -1
- package/dist/component/server/{implementation/types.js → types.js} +1 -1
- package/dist/component/server/types.js.map +1 -0
- package/dist/component/server/{implementation/users.js → users.js} +54 -35
- package/dist/component/server/users.js.map +1 -0
- package/dist/component/server/utils.js +110 -4
- package/dist/component/server/utils.js.map +1 -1
- package/dist/core/types.d.ts +369 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/factors/device.js +105 -0
- package/dist/factors/device.js.map +1 -0
- package/dist/factors/passkey.js +181 -0
- package/dist/factors/passkey.js.map +1 -0
- package/dist/factors/totp.js +122 -0
- package/dist/factors/totp.js.map +1 -0
- package/dist/providers/anonymous.d.ts +3 -9
- package/dist/providers/anonymous.d.ts.map +1 -1
- package/dist/providers/anonymous.js +1 -18
- package/dist/providers/anonymous.js.map +1 -1
- package/dist/providers/credentials.d.ts +8 -10
- package/dist/providers/credentials.d.ts.map +1 -1
- package/dist/providers/credentials.js +3 -5
- package/dist/providers/credentials.js.map +1 -1
- package/dist/providers/device.d.ts +18 -10
- package/dist/providers/device.d.ts.map +1 -1
- package/dist/providers/device.js +4 -8
- package/dist/providers/device.js.map +1 -1
- package/dist/providers/email.d.ts +50 -23
- package/dist/providers/email.d.ts.map +1 -1
- package/dist/providers/email.js +58 -34
- package/dist/providers/email.js.map +1 -1
- package/dist/providers/index.d.ts +7 -3
- package/dist/providers/index.js +4 -1
- package/dist/providers/oauth.d.ts.map +1 -1
- package/dist/providers/oauth.js.map +1 -1
- package/dist/providers/passkey.d.ts +12 -9
- package/dist/providers/passkey.d.ts.map +1 -1
- package/dist/providers/passkey.js +1 -7
- package/dist/providers/passkey.js.map +1 -1
- package/dist/providers/password.d.ts +6 -12
- package/dist/providers/password.d.ts.map +1 -1
- package/dist/providers/password.js +189 -89
- package/dist/providers/password.js.map +1 -1
- package/dist/providers/phone.d.ts +40 -11
- package/dist/providers/phone.d.ts.map +1 -1
- package/dist/providers/phone.js +52 -21
- package/dist/providers/phone.js.map +1 -1
- package/dist/providers/sso.d.ts +50 -0
- package/dist/providers/sso.d.ts.map +1 -0
- package/dist/providers/sso.js +34 -0
- package/dist/providers/sso.js.map +1 -0
- package/dist/providers/totp.d.ts +12 -9
- package/dist/providers/totp.d.ts.map +1 -1
- package/dist/providers/totp.js +1 -7
- package/dist/providers/totp.js.map +1 -1
- package/dist/runtime/browser.js +68 -0
- package/dist/runtime/browser.js.map +1 -0
- package/dist/runtime/invite.js +51 -0
- package/dist/runtime/invite.js.map +1 -0
- package/dist/runtime/proxy.js +70 -0
- package/dist/runtime/proxy.js.map +1 -0
- package/dist/runtime/storage.js +37 -0
- package/dist/runtime/storage.js.map +1 -0
- package/dist/server/auth.d.ts +335 -370
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +204 -123
- package/dist/server/auth.js.map +1 -1
- package/dist/server/authError.d.ts +46 -0
- package/dist/server/authError.d.ts.map +1 -0
- package/dist/server/authError.js +34 -0
- package/dist/server/authError.js.map +1 -0
- package/dist/server/config.d.ts +1 -0
- package/dist/server/{providers.js → config.js} +43 -12
- package/dist/server/config.js.map +1 -0
- package/dist/server/cookies.d.ts +1 -38
- package/dist/server/cookies.js +3 -0
- package/dist/server/cookies.js.map +1 -1
- package/dist/server/core.d.ts +1436 -0
- package/dist/server/core.d.ts.map +1 -0
- package/dist/server/core.js +713 -0
- package/dist/server/core.js.map +1 -0
- package/dist/server/crypto.d.ts +8 -0
- package/dist/server/crypto.d.ts.map +1 -0
- package/dist/server/crypto.js +38 -0
- package/dist/server/crypto.js.map +1 -0
- package/dist/server/db.d.ts +1 -0
- package/dist/server/{implementation/db.js → db.js} +2 -1
- package/dist/server/db.js.map +1 -0
- package/dist/server/device.d.ts +1 -0
- package/dist/server/device.js +109 -0
- package/dist/server/device.js.map +1 -0
- package/dist/server/enterprise/config.d.ts +1 -0
- package/dist/server/enterprise/config.js +46 -0
- package/dist/server/enterprise/config.js.map +1 -0
- package/dist/server/enterprise/domain.d.ts +409 -0
- package/dist/server/enterprise/domain.d.ts.map +1 -0
- package/dist/server/enterprise/domain.js +885 -0
- package/dist/server/enterprise/domain.js.map +1 -0
- package/dist/server/enterprise/http.d.ts +26 -0
- package/dist/server/enterprise/http.d.ts.map +1 -0
- package/dist/server/enterprise/http.js +766 -0
- package/dist/server/enterprise/http.js.map +1 -0
- package/dist/server/enterprise/oidc.d.ts +1 -0
- package/dist/server/enterprise/oidc.js +248 -0
- package/dist/server/enterprise/oidc.js.map +1 -0
- package/dist/server/enterprise/policy.d.ts +1 -0
- package/dist/server/enterprise/policy.js +85 -0
- package/dist/server/enterprise/policy.js.map +1 -0
- package/dist/server/enterprise/saml.d.ts +1 -0
- package/dist/server/enterprise/saml.js +338 -0
- package/dist/server/enterprise/saml.js.map +1 -0
- package/dist/server/enterprise/scim.d.ts +1 -0
- package/dist/server/enterprise/scim.js +97 -0
- package/dist/server/enterprise/scim.js.map +1 -0
- package/dist/server/enterprise/shared.d.ts +5 -0
- package/dist/server/enterprise/shared.d.ts.map +1 -0
- package/dist/server/enterprise/shared.js +51 -0
- package/dist/server/enterprise/shared.js.map +1 -0
- package/dist/server/enterprise/validators.d.ts +1 -0
- package/dist/server/enterprise/validators.js +60 -0
- package/dist/server/enterprise/validators.js.map +1 -0
- package/dist/server/errors.d.ts +33 -1
- package/dist/server/errors.d.ts.map +1 -1
- package/dist/server/errors.js +44 -1
- package/dist/server/errors.js.map +1 -1
- package/dist/server/http.d.ts +59 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +288 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/identity.d.ts +1 -0
- package/dist/server/identity.js +13 -0
- package/dist/server/identity.js.map +1 -0
- package/dist/server/index.d.ts +4 -182
- package/dist/server/index.js +4 -376
- package/dist/server/keys.d.ts +1 -0
- package/dist/{component/server/implementation → server}/keys.js +9 -31
- package/dist/server/keys.js.map +1 -0
- package/dist/server/limits.d.ts +1 -0
- package/dist/server/limits.js +61 -0
- package/dist/server/limits.js.map +1 -0
- package/dist/server/mounts.d.ts +647 -0
- package/dist/server/mounts.d.ts.map +1 -0
- package/dist/server/mounts.js +643 -0
- package/dist/server/mounts.js.map +1 -0
- package/dist/server/mutations/account.d.ts +30 -0
- package/dist/server/mutations/account.d.ts.map +1 -0
- package/dist/server/mutations/account.js +44 -0
- package/dist/server/mutations/account.js.map +1 -0
- package/dist/server/mutations/code.d.ts +30 -0
- package/dist/server/mutations/code.d.ts.map +1 -0
- package/dist/server/{implementation/mutations → mutations}/code.js +7 -4
- package/dist/server/mutations/code.js.map +1 -0
- package/dist/server/mutations/index.d.ts +14 -0
- package/dist/server/mutations/index.js +15 -0
- package/dist/server/mutations/invalidate.d.ts +20 -0
- package/dist/server/mutations/invalidate.d.ts.map +1 -0
- package/dist/server/mutations/invalidate.js +32 -0
- package/dist/server/mutations/invalidate.js.map +1 -0
- package/dist/server/mutations/oauth.d.ts +28 -0
- package/dist/server/mutations/oauth.d.ts.map +1 -0
- package/dist/server/mutations/oauth.js +110 -0
- package/dist/server/mutations/oauth.js.map +1 -0
- package/dist/server/mutations/refresh.d.ts +21 -0
- package/dist/server/mutations/refresh.d.ts.map +1 -0
- package/dist/server/mutations/refresh.js +119 -0
- package/dist/server/mutations/refresh.js.map +1 -0
- package/dist/server/mutations/register.d.ts +38 -0
- package/dist/server/mutations/register.d.ts.map +1 -0
- package/dist/server/mutations/register.js +83 -0
- package/dist/server/mutations/register.js.map +1 -0
- package/dist/server/mutations/retrieve.d.ts +33 -0
- package/dist/server/mutations/retrieve.d.ts.map +1 -0
- package/dist/server/mutations/retrieve.js +65 -0
- package/dist/server/mutations/retrieve.js.map +1 -0
- package/dist/server/mutations/signature.d.ts +22 -0
- package/dist/server/mutations/signature.d.ts.map +1 -0
- package/dist/server/mutations/signature.js +32 -0
- package/dist/server/mutations/signature.js.map +1 -0
- package/dist/server/mutations/signin.d.ts +22 -0
- package/dist/server/mutations/signin.d.ts.map +1 -0
- package/dist/server/{implementation/mutations → mutations}/signin.js +2 -2
- package/dist/server/mutations/signin.js.map +1 -0
- package/dist/server/mutations/signout.d.ts +16 -0
- package/dist/server/mutations/signout.d.ts.map +1 -0
- package/dist/server/mutations/signout.js +27 -0
- package/dist/server/mutations/signout.js.map +1 -0
- package/dist/server/mutations/store/refs.d.ts +12 -0
- package/dist/server/mutations/store/refs.d.ts.map +1 -0
- package/dist/server/mutations/store/refs.js +15 -0
- package/dist/server/mutations/store/refs.js.map +1 -0
- package/dist/server/mutations/store.d.ts +306 -0
- package/dist/server/mutations/store.d.ts.map +1 -0
- package/dist/server/mutations/store.js +85 -0
- package/dist/server/mutations/store.js.map +1 -0
- package/dist/server/mutations/verifier.d.ts +13 -0
- package/dist/server/mutations/verifier.d.ts.map +1 -0
- package/dist/server/mutations/verifier.js +18 -0
- package/dist/server/mutations/verifier.js.map +1 -0
- package/dist/server/mutations/verify.d.ts +26 -0
- package/dist/server/mutations/verify.d.ts.map +1 -0
- package/dist/server/mutations/verify.js +98 -0
- package/dist/server/mutations/verify.js.map +1 -0
- package/dist/server/oauth.d.ts +1 -48
- package/dist/server/oauth.js +107 -64
- package/dist/server/oauth.js.map +1 -1
- package/dist/server/passkey.d.ts +27 -0
- package/dist/server/passkey.d.ts.map +1 -0
- package/dist/server/passkey.js +328 -0
- package/dist/server/passkey.js.map +1 -0
- package/dist/server/redirects.d.ts +1 -0
- package/dist/{component/server/implementation → server}/redirects.js +13 -11
- package/dist/server/redirects.js.map +1 -0
- package/dist/server/refresh.d.ts +1 -0
- package/dist/server/refresh.js +96 -0
- package/dist/server/refresh.js.map +1 -0
- package/dist/server/runtime.d.ts +136 -0
- package/dist/server/runtime.d.ts.map +1 -0
- package/dist/server/runtime.js +413 -0
- package/dist/server/runtime.js.map +1 -0
- package/dist/server/sessions.d.ts +1 -0
- package/dist/{component/server/implementation → server}/sessions.js +14 -8
- package/dist/server/sessions.js.map +1 -0
- package/dist/server/signin.d.ts +1 -0
- package/dist/server/signin.js +201 -0
- package/dist/server/signin.js.map +1 -0
- package/dist/server/ssr.d.ts +226 -0
- package/dist/server/ssr.d.ts.map +1 -0
- package/dist/server/ssr.js +786 -0
- package/dist/server/ssr.js.map +1 -0
- package/dist/server/templates.d.ts +1 -21
- package/dist/server/templates.js +2 -1
- package/dist/server/templates.js.map +1 -1
- package/dist/server/tokens.d.ts +1 -0
- package/dist/server/tokens.js +17 -0
- package/dist/server/tokens.js.map +1 -0
- package/dist/server/totp.d.ts +1 -0
- package/dist/server/totp.js +148 -0
- package/dist/server/totp.js.map +1 -0
- package/dist/server/types.d.ts +498 -306
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +108 -1
- package/dist/server/types.js.map +1 -0
- package/dist/server/users.d.ts +1 -0
- package/dist/server/{implementation/users.js → users.js} +54 -35
- package/dist/server/users.js.map +1 -0
- package/dist/server/utils.d.ts +1 -6
- package/dist/server/utils.js +110 -4
- package/dist/server/utils.js.map +1 -1
- package/package.json +49 -46
- package/src/authorization/index.ts +83 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/command.ts +6 -5
- package/src/cli/index.ts +456 -248
- package/src/cli/keys.ts +3 -0
- package/src/client/core/types.ts +437 -0
- package/src/client/factors/device.ts +160 -0
- package/src/client/factors/passkey.ts +282 -0
- package/src/client/factors/totp.ts +150 -0
- package/src/client/index.ts +745 -989
- package/src/client/runtime/browser.ts +112 -0
- package/src/client/runtime/invite.ts +65 -0
- package/src/client/runtime/proxy.ts +111 -0
- package/src/client/runtime/storage.ts +79 -0
- package/src/component/_generated/api.ts +42 -0
- package/src/component/_generated/component.ts +3123 -102
- package/src/component/functions.ts +38 -22
- package/src/component/index.ts +10 -20
- package/src/component/model.ts +449 -0
- package/src/component/public/enterprise/audit.ts +120 -0
- package/src/component/public/enterprise/core.ts +354 -0
- package/src/component/public/enterprise/domains.ts +323 -0
- package/src/component/public/enterprise/scim.ts +396 -0
- package/src/component/public/enterprise/secrets.ts +132 -0
- package/src/component/public/enterprise/webhooks.ts +306 -0
- package/src/component/public/factors/devices.ts +223 -0
- package/src/component/public/factors/passkeys.ts +242 -0
- package/src/component/public/factors/totp.ts +258 -0
- package/src/component/public/groups/core.ts +481 -0
- package/src/component/public/groups/invites.ts +602 -0
- package/src/component/public/groups/members.ts +409 -0
- package/src/component/public/identity/accounts.ts +206 -0
- package/src/component/public/identity/codes.ts +148 -0
- package/src/component/public/identity/sessions.ts +209 -0
- package/src/component/public/identity/tokens.ts +250 -0
- package/src/component/public/identity/users.ts +354 -0
- package/src/component/public/identity/verifiers.ts +157 -0
- package/src/component/public/security/keys.ts +365 -0
- package/src/component/public/security/limits.ts +173 -0
- package/src/component/public.ts +26 -1766
- package/src/component/schema.ts +273 -100
- package/src/providers/anonymous.ts +10 -20
- package/src/providers/credentials.ts +14 -22
- package/src/providers/device.ts +3 -14
- package/src/providers/email.ts +83 -47
- package/src/providers/index.ts +7 -0
- package/src/providers/oauth.ts +5 -3
- package/src/providers/passkey.ts +0 -13
- package/src/providers/password.ts +307 -130
- package/src/providers/phone.ts +81 -37
- package/src/providers/sso.ts +54 -0
- package/src/providers/totp.ts +0 -13
- package/src/samlify.d.ts +53 -0
- package/src/server/auth.ts +701 -247
- package/src/server/authError.ts +44 -0
- package/src/server/{providers.ts → config.ts} +84 -15
- package/src/server/cookies.ts +8 -1
- package/src/server/core.ts +2095 -0
- package/src/server/crypto.ts +88 -0
- package/src/server/{implementation/db.ts → db.ts} +90 -15
- package/src/server/device.ts +221 -0
- package/src/server/enterprise/config.ts +51 -0
- package/src/server/enterprise/domain.ts +1751 -0
- package/src/server/enterprise/http.ts +1324 -0
- package/src/server/enterprise/oidc.ts +500 -0
- package/src/server/enterprise/policy.ts +128 -0
- package/src/server/enterprise/saml.ts +578 -0
- package/src/server/enterprise/scim.ts +135 -0
- package/src/server/enterprise/shared.ts +134 -0
- package/src/server/enterprise/validators.ts +93 -0
- package/src/server/errors.ts +130 -119
- package/src/server/http.ts +531 -0
- package/src/server/identity.ts +18 -0
- package/src/server/index.ts +32 -650
- package/src/server/{implementation/keys.ts → keys.ts} +16 -44
- package/src/server/limits.ts +134 -0
- package/src/server/mounts.ts +948 -0
- package/src/server/mutations/account.ts +76 -0
- package/src/server/{implementation/mutations → mutations}/code.ts +22 -11
- package/src/server/mutations/index.ts +13 -0
- package/src/server/mutations/invalidate.ts +50 -0
- package/src/server/mutations/oauth.ts +237 -0
- package/src/server/mutations/refresh.ts +298 -0
- package/src/server/mutations/register.ts +200 -0
- package/src/server/mutations/retrieve.ts +109 -0
- package/src/server/mutations/signature.ts +50 -0
- package/src/server/{implementation/mutations → mutations}/signin.ts +9 -7
- package/src/server/mutations/signout.ts +43 -0
- package/src/server/mutations/store/refs.ts +10 -0
- package/src/server/mutations/store.ts +138 -0
- package/src/server/mutations/verifier.ts +34 -0
- package/src/server/mutations/verify.ts +202 -0
- package/src/server/oauth.ts +243 -131
- package/src/server/passkey.ts +784 -0
- package/src/server/{implementation/redirects.ts → redirects.ts} +21 -16
- package/src/server/refresh.ts +222 -0
- package/src/server/runtime.ts +880 -0
- package/src/server/{implementation/sessions.ts → sessions.ts} +33 -25
- package/src/server/signin.ts +438 -0
- package/src/server/ssr.ts +1764 -0
- package/src/server/templates.ts +8 -3
- package/src/server/{implementation/tokens.ts → tokens.ts} +11 -5
- package/src/server/totp.ts +349 -0
- package/src/server/types.ts +972 -207
- package/src/server/{implementation/users.ts → users.ts} +129 -75
- package/src/server/utils.ts +192 -5
- package/src/test.ts +28 -4
- package/dist/bin.cjs +0 -27757
- package/dist/component/providers/email.js +0 -47
- package/dist/component/providers/email.js.map +0 -1
- package/dist/component/public.js.map +0 -1
- package/dist/component/server/implementation/db.js.map +0 -1
- package/dist/component/server/implementation/device.js +0 -135
- package/dist/component/server/implementation/device.js.map +0 -1
- package/dist/component/server/implementation/index.d.ts +0 -870
- package/dist/component/server/implementation/index.d.ts.map +0 -1
- package/dist/component/server/implementation/index.js +0 -610
- package/dist/component/server/implementation/index.js.map +0 -1
- package/dist/component/server/implementation/keys.js.map +0 -1
- package/dist/component/server/implementation/mutations/account.js +0 -39
- package/dist/component/server/implementation/mutations/account.js.map +0 -1
- package/dist/component/server/implementation/mutations/code.js.map +0 -1
- package/dist/component/server/implementation/mutations/index.js +0 -70
- package/dist/component/server/implementation/mutations/index.js.map +0 -1
- package/dist/component/server/implementation/mutations/invalidate.js +0 -29
- package/dist/component/server/implementation/mutations/invalidate.js.map +0 -1
- package/dist/component/server/implementation/mutations/oauth.js +0 -51
- package/dist/component/server/implementation/mutations/oauth.js.map +0 -1
- package/dist/component/server/implementation/mutations/refresh.js +0 -85
- package/dist/component/server/implementation/mutations/refresh.js.map +0 -1
- package/dist/component/server/implementation/mutations/register.js +0 -65
- package/dist/component/server/implementation/mutations/register.js.map +0 -1
- package/dist/component/server/implementation/mutations/retrieve.js +0 -50
- package/dist/component/server/implementation/mutations/retrieve.js.map +0 -1
- package/dist/component/server/implementation/mutations/signature.js +0 -27
- package/dist/component/server/implementation/mutations/signature.js.map +0 -1
- package/dist/component/server/implementation/mutations/signin.js.map +0 -1
- package/dist/component/server/implementation/mutations/signout.js +0 -27
- package/dist/component/server/implementation/mutations/signout.js.map +0 -1
- package/dist/component/server/implementation/mutations/store.js +0 -12
- package/dist/component/server/implementation/mutations/store.js.map +0 -1
- package/dist/component/server/implementation/mutations/verifier.js +0 -16
- package/dist/component/server/implementation/mutations/verifier.js.map +0 -1
- package/dist/component/server/implementation/mutations/verify.js +0 -105
- package/dist/component/server/implementation/mutations/verify.js.map +0 -1
- package/dist/component/server/implementation/passkey.js +0 -307
- package/dist/component/server/implementation/passkey.js.map +0 -1
- package/dist/component/server/implementation/provider.js +0 -19
- package/dist/component/server/implementation/provider.js.map +0 -1
- package/dist/component/server/implementation/ratelimit.js +0 -48
- package/dist/component/server/implementation/ratelimit.js.map +0 -1
- package/dist/component/server/implementation/redirects.js.map +0 -1
- package/dist/component/server/implementation/refresh.js +0 -109
- package/dist/component/server/implementation/refresh.js.map +0 -1
- package/dist/component/server/implementation/sessions.js.map +0 -1
- package/dist/component/server/implementation/signin.js +0 -148
- package/dist/component/server/implementation/signin.js.map +0 -1
- package/dist/component/server/implementation/tokens.js +0 -15
- package/dist/component/server/implementation/tokens.js.map +0 -1
- package/dist/component/server/implementation/totp.js +0 -142
- package/dist/component/server/implementation/totp.js.map +0 -1
- package/dist/component/server/implementation/types.d.ts +0 -42
- package/dist/component/server/implementation/types.d.ts.map +0 -1
- package/dist/component/server/implementation/types.js.map +0 -1
- package/dist/component/server/implementation/users.js.map +0 -1
- package/dist/component/server/implementation/utils.js +0 -56
- package/dist/component/server/implementation/utils.js.map +0 -1
- package/dist/component/server/providers.js.map +0 -1
- package/dist/component/server/templates.js +0 -84
- package/dist/component/server/templates.js.map +0 -1
- package/dist/server/cookies.d.ts.map +0 -1
- package/dist/server/implementation/db.d.ts +0 -86
- package/dist/server/implementation/db.d.ts.map +0 -1
- package/dist/server/implementation/db.js.map +0 -1
- package/dist/server/implementation/device.d.ts +0 -30
- package/dist/server/implementation/device.d.ts.map +0 -1
- package/dist/server/implementation/device.js +0 -135
- package/dist/server/implementation/device.js.map +0 -1
- package/dist/server/implementation/index.d.ts +0 -870
- package/dist/server/implementation/index.d.ts.map +0 -1
- package/dist/server/implementation/index.js +0 -610
- package/dist/server/implementation/index.js.map +0 -1
- package/dist/server/implementation/keys.d.ts +0 -66
- package/dist/server/implementation/keys.d.ts.map +0 -1
- package/dist/server/implementation/keys.js.map +0 -1
- package/dist/server/implementation/mutations/account.d.ts +0 -27
- package/dist/server/implementation/mutations/account.d.ts.map +0 -1
- package/dist/server/implementation/mutations/account.js +0 -39
- package/dist/server/implementation/mutations/account.js.map +0 -1
- package/dist/server/implementation/mutations/code.d.ts +0 -29
- package/dist/server/implementation/mutations/code.d.ts.map +0 -1
- package/dist/server/implementation/mutations/code.js.map +0 -1
- package/dist/server/implementation/mutations/index.d.ts +0 -310
- package/dist/server/implementation/mutations/index.d.ts.map +0 -1
- package/dist/server/implementation/mutations/index.js +0 -70
- package/dist/server/implementation/mutations/index.js.map +0 -1
- package/dist/server/implementation/mutations/invalidate.d.ts +0 -18
- package/dist/server/implementation/mutations/invalidate.d.ts.map +0 -1
- package/dist/server/implementation/mutations/invalidate.js +0 -29
- package/dist/server/implementation/mutations/invalidate.js.map +0 -1
- package/dist/server/implementation/mutations/oauth.d.ts +0 -23
- package/dist/server/implementation/mutations/oauth.d.ts.map +0 -1
- package/dist/server/implementation/mutations/oauth.js +0 -51
- package/dist/server/implementation/mutations/oauth.js.map +0 -1
- package/dist/server/implementation/mutations/refresh.d.ts +0 -20
- package/dist/server/implementation/mutations/refresh.d.ts.map +0 -1
- package/dist/server/implementation/mutations/refresh.js +0 -85
- package/dist/server/implementation/mutations/refresh.js.map +0 -1
- package/dist/server/implementation/mutations/register.d.ts +0 -37
- package/dist/server/implementation/mutations/register.d.ts.map +0 -1
- package/dist/server/implementation/mutations/register.js +0 -65
- package/dist/server/implementation/mutations/register.js.map +0 -1
- package/dist/server/implementation/mutations/retrieve.d.ts +0 -31
- package/dist/server/implementation/mutations/retrieve.d.ts.map +0 -1
- package/dist/server/implementation/mutations/retrieve.js +0 -50
- package/dist/server/implementation/mutations/retrieve.js.map +0 -1
- package/dist/server/implementation/mutations/signature.d.ts +0 -19
- package/dist/server/implementation/mutations/signature.d.ts.map +0 -1
- package/dist/server/implementation/mutations/signature.js +0 -27
- package/dist/server/implementation/mutations/signature.js.map +0 -1
- package/dist/server/implementation/mutations/signin.d.ts +0 -21
- package/dist/server/implementation/mutations/signin.d.ts.map +0 -1
- package/dist/server/implementation/mutations/signin.js.map +0 -1
- package/dist/server/implementation/mutations/signout.d.ts +0 -14
- package/dist/server/implementation/mutations/signout.d.ts.map +0 -1
- package/dist/server/implementation/mutations/signout.js +0 -27
- package/dist/server/implementation/mutations/signout.js.map +0 -1
- package/dist/server/implementation/mutations/store.d.ts +0 -11
- package/dist/server/implementation/mutations/store.d.ts.map +0 -1
- package/dist/server/implementation/mutations/store.js +0 -12
- package/dist/server/implementation/mutations/store.js.map +0 -1
- package/dist/server/implementation/mutations/verifier.d.ts +0 -11
- package/dist/server/implementation/mutations/verifier.d.ts.map +0 -1
- package/dist/server/implementation/mutations/verifier.js +0 -16
- package/dist/server/implementation/mutations/verifier.js.map +0 -1
- package/dist/server/implementation/mutations/verify.d.ts +0 -25
- package/dist/server/implementation/mutations/verify.d.ts.map +0 -1
- package/dist/server/implementation/mutations/verify.js +0 -105
- package/dist/server/implementation/mutations/verify.js.map +0 -1
- package/dist/server/implementation/passkey.d.ts +0 -24
- package/dist/server/implementation/passkey.d.ts.map +0 -1
- package/dist/server/implementation/passkey.js +0 -307
- package/dist/server/implementation/passkey.js.map +0 -1
- package/dist/server/implementation/provider.d.ts +0 -10
- package/dist/server/implementation/provider.d.ts.map +0 -1
- package/dist/server/implementation/provider.js +0 -19
- package/dist/server/implementation/provider.js.map +0 -1
- package/dist/server/implementation/ratelimit.d.ts +0 -10
- package/dist/server/implementation/ratelimit.d.ts.map +0 -1
- package/dist/server/implementation/ratelimit.js +0 -48
- package/dist/server/implementation/ratelimit.js.map +0 -1
- package/dist/server/implementation/redirects.d.ts +0 -10
- package/dist/server/implementation/redirects.d.ts.map +0 -1
- package/dist/server/implementation/redirects.js.map +0 -1
- package/dist/server/implementation/refresh.d.ts +0 -37
- package/dist/server/implementation/refresh.d.ts.map +0 -1
- package/dist/server/implementation/refresh.js +0 -109
- package/dist/server/implementation/refresh.js.map +0 -1
- package/dist/server/implementation/sessions.d.ts +0 -29
- package/dist/server/implementation/sessions.d.ts.map +0 -1
- package/dist/server/implementation/sessions.js.map +0 -1
- package/dist/server/implementation/signin.d.ts +0 -55
- package/dist/server/implementation/signin.d.ts.map +0 -1
- package/dist/server/implementation/signin.js +0 -148
- package/dist/server/implementation/signin.js.map +0 -1
- package/dist/server/implementation/tokens.d.ts +0 -11
- package/dist/server/implementation/tokens.d.ts.map +0 -1
- package/dist/server/implementation/tokens.js +0 -15
- package/dist/server/implementation/tokens.js.map +0 -1
- package/dist/server/implementation/totp.d.ts +0 -31
- package/dist/server/implementation/totp.d.ts.map +0 -1
- package/dist/server/implementation/totp.js +0 -142
- package/dist/server/implementation/totp.js.map +0 -1
- package/dist/server/implementation/types.d.ts +0 -189
- package/dist/server/implementation/types.d.ts.map +0 -1
- package/dist/server/implementation/types.js +0 -97
- package/dist/server/implementation/types.js.map +0 -1
- package/dist/server/implementation/users.d.ts +0 -30
- package/dist/server/implementation/users.d.ts.map +0 -1
- package/dist/server/implementation/users.js.map +0 -1
- package/dist/server/implementation/utils.d.ts +0 -19
- package/dist/server/implementation/utils.d.ts.map +0 -1
- package/dist/server/implementation/utils.js +0 -56
- package/dist/server/implementation/utils.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/oauth.d.ts.map +0 -1
- package/dist/server/providers.d.ts +0 -72
- package/dist/server/providers.d.ts.map +0 -1
- package/dist/server/providers.js.map +0 -1
- package/dist/server/templates.d.ts.map +0 -1
- package/dist/server/utils.d.ts.map +0 -1
- package/dist/server/version.d.ts +0 -5
- package/dist/server/version.d.ts.map +0 -1
- package/dist/server/version.js +0 -6
- package/dist/server/version.js.map +0 -1
- package/src/cli/utils.ts +0 -248
- package/src/server/implementation/device.ts +0 -307
- package/src/server/implementation/index.ts +0 -1583
- package/src/server/implementation/mutations/account.ts +0 -50
- package/src/server/implementation/mutations/index.ts +0 -157
- package/src/server/implementation/mutations/invalidate.ts +0 -42
- package/src/server/implementation/mutations/oauth.ts +0 -73
- package/src/server/implementation/mutations/refresh.ts +0 -175
- package/src/server/implementation/mutations/register.ts +0 -100
- package/src/server/implementation/mutations/retrieve.ts +0 -79
- package/src/server/implementation/mutations/signature.ts +0 -39
- package/src/server/implementation/mutations/signout.ts +0 -35
- package/src/server/implementation/mutations/store.ts +0 -7
- package/src/server/implementation/mutations/verifier.ts +0 -24
- package/src/server/implementation/mutations/verify.ts +0 -194
- package/src/server/implementation/passkey.ts +0 -620
- package/src/server/implementation/provider.ts +0 -36
- package/src/server/implementation/ratelimit.ts +0 -79
- package/src/server/implementation/refresh.ts +0 -172
- package/src/server/implementation/signin.ts +0 -296
- package/src/server/implementation/totp.ts +0 -342
- package/src/server/implementation/types.ts +0 -444
- package/src/server/implementation/utils.ts +0 -91
- package/src/server/version.ts +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","names":[],"sources":["../../../../src/server/mutations/account.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport { GetProviderOrThrowFunc, hash } from \"../crypto\";\nimport * as Provider from \"../crypto\";\nimport { MutationCtx } from \"../types\";\nimport { LOG_LEVELS, logWithLevel, maybeRedact } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const modifyAccountArgs = v.object({\n provider: v.string(),\n account: v.object({ id: v.string(), secret: v.string() }),\n});\n\nexport function modifyAccountImpl(\n ctx: MutationCtx,\n args: Infer<typeof modifyAccountArgs>,\n getProviderOrThrow: GetProviderOrThrowFunc,\n config: Provider.Config,\n): Fx<void, AuthError> {\n const { provider, account } = args;\n const db = authDb(ctx, config);\n\n logWithLevel(LOG_LEVELS.DEBUG, \"modifyAccountImpl args:\", {\n provider,\n account: { id: account.id, secret: maybeRedact(account.secret ?? \"\") },\n });\n\n return Fx.from({\n ok: () => db.accounts.get(provider, account.id),\n err: () =>\n new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n `Cannot modify account with ID ${account.id} because it does not exist`,\n ),\n }).pipe(\n Fx.chain((doc) =>\n doc === null\n ? Fx.fail(\n new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n `Cannot modify account with ID ${account.id} because it does not exist`,\n ),\n )\n : Fx.succeed(doc),\n ),\n Fx.chain((existingAccount) =>\n hash(getProviderOrThrow(provider), account.secret).pipe(\n Fx.chain((hashedSecret) =>\n Fx.from({\n ok: () =>\n db.accounts.patch(existingAccount._id, { secret: hashedSecret }),\n err: () =>\n new AuthError(\"INTERNAL_ERROR\", \"Failed to patch account\"),\n }),\n ),\n ),\n ),\n Fx.map(() => undefined),\n );\n}\n\nexport const callModifyAccount = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof modifyAccountArgs>,\n): Promise<void> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"modifyAccount\",\n ...args,\n },\n });\n};\n"],"mappings":";;;;;;;;;AAYA,MAAa,oBAAoB,EAAE,OAAO;CACxC,UAAU,EAAE,QAAQ;CACpB,SAAS,EAAE,OAAO;EAAE,IAAI,EAAE,QAAQ;EAAE,QAAQ,EAAE,QAAQ;EAAE,CAAC;CAC1D,CAAC;AAEF,SAAgB,kBACd,KACA,MACA,oBACA,QACqB;CACrB,MAAM,EAAE,UAAU,YAAY;CAC9B,MAAM,KAAK,OAAO,KAAK,OAAO;AAE9B,cAAa,WAAW,OAAO,2BAA2B;EACxD;EACA,SAAS;GAAE,IAAI,QAAQ;GAAI,QAAQ,YAAY,QAAQ,UAAU,GAAG;GAAE;EACvE,CAAC;AAEF,QAAO,GAAG,KAAK;EACb,UAAU,GAAG,SAAS,IAAI,UAAU,QAAQ,GAAG;EAC/C,WACE,IAAI,UACF,qBACA,iCAAiC,QAAQ,GAAG,4BAC7C;EACJ,CAAC,CAAC,KACD,GAAG,OAAO,QACR,QAAQ,OACJ,GAAG,KACD,IAAI,UACF,qBACA,iCAAiC,QAAQ,GAAG,4BAC7C,CACF,GACD,GAAG,QAAQ,IAAI,CACpB,EACD,GAAG,OAAO,oBACR,KAAK,mBAAmB,SAAS,EAAE,QAAQ,OAAO,CAAC,KACjD,GAAG,OAAO,iBACR,GAAG,KAAK;EACN,UACE,GAAG,SAAS,MAAM,gBAAgB,KAAK,EAAE,QAAQ,cAAc,CAAC;EAClE,WACE,IAAI,UAAU,kBAAkB,0BAA0B;EAC7D,CAAC,CACH,CACF,CACF,EACD,GAAG,UAAU,OAAU,CACxB;;AAGH,MAAa,oBAAoB,OAC/B,KACA,SACkB;AAClB,QAAO,IAAI,YAAY,gBAAgB,EACrC,MAAM;EACJ,MAAM;EACN,GAAG;EACJ,EACF,CAAC"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
1
2
|
import { LOG_LEVELS, logWithLevel, sha256 } from "../utils.js";
|
|
2
3
|
import { authDb } from "../db.js";
|
|
4
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
3
5
|
import { getAuthSessionId } from "../sessions.js";
|
|
4
|
-
import {
|
|
5
|
-
import { getAccountOrThrow, upsertUserAndAccount } from "../users.js";
|
|
6
|
+
import { upsertUserAndAccount } from "../users.js";
|
|
6
7
|
import { v } from "convex/values";
|
|
7
8
|
|
|
8
|
-
//#region src/server/
|
|
9
|
+
//#region src/server/mutations/code.ts
|
|
9
10
|
const createVerificationCodeArgs = v.object({
|
|
10
11
|
accountId: v.optional(v.string()),
|
|
11
12
|
provider: v.string(),
|
|
@@ -20,7 +21,9 @@ async function createVerificationCodeImpl(ctx, args, getProviderOrThrow, config)
|
|
|
20
21
|
const { email, phone, code, expirationTime, provider: providerId, accountId: existingAccountId, allowExtraProviders } = args;
|
|
21
22
|
const db = authDb(ctx, config);
|
|
22
23
|
const typedExistingAccountId = existingAccountId;
|
|
23
|
-
const existingAccount = typedExistingAccountId !== void 0 ? await
|
|
24
|
+
const existingAccount = typedExistingAccountId !== void 0 ? await db.accounts.getById(typedExistingAccountId) ?? (() => {
|
|
25
|
+
throw new AuthError("ACCOUNT_NOT_FOUND", `Expected an account to exist for ID "${typedExistingAccountId}"`).toConvexError();
|
|
26
|
+
})() : await db.accounts.get(providerId, email ?? phone);
|
|
24
27
|
const provider = getProviderOrThrow(providerId, allowExtraProviders);
|
|
25
28
|
const { accountId } = await upsertUserAndAccount(ctx, await getAuthSessionId(ctx), existingAccount !== null ? { existingAccount } : { providerAccountId: email ?? phone }, provider.type === "email" ? {
|
|
26
29
|
type: "email",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code.js","names":[],"sources":["../../../../src/server/mutations/code.ts"],"sourcesContent":["import type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { GenericId, Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport * as Provider from \"../crypto\";\nimport { getAuthSessionId } from \"../sessions\";\nimport { MutationCtx } from \"../types\";\nimport { EmailConfig, PhoneConfig } from \"../types\";\nimport { upsertUserAndAccount } from \"../users\";\nimport { LOG_LEVELS, logWithLevel, sha256 } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const createVerificationCodeArgs = v.object({\n accountId: v.optional(v.string()),\n provider: v.string(),\n email: v.optional(v.string()),\n phone: v.optional(v.string()),\n code: v.string(),\n expirationTime: v.number(),\n allowExtraProviders: v.boolean(),\n});\n\ntype ReturnType = string;\n\nexport async function createVerificationCodeImpl(\n ctx: MutationCtx,\n args: Infer<typeof createVerificationCodeArgs>,\n getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n config: Provider.Config,\n): Promise<ReturnType> {\n logWithLevel(LOG_LEVELS.DEBUG, \"createVerificationCodeImpl args:\", args);\n const {\n email,\n phone,\n code,\n expirationTime,\n provider: providerId,\n accountId: existingAccountId,\n allowExtraProviders,\n } = args;\n const db = authDb(ctx, config);\n const typedExistingAccountId = existingAccountId as\n | GenericId<\"Account\">\n | undefined;\n const existingAccount =\n typedExistingAccountId !== undefined\n ? ((await db.accounts.getById(typedExistingAccountId)) ??\n (() => {\n throw new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n `Expected an account to exist for ID \"${typedExistingAccountId}\"`,\n ).toConvexError();\n })())\n : await db.accounts.get(providerId, email ?? phone!);\n\n const provider = getProviderOrThrow(providerId, allowExtraProviders) as\n | EmailConfig\n | PhoneConfig;\n const { accountId } = await upsertUserAndAccount(\n ctx,\n await getAuthSessionId(ctx),\n existingAccount !== null\n ? { existingAccount }\n : { providerAccountId: email ?? phone! },\n provider.type === \"email\"\n ? { type: \"email\", provider, profile: { email: email! } }\n : { type: \"phone\", provider, profile: { phone: phone! } },\n config,\n );\n await generateUniqueVerificationCode(\n ctx,\n accountId,\n providerId,\n code,\n expirationTime,\n { email, phone },\n config,\n );\n return email ?? phone!;\n}\n\nexport const callCreateVerificationCode = async <\n DataModel extends GenericDataModel,\n>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof createVerificationCodeArgs>,\n): Promise<ReturnType> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"createVerificationCode\",\n ...args,\n },\n });\n};\n\nasync function generateUniqueVerificationCode(\n ctx: MutationCtx,\n accountId: GenericId<\"Account\">,\n provider: string,\n code: string,\n expirationTime: number,\n { email, phone }: { email?: string; phone?: string },\n config: Provider.Config,\n) {\n const db = authDb(ctx, config);\n const existingCode = await db.verificationCodes.getByAccountId(accountId);\n if (existingCode !== null) {\n await db.verificationCodes.delete(existingCode._id);\n }\n await db.verificationCodes.create({\n accountId,\n provider,\n code: await sha256(code),\n expirationTime,\n emailVerified: email,\n phoneVerified: phone,\n });\n}\n"],"mappings":";;;;;;;;;AAaA,MAAa,6BAA6B,EAAE,OAAO;CACjD,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC;CACjC,UAAU,EAAE,QAAQ;CACpB,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC;CAC7B,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC;CAC7B,MAAM,EAAE,QAAQ;CAChB,gBAAgB,EAAE,QAAQ;CAC1B,qBAAqB,EAAE,SAAS;CACjC,CAAC;AAIF,eAAsB,2BACpB,KACA,MACA,oBACA,QACqB;AACrB,cAAa,WAAW,OAAO,oCAAoC,KAAK;CACxE,MAAM,EACJ,OACA,OACA,MACA,gBACA,UAAU,YACV,WAAW,mBACX,wBACE;CACJ,MAAM,KAAK,OAAO,KAAK,OAAO;CAC9B,MAAM,yBAAyB;CAG/B,MAAM,kBACJ,2BAA2B,SACrB,MAAM,GAAG,SAAS,QAAQ,uBAAuB,WAC5C;AACL,QAAM,IAAI,UACR,qBACA,wCAAwC,uBAAuB,GAChE,CAAC,eAAe;KACf,GACJ,MAAM,GAAG,SAAS,IAAI,YAAY,SAAS,MAAO;CAExD,MAAM,WAAW,mBAAmB,YAAY,oBAAoB;CAGpE,MAAM,EAAE,cAAc,MAAM,qBAC1B,KACA,MAAM,iBAAiB,IAAI,EAC3B,oBAAoB,OAChB,EAAE,iBAAiB,GACnB,EAAE,mBAAmB,SAAS,OAAQ,EAC1C,SAAS,SAAS,UACd;EAAE,MAAM;EAAS;EAAU,SAAS,EAAS,OAAQ;EAAE,GACvD;EAAE,MAAM;EAAS;EAAU,SAAS,EAAS,OAAQ;EAAE,EAC3D,OACD;AACD,OAAM,+BACJ,KACA,WACA,YACA,MACA,gBACA;EAAE;EAAO;EAAO,EAChB,OACD;AACD,QAAO,SAAS;;AAGlB,MAAa,6BAA6B,OAGxC,KACA,SACwB;AACxB,QAAO,IAAI,YAAY,gBAAgB,EACrC,MAAM;EACJ,MAAM;EACN,GAAG;EACJ,EACF,CAAC;;AAGJ,eAAe,+BACb,KACA,WACA,UACA,MACA,gBACA,EAAE,OAAO,SACT,QACA;CACA,MAAM,KAAK,OAAO,KAAK,OAAO;CAC9B,MAAM,eAAe,MAAM,GAAG,kBAAkB,eAAe,UAAU;AACzE,KAAI,iBAAiB,KACnB,OAAM,GAAG,kBAAkB,OAAO,aAAa,IAAI;AAErD,OAAM,GAAG,kBAAkB,OAAO;EAChC;EACA;EACA,MAAM,MAAM,OAAO,KAAK;EACxB;EACA,eAAe;EACf,eAAe;EAChB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { LOG_LEVELS, logWithLevel } from "../utils.js";
|
|
2
|
+
import { authDb } from "../db.js";
|
|
3
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
4
|
+
import { deleteSession } from "../sessions.js";
|
|
5
|
+
import { v } from "convex/values";
|
|
6
|
+
import { Fx } from "@robelest/fx";
|
|
7
|
+
|
|
8
|
+
//#region src/server/mutations/invalidate.ts
|
|
9
|
+
const invalidateSessionsArgs = v.object({
|
|
10
|
+
userId: v.string(),
|
|
11
|
+
except: v.optional(v.array(v.string()))
|
|
12
|
+
});
|
|
13
|
+
const callInvalidateSessions = async (ctx, args) => {
|
|
14
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
15
|
+
type: "invalidateSessions",
|
|
16
|
+
...args
|
|
17
|
+
} });
|
|
18
|
+
};
|
|
19
|
+
function invalidateSessionsImpl(ctx, args, config) {
|
|
20
|
+
return Fx.gen(function* () {
|
|
21
|
+
logWithLevel(LOG_LEVELS.DEBUG, "invalidateSessionsImpl args:", args);
|
|
22
|
+
const { userId, except } = args;
|
|
23
|
+
const exceptSet = new Set(except ?? []);
|
|
24
|
+
const typedUserId = userId;
|
|
25
|
+
const sessions = yield* Fx.promise(() => authDb(ctx, config).sessions.listByUser(typedUserId));
|
|
26
|
+
yield* Fx.each(sessions, (session) => exceptSet.has(session._id) ? Fx.unit : Fx.promise(() => deleteSession(ctx, session, config)));
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { callInvalidateSessions, invalidateSessionsArgs, invalidateSessionsImpl };
|
|
32
|
+
//# sourceMappingURL=invalidate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invalidate.js","names":[],"sources":["../../../../src/server/mutations/invalidate.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { GenericId, Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport * as Provider from \"../crypto\";\nimport { deleteSession } from \"../sessions\";\nimport { Doc, MutationCtx } from \"../types\";\nimport { LOG_LEVELS, logWithLevel } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const invalidateSessionsArgs = v.object({\n userId: v.string(),\n except: v.optional(v.array(v.string())),\n});\n\nexport const callInvalidateSessions = async <\n DataModel extends GenericDataModel,\n>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof invalidateSessionsArgs>,\n): Promise<void> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"invalidateSessions\",\n ...args,\n },\n });\n};\n\nexport function invalidateSessionsImpl(\n ctx: MutationCtx,\n args: Infer<typeof invalidateSessionsArgs>,\n config: Provider.Config,\n): Fx<void, never> {\n return Fx.gen(function* () {\n logWithLevel(LOG_LEVELS.DEBUG, \"invalidateSessionsImpl args:\", args);\n const { userId, except } = args;\n const exceptSet = new Set(except ?? []);\n const typedUserId = userId as GenericId<\"User\">;\n const sessions = (yield* Fx.promise(() =>\n authDb(ctx, config).sessions.listByUser(typedUserId),\n )) as Doc<\"Session\">[];\n yield* Fx.each(sessions, (session: Doc<\"Session\">) =>\n exceptSet.has(session._id)\n ? Fx.unit\n : Fx.promise(() => deleteSession(ctx, session, config)),\n );\n });\n}\n"],"mappings":";;;;;;;;AAWA,MAAa,yBAAyB,EAAE,OAAO;CAC7C,QAAQ,EAAE,QAAQ;CAClB,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;CACxC,CAAC;AAEF,MAAa,yBAAyB,OAGpC,KACA,SACkB;AAClB,QAAO,IAAI,YAAY,gBAAgB,EACrC,MAAM;EACJ,MAAM;EACN,GAAG;EACJ,EACF,CAAC;;AAGJ,SAAgB,uBACd,KACA,MACA,QACiB;AACjB,QAAO,GAAG,IAAI,aAAa;AACzB,eAAa,WAAW,OAAO,gCAAgC,KAAK;EACpE,MAAM,EAAE,QAAQ,WAAW;EAC3B,MAAM,YAAY,IAAI,IAAI,UAAU,EAAE,CAAC;EACvC,MAAM,cAAc;EACpB,MAAM,WAAY,OAAO,GAAG,cAC1B,OAAO,KAAK,OAAO,CAAC,SAAS,WAAW,YAAY,CACrD;AACD,SAAO,GAAG,KAAK,WAAW,YACxB,UAAU,IAAI,QAAQ,IAAI,GACtB,GAAG,OACH,GAAG,cAAc,cAAc,KAAK,SAAS,OAAO,CAAC,CAC1D;GACD"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
|
+
import { generateRandomString, logWithLevel, sha256 } from "../utils.js";
|
|
3
|
+
import { authDb } from "../db.js";
|
|
4
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
5
|
+
import { upsertUserAndAccount } from "../users.js";
|
|
6
|
+
import { ENTERPRISE_OIDC_PROVIDER_PREFIX, ENTERPRISE_SAML_PROVIDER_PREFIX, isEnterpriseProviderId } from "../enterprise/shared.js";
|
|
7
|
+
import { createSyntheticOAuthMaterializedConfig } from "../enterprise/oidc.js";
|
|
8
|
+
import { normalizeEnterprisePolicy } from "../enterprise/policy.js";
|
|
9
|
+
import { v } from "convex/values";
|
|
10
|
+
import { Fx } from "@robelest/fx";
|
|
11
|
+
|
|
12
|
+
//#region src/server/mutations/oauth.ts
|
|
13
|
+
const OAUTH_SIGN_IN_EXPIRATION_MS = 1e3 * 60 * 2;
|
|
14
|
+
const userOAuthArgs = v.object({
|
|
15
|
+
provider: v.string(),
|
|
16
|
+
providerAccountId: v.string(),
|
|
17
|
+
profile: v.any(),
|
|
18
|
+
signature: v.string(),
|
|
19
|
+
accountExtend: v.optional(v.any())
|
|
20
|
+
});
|
|
21
|
+
function normalizeAccountExtend(provider, providerAccountId, accountExtend) {
|
|
22
|
+
const baseIdentity = {
|
|
23
|
+
type: "oauth",
|
|
24
|
+
provider,
|
|
25
|
+
providerAccountId
|
|
26
|
+
};
|
|
27
|
+
if (provider.startsWith(ENTERPRISE_OIDC_PROVIDER_PREFIX)) {
|
|
28
|
+
baseIdentity.type = "enterprise-oidc";
|
|
29
|
+
baseIdentity.enterpriseId = provider.slice(ENTERPRISE_OIDC_PROVIDER_PREFIX.length);
|
|
30
|
+
}
|
|
31
|
+
if (provider.startsWith(ENTERPRISE_SAML_PROVIDER_PREFIX)) {
|
|
32
|
+
baseIdentity.type = "enterprise-saml";
|
|
33
|
+
baseIdentity.enterpriseId = provider.slice(ENTERPRISE_SAML_PROVIDER_PREFIX.length);
|
|
34
|
+
}
|
|
35
|
+
const provided = typeof accountExtend === "object" && accountExtend !== null && !Array.isArray(accountExtend) ? accountExtend : void 0;
|
|
36
|
+
const providedIdentity = provided && typeof provided.identity === "object" && provided.identity !== null && !Array.isArray(provided.identity) ? provided.identity : void 0;
|
|
37
|
+
return {
|
|
38
|
+
...provided,
|
|
39
|
+
identity: {
|
|
40
|
+
...baseIdentity,
|
|
41
|
+
...providedIdentity
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function userOAuthImpl(ctx, args, getProviderOrThrow, config) {
|
|
46
|
+
return Fx.gen(function* () {
|
|
47
|
+
logWithLevel("DEBUG", "userOAuthImpl args:", args);
|
|
48
|
+
const { profile, provider, providerAccountId, signature, accountExtend } = args;
|
|
49
|
+
const db = authDb(ctx, config);
|
|
50
|
+
const existingAccount = yield* Fx.promise(() => db.accounts.get(provider, providerAccountId));
|
|
51
|
+
const enterpriseId = provider.startsWith(ENTERPRISE_OIDC_PROVIDER_PREFIX) ? provider.slice(ENTERPRISE_OIDC_PROVIDER_PREFIX.length) : provider.startsWith(ENTERPRISE_SAML_PROVIDER_PREFIX) ? provider.slice(ENTERPRISE_SAML_PROVIDER_PREFIX.length) : null;
|
|
52
|
+
const enterprise = enterpriseId !== null ? yield* Fx.promise(() => ctx.runQuery(config.component.public.enterpriseGet, { enterpriseId })) : null;
|
|
53
|
+
const enterprisePolicy = enterprise ? normalizeEnterprisePolicy(enterprise.policy) : null;
|
|
54
|
+
const enterpriseProtocol = provider.startsWith(ENTERPRISE_OIDC_PROVIDER_PREFIX) ? "oidc" : provider.startsWith(ENTERPRISE_SAML_PROVIDER_PREFIX) ? "saml" : null;
|
|
55
|
+
const existingScimIdentity = enterpriseId !== null && existingAccount === null && enterprisePolicy?.provisioning.scimReuse.user === "externalId" ? yield* Fx.promise(() => ctx.runQuery(config.component.public.enterpriseScimIdentityGet, {
|
|
56
|
+
enterpriseId,
|
|
57
|
+
resourceType: "user",
|
|
58
|
+
externalId: providerAccountId
|
|
59
|
+
})) : null;
|
|
60
|
+
const verifier = yield* Fx.from({
|
|
61
|
+
ok: () => db.verifiers.getBySignature(signature),
|
|
62
|
+
err: () => new AuthError("OAUTH_INVALID_STATE")
|
|
63
|
+
}).pipe(Fx.chain((doc) => doc === null ? Fx.fail(new AuthError("OAUTH_INVALID_STATE")) : Fx.succeed(doc)));
|
|
64
|
+
const { accountId } = yield* Fx.promise(() => upsertUserAndAccount(ctx, verifier.sessionId ?? null, existingAccount !== null ? { existingAccount } : { providerAccountId }, {
|
|
65
|
+
type: "oauth",
|
|
66
|
+
provider: isEnterpriseProviderId(provider) ? createSyntheticOAuthMaterializedConfig(provider, { accountLinking: enterpriseProtocol === "oidc" ? enterprisePolicy?.identity.accountLinking.oidc : enterpriseProtocol === "saml" ? enterprisePolicy?.identity.accountLinking.saml : void 0 }) : getProviderOrThrow(provider),
|
|
67
|
+
profile,
|
|
68
|
+
accountExtend: normalizeAccountExtend(provider, providerAccountId, accountExtend)
|
|
69
|
+
}, config, existingScimIdentity?.userId ? { existingUserId: existingScimIdentity.userId } : void 0));
|
|
70
|
+
if (enterpriseId !== null && enterprisePolicy?.provisioning.jit.mode === "createUserAndMembership") {
|
|
71
|
+
const userId = (yield* Fx.promise(() => db.accounts.getById(accountId)))?.userId;
|
|
72
|
+
if (userId) {
|
|
73
|
+
const groupId = enterprise?.groupId;
|
|
74
|
+
if (groupId) {
|
|
75
|
+
if ((yield* Fx.promise(() => ctx.runQuery(config.component.public.memberGetByGroupAndUser, {
|
|
76
|
+
userId,
|
|
77
|
+
groupId
|
|
78
|
+
}))) === null) yield* Fx.promise(() => ctx.runMutation(config.component.public.memberAdd, {
|
|
79
|
+
groupId,
|
|
80
|
+
userId,
|
|
81
|
+
roleIds: enterprisePolicy.provisioning.jit.defaultRoleIds,
|
|
82
|
+
status: "active"
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const code = generateRandomString(8, "0123456789");
|
|
88
|
+
yield* Fx.promise(() => db.verifiers.delete(verifier._id));
|
|
89
|
+
const existingVerificationCode = yield* Fx.promise(() => db.verificationCodes.getByAccountId(accountId));
|
|
90
|
+
if (existingVerificationCode !== null) yield* Fx.promise(() => db.verificationCodes.delete(existingVerificationCode._id));
|
|
91
|
+
yield* Fx.promise(async () => db.verificationCodes.create({
|
|
92
|
+
code: await sha256(code),
|
|
93
|
+
accountId,
|
|
94
|
+
provider,
|
|
95
|
+
expirationTime: Date.now() + OAUTH_SIGN_IN_EXPIRATION_MS,
|
|
96
|
+
verifier: verifier._id
|
|
97
|
+
}));
|
|
98
|
+
return code;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const callUserOAuth = async (ctx, args) => {
|
|
102
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
103
|
+
type: "userOAuth",
|
|
104
|
+
...args
|
|
105
|
+
} });
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
export { callUserOAuth, userOAuthArgs, userOAuthImpl };
|
|
110
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","names":[],"sources":["../../../../src/server/mutations/oauth.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport * as Provider from \"../crypto\";\nimport {\n createSyntheticOAuthMaterializedConfig,\n} from \"../enterprise/oidc\";\nimport { normalizeEnterprisePolicy } from \"../enterprise/policy\";\nimport {\n ENTERPRISE_OIDC_PROVIDER_PREFIX,\n ENTERPRISE_SAML_PROVIDER_PREFIX,\n isEnterpriseProviderId,\n} from \"../enterprise/shared\";\nimport { MutationCtx } from \"../types\";\nimport type { AuthProviderMaterializedConfig } from \"../types\";\nimport { upsertUserAndAccount } from \"../users\";\nimport { generateRandomString, logWithLevel, sha256 } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nconst OAUTH_SIGN_IN_EXPIRATION_MS = 1000 * 60 * 2; // 2 minutes\n\nexport const userOAuthArgs = v.object({\n provider: v.string(),\n providerAccountId: v.string(),\n profile: v.any(),\n signature: v.string(),\n accountExtend: v.optional(v.any()),\n});\n\nfunction normalizeAccountExtend(\n provider: string,\n providerAccountId: string,\n accountExtend: unknown,\n) {\n const baseIdentity: Record<string, unknown> = {\n type: \"oauth\",\n provider,\n providerAccountId,\n };\n if (provider.startsWith(ENTERPRISE_OIDC_PROVIDER_PREFIX)) {\n baseIdentity.type = \"enterprise-oidc\";\n baseIdentity.enterpriseId = provider.slice(\n ENTERPRISE_OIDC_PROVIDER_PREFIX.length,\n );\n }\n if (provider.startsWith(ENTERPRISE_SAML_PROVIDER_PREFIX)) {\n baseIdentity.type = \"enterprise-saml\";\n baseIdentity.enterpriseId = provider.slice(\n ENTERPRISE_SAML_PROVIDER_PREFIX.length,\n );\n }\n const provided =\n typeof accountExtend === \"object\" &&\n accountExtend !== null &&\n !Array.isArray(accountExtend)\n ? (accountExtend as Record<string, unknown>)\n : undefined;\n const providedIdentity =\n provided &&\n typeof provided.identity === \"object\" &&\n provided.identity !== null &&\n !Array.isArray(provided.identity)\n ? (provided.identity as Record<string, unknown>)\n : undefined;\n return {\n ...provided,\n identity: {\n ...baseIdentity,\n ...providedIdentity,\n },\n };\n}\n\ntype ReturnType = string;\n\nexport function userOAuthImpl(\n ctx: MutationCtx,\n args: Infer<typeof userOAuthArgs>,\n getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n config: Provider.Config,\n): Fx<ReturnType, AuthError> {\n return Fx.gen(function* () {\n logWithLevel(\"DEBUG\", \"userOAuthImpl args:\", args);\n const { profile, provider, providerAccountId, signature, accountExtend } =\n args;\n const db = authDb(ctx, config);\n const existingAccount = yield* Fx.promise(() =>\n db.accounts.get(provider, providerAccountId),\n );\n const enterpriseId = provider.startsWith(ENTERPRISE_OIDC_PROVIDER_PREFIX)\n ? provider.slice(ENTERPRISE_OIDC_PROVIDER_PREFIX.length)\n : provider.startsWith(ENTERPRISE_SAML_PROVIDER_PREFIX)\n ? provider.slice(ENTERPRISE_SAML_PROVIDER_PREFIX.length)\n : null;\n const enterprise =\n enterpriseId !== null\n ? yield* Fx.promise(() =>\n ctx.runQuery(config.component.public.enterpriseGet, {\n enterpriseId,\n }),\n )\n : null;\n const enterprisePolicy = enterprise\n ? normalizeEnterprisePolicy(enterprise.policy)\n : null;\n const enterpriseProtocol = provider.startsWith(\n ENTERPRISE_OIDC_PROVIDER_PREFIX,\n )\n ? \"oidc\"\n : provider.startsWith(ENTERPRISE_SAML_PROVIDER_PREFIX)\n ? \"saml\"\n : null;\n\n const existingScimIdentity =\n enterpriseId !== null &&\n existingAccount === null &&\n enterprisePolicy?.provisioning.scimReuse.user === \"externalId\"\n ? yield* Fx.promise(() =>\n ctx.runQuery(config.component.public.enterpriseScimIdentityGet, {\n enterpriseId,\n resourceType: \"user\",\n externalId: providerAccountId,\n }),\n )\n : null;\n\n const verifier = yield* Fx.from({\n ok: () => db.verifiers.getBySignature(signature),\n err: () => new AuthError(\"OAUTH_INVALID_STATE\"),\n }).pipe(\n Fx.chain((doc) =>\n doc === null\n ? Fx.fail(new AuthError(\"OAUTH_INVALID_STATE\"))\n : Fx.succeed(doc),\n ),\n );\n\n const { accountId } = yield* Fx.promise(() =>\n upsertUserAndAccount(\n ctx,\n verifier.sessionId ?? null,\n existingAccount !== null ? { existingAccount } : { providerAccountId },\n {\n type: \"oauth\",\n provider: (isEnterpriseProviderId(provider)\n ? createSyntheticOAuthMaterializedConfig(provider, {\n accountLinking:\n enterpriseProtocol === \"oidc\"\n ? enterprisePolicy?.identity.accountLinking.oidc\n : enterpriseProtocol === \"saml\"\n ? enterprisePolicy?.identity.accountLinking.saml\n : undefined,\n })\n : getProviderOrThrow(provider)) as AuthProviderMaterializedConfig,\n profile,\n accountExtend: normalizeAccountExtend(\n provider,\n providerAccountId,\n accountExtend,\n ),\n },\n config,\n existingScimIdentity?.userId\n ? { existingUserId: existingScimIdentity.userId }\n : undefined,\n ),\n );\n\n // JIT group provisioning: if this is an enterprise SSO sign-in and the\n // enterprise connection has a groupId, auto-add the user as a member of\n // that group if they aren't already a member.\n if (\n enterpriseId !== null &&\n enterprisePolicy?.provisioning.jit.mode === \"createUserAndMembership\"\n ) {\n const account = yield* Fx.promise(() => db.accounts.getById(accountId));\n const userId = account?.userId;\n if (userId) {\n const groupId = (enterprise as any)?.groupId as string | undefined;\n if (groupId) {\n const existingMembership = yield* Fx.promise(() =>\n ctx.runQuery(config.component.public.memberGetByGroupAndUser, {\n userId,\n groupId,\n }),\n );\n if (existingMembership === null) {\n yield* Fx.promise(() =>\n ctx.runMutation(config.component.public.memberAdd, {\n groupId,\n userId,\n roleIds: enterprisePolicy.provisioning.jit.defaultRoleIds,\n status: \"active\",\n }),\n );\n }\n }\n }\n }\n\n const code = generateRandomString(8, \"0123456789\");\n yield* Fx.promise(() => db.verifiers.delete(verifier._id));\n const existingVerificationCode = yield* Fx.promise(() =>\n db.verificationCodes.getByAccountId(accountId),\n );\n if (existingVerificationCode !== null) {\n yield* Fx.promise(() =>\n db.verificationCodes.delete(existingVerificationCode._id),\n );\n }\n yield* Fx.promise(async () =>\n db.verificationCodes.create({\n code: await sha256(code),\n accountId,\n provider,\n expirationTime: Date.now() + OAUTH_SIGN_IN_EXPIRATION_MS,\n verifier: verifier._id,\n }),\n );\n return code;\n });\n}\n\nexport const callUserOAuth = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof userOAuthArgs>,\n): Promise<ReturnType> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"userOAuth\",\n ...args,\n },\n });\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { logWithLevel, maybeRedact } from "../utils.js";
|
|
2
|
+
import { authDb } from "../db.js";
|
|
3
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
4
|
+
import { REFRESH_TOKEN_REUSE_WINDOW_MS, invalidateRefreshTokensInSubtree, parseRefreshToken, refreshTokenIfValid } from "../refresh.js";
|
|
5
|
+
import { generateTokensForSession } from "../sessions.js";
|
|
6
|
+
import { v } from "convex/values";
|
|
7
|
+
import { Fx } from "@robelest/fx";
|
|
8
|
+
|
|
9
|
+
//#region src/server/mutations/refresh.ts
|
|
10
|
+
const refreshSessionArgs = v.object({ refreshToken: v.string() });
|
|
11
|
+
/** A soft refresh failure — logged and collapsed to null at the boundary. */
|
|
12
|
+
var RefreshFailure = class {
|
|
13
|
+
_tag = "RefreshFailure";
|
|
14
|
+
constructor(reason) {
|
|
15
|
+
this.reason = reason;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
async function refreshSessionImpl(ctx, args, _getProviderOrThrow, config) {
|
|
19
|
+
const db = authDb(ctx, config);
|
|
20
|
+
const { refreshToken } = args;
|
|
21
|
+
return Fx.run(parseRefreshToken(refreshToken).pipe(Fx.recover((err) => Fx.fail(new RefreshFailure(err.message))), Fx.tap(({ refreshTokenId, sessionId: tokenSessionId }) => Fx.sync(() => logWithLevel("DEBUG", `refreshSessionImpl args: Token ID: ${maybeRedact(refreshTokenId)} Session ID: ${maybeRedact(tokenSessionId)}`))), Fx.chain(({ refreshTokenId, sessionId: tokenSessionId }) => refreshTokenIfValid(ctx, refreshTokenId, tokenSessionId, config).pipe(Fx.chain((validationResult) => validationResult === null ? Fx.gen(function* () {
|
|
22
|
+
yield* Fx.from({
|
|
23
|
+
ok: async () => {
|
|
24
|
+
const session = await db.sessions.getById(tokenSessionId);
|
|
25
|
+
if (session !== null) await db.sessions.delete(session._id);
|
|
26
|
+
},
|
|
27
|
+
err: () => new RefreshFailure("Skipping invalid session id during refresh cleanup")
|
|
28
|
+
}).pipe(Fx.recover((f) => {
|
|
29
|
+
logWithLevel("DEBUG", f.reason);
|
|
30
|
+
return Fx.succeed(void 0);
|
|
31
|
+
}));
|
|
32
|
+
yield* Fx.from({
|
|
33
|
+
ok: () => authDb(ctx, config).refreshTokens.deleteAll(tokenSessionId),
|
|
34
|
+
err: () => new RefreshFailure("Skipping invalid token session id during refresh token cleanup")
|
|
35
|
+
}).pipe(Fx.recover((f) => {
|
|
36
|
+
logWithLevel("DEBUG", f.reason);
|
|
37
|
+
return Fx.succeed(void 0);
|
|
38
|
+
}));
|
|
39
|
+
return null;
|
|
40
|
+
}) : (() => {
|
|
41
|
+
const { session } = validationResult;
|
|
42
|
+
const sessionId = session._id;
|
|
43
|
+
const userId = session.userId;
|
|
44
|
+
const tokenFirstUsed = validationResult.refreshTokenDoc.firstUsedTime;
|
|
45
|
+
return tokenFirstUsed === void 0 ? Fx.from({
|
|
46
|
+
ok: async () => {
|
|
47
|
+
await db.refreshTokens.patch(refreshTokenId, { firstUsedTime: Date.now() });
|
|
48
|
+
const result = await generateTokensForSession(ctx, config, {
|
|
49
|
+
userId,
|
|
50
|
+
sessionId,
|
|
51
|
+
issuedRefreshTokenId: null,
|
|
52
|
+
parentRefreshTokenId: refreshTokenId
|
|
53
|
+
});
|
|
54
|
+
const { refreshTokenId: newRefreshTokenId } = await Fx.run(parseRefreshToken(result.refreshToken));
|
|
55
|
+
logWithLevel("DEBUG", `Exchanged ${maybeRedact(validationResult.refreshTokenDoc._id)} (first use) for new refresh token ${maybeRedact(newRefreshTokenId)}`);
|
|
56
|
+
return result;
|
|
57
|
+
},
|
|
58
|
+
err: () => new RefreshFailure("Failed during first-use token exchange")
|
|
59
|
+
}) : Fx.from({
|
|
60
|
+
ok: () => authDb(ctx, config).refreshTokens.getActive(tokenSessionId),
|
|
61
|
+
err: () => new RefreshFailure("Failed to load active refresh token")
|
|
62
|
+
}).pipe(Fx.chain((activeRefreshToken) => {
|
|
63
|
+
logWithLevel("DEBUG", `Active refresh token: ${maybeRedact(activeRefreshToken?._id ?? "(none)")}, parent ${maybeRedact(activeRefreshToken?.parentRefreshTokenId ?? "(none)")}`);
|
|
64
|
+
const reuseDispatch = activeRefreshToken !== null && activeRefreshToken.parentRefreshTokenId === refreshTokenId ? {
|
|
65
|
+
tag: "parentOfActive",
|
|
66
|
+
activeRefreshToken
|
|
67
|
+
} : tokenFirstUsed + REFRESH_TOKEN_REUSE_WINDOW_MS > Date.now() ? { tag: "withinReuseWindow" } : { tag: "outsideReuseWindow" };
|
|
68
|
+
if (reuseDispatch.tag === "parentOfActive") return Fx.from({
|
|
69
|
+
ok: () => generateTokensForSession(ctx, config, {
|
|
70
|
+
userId,
|
|
71
|
+
sessionId,
|
|
72
|
+
issuedRefreshTokenId: reuseDispatch.activeRefreshToken._id,
|
|
73
|
+
parentRefreshTokenId: refreshTokenId
|
|
74
|
+
}),
|
|
75
|
+
err: () => new RefreshFailure("Failed to generate tokens for parent reuse")
|
|
76
|
+
}).pipe(Fx.tap(() => Fx.sync(() => logWithLevel("DEBUG", `Token ${maybeRedact(validationResult.refreshTokenDoc._id)} is parent of active refresh token ${maybeRedact(reuseDispatch.activeRefreshToken._id)}, so returning that token`))));
|
|
77
|
+
if (reuseDispatch.tag === "withinReuseWindow") return Fx.from({
|
|
78
|
+
ok: async () => {
|
|
79
|
+
const result = await generateTokensForSession(ctx, config, {
|
|
80
|
+
userId,
|
|
81
|
+
sessionId,
|
|
82
|
+
issuedRefreshTokenId: null,
|
|
83
|
+
parentRefreshTokenId: refreshTokenId
|
|
84
|
+
});
|
|
85
|
+
const { refreshTokenId: newRefreshTokenId } = await Fx.run(parseRefreshToken(result.refreshToken));
|
|
86
|
+
logWithLevel("DEBUG", `Exchanged ${maybeRedact(validationResult.refreshTokenDoc._id)} (reuse) for new refresh token ${maybeRedact(newRefreshTokenId)}`);
|
|
87
|
+
return result;
|
|
88
|
+
},
|
|
89
|
+
err: () => new RefreshFailure("Failed to generate tokens for reuse window")
|
|
90
|
+
});
|
|
91
|
+
logWithLevel("ERROR", "Refresh token used outside of reuse window");
|
|
92
|
+
logWithLevel("DEBUG", `Token ${maybeRedact(validationResult.refreshTokenDoc._id)} being used outside of reuse window, so invalidating all refresh tokens in subtree`);
|
|
93
|
+
return Fx.from({
|
|
94
|
+
ok: async () => {
|
|
95
|
+
const tokensToInvalidate = await invalidateRefreshTokensInSubtree(ctx, validationResult.refreshTokenDoc, config);
|
|
96
|
+
logWithLevel("DEBUG", `Invalidated ${tokensToInvalidate.length} refresh tokens in subtree: ${tokensToInvalidate.map((token) => maybeRedact(token._id)).join(", ")}`);
|
|
97
|
+
return null;
|
|
98
|
+
},
|
|
99
|
+
err: () => new RefreshFailure("Failed to invalidate refresh tokens in subtree")
|
|
100
|
+
});
|
|
101
|
+
}));
|
|
102
|
+
})()))), Fx.fold({
|
|
103
|
+
ok: (result) => result,
|
|
104
|
+
err: (failure) => {
|
|
105
|
+
logWithLevel("DEBUG", failure.reason);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
})));
|
|
109
|
+
}
|
|
110
|
+
const callRefreshSession = async (ctx, args) => {
|
|
111
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
112
|
+
type: "refreshSession",
|
|
113
|
+
...args
|
|
114
|
+
} });
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
export { callRefreshSession, refreshSessionArgs, refreshSessionImpl };
|
|
119
|
+
//# sourceMappingURL=refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh.js","names":[],"sources":["../../../../src/server/mutations/refresh.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport * as Provider from \"../crypto\";\nimport {\n invalidateRefreshTokensInSubtree,\n parseRefreshToken,\n REFRESH_TOKEN_REUSE_WINDOW_MS,\n refreshTokenIfValid,\n} from \"../refresh\";\nimport { generateTokensForSession } from \"../sessions\";\nimport { MutationCtx } from \"../types\";\nimport { logWithLevel, maybeRedact } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const refreshSessionArgs = v.object({\n refreshToken: v.string(),\n});\n\ntype RefreshResult = null | {\n token: string;\n refreshToken: string;\n};\n\n// ============================================================================\n// Small helpers for the refresh pipeline\n// ============================================================================\n\n/** A soft refresh failure — logged and collapsed to null at the boundary. */\nclass RefreshFailure {\n readonly _tag = \"RefreshFailure\" as const;\n constructor(readonly reason: string) {}\n}\n\n// ============================================================================\n// Main exported function\n// ============================================================================\n\nexport async function refreshSessionImpl(\n ctx: MutationCtx,\n args: Infer<typeof refreshSessionArgs>,\n _getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n config: Provider.Config,\n): Promise<RefreshResult> {\n const db = authDb(ctx, config);\n const { refreshToken } = args;\n\n return Fx.run(\n parseRefreshToken(refreshToken).pipe(\n Fx.recover((err: AuthError) => Fx.fail(new RefreshFailure(err.message))),\n Fx.tap(({ refreshTokenId, sessionId: tokenSessionId }) =>\n Fx.sync(() =>\n logWithLevel(\n \"DEBUG\",\n `refreshSessionImpl args: Token ID: ${maybeRedact(refreshTokenId)} Session ID: ${maybeRedact(tokenSessionId)}`,\n ),\n ),\n ),\n Fx.chain(({ refreshTokenId, sessionId: tokenSessionId }) =>\n refreshTokenIfValid(ctx, refreshTokenId, tokenSessionId, config).pipe(\n Fx.chain((validationResult) =>\n validationResult === null\n ? Fx.gen(function* () {\n yield* Fx.from({\n ok: async () => {\n const session = await (db as any).sessions.getById(\n tokenSessionId,\n );\n if (session !== null) {\n await (db as any).sessions.delete(session._id);\n }\n },\n err: () =>\n new RefreshFailure(\n \"Skipping invalid session id during refresh cleanup\",\n ),\n }).pipe(\n Fx.recover((f) => {\n logWithLevel(\"DEBUG\", f.reason);\n return Fx.succeed(undefined as void);\n }),\n );\n\n yield* Fx.from({\n ok: () =>\n authDb(ctx, config).refreshTokens.deleteAll(\n tokenSessionId as any,\n ),\n err: () =>\n new RefreshFailure(\n \"Skipping invalid token session id during refresh token cleanup\",\n ),\n }).pipe(\n Fx.recover((f) => {\n logWithLevel(\"DEBUG\", f.reason);\n return Fx.succeed(undefined as void);\n }),\n );\n\n return null;\n })\n : (() => {\n const { session } = validationResult;\n const sessionId = session._id;\n const userId = session.userId;\n const tokenFirstUsed =\n validationResult.refreshTokenDoc.firstUsedTime;\n return tokenFirstUsed === undefined\n ? Fx.from({\n ok: async () => {\n await (db as any).refreshTokens.patch(\n refreshTokenId,\n {\n firstUsedTime: Date.now(),\n },\n );\n const result = await generateTokensForSession(\n ctx,\n config,\n {\n userId,\n sessionId,\n issuedRefreshTokenId: null,\n parentRefreshTokenId: refreshTokenId as any,\n },\n );\n const { refreshTokenId: newRefreshTokenId } =\n await Fx.run(\n parseRefreshToken(result.refreshToken),\n );\n logWithLevel(\n \"DEBUG\",\n `Exchanged ${maybeRedact(validationResult.refreshTokenDoc._id)} (first use) for new refresh token ${maybeRedact(newRefreshTokenId)}`,\n );\n return result;\n },\n err: () =>\n new RefreshFailure(\n \"Failed during first-use token exchange\",\n ),\n })\n : Fx.from({\n ok: () =>\n authDb(ctx, config).refreshTokens.getActive(\n tokenSessionId as any,\n ),\n err: () =>\n new RefreshFailure(\n \"Failed to load active refresh token\",\n ),\n }).pipe(\n Fx.chain((activeRefreshToken) => {\n logWithLevel(\n \"DEBUG\",\n `Active refresh token: ${maybeRedact(activeRefreshToken?._id ?? \"(none)\")}, parent ${maybeRedact(activeRefreshToken?.parentRefreshTokenId ?? \"(none)\")}`,\n );\n\n const reuseDispatch =\n activeRefreshToken !== null &&\n activeRefreshToken.parentRefreshTokenId ===\n refreshTokenId\n ? ({\n tag: \"parentOfActive\",\n activeRefreshToken,\n } as const)\n : tokenFirstUsed + REFRESH_TOKEN_REUSE_WINDOW_MS >\n Date.now()\n ? ({ tag: \"withinReuseWindow\" } as const)\n : ({ tag: \"outsideReuseWindow\" } as const);\n\n if (reuseDispatch.tag === \"parentOfActive\") {\n return Fx.from({\n ok: () =>\n generateTokensForSession(ctx, config, {\n userId,\n sessionId,\n issuedRefreshTokenId:\n reuseDispatch.activeRefreshToken._id,\n parentRefreshTokenId: refreshTokenId as any,\n }),\n err: () =>\n new RefreshFailure(\n \"Failed to generate tokens for parent reuse\",\n ),\n }).pipe(\n Fx.tap(() =>\n Fx.sync(() =>\n logWithLevel(\n \"DEBUG\",\n `Token ${maybeRedact(validationResult.refreshTokenDoc._id)} is parent of active refresh token ${maybeRedact(reuseDispatch.activeRefreshToken._id)}, so returning that token`,\n ),\n ),\n ),\n );\n }\n\n if (reuseDispatch.tag === \"withinReuseWindow\") {\n return Fx.from({\n ok: async () => {\n const result = await generateTokensForSession(\n ctx,\n config,\n {\n userId,\n sessionId,\n issuedRefreshTokenId: null,\n parentRefreshTokenId: refreshTokenId as any,\n },\n );\n const { refreshTokenId: newRefreshTokenId } =\n await Fx.run(\n parseRefreshToken(result.refreshToken),\n );\n logWithLevel(\n \"DEBUG\",\n `Exchanged ${maybeRedact(validationResult.refreshTokenDoc._id)} (reuse) for new refresh token ${maybeRedact(newRefreshTokenId)}`,\n );\n return result;\n },\n err: () =>\n new RefreshFailure(\n \"Failed to generate tokens for reuse window\",\n ),\n });\n }\n\n logWithLevel(\n \"ERROR\",\n \"Refresh token used outside of reuse window\",\n );\n logWithLevel(\n \"DEBUG\",\n `Token ${maybeRedact(validationResult.refreshTokenDoc._id)} being used outside of reuse window, so invalidating all refresh tokens in subtree`,\n );\n return Fx.from({\n ok: async () => {\n const tokensToInvalidate =\n await invalidateRefreshTokensInSubtree(\n ctx,\n validationResult.refreshTokenDoc,\n config,\n );\n logWithLevel(\n \"DEBUG\",\n `Invalidated ${tokensToInvalidate.length} refresh tokens in subtree: ${tokensToInvalidate\n .map((token) => maybeRedact(token._id))\n .join(\", \")}`,\n );\n return null;\n },\n err: () =>\n new RefreshFailure(\n \"Failed to invalidate refresh tokens in subtree\",\n ),\n });\n }),\n );\n })(),\n ),\n ),\n ),\n Fx.fold({\n ok: (result) => result,\n err: (failure) => {\n logWithLevel(\"DEBUG\", failure.reason);\n return null;\n },\n }),\n ),\n );\n}\n\n// ============================================================================\n// Invalid token path — cleanup session and refresh tokens\n// ============================================================================\n\n// ============================================================================\n// Valid token path — dispatch on first-use / parent / reuse-window / stale\n// ============================================================================\n\n// ============================================================================\n// Action-level caller (unchanged — just forwards to mutation)\n// ============================================================================\n\nexport const callRefreshSession = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof refreshSessionArgs>,\n): Promise<RefreshResult> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"refreshSession\",\n ...args,\n },\n });\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
|
+
import { LOG_LEVELS, logWithLevel, maybeRedact } from "../utils.js";
|
|
3
|
+
import { authDb } from "../db.js";
|
|
4
|
+
import { hash, verify } from "../crypto.js";
|
|
5
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
6
|
+
import { getAuthSessionId } from "../sessions.js";
|
|
7
|
+
import { upsertUserAndAccount } from "../users.js";
|
|
8
|
+
import { v } from "convex/values";
|
|
9
|
+
import { Fx } from "@robelest/fx";
|
|
10
|
+
|
|
11
|
+
//#region src/server/mutations/register.ts
|
|
12
|
+
const createAccountFromCredentialsArgs = v.object({
|
|
13
|
+
provider: v.string(),
|
|
14
|
+
account: v.object({
|
|
15
|
+
id: v.string(),
|
|
16
|
+
secret: v.optional(v.string())
|
|
17
|
+
}),
|
|
18
|
+
profile: v.any(),
|
|
19
|
+
shouldLinkViaEmail: v.optional(v.boolean()),
|
|
20
|
+
shouldLinkViaPhone: v.optional(v.boolean())
|
|
21
|
+
});
|
|
22
|
+
async function createAccountFromCredentialsImpl(ctx, args, getProviderOrThrow, config) {
|
|
23
|
+
logWithLevel(LOG_LEVELS.DEBUG, "createAccountFromCredentialsImpl args:", {
|
|
24
|
+
provider: args.provider,
|
|
25
|
+
account: {
|
|
26
|
+
id: args.account.id,
|
|
27
|
+
secret: maybeRedact(args.account.secret ?? "")
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const { provider: providerId, account, profile, shouldLinkViaEmail, shouldLinkViaPhone } = args;
|
|
31
|
+
const db = authDb(ctx, config);
|
|
32
|
+
const provider = getProviderOrThrow(providerId);
|
|
33
|
+
return Fx.run(Fx.from({
|
|
34
|
+
ok: () => db.accounts.get(provider.id, account.id),
|
|
35
|
+
err: () => new AuthError("INTERNAL_ERROR", "Failed to look up account")
|
|
36
|
+
}).pipe(Fx.chain((existingAccount) => {
|
|
37
|
+
if (existingAccount !== null) return (account.secret !== void 0 ? verify(provider, account.secret, existingAccount.secret ?? "").pipe(Fx.chain((valid) => valid ? Fx.succeed(void 0) : Fx.fail(new AuthError("ACCOUNT_ALREADY_EXISTS", `Account ${account.id} already exists`)))) : Fx.succeed(void 0)).pipe(Fx.chain(() => Fx.from({
|
|
38
|
+
ok: () => db.users.getById(existingAccount.userId),
|
|
39
|
+
err: () => new AuthError("ACCOUNT_NOT_FOUND", `Linked user for account ${account.id} was not found.`)
|
|
40
|
+
}).pipe(Fx.chain((doc) => doc === null ? Fx.fail(new AuthError("ACCOUNT_NOT_FOUND", `Linked user for account ${account.id} was not found.`)) : Fx.succeed(doc)))), Fx.map((user) => ({
|
|
41
|
+
account: existingAccount,
|
|
42
|
+
user
|
|
43
|
+
})));
|
|
44
|
+
return (account.secret !== void 0 ? hash(provider, account.secret) : Fx.succeed(void 0)).pipe(Fx.chain((secret) => Fx.from({
|
|
45
|
+
ok: async () => upsertUserAndAccount(ctx, await getAuthSessionId(ctx), {
|
|
46
|
+
providerAccountId: account.id,
|
|
47
|
+
secret
|
|
48
|
+
}, {
|
|
49
|
+
type: "credentials",
|
|
50
|
+
provider,
|
|
51
|
+
profile,
|
|
52
|
+
shouldLinkViaEmail,
|
|
53
|
+
shouldLinkViaPhone
|
|
54
|
+
}, config),
|
|
55
|
+
err: () => new AuthError("INTERNAL_ERROR")
|
|
56
|
+
})), Fx.chain((result) => {
|
|
57
|
+
const { userId, accountId } = result;
|
|
58
|
+
return Fx.zip(Fx.from({
|
|
59
|
+
ok: () => db.accounts.getById(accountId),
|
|
60
|
+
err: () => new AuthError("INTERNAL_ERROR")
|
|
61
|
+
}), Fx.from({
|
|
62
|
+
ok: () => db.users.getById(userId),
|
|
63
|
+
err: () => new AuthError("INTERNAL_ERROR")
|
|
64
|
+
}));
|
|
65
|
+
}), Fx.chain((pair) => {
|
|
66
|
+
const [createdAccount, createdUser] = pair;
|
|
67
|
+
return createdAccount === null ? Fx.fail(new AuthError("ACCOUNT_NOT_FOUND", `Created account was not found.`)) : createdUser === null ? Fx.fail(new AuthError("USER_UPDATE_FAILED", `Created user was not found.`)) : Fx.succeed({
|
|
68
|
+
account: createdAccount,
|
|
69
|
+
user: createdUser
|
|
70
|
+
});
|
|
71
|
+
}));
|
|
72
|
+
}), Fx.recover((e) => Fx.fatal(e.toConvexError()))));
|
|
73
|
+
}
|
|
74
|
+
const callCreateAccountFromCredentials = async (ctx, args) => {
|
|
75
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
76
|
+
type: "createAccountFromCredentials",
|
|
77
|
+
...args
|
|
78
|
+
} });
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
export { callCreateAccountFromCredentials, createAccountFromCredentialsArgs, createAccountFromCredentialsImpl };
|
|
83
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","names":["Provider.verify","Provider.hash"],"sources":["../../../../src/server/mutations/register.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport * as Provider from \"../crypto\";\nimport { getAuthSessionId } from \"../sessions\";\nimport { Doc, MutationCtx } from \"../types\";\nimport { ConvexCredentialsConfig } from \"../types\";\nimport { upsertUserAndAccount } from \"../users\";\nimport { LOG_LEVELS, logWithLevel, maybeRedact } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const createAccountFromCredentialsArgs = v.object({\n provider: v.string(),\n account: v.object({ id: v.string(), secret: v.optional(v.string()) }),\n profile: v.any(),\n shouldLinkViaEmail: v.optional(v.boolean()),\n shouldLinkViaPhone: v.optional(v.boolean()),\n});\n\ntype ReturnType = { account: Doc<\"Account\">; user: Doc<\"User\"> };\n\nexport async function createAccountFromCredentialsImpl(\n ctx: MutationCtx,\n args: Infer<typeof createAccountFromCredentialsArgs>,\n getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n config: Provider.Config,\n): Promise<ReturnType> {\n logWithLevel(LOG_LEVELS.DEBUG, \"createAccountFromCredentialsImpl args:\", {\n provider: args.provider,\n account: {\n id: args.account.id,\n secret: maybeRedact(args.account.secret ?? \"\"),\n },\n });\n\n const {\n provider: providerId,\n account,\n profile,\n shouldLinkViaEmail,\n shouldLinkViaPhone,\n } = args;\n const db = authDb(ctx, config);\n const provider = getProviderOrThrow(providerId) as ConvexCredentialsConfig;\n\n return Fx.run(\n Fx.from({\n ok: () =>\n db.accounts.get(\n provider.id,\n account.id,\n ) as Promise<Doc<\"Account\"> | null>,\n err: () => new AuthError(\"INTERNAL_ERROR\", \"Failed to look up account\"),\n }).pipe(\n Fx.chain((existingAccount) => {\n if (existingAccount !== null) {\n const verifyExistingAccountFx =\n account.secret !== undefined\n ? Provider.verify(\n provider,\n account.secret,\n existingAccount.secret ?? \"\",\n ).pipe(\n Fx.chain((valid) =>\n valid\n ? Fx.succeed(undefined)\n : Fx.fail(\n new AuthError(\n \"ACCOUNT_ALREADY_EXISTS\",\n `Account ${account.id} already exists`,\n ),\n ),\n ),\n )\n : Fx.succeed(undefined);\n\n return verifyExistingAccountFx.pipe(\n Fx.chain(() =>\n Fx.from({\n ok: () =>\n db.users.getById(\n existingAccount.userId,\n ) as Promise<Doc<\"User\"> | null>,\n err: () =>\n new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n `Linked user for account ${account.id} was not found.`,\n ),\n }).pipe(\n Fx.chain((doc) =>\n doc === null\n ? Fx.fail(\n new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n `Linked user for account ${account.id} was not found.`,\n ),\n )\n : Fx.succeed(doc),\n ),\n ),\n ),\n Fx.map((user) => ({\n account: existingAccount,\n user,\n })),\n );\n }\n\n const secretFx: Fx<string | undefined, AuthError> =\n account.secret !== undefined\n ? Provider.hash(provider, account.secret)\n : Fx.succeed<string | undefined>(undefined);\n\n return secretFx.pipe(\n Fx.chain((secret) =>\n Fx.from({\n ok: async () =>\n upsertUserAndAccount(\n ctx,\n await getAuthSessionId(ctx),\n { providerAccountId: account.id, secret },\n {\n type: \"credentials\",\n provider,\n profile,\n shouldLinkViaEmail,\n shouldLinkViaPhone,\n },\n config,\n ),\n err: () => new AuthError(\"INTERNAL_ERROR\"),\n }),\n ),\n Fx.chain((result) => {\n const { userId, accountId } = result as {\n userId: string;\n accountId: string;\n };\n return Fx.zip(\n Fx.from({\n ok: () =>\n db.accounts.getById(\n accountId,\n ) as Promise<Doc<\"Account\"> | null>,\n err: () => new AuthError(\"INTERNAL_ERROR\"),\n }),\n Fx.from({\n ok: () =>\n db.users.getById(userId) as Promise<Doc<\"User\"> | null>,\n err: () => new AuthError(\"INTERNAL_ERROR\"),\n }),\n );\n }),\n Fx.chain((pair) => {\n const [createdAccount, createdUser] = pair as [\n Doc<\"Account\"> | null,\n Doc<\"User\"> | null,\n ];\n return createdAccount === null\n ? Fx.fail(\n new AuthError(\n \"ACCOUNT_NOT_FOUND\",\n `Created account was not found.`,\n ),\n )\n : createdUser === null\n ? Fx.fail(\n new AuthError(\n \"USER_UPDATE_FAILED\",\n `Created user was not found.`,\n ),\n )\n : Fx.succeed({\n account: createdAccount,\n user: createdUser,\n });\n }),\n );\n }),\n Fx.recover((e) => Fx.fatal((e as AuthError).toConvexError())),\n ),\n ) as Promise<ReturnType>;\n}\n\nexport const callCreateAccountFromCredentials = async <\n DataModel extends GenericDataModel,\n>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof createAccountFromCredentialsArgs>,\n): Promise<ReturnType> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"createAccountFromCredentials\",\n ...args,\n },\n });\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
|
+
import { LOG_LEVELS, logWithLevel, maybeRedact } from "../utils.js";
|
|
3
|
+
import { authDb } from "../db.js";
|
|
4
|
+
import { verify } from "../crypto.js";
|
|
5
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
6
|
+
import { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit } from "../limits.js";
|
|
7
|
+
import { v } from "convex/values";
|
|
8
|
+
import { Fx } from "@robelest/fx";
|
|
9
|
+
|
|
10
|
+
//#region src/server/mutations/retrieve.ts
|
|
11
|
+
const retrieveAccountWithCredentialsArgs = v.object({
|
|
12
|
+
provider: v.string(),
|
|
13
|
+
account: v.object({
|
|
14
|
+
id: v.string(),
|
|
15
|
+
secret: v.optional(v.string())
|
|
16
|
+
})
|
|
17
|
+
});
|
|
18
|
+
function retrieveAccountWithCredentialsImpl(ctx, args, getProviderOrThrow, config) {
|
|
19
|
+
const { provider: providerId, account } = args;
|
|
20
|
+
const db = authDb(ctx, config);
|
|
21
|
+
logWithLevel(LOG_LEVELS.DEBUG, "retrieveAccountWithCredentialsImpl args:", {
|
|
22
|
+
provider: providerId,
|
|
23
|
+
account: {
|
|
24
|
+
id: account.id,
|
|
25
|
+
secret: maybeRedact(account.secret ?? "")
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return Fx.from({
|
|
29
|
+
ok: async () => {
|
|
30
|
+
const existingAccount = await db.accounts.get(providerId, account.id);
|
|
31
|
+
if (existingAccount === null) return "InvalidAccountId";
|
|
32
|
+
if (account.secret !== void 0) {
|
|
33
|
+
if (await Fx.run(isSignInRateLimited(ctx, existingAccount._id, config))) return "TooManyFailedAttempts";
|
|
34
|
+
if (!await Fx.run(verify(getProviderOrThrow(providerId), account.secret, existingAccount.secret ?? ""))) {
|
|
35
|
+
await Fx.run(recordFailedSignIn(ctx, existingAccount._id, config));
|
|
36
|
+
return "InvalidSecret";
|
|
37
|
+
}
|
|
38
|
+
await Fx.run(resetSignInRateLimit(ctx, existingAccount._id, config));
|
|
39
|
+
}
|
|
40
|
+
const user = await db.users.getById(existingAccount.userId);
|
|
41
|
+
if (user === null) {
|
|
42
|
+
logWithLevel(LOG_LEVELS.ERROR, `Account ${existingAccount._id} is linked to missing user ${existingAccount.userId}`);
|
|
43
|
+
return "InvalidAccountId";
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
account: existingAccount,
|
|
47
|
+
user
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
err: () => new AuthError("INTERNAL_ERROR", "Failed to look up account")
|
|
51
|
+
}).pipe(Fx.fold({
|
|
52
|
+
ok: (v$1) => v$1,
|
|
53
|
+
err: () => "InvalidAccountId"
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
const callRetrieveAccountWithCredentials = async (ctx, args) => {
|
|
57
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
58
|
+
type: "retrieveAccountWithCredentials",
|
|
59
|
+
...args
|
|
60
|
+
} });
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
export { callRetrieveAccountWithCredentials, retrieveAccountWithCredentialsArgs, retrieveAccountWithCredentialsImpl };
|
|
65
|
+
//# sourceMappingURL=retrieve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retrieve.js","names":["Provider.verify","v"],"sources":["../../../../src/server/mutations/retrieve.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport * as Provider from \"../crypto\";\nimport {\n isSignInRateLimited,\n recordFailedSignIn,\n resetSignInRateLimit,\n} from \"../limits\";\nimport { Doc, MutationCtx } from \"../types\";\nimport { LOG_LEVELS, logWithLevel, maybeRedact } from \"../utils\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const retrieveAccountWithCredentialsArgs = v.object({\n provider: v.string(),\n account: v.object({ id: v.string(), secret: v.optional(v.string()) }),\n});\n\ntype ReturnType =\n | \"InvalidAccountId\"\n | \"TooManyFailedAttempts\"\n | \"InvalidSecret\"\n | { account: Doc<\"Account\">; user: Doc<\"User\"> };\n\nexport function retrieveAccountWithCredentialsImpl(\n ctx: MutationCtx,\n args: Infer<typeof retrieveAccountWithCredentialsArgs>,\n getProviderOrThrow: Provider.GetProviderOrThrowFunc,\n config: Provider.Config,\n): Fx<ReturnType> {\n const { provider: providerId, account } = args;\n const db = authDb(ctx, config);\n\n logWithLevel(LOG_LEVELS.DEBUG, \"retrieveAccountWithCredentialsImpl args:\", {\n provider: providerId,\n account: { id: account.id, secret: maybeRedact(account.secret ?? \"\") },\n });\n\n return Fx.from({\n ok: async () => {\n const existingAccount = (await db.accounts.get(\n providerId,\n account.id,\n )) as Doc<\"Account\"> | null;\n if (existingAccount === null) {\n return \"InvalidAccountId\" as const;\n }\n\n if (account.secret !== undefined) {\n const limited = await Fx.run(\n isSignInRateLimited(ctx, existingAccount._id, config),\n );\n if (limited) {\n return \"TooManyFailedAttempts\" as const;\n }\n\n const valid = await Fx.run(\n Provider.verify(\n getProviderOrThrow(providerId),\n account.secret,\n existingAccount.secret ?? \"\",\n ),\n );\n if (!valid) {\n await Fx.run(recordFailedSignIn(ctx, existingAccount._id, config));\n return \"InvalidSecret\" as const;\n }\n\n await Fx.run(resetSignInRateLimit(ctx, existingAccount._id, config));\n }\n\n const user = (await db.users.getById(\n existingAccount.userId,\n )) as Doc<\"User\"> | null;\n if (user === null) {\n logWithLevel(\n LOG_LEVELS.ERROR,\n `Account ${existingAccount._id} is linked to missing user ${existingAccount.userId}`,\n );\n return \"InvalidAccountId\" as const;\n }\n\n return { account: existingAccount, user } as const;\n },\n err: () => new AuthError(\"INTERNAL_ERROR\", \"Failed to look up account\"),\n }).pipe(\n Fx.fold({\n ok: (v) => v as ReturnType,\n err: () => \"InvalidAccountId\" as ReturnType,\n }),\n );\n}\n\nexport const callRetrieveAccountWithCredentials = async <\n DataModel extends GenericDataModel,\n>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof retrieveAccountWithCredentialsArgs>,\n): Promise<ReturnType> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"retrieveAccountWithCredentials\",\n ...args,\n },\n });\n};\n"],"mappings":";;;;;;;;;;AAgBA,MAAa,qCAAqC,EAAE,OAAO;CACzD,UAAU,EAAE,QAAQ;CACpB,SAAS,EAAE,OAAO;EAAE,IAAI,EAAE,QAAQ;EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;EAAE,CAAC;CACtE,CAAC;AAQF,SAAgB,mCACd,KACA,MACA,oBACA,QACgB;CAChB,MAAM,EAAE,UAAU,YAAY,YAAY;CAC1C,MAAM,KAAK,OAAO,KAAK,OAAO;AAE9B,cAAa,WAAW,OAAO,4CAA4C;EACzE,UAAU;EACV,SAAS;GAAE,IAAI,QAAQ;GAAI,QAAQ,YAAY,QAAQ,UAAU,GAAG;GAAE;EACvE,CAAC;AAEF,QAAO,GAAG,KAAK;EACb,IAAI,YAAY;GACd,MAAM,kBAAmB,MAAM,GAAG,SAAS,IACzC,YACA,QAAQ,GACT;AACD,OAAI,oBAAoB,KACtB,QAAO;AAGT,OAAI,QAAQ,WAAW,QAAW;AAIhC,QAHgB,MAAM,GAAG,IACvB,oBAAoB,KAAK,gBAAgB,KAAK,OAAO,CACtD,CAEC,QAAO;AAUT,QAAI,CAPU,MAAM,GAAG,IACrBA,OACE,mBAAmB,WAAW,EAC9B,QAAQ,QACR,gBAAgB,UAAU,GAC3B,CACF,EACW;AACV,WAAM,GAAG,IAAI,mBAAmB,KAAK,gBAAgB,KAAK,OAAO,CAAC;AAClE,YAAO;;AAGT,UAAM,GAAG,IAAI,qBAAqB,KAAK,gBAAgB,KAAK,OAAO,CAAC;;GAGtE,MAAM,OAAQ,MAAM,GAAG,MAAM,QAC3B,gBAAgB,OACjB;AACD,OAAI,SAAS,MAAM;AACjB,iBACE,WAAW,OACX,WAAW,gBAAgB,IAAI,6BAA6B,gBAAgB,SAC7E;AACD,WAAO;;AAGT,UAAO;IAAE,SAAS;IAAiB;IAAM;;EAE3C,WAAW,IAAI,UAAU,kBAAkB,4BAA4B;EACxE,CAAC,CAAC,KACD,GAAG,KAAK;EACN,KAAK,QAAMC;EACX,WAAW;EACZ,CAAC,CACH;;AAGH,MAAa,qCAAqC,OAGhD,KACA,SACwB;AACxB,QAAO,IAAI,YAAY,gBAAgB,EACrC,MAAM;EACJ,MAAM;EACN,GAAG;EACJ,EACF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
|
+
import { authDb } from "../db.js";
|
|
3
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
4
|
+
import { v } from "convex/values";
|
|
5
|
+
import { Fx } from "@robelest/fx";
|
|
6
|
+
|
|
7
|
+
//#region src/server/mutations/signature.ts
|
|
8
|
+
const verifierSignatureArgs = v.object({
|
|
9
|
+
verifier: v.string(),
|
|
10
|
+
signature: v.string()
|
|
11
|
+
});
|
|
12
|
+
function verifierSignatureImpl(ctx, args, config) {
|
|
13
|
+
return Fx.gen(function* () {
|
|
14
|
+
const { verifier, signature } = args;
|
|
15
|
+
const db = authDb(ctx, config);
|
|
16
|
+
const verifierDoc = yield* Fx.from({
|
|
17
|
+
ok: () => db.verifiers.getById(verifier),
|
|
18
|
+
err: () => new AuthError("INVALID_VERIFIER")
|
|
19
|
+
}).pipe(Fx.chain((doc) => doc === null ? Fx.fail(new AuthError("INVALID_VERIFIER")) : Fx.succeed(doc)));
|
|
20
|
+
yield* Fx.promise(() => db.verifiers.patch(verifierDoc._id, { signature }));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const callVerifierSignature = async (ctx, args) => {
|
|
24
|
+
return ctx.runMutation(AUTH_STORE_REF, { args: {
|
|
25
|
+
type: "verifierSignature",
|
|
26
|
+
...args
|
|
27
|
+
} });
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { callVerifierSignature, verifierSignatureArgs, verifierSignatureImpl };
|
|
32
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.js","names":[],"sources":["../../../../src/server/mutations/signature.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport type { GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { GenericId, Infer, v } from \"convex/values\";\n\nimport { authDb } from \"../db\";\nimport { AuthError } from \"../authError\";\nimport * as Provider from \"../crypto\";\nimport { MutationCtx } from \"../types\";\nimport { AUTH_STORE_REF } from \"./store/refs\";\n\nexport const verifierSignatureArgs = v.object({\n verifier: v.string(),\n signature: v.string(),\n});\n\ntype ReturnType = void;\n\nexport function verifierSignatureImpl(\n ctx: MutationCtx,\n args: Infer<typeof verifierSignatureArgs>,\n config: Provider.Config,\n): Fx<ReturnType, AuthError> {\n return Fx.gen(function* () {\n const { verifier, signature } = args;\n const db = authDb(ctx, config);\n const verifierDoc = yield* Fx.from({\n ok: () => db.verifiers.getById(verifier as GenericId<\"AuthVerifier\">),\n err: () => new AuthError(\"INVALID_VERIFIER\"),\n }).pipe(\n Fx.chain((doc) =>\n doc === null\n ? Fx.fail(new AuthError(\"INVALID_VERIFIER\"))\n : Fx.succeed(doc),\n ),\n );\n yield* Fx.promise(() => db.verifiers.patch(verifierDoc._id, { signature }));\n });\n}\n\nexport const callVerifierSignature = async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: Infer<typeof verifierSignatureArgs>,\n): Promise<void> => {\n return ctx.runMutation(AUTH_STORE_REF, {\n args: {\n type: \"verifierSignature\",\n ...args,\n },\n });\n};\n"],"mappings":";;;;;;;AAUA,MAAa,wBAAwB,EAAE,OAAO;CAC5C,UAAU,EAAE,QAAQ;CACpB,WAAW,EAAE,QAAQ;CACtB,CAAC;AAIF,SAAgB,sBACd,KACA,MACA,QAC2B;AAC3B,QAAO,GAAG,IAAI,aAAa;EACzB,MAAM,EAAE,UAAU,cAAc;EAChC,MAAM,KAAK,OAAO,KAAK,OAAO;EAC9B,MAAM,cAAc,OAAO,GAAG,KAAK;GACjC,UAAU,GAAG,UAAU,QAAQ,SAAsC;GACrE,WAAW,IAAI,UAAU,mBAAmB;GAC7C,CAAC,CAAC,KACD,GAAG,OAAO,QACR,QAAQ,OACJ,GAAG,KAAK,IAAI,UAAU,mBAAmB,CAAC,GAC1C,GAAG,QAAQ,IAAI,CACpB,CACF;AACD,SAAO,GAAG,cAAc,GAAG,UAAU,MAAM,YAAY,KAAK,EAAE,WAAW,CAAC,CAAC;GAC3E;;AAGJ,MAAa,wBAAwB,OACnC,KACA,SACkB;AAClB,QAAO,IAAI,YAAY,gBAAgB,EACrC,MAAM;EACJ,MAAM;EACN,GAAG;EACJ,EACF,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { LOG_LEVELS, logWithLevel } from "../utils.js";
|
|
2
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
2
3
|
import { createNewAndDeleteExistingSession, maybeGenerateTokensForSession } from "../sessions.js";
|
|
3
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
4
4
|
import { v } from "convex/values";
|
|
5
5
|
|
|
6
|
-
//#region src/server/
|
|
6
|
+
//#region src/server/mutations/signin.ts
|
|
7
7
|
const signInArgs = v.object({
|
|
8
8
|
userId: v.string(),
|
|
9
9
|
sessionId: v.optional(v.string()),
|