@robelest/convex-auth 0.0.4-preview.18 → 0.0.4-preview.19
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 +6 -3
- package/dist/authorization/index.d.ts +46 -0
- package/dist/authorization/index.d.ts.map +1 -1
- package/dist/authorization/index.js +46 -0
- package/dist/authorization/index.js.map +1 -1
- package/dist/bin.cjs +21 -13
- 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 -16
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +67 -565
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +40 -12
- 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 +1306 -1344
- 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 -2
- package/dist/component/model.d.ts +80 -80
- package/dist/component/model.d.ts.map +1 -1
- package/dist/component/model.js +5 -1
- package/dist/component/model.js.map +1 -1
- package/dist/component/providers/credentials.d.ts +3 -2
- package/dist/component/providers/credentials.d.ts.map +1 -1
- package/dist/component/providers/email.d.ts +30 -0
- package/dist/component/providers/email.d.ts.map +1 -1
- package/dist/component/providers/phone.d.ts +28 -0
- package/dist/component/providers/phone.d.ts.map +1 -1
- 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 +22 -7
- package/dist/component/public.js +21 -6
- package/dist/component/schema.d.ts +288 -288
- package/dist/component/server/auth.d.ts +212 -25
- package/dist/component/server/auth.d.ts.map +1 -1
- package/dist/component/server/auth.js +68 -4
- 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} +2 -2
- package/dist/component/server/config.js.map +1 -0
- package/dist/component/server/{domains/core.js → core.js} +107 -88
- package/dist/component/server/core.js.map +1 -0
- package/dist/component/server/{provider.js → crypto.js} +3 -3
- package/dist/component/server/crypto.js.map +1 -0
- package/dist/component/server/device.js +1 -1
- package/dist/component/server/device.js.map +1 -1
- package/dist/component/server/enterprise/config.js +46 -0
- package/dist/component/server/enterprise/config.js.map +1 -0
- package/dist/component/server/{domains/sso.js → enterprise/domain.js} +6 -5
- 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.js.map +1 -1
- package/dist/component/server/http.js +2 -1
- package/dist/component/server/http.js.map +1 -1
- package/dist/component/server/identity.js +1 -1
- package/dist/component/server/identity.js.map +1 -1
- package/dist/component/server/{ratelimit.js → limits.js} +3 -3
- package/dist/component/server/limits.js.map +1 -0
- package/dist/component/server/mutations/account.js +3 -3
- package/dist/component/server/mutations/account.js.map +1 -1
- package/dist/component/server/mutations/code.js +2 -2
- package/dist/component/server/mutations/code.js.map +1 -1
- package/dist/component/server/mutations/invalidate.js +1 -1
- package/dist/component/server/mutations/invalidate.js.map +1 -1
- package/dist/component/server/mutations/oauth.js +5 -3
- package/dist/component/server/mutations/oauth.js.map +1 -1
- package/dist/component/server/mutations/refresh.js +1 -1
- package/dist/component/server/mutations/refresh.js.map +1 -1
- package/dist/component/server/mutations/register.js +3 -3
- package/dist/component/server/mutations/register.js.map +1 -1
- package/dist/component/server/mutations/retrieve.js +4 -4
- package/dist/component/server/mutations/retrieve.js.map +1 -1
- package/dist/component/server/mutations/signature.js +2 -2
- package/dist/component/server/mutations/signature.js.map +1 -1
- package/dist/component/server/mutations/signin.js +1 -1
- package/dist/component/server/mutations/signin.js.map +1 -1
- package/dist/component/server/mutations/signout.js +1 -1
- package/dist/component/server/mutations/signout.js.map +1 -1
- 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 +80 -10
- package/dist/component/server/mutations/store.js.map +1 -1
- package/dist/component/server/mutations/verifier.js +1 -1
- package/dist/component/server/mutations/verifier.js.map +1 -1
- package/dist/component/server/mutations/verify.js +4 -3
- package/dist/component/server/mutations/verify.js.map +1 -1
- package/dist/component/server/oauth.js +1 -1
- package/dist/component/server/oauth.js.map +1 -1
- package/dist/component/server/passkey.js +2 -1
- package/dist/component/server/passkey.js.map +1 -1
- package/dist/component/server/redirects.js +1 -1
- package/dist/component/server/redirects.js.map +1 -1
- package/dist/component/server/refresh.js +1 -1
- package/dist/component/server/refresh.js.map +1 -1
- package/dist/component/server/{factory.d.ts → runtime.d.ts} +2 -2
- 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/component/server/signin.js +2 -1
- package/dist/component/server/signin.js.map +1 -1
- package/dist/component/server/totp.js +2 -1
- package/dist/component/server/totp.js.map +1 -1
- package/dist/component/server/types.d.ts +225 -41
- package/dist/component/server/types.d.ts.map +1 -1
- package/dist/component/server/types.js.map +1 -1
- package/dist/component/server/users.js +1 -1
- package/dist/component/server/users.js.map +1 -1
- package/dist/component/server/utils.js +1 -1
- 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/credentials.d.ts +5 -2
- package/dist/providers/credentials.d.ts.map +1 -1
- package/dist/providers/credentials.js +2 -0
- package/dist/providers/credentials.js.map +1 -1
- package/dist/providers/email.d.ts +30 -0
- package/dist/providers/email.d.ts.map +1 -1
- package/dist/providers/email.js +24 -0
- package/dist/providers/email.js.map +1 -1
- package/dist/providers/phone.d.ts +28 -0
- package/dist/providers/phone.d.ts.map +1 -1
- package/dist/providers/phone.js +22 -0
- package/dist/providers/phone.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 +218 -28
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +68 -4
- package/dist/server/auth.js.map +1 -1
- package/dist/server/{fx.d.ts → authError.d.ts} +25 -15
- 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/{providers.js → config.js} +2 -2
- package/dist/server/config.js.map +1 -0
- package/dist/server/core.d.ts +1436 -0
- package/dist/server/core.d.ts.map +1 -0
- package/dist/server/{domains/core.js → core.js} +107 -88
- package/dist/server/core.js.map +1 -0
- package/dist/server/{provider.d.ts → crypto.d.ts} +2 -2
- package/dist/server/crypto.d.ts.map +1 -0
- package/dist/server/{provider.js → crypto.js} +3 -3
- package/dist/{component/server/provider.js.map → server/crypto.js.map} +1 -1
- package/dist/server/device.js +1 -1
- package/dist/server/device.js.map +1 -1
- package/dist/server/enterprise/config.js +46 -0
- package/dist/server/enterprise/config.js.map +1 -0
- package/dist/server/{domains/sso.d.ts → enterprise/domain.d.ts} +4 -4
- package/dist/server/enterprise/domain.d.ts.map +1 -0
- package/dist/server/{domains/sso.js → enterprise/domain.js} +6 -5
- 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.js +248 -0
- package/dist/server/enterprise/oidc.js.map +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/{enterpriseValidators.js → enterprise/validators.js} +2 -2
- package/dist/server/enterprise/validators.js.map +1 -0
- package/dist/server/errors.d.ts +2 -0
- package/dist/server/errors.d.ts.map +1 -1
- package/dist/server/errors.js +2 -0
- package/dist/server/errors.js.map +1 -1
- package/dist/server/http.d.ts +2 -2
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +2 -1
- package/dist/server/http.js.map +1 -1
- package/dist/server/identity.js +1 -1
- package/dist/server/identity.js.map +1 -1
- package/dist/server/index.d.ts +4 -705
- package/dist/server/index.js +4 -1367
- package/dist/server/limits.d.ts +1 -0
- package/dist/server/{ratelimit.js → limits.js} +3 -3
- 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 +8 -8
- package/dist/server/mutations/account.js +3 -3
- package/dist/server/mutations/account.js.map +1 -1
- package/dist/server/mutations/code.d.ts +13 -13
- package/dist/server/mutations/code.js +2 -2
- package/dist/server/mutations/code.js.map +1 -1
- package/dist/server/mutations/index.d.ts +8 -312
- package/dist/server/mutations/index.js +14 -84
- package/dist/server/mutations/invalidate.d.ts +5 -5
- package/dist/server/mutations/invalidate.d.ts.map +1 -1
- package/dist/server/mutations/invalidate.js +1 -1
- package/dist/server/mutations/invalidate.js.map +1 -1
- package/dist/server/mutations/oauth.d.ts +9 -9
- package/dist/server/mutations/oauth.d.ts.map +1 -1
- package/dist/server/mutations/oauth.js +5 -3
- package/dist/server/mutations/oauth.js.map +1 -1
- package/dist/server/mutations/refresh.d.ts +4 -4
- package/dist/server/mutations/refresh.js +1 -1
- package/dist/server/mutations/refresh.js.map +1 -1
- package/dist/server/mutations/register.d.ts +10 -10
- package/dist/server/mutations/register.d.ts.map +1 -1
- package/dist/server/mutations/register.js +3 -3
- package/dist/server/mutations/register.js.map +1 -1
- package/dist/server/mutations/retrieve.d.ts +8 -10
- package/dist/server/mutations/retrieve.d.ts.map +1 -1
- package/dist/server/mutations/retrieve.js +5 -7
- package/dist/server/mutations/retrieve.js.map +1 -1
- package/dist/server/mutations/signature.d.ts +6 -6
- package/dist/server/mutations/signature.d.ts.map +1 -1
- package/dist/server/mutations/signature.js +2 -2
- package/dist/server/mutations/signature.js.map +1 -1
- package/dist/server/mutations/signin.d.ts +1 -1
- package/dist/server/mutations/signin.js +1 -1
- package/dist/server/mutations/signin.js.map +1 -1
- package/dist/server/mutations/signout.d.ts +1 -1
- package/dist/server/mutations/signout.js +1 -1
- package/dist/server/mutations/signout.js.map +1 -1
- 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 +303 -9
- package/dist/server/mutations/store.d.ts.map +1 -1
- package/dist/server/mutations/store.js +80 -10
- package/dist/server/mutations/store.js.map +1 -1
- package/dist/server/mutations/verifier.d.ts +1 -1
- package/dist/server/mutations/verifier.js +1 -1
- package/dist/server/mutations/verifier.js.map +1 -1
- package/dist/server/mutations/verify.d.ts +8 -8
- package/dist/server/mutations/verify.d.ts.map +1 -1
- package/dist/server/mutations/verify.js +4 -3
- package/dist/server/mutations/verify.js.map +1 -1
- package/dist/server/oauth.js +1 -1
- package/dist/server/oauth.js.map +1 -1
- package/dist/server/passkey.d.ts +2 -2
- package/dist/server/passkey.d.ts.map +1 -1
- package/dist/server/passkey.js +3 -2
- package/dist/server/passkey.js.map +1 -1
- package/dist/server/redirects.js +1 -1
- package/dist/server/redirects.js.map +1 -1
- package/dist/server/refresh.js +1 -1
- package/dist/server/refresh.js.map +1 -1
- package/dist/server/{factory.d.ts → runtime.d.ts} +16 -16
- 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/signin.js +3 -2
- package/dist/server/signin.js.map +1 -1
- 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/totp.js +2 -1
- package/dist/server/totp.js.map +1 -1
- package/dist/server/types.d.ts +242 -42
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +12 -1
- package/dist/server/types.js.map +1 -1
- package/dist/server/users.js +1 -1
- package/dist/server/users.js.map +1 -1
- package/dist/server/utils.js +1 -1
- package/dist/server/utils.js.map +1 -1
- package/package.json +3 -4
- package/src/authorization/index.ts +46 -0
- package/src/cli/index.ts +38 -20
- 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 +133 -1267
- 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 +40 -12
- package/src/component/_generated/component.ts +1772 -1798
- package/src/component/model.ts +6 -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 +27 -5
- package/src/providers/credentials.ts +4 -5
- package/src/providers/email.ts +30 -0
- package/src/providers/phone.ts +28 -0
- package/src/server/auth.ts +282 -28
- package/src/server/authError.ts +44 -0
- package/src/server/core.ts +2095 -0
- package/src/server/{provider.ts → crypto.ts} +1 -1
- package/src/server/device.ts +1 -1
- package/src/server/enterprise/config.ts +51 -0
- package/src/server/{domains/sso.ts → enterprise/domain.ts} +4 -2
- 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/errors.ts +2 -0
- package/src/server/http.ts +3 -1
- package/src/server/identity.ts +1 -1
- package/src/server/index.ts +32 -2605
- package/src/server/{ratelimit.ts → limits.ts} +1 -1
- package/src/server/mounts.ts +948 -0
- package/src/server/mutations/account.ts +4 -4
- package/src/server/mutations/code.ts +3 -3
- package/src/server/mutations/index.ts +8 -148
- package/src/server/mutations/invalidate.ts +2 -2
- package/src/server/mutations/oauth.ts +8 -6
- package/src/server/mutations/refresh.ts +3 -3
- package/src/server/mutations/register.ts +3 -3
- package/src/server/mutations/retrieve.ts +4 -8
- package/src/server/mutations/signature.ts +3 -3
- package/src/server/mutations/signin.ts +2 -2
- package/src/server/mutations/signout.ts +2 -2
- package/src/server/mutations/store/refs.ts +10 -0
- package/src/server/mutations/store.ts +137 -9
- package/src/server/mutations/verifier.ts +2 -2
- package/src/server/mutations/verify.ts +5 -5
- package/src/server/oauth.ts +1 -1
- package/src/server/passkey.ts +3 -4
- package/src/server/redirects.ts +1 -1
- package/src/server/refresh.ts +1 -1
- package/src/server/runtime.ts +880 -0
- package/src/server/signin.ts +3 -1
- package/src/server/ssr.ts +1764 -0
- package/src/server/totp.ts +3 -1
- package/src/server/types.ts +254 -43
- package/src/server/users.ts +1 -1
- package/src/server/utils.ts +1 -1
- package/src/test.ts +25 -0
- package/dist/component/public/enterprise.d.ts +0 -54
- package/dist/component/public/enterprise.d.ts.map +0 -1
- package/dist/component/public/enterprise.js +0 -515
- package/dist/component/public/enterprise.js.map +0 -1
- package/dist/component/public/factors.d.ts +0 -52
- package/dist/component/public/factors.d.ts.map +0 -1
- package/dist/component/public/factors.js +0 -285
- package/dist/component/public/factors.js.map +0 -1
- package/dist/component/public/groups.d.ts +0 -124
- package/dist/component/public/groups.d.ts.map +0 -1
- package/dist/component/public/groups.js +0 -680
- package/dist/component/public/groups.js.map +0 -1
- package/dist/component/public/identity.d.ts +0 -93
- package/dist/component/public/identity.d.ts.map +0 -1
- package/dist/component/public/identity.js +0 -426
- package/dist/component/public/identity.js.map +0 -1
- package/dist/component/public/keys.d.ts +0 -41
- package/dist/component/public/keys.d.ts.map +0 -1
- package/dist/component/public/keys.js +0 -157
- package/dist/component/public/keys.js.map +0 -1
- package/dist/component/public/shared.d.ts +0 -26
- package/dist/component/public/shared.d.ts.map +0 -1
- package/dist/component/public/shared.js +0 -32
- package/dist/component/public/shared.js.map +0 -1
- package/dist/component/server/domains/core.js.map +0 -1
- package/dist/component/server/domains/sso.js.map +0 -1
- package/dist/component/server/factory.d.ts.map +0 -1
- package/dist/component/server/factory.js +0 -1134
- package/dist/component/server/factory.js.map +0 -1
- package/dist/component/server/fx.js +0 -66
- package/dist/component/server/fx.js.map +0 -1
- package/dist/component/server/mutations/index.js +0 -85
- package/dist/component/server/mutations/index.js.map +0 -1
- package/dist/component/server/providers.js.map +0 -1
- package/dist/component/server/ratelimit.js.map +0 -1
- package/dist/component/server/sso.js +0 -830
- package/dist/component/server/sso.js.map +0 -1
- package/dist/server/domains/core.d.ts +0 -449
- package/dist/server/domains/core.d.ts.map +0 -1
- package/dist/server/domains/core.js.map +0 -1
- package/dist/server/domains/sso.d.ts.map +0 -1
- package/dist/server/domains/sso.js.map +0 -1
- package/dist/server/enterpriseValidators.js.map +0 -1
- package/dist/server/factory.d.ts.map +0 -1
- package/dist/server/factory.js +0 -1134
- package/dist/server/factory.js.map +0 -1
- package/dist/server/fx.d.ts.map +0 -1
- package/dist/server/fx.js +0 -66
- package/dist/server/fx.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/mutations/index.d.ts.map +0 -1
- package/dist/server/mutations/index.js.map +0 -1
- package/dist/server/provider.d.ts.map +0 -1
- package/dist/server/provider.js.map +0 -1
- package/dist/server/providers.js.map +0 -1
- package/dist/server/ratelimit.js.map +0 -1
- package/dist/server/sso.js +0 -830
- package/dist/server/sso.js.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/component/public/enterprise.ts +0 -753
- package/src/component/public/factors.ts +0 -333
- package/src/component/public/groups.ts +0 -1066
- package/src/component/public/identity.ts +0 -569
- package/src/component/public/keys.ts +0 -209
- package/src/component/public/shared.ts +0 -119
- package/src/server/domains/core.ts +0 -1096
- package/src/server/factory.ts +0 -2181
- package/src/server/fx.ts +0 -152
- package/src/server/sso.ts +0 -1516
- package/src/server/version.ts +0 -2
- /package/dist/server/{enterpriseValidators.d.ts → config.d.ts} +0 -0
- /package/dist/server/{providers.d.ts → enterprise/config.d.ts} +0 -0
- /package/dist/server/{ratelimit.d.ts → enterprise/oidc.d.ts} +0 -0
- /package/dist/server/{sso.d.ts → enterprise/policy.d.ts} +0 -0
- /package/src/server/{providers.ts → config.ts} +0 -0
- /package/src/server/{enterpriseValidators.ts → enterprise/validators.ts} +0 -0
|
@@ -1,85 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { Fx } from "@robelest/fx";
|
|
15
|
-
import { v } from "convex/values";
|
|
1
|
+
import { callModifyAccount } from "./account.js";
|
|
2
|
+
import { callCreateVerificationCode } from "./code.js";
|
|
3
|
+
import { callInvalidateSessions } from "./invalidate.js";
|
|
4
|
+
import { callUserOAuth } from "./oauth.js";
|
|
5
|
+
import { callRefreshSession } from "./refresh.js";
|
|
6
|
+
import { callCreateAccountFromCredentials } from "./register.js";
|
|
7
|
+
import { callRetrieveAccountWithCredentials } from "./retrieve.js";
|
|
8
|
+
import { callVerifierSignature } from "./signature.js";
|
|
9
|
+
import { callSignIn } from "./signin.js";
|
|
10
|
+
import { callSignOut } from "./signout.js";
|
|
11
|
+
import { callVerifier } from "./verifier.js";
|
|
12
|
+
import { callVerifyCodeAndSignIn } from "./verify.js";
|
|
13
|
+
import { storeArgs, storeImpl } from "./store.js";
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
const storeArgs = v.object({ args: v.union(v.object({
|
|
19
|
-
type: v.literal("signIn"),
|
|
20
|
-
...signInArgs.fields
|
|
21
|
-
}), v.object({ type: v.literal("signOut") }), v.object({
|
|
22
|
-
type: v.literal("refreshSession"),
|
|
23
|
-
...refreshSessionArgs.fields
|
|
24
|
-
}), v.object({
|
|
25
|
-
type: v.literal("verifyCodeAndSignIn"),
|
|
26
|
-
...verifyCodeAndSignInArgs.fields
|
|
27
|
-
}), v.object({ type: v.literal("verifier") }), v.object({
|
|
28
|
-
type: v.literal("verifierSignature"),
|
|
29
|
-
...verifierSignatureArgs.fields
|
|
30
|
-
}), v.object({
|
|
31
|
-
type: v.literal("userOAuth"),
|
|
32
|
-
...userOAuthArgs.fields
|
|
33
|
-
}), v.object({
|
|
34
|
-
type: v.literal("createVerificationCode"),
|
|
35
|
-
...createVerificationCodeArgs.fields
|
|
36
|
-
}), v.object({
|
|
37
|
-
type: v.literal("createAccountFromCredentials"),
|
|
38
|
-
...createAccountFromCredentialsArgs.fields
|
|
39
|
-
}), v.object({
|
|
40
|
-
type: v.literal("retrieveAccountWithCredentials"),
|
|
41
|
-
...retrieveAccountWithCredentialsArgs.fields
|
|
42
|
-
}), v.object({
|
|
43
|
-
type: v.literal("modifyAccount"),
|
|
44
|
-
...modifyAccountArgs.fields
|
|
45
|
-
}), v.object({
|
|
46
|
-
type: v.literal("invalidateSessions"),
|
|
47
|
-
...invalidateSessionsArgs.fields
|
|
48
|
-
})) });
|
|
49
|
-
const storeImpl = async (ctx, fnArgs, getProviderOrThrow, config) => {
|
|
50
|
-
const args = fnArgs.args;
|
|
51
|
-
logWithLevel(LOG_LEVELS.INFO, `\`auth:store\` type: ${args.type}`);
|
|
52
|
-
return Fx.run(Fx.match(args, args.type, {
|
|
53
|
-
signIn: (a) => Fx.from({
|
|
54
|
-
ok: () => signInImpl(ctx, a, config),
|
|
55
|
-
err: (e) => e
|
|
56
|
-
}),
|
|
57
|
-
signOut: () => signOutImpl(ctx, config),
|
|
58
|
-
refreshSession: (a) => Fx.from({
|
|
59
|
-
ok: () => refreshSessionImpl(ctx, a, getProviderOrThrow, config),
|
|
60
|
-
err: (e) => e
|
|
61
|
-
}),
|
|
62
|
-
verifyCodeAndSignIn: (a) => Fx.from({
|
|
63
|
-
ok: () => verifyCodeAndSignInImpl(ctx, a, getProviderOrThrow, config),
|
|
64
|
-
err: (e) => e
|
|
65
|
-
}),
|
|
66
|
-
verifier: () => verifierImpl(ctx, config),
|
|
67
|
-
verifierSignature: (a) => verifierSignatureImpl(ctx, a, config).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),
|
|
68
|
-
userOAuth: (a) => userOAuthImpl(ctx, a, getProviderOrThrow, config).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),
|
|
69
|
-
createVerificationCode: (a) => Fx.from({
|
|
70
|
-
ok: () => createVerificationCodeImpl(ctx, a, getProviderOrThrow, config),
|
|
71
|
-
err: (e) => e
|
|
72
|
-
}),
|
|
73
|
-
createAccountFromCredentials: (a) => Fx.from({
|
|
74
|
-
ok: () => createAccountFromCredentialsImpl(ctx, a, getProviderOrThrow, config),
|
|
75
|
-
err: (e) => e
|
|
76
|
-
}),
|
|
77
|
-
retrieveAccountWithCredentials: (a) => retrieveAccountWithCredentialsImpl(ctx, a, getProviderOrThrow, config),
|
|
78
|
-
modifyAccount: (a) => modifyAccountImpl(ctx, a, getProviderOrThrow, config).pipe(Fx.recover((e) => Fx.fatal(e.toConvexError()))),
|
|
79
|
-
invalidateSessions: (a) => invalidateSessionsImpl(ctx, a, config)
|
|
80
|
-
}));
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
//#endregion
|
|
84
|
-
export { callCreateAccountFromCredentials, callCreateVerificationCode, callInvalidateSessions, callModifyAccount, callRefreshSession, callRetreiveAccountWithCredentials, callRetrieveAccountWithCredentials, callSignIn, callSignOut, callUserOAuth, callVerifier, callVerifierSignature, callVerifyCodeAndSignIn, storeArgs, storeImpl };
|
|
85
|
-
//# sourceMappingURL=index.js.map
|
|
15
|
+
export { callCreateAccountFromCredentials, callCreateVerificationCode, callInvalidateSessions, callModifyAccount, callRefreshSession, callRetrieveAccountWithCredentials, callSignIn, callSignOut, callUserOAuth, callVerifier, callVerifierSignature, callVerifyCodeAndSignIn, storeArgs, storeImpl };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { MutationCtx } from "../types.js";
|
|
2
|
-
import { Config } from "../
|
|
2
|
+
import { Config } from "../crypto.js";
|
|
3
3
|
import { Fx } from "@robelest/fx";
|
|
4
4
|
import { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
5
|
-
import * as
|
|
5
|
+
import * as convex_values104 from "convex/values";
|
|
6
6
|
import { Infer } from "convex/values";
|
|
7
7
|
|
|
8
8
|
//#region src/server/mutations/invalidate.d.ts
|
|
9
|
-
declare const invalidateSessionsArgs:
|
|
9
|
+
declare const invalidateSessionsArgs: convex_values104.VObject<{
|
|
10
10
|
except?: string[] | undefined;
|
|
11
11
|
userId: string;
|
|
12
12
|
}, {
|
|
13
|
-
userId:
|
|
14
|
-
except:
|
|
13
|
+
userId: convex_values104.VString<string, "required">;
|
|
14
|
+
except: convex_values104.VArray<string[] | undefined, convex_values104.VString<string, "required">, "optional">;
|
|
15
15
|
}, "required", "userId" | "except">;
|
|
16
16
|
declare const callInvalidateSessions: <DataModel extends GenericDataModel>(ctx: GenericActionCtx<DataModel>, args: Infer<typeof invalidateSessionsArgs>) => Promise<void>;
|
|
17
17
|
declare function invalidateSessionsImpl(ctx: MutationCtx, args: Infer<typeof invalidateSessionsArgs>, config: Config): Fx<void, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidate.d.ts","names":[],"sources":["../../../src/server/mutations/invalidate.ts"],"mappings":";;;;;;;;cAWa,sBAAA,
|
|
1
|
+
{"version":3,"file":"invalidate.d.ts","names":[],"sources":["../../../src/server/mutations/invalidate.ts"],"mappings":";;;;;;;;cAWa,sBAAA,mBAAsB,OAAA;;;;UAGjC,gBAAA,CAAA,OAAA;;;cAEW,sBAAA,qBACO,gBAAA,EAElB,GAAA,EAAK,gBAAA,CAAiB,SAAA,GACtB,IAAA,EAAM,KAAA,QAAa,sBAAA,MAClB,OAAA;AAAA,iBASa,sBAAA,CACd,GAAA,EAAK,WAAA,EACL,IAAA,EAAM,KAAA,QAAa,sBAAA,GACnB,MAAA,EAAQ,MAAA,GACP,EAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LOG_LEVELS, logWithLevel } from "../utils.js";
|
|
2
2
|
import { authDb } from "../db.js";
|
|
3
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
3
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
4
4
|
import { deleteSession } from "../sessions.js";
|
|
5
5
|
import { Fx } from "@robelest/fx";
|
|
6
6
|
import { v } from "convex/values";
|
|
@@ -1 +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 \"../
|
|
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"}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { MutationCtx } from "../types.js";
|
|
2
|
-
import { AuthError } from "../
|
|
3
|
-
import { Config, GetProviderOrThrowFunc } from "../
|
|
2
|
+
import { AuthError } from "../authError.js";
|
|
3
|
+
import { Config, GetProviderOrThrowFunc } from "../crypto.js";
|
|
4
4
|
import { Fx } from "@robelest/fx";
|
|
5
5
|
import { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
6
|
-
import * as
|
|
6
|
+
import * as convex_values12 from "convex/values";
|
|
7
7
|
import { Infer } from "convex/values";
|
|
8
8
|
|
|
9
9
|
//#region src/server/mutations/oauth.d.ts
|
|
10
|
-
declare const userOAuthArgs:
|
|
10
|
+
declare const userOAuthArgs: convex_values12.VObject<{
|
|
11
11
|
accountExtend?: any;
|
|
12
12
|
provider: string;
|
|
13
13
|
signature: string;
|
|
14
14
|
providerAccountId: string;
|
|
15
15
|
profile: any;
|
|
16
16
|
}, {
|
|
17
|
-
provider:
|
|
18
|
-
providerAccountId:
|
|
19
|
-
profile:
|
|
20
|
-
signature:
|
|
21
|
-
accountExtend:
|
|
17
|
+
provider: convex_values12.VString<string, "required">;
|
|
18
|
+
providerAccountId: convex_values12.VString<string, "required">;
|
|
19
|
+
profile: convex_values12.VAny<any, "required", string>;
|
|
20
|
+
signature: convex_values12.VString<string, "required">;
|
|
21
|
+
accountExtend: convex_values12.VAny<any, "optional", string>;
|
|
22
22
|
}, "required", "provider" | "signature" | "providerAccountId" | "profile" | "accountExtend" | `profile.${string}` | `accountExtend.${string}`>;
|
|
23
23
|
type ReturnType = string;
|
|
24
24
|
declare function userOAuthImpl(ctx: MutationCtx, args: Infer<typeof userOAuthArgs>, getProviderOrThrow: GetProviderOrThrowFunc, config: Config): Fx<ReturnType, AuthError>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","names":[],"sources":["../../../src/server/mutations/oauth.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","names":[],"sources":["../../../src/server/mutations/oauth.ts"],"mappings":";;;;;;;;;cAwBa,aAAA,kBAAa,OAAA;;;;;;;YAMxB,eAAA,CAAA,OAAA;;;;;;KA8CG,UAAA;AAAA,iBAEW,aAAA,CACd,GAAA,EAAK,WAAA,EACL,IAAA,EAAM,KAAA,QAAa,aAAA,GACnB,kBAAA,EAAoB,sBAAA,EACpB,MAAA,EAAQ,MAAA,GACP,EAAA,CAAG,UAAA,EAAY,SAAA;AAAA,cA+IL,aAAA,qBAAyC,gBAAA,EACpD,GAAA,EAAK,gBAAA,CAAiB,SAAA,GACtB,IAAA,EAAM,KAAA,QAAa,aAAA,MAClB,OAAA,CAAQ,UAAA"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { AuthError } from "../
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
2
|
import { generateRandomString, logWithLevel, sha256 } from "../utils.js";
|
|
3
3
|
import { authDb } from "../db.js";
|
|
4
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
4
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
5
5
|
import { upsertUserAndAccount } from "../users.js";
|
|
6
|
-
import { ENTERPRISE_OIDC_PROVIDER_PREFIX, ENTERPRISE_SAML_PROVIDER_PREFIX,
|
|
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";
|
|
7
9
|
import { Fx } from "@robelest/fx";
|
|
8
10
|
import { v } from "convex/values";
|
|
9
11
|
|
|
@@ -1 +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 \"../fx\";\nimport * as Provider from \"../provider\";\nimport {\n ENTERPRISE_OIDC_PROVIDER_PREFIX,\n ENTERPRISE_SAML_PROVIDER_PREFIX,\n createSyntheticOAuthMaterializedConfig,\n isEnterpriseProviderId,\n normalizeEnterprisePolicy,\n} from \"../sso\";\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\";\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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"}
|
|
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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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { MutationCtx } from "../types.js";
|
|
2
|
-
import { Config, GetProviderOrThrowFunc } from "../
|
|
2
|
+
import { Config, GetProviderOrThrowFunc } from "../crypto.js";
|
|
3
3
|
import { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
4
|
-
import * as
|
|
4
|
+
import * as convex_values18 from "convex/values";
|
|
5
5
|
import { Infer } from "convex/values";
|
|
6
6
|
|
|
7
7
|
//#region src/server/mutations/refresh.d.ts
|
|
8
|
-
declare const refreshSessionArgs:
|
|
8
|
+
declare const refreshSessionArgs: convex_values18.VObject<{
|
|
9
9
|
refreshToken: string;
|
|
10
10
|
}, {
|
|
11
|
-
refreshToken:
|
|
11
|
+
refreshToken: convex_values18.VString<string, "required">;
|
|
12
12
|
}, "required", "refreshToken">;
|
|
13
13
|
type RefreshResult = null | {
|
|
14
14
|
token: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { logWithLevel, maybeRedact } from "../utils.js";
|
|
2
2
|
import { authDb } from "../db.js";
|
|
3
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
3
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
4
4
|
import { REFRESH_TOKEN_REUSE_WINDOW_MS, invalidateRefreshTokensInSubtree, parseRefreshToken, refreshTokenIfValid } from "../refresh.js";
|
|
5
5
|
import { generateTokensForSession } from "../sessions.js";
|
|
6
6
|
import { Fx } from "@robelest/fx";
|
|
@@ -1 +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 \"../fx\";\nimport * as Provider from \"../provider\";\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\";\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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"}
|
|
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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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Doc, MutationCtx } from "../types.js";
|
|
2
|
-
import { Config, GetProviderOrThrowFunc } from "../
|
|
2
|
+
import { Config, GetProviderOrThrowFunc } from "../crypto.js";
|
|
3
3
|
import { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
4
|
-
import * as
|
|
4
|
+
import * as convex_values0 from "convex/values";
|
|
5
5
|
import { Infer } from "convex/values";
|
|
6
6
|
|
|
7
7
|
//#region src/server/mutations/register.d.ts
|
|
8
|
-
declare const createAccountFromCredentialsArgs:
|
|
8
|
+
declare const createAccountFromCredentialsArgs: convex_values0.VObject<{
|
|
9
9
|
shouldLinkViaEmail?: boolean | undefined;
|
|
10
10
|
shouldLinkViaPhone?: boolean | undefined;
|
|
11
11
|
provider: string;
|
|
@@ -15,17 +15,17 @@ declare const createAccountFromCredentialsArgs: convex_values109.VObject<{
|
|
|
15
15
|
id: string;
|
|
16
16
|
};
|
|
17
17
|
}, {
|
|
18
|
-
provider:
|
|
19
|
-
account:
|
|
18
|
+
provider: convex_values0.VString<string, "required">;
|
|
19
|
+
account: convex_values0.VObject<{
|
|
20
20
|
secret?: string | undefined;
|
|
21
21
|
id: string;
|
|
22
22
|
}, {
|
|
23
|
-
id:
|
|
24
|
-
secret:
|
|
23
|
+
id: convex_values0.VString<string, "required">;
|
|
24
|
+
secret: convex_values0.VString<string | undefined, "optional">;
|
|
25
25
|
}, "required", "id" | "secret">;
|
|
26
|
-
profile:
|
|
27
|
-
shouldLinkViaEmail:
|
|
28
|
-
shouldLinkViaPhone:
|
|
26
|
+
profile: convex_values0.VAny<any, "required", string>;
|
|
27
|
+
shouldLinkViaEmail: convex_values0.VBoolean<boolean | undefined, "optional">;
|
|
28
|
+
shouldLinkViaPhone: convex_values0.VBoolean<boolean | undefined, "optional">;
|
|
29
29
|
}, "required", "provider" | "profile" | `profile.${string}` | "account" | "shouldLinkViaEmail" | "shouldLinkViaPhone" | "account.id" | "account.secret">;
|
|
30
30
|
type ReturnType = {
|
|
31
31
|
account: Doc<"Account">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","names":[],"sources":["../../../src/server/mutations/register.ts"],"mappings":";;;;;;;cAca,gCAAA,
|
|
1
|
+
{"version":3,"file":"register.d.ts","names":[],"sources":["../../../src/server/mutations/register.ts"],"mappings":";;;;;;;cAca,gCAAA,iBAAgC,OAAA;;;;;;;;;;YAM3C,cAAA,CAAA,OAAA;;;;;;;;;;;;KAEG,UAAA;EAAe,OAAA,EAAS,GAAA;EAAgB,IAAA,EAAM,GAAA;AAAA;AAAA,iBAE7B,gCAAA,CACpB,GAAA,EAAK,WAAA,EACL,IAAA,EAAM,KAAA,QAAa,gCAAA,GACnB,kBAAA,EAAoB,sBAAA,EACpB,MAAA,EAAQ,MAAA,GACP,OAAA,CAAQ,UAAA;AAAA,cA8JE,gCAAA,qBACO,gBAAA,EAElB,GAAA,EAAK,gBAAA,CAAiB,SAAA,GACtB,IAAA,EAAM,KAAA,QAAa,gCAAA,MAClB,OAAA,CAAQ,UAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AuthError } from "../
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
2
|
import { LOG_LEVELS, logWithLevel, maybeRedact } from "../utils.js";
|
|
3
3
|
import { authDb } from "../db.js";
|
|
4
|
-
import { hash, verify } from "../
|
|
5
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
4
|
+
import { hash, verify } from "../crypto.js";
|
|
5
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
6
6
|
import { getAuthSessionId } from "../sessions.js";
|
|
7
7
|
import { upsertUserAndAccount } from "../users.js";
|
|
8
8
|
import { Fx } from "@robelest/fx";
|
|
@@ -1 +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 \"../
|
|
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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"}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { Doc, MutationCtx } from "../types.js";
|
|
2
|
-
import { Config, GetProviderOrThrowFunc } from "../
|
|
2
|
+
import { Config, GetProviderOrThrowFunc } from "../crypto.js";
|
|
3
3
|
import { Fx } from "@robelest/fx";
|
|
4
4
|
import { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
5
|
-
import * as
|
|
5
|
+
import * as convex_values20 from "convex/values";
|
|
6
6
|
import { Infer } from "convex/values";
|
|
7
7
|
|
|
8
8
|
//#region src/server/mutations/retrieve.d.ts
|
|
9
|
-
declare const retrieveAccountWithCredentialsArgs:
|
|
9
|
+
declare const retrieveAccountWithCredentialsArgs: convex_values20.VObject<{
|
|
10
10
|
provider: string;
|
|
11
11
|
account: {
|
|
12
12
|
secret?: string | undefined;
|
|
13
13
|
id: string;
|
|
14
14
|
};
|
|
15
15
|
}, {
|
|
16
|
-
provider:
|
|
17
|
-
account:
|
|
16
|
+
provider: convex_values20.VString<string, "required">;
|
|
17
|
+
account: convex_values20.VObject<{
|
|
18
18
|
secret?: string | undefined;
|
|
19
19
|
id: string;
|
|
20
20
|
}, {
|
|
21
|
-
id:
|
|
22
|
-
secret:
|
|
21
|
+
id: convex_values20.VString<string, "required">;
|
|
22
|
+
secret: convex_values20.VString<string | undefined, "optional">;
|
|
23
23
|
}, "required", "id" | "secret">;
|
|
24
24
|
}, "required", "provider" | "account" | "account.id" | "account.secret">;
|
|
25
25
|
type ReturnType = "InvalidAccountId" | "TooManyFailedAttempts" | "InvalidSecret" | {
|
|
@@ -28,8 +28,6 @@ type ReturnType = "InvalidAccountId" | "TooManyFailedAttempts" | "InvalidSecret"
|
|
|
28
28
|
};
|
|
29
29
|
declare function retrieveAccountWithCredentialsImpl(ctx: MutationCtx, args: Infer<typeof retrieveAccountWithCredentialsArgs>, getProviderOrThrow: GetProviderOrThrowFunc, config: Config): Fx<ReturnType>;
|
|
30
30
|
declare const callRetrieveAccountWithCredentials: <DataModel extends GenericDataModel>(ctx: GenericActionCtx<DataModel>, args: Infer<typeof retrieveAccountWithCredentialsArgs>) => Promise<ReturnType>;
|
|
31
|
-
/** @deprecated Typo kept for backward compatibility. */
|
|
32
|
-
declare const callRetreiveAccountWithCredentials: <DataModel extends GenericDataModel>(ctx: GenericActionCtx<DataModel>, args: Infer<typeof retrieveAccountWithCredentialsArgs>) => Promise<ReturnType>;
|
|
33
31
|
//#endregion
|
|
34
|
-
export {
|
|
32
|
+
export { callRetrieveAccountWithCredentials, retrieveAccountWithCredentialsArgs, retrieveAccountWithCredentialsImpl };
|
|
35
33
|
//# sourceMappingURL=retrieve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retrieve.d.ts","names":[],"sources":["../../../src/server/mutations/retrieve.ts"],"mappings":";;;;;;;;cAgBa,kCAAA,kBAAkC,OAAA;;;;;;;YAG7C,eAAA,CAAA,OAAA;;;;;;;;;KAEG,UAAA;EAIC,OAAA,EAAS,GAAA;EAAgB,IAAA,EAAM,GAAA;AAAA;AAAA,iBAErB,kCAAA,CACd,GAAA,EAAK,WAAA,EACL,IAAA,EAAM,KAAA,QAAa,kCAAA,GACnB,kBAAA,EAAoB,sBAAA,EACpB,MAAA,EAAQ,MAAA,GACP,EAAA,CAAG,UAAA;AAAA,cAgEO,kCAAA,qBACO,gBAAA,EAElB,GAAA,EAAK,gBAAA,CAAiB,SAAA,GACtB,IAAA,EAAM,KAAA,QAAa,kCAAA,MAClB,OAAA,CAAQ,UAAA
|
|
1
|
+
{"version":3,"file":"retrieve.d.ts","names":[],"sources":["../../../src/server/mutations/retrieve.ts"],"mappings":";;;;;;;;cAgBa,kCAAA,kBAAkC,OAAA;;;;;;;YAG7C,eAAA,CAAA,OAAA;;;;;;;;;KAEG,UAAA;EAIC,OAAA,EAAS,GAAA;EAAgB,IAAA,EAAM,GAAA;AAAA;AAAA,iBAErB,kCAAA,CACd,GAAA,EAAK,WAAA,EACL,IAAA,EAAM,KAAA,QAAa,kCAAA,GACnB,kBAAA,EAAoB,sBAAA,EACpB,MAAA,EAAQ,MAAA,GACP,EAAA,CAAG,UAAA;AAAA,cAgEO,kCAAA,qBACO,gBAAA,EAElB,GAAA,EAAK,gBAAA,CAAiB,SAAA,GACtB,IAAA,EAAM,KAAA,QAAa,kCAAA,MAClB,OAAA,CAAQ,UAAA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AuthError } from "../
|
|
1
|
+
import { AuthError } from "../authError.js";
|
|
2
2
|
import { LOG_LEVELS, logWithLevel, maybeRedact } from "../utils.js";
|
|
3
3
|
import { authDb } from "../db.js";
|
|
4
|
-
import { verify } from "../
|
|
5
|
-
import { AUTH_STORE_REF } from "./store.js";
|
|
6
|
-
import { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit } from "../
|
|
4
|
+
import { verify } from "../crypto.js";
|
|
5
|
+
import { AUTH_STORE_REF } from "./store/refs.js";
|
|
6
|
+
import { isSignInRateLimited, recordFailedSignIn, resetSignInRateLimit } from "../limits.js";
|
|
7
7
|
import { Fx } from "@robelest/fx";
|
|
8
8
|
import { v } from "convex/values";
|
|
9
9
|
|
|
@@ -59,9 +59,7 @@ const callRetrieveAccountWithCredentials = async (ctx, args) => {
|
|
|
59
59
|
...args
|
|
60
60
|
} });
|
|
61
61
|
};
|
|
62
|
-
/** @deprecated Typo kept for backward compatibility. */
|
|
63
|
-
const callRetreiveAccountWithCredentials = callRetrieveAccountWithCredentials;
|
|
64
62
|
|
|
65
63
|
//#endregion
|
|
66
|
-
export {
|
|
64
|
+
export { callRetrieveAccountWithCredentials, retrieveAccountWithCredentialsArgs, retrieveAccountWithCredentialsImpl };
|
|
67
65
|
//# sourceMappingURL=retrieve.js.map
|
|
@@ -1 +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 \"../
|
|
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"}
|