@lastshotlabs/bunshot 0.0.25 → 0.0.28
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/.oclif.manifest.json +39 -0
- package/README.md +8282 -2147
- package/dist/cli/commands/init.js +690 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli.js +4 -4
- package/dist/packages/bunshot-admin/src/index.d.ts +15 -0
- package/dist/packages/bunshot-admin/src/index.js +11 -0
- package/dist/packages/bunshot-admin/src/lib/resourceTypes.d.ts +8 -0
- package/dist/packages/bunshot-admin/src/lib/resourceTypes.js +33 -0
- package/dist/packages/bunshot-admin/src/lib/typedRoute.d.ts +14 -0
- package/dist/packages/bunshot-admin/src/lib/typedRoute.js +17 -0
- package/dist/packages/bunshot-admin/src/plugin.d.ts +4 -0
- package/dist/packages/bunshot-admin/src/plugin.js +46 -0
- package/dist/packages/bunshot-admin/src/providers/auth0Access.d.ts +6 -0
- package/dist/packages/bunshot-admin/src/providers/auth0Access.js +32 -0
- package/dist/packages/bunshot-admin/src/routes/admin.d.ts +10 -0
- package/dist/packages/bunshot-admin/src/routes/admin.js +923 -0
- package/dist/packages/bunshot-admin/src/routes/mail.d.ts +6 -0
- package/dist/packages/bunshot-admin/src/routes/mail.js +114 -0
- package/dist/packages/bunshot-admin/src/routes/permissions.d.ts +8 -0
- package/dist/packages/bunshot-admin/src/routes/permissions.js +315 -0
- package/dist/packages/bunshot-admin/src/types/config.d.ts +16 -0
- package/dist/packages/bunshot-admin/src/types/config.js +37 -0
- package/dist/packages/bunshot-admin/src/types/env.d.ts +14 -0
- package/dist/packages/bunshot-admin/src/types/provider.d.ts +1 -0
- package/dist/packages/bunshot-admin/src/types/provider.js +4 -0
- package/dist/packages/bunshot-auth/src/adapters/memoryAuth.d.ts +66 -0
- package/dist/packages/bunshot-auth/src/adapters/memoryAuth.js +1063 -0
- package/dist/packages/bunshot-auth/src/adapters/mongoAuth.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/adapters/mongoAuth.js +536 -0
- package/dist/packages/bunshot-auth/src/adapters/sqliteAuth.d.ts +88 -0
- package/dist/packages/bunshot-auth/src/adapters/sqliteAuth.js +1366 -0
- package/dist/packages/bunshot-auth/src/admin/bunshotAccess.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/admin/bunshotAccess.js +23 -0
- package/dist/packages/bunshot-auth/src/admin/bunshotUsers.d.ts +5 -0
- package/dist/packages/bunshot-auth/src/admin/bunshotUsers.js +131 -0
- package/dist/packages/bunshot-auth/src/bootstrap.d.ts +38 -0
- package/dist/packages/bunshot-auth/src/bootstrap.js +384 -0
- package/dist/packages/bunshot-auth/src/config/appConfig.d.ts +3 -0
- package/dist/packages/bunshot-auth/src/config/appConfig.js +4 -0
- package/dist/packages/bunshot-auth/src/config/authConfig.d.ts +478 -0
- package/dist/packages/bunshot-auth/src/config/authConfig.js +46 -0
- package/dist/packages/bunshot-auth/src/config/configLock.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/config/configLock.js +10 -0
- package/dist/packages/bunshot-auth/src/index.d.ts +25 -0
- package/dist/packages/bunshot-auth/src/index.js +23 -0
- package/dist/packages/bunshot-auth/src/infra/mongo.d.ts +15 -0
- package/dist/packages/bunshot-auth/src/infra/mongo.js +44 -0
- package/dist/packages/bunshot-auth/src/infra/queue.d.ts +14 -0
- package/dist/packages/bunshot-auth/src/infra/queue.js +27 -0
- package/dist/packages/bunshot-auth/src/infra/redis.d.ts +5 -0
- package/dist/packages/bunshot-auth/src/infra/redis.js +15 -0
- package/dist/packages/bunshot-auth/src/infra/signing.d.ts +7 -0
- package/dist/packages/bunshot-auth/src/infra/signing.js +8 -0
- package/dist/packages/bunshot-auth/src/lib/accountLockout.d.ts +34 -0
- package/dist/packages/bunshot-auth/src/lib/accountLockout.js +244 -0
- package/dist/packages/bunshot-auth/src/lib/adapterTiers.d.ts +1 -0
- package/dist/packages/bunshot-auth/src/lib/adapterTiers.js +1 -0
- package/dist/packages/bunshot-auth/src/lib/authAdapter.d.ts +1 -0
- package/dist/packages/bunshot-auth/src/lib/authAdapter.js +1 -0
- package/dist/packages/bunshot-auth/src/lib/authContext.d.ts +15 -0
- package/dist/packages/bunshot-auth/src/lib/authContext.js +1 -0
- package/dist/packages/bunshot-auth/src/lib/authEventBus.d.ts +4 -0
- package/dist/packages/bunshot-auth/src/lib/authEventBus.js +15 -0
- package/dist/packages/bunshot-auth/src/lib/authRateLimit.d.ts +28 -0
- package/dist/packages/bunshot-auth/src/lib/authRateLimit.js +205 -0
- package/dist/packages/bunshot-auth/src/lib/breachedPassword.d.ts +19 -0
- package/dist/packages/bunshot-auth/src/lib/breachedPassword.js +61 -0
- package/dist/packages/bunshot-auth/src/lib/cache.d.ts +12 -0
- package/dist/packages/bunshot-auth/src/lib/cache.js +120 -0
- package/dist/packages/bunshot-auth/src/lib/clientIp.d.ts +4 -0
- package/dist/{lib → packages/bunshot-auth/src/lib}/clientIp.js +14 -7
- package/dist/packages/bunshot-auth/src/lib/cookieOptions.d.ts +27 -0
- package/dist/packages/bunshot-auth/src/lib/cookieOptions.js +33 -0
- package/dist/packages/bunshot-auth/src/lib/credentialStuffing.d.ts +40 -0
- package/dist/packages/bunshot-auth/src/lib/credentialStuffing.js +221 -0
- package/dist/packages/bunshot-auth/src/lib/deletionCancelToken.d.ts +19 -0
- package/dist/packages/bunshot-auth/src/lib/deletionCancelToken.js +148 -0
- package/dist/packages/bunshot-auth/src/lib/emailTemplates.d.ts +23 -0
- package/dist/packages/bunshot-auth/src/lib/emailTemplates.js +265 -0
- package/dist/packages/bunshot-auth/src/lib/emailVerification.d.ts +30 -0
- package/dist/packages/bunshot-auth/src/lib/emailVerification.js +200 -0
- package/dist/packages/bunshot-auth/src/lib/env.d.ts +1 -0
- package/dist/packages/bunshot-auth/src/lib/env.js +3 -0
- package/dist/packages/bunshot-auth/src/lib/fingerprint.js +36 -0
- package/dist/{lib → packages/bunshot-auth/src/lib}/groups.d.ts +15 -16
- package/dist/{lib → packages/bunshot-auth/src/lib}/groups.js +22 -34
- package/dist/packages/bunshot-auth/src/lib/jwks.d.ts +28 -0
- package/dist/packages/bunshot-auth/src/lib/jwks.js +79 -0
- package/dist/packages/bunshot-auth/src/lib/jwt.d.ts +12 -0
- package/dist/packages/bunshot-auth/src/lib/jwt.js +86 -0
- package/dist/packages/bunshot-auth/src/lib/logger.d.ts +3 -0
- package/dist/packages/bunshot-auth/src/lib/logger.js +13 -0
- package/dist/packages/bunshot-auth/src/lib/m2m.d.ts +30 -0
- package/dist/packages/bunshot-auth/src/lib/m2m.js +44 -0
- package/dist/packages/bunshot-auth/src/lib/magicLink.d.ts +13 -0
- package/dist/packages/bunshot-auth/src/lib/magicLink.js +145 -0
- package/dist/packages/bunshot-auth/src/lib/mfaChallenge.d.ts +60 -0
- package/dist/packages/bunshot-auth/src/lib/mfaChallenge.js +419 -0
- package/dist/packages/bunshot-auth/src/lib/oauth.d.ts +82 -0
- package/dist/packages/bunshot-auth/src/lib/oauth.js +177 -0
- package/dist/packages/bunshot-auth/src/lib/oauthCode.d.ts +19 -0
- package/dist/packages/bunshot-auth/src/lib/oauthCode.js +182 -0
- package/dist/packages/bunshot-auth/src/lib/oauthReauth.d.ts +19 -0
- package/dist/packages/bunshot-auth/src/lib/oauthReauth.js +255 -0
- package/dist/packages/bunshot-auth/src/lib/organization.d.ts +66 -0
- package/dist/packages/bunshot-auth/src/lib/organization.js +225 -0
- package/dist/packages/bunshot-auth/src/lib/passwordHistory.d.ts +12 -0
- package/dist/packages/bunshot-auth/src/lib/passwordHistory.js +31 -0
- package/dist/packages/bunshot-auth/src/lib/resetPassword.d.ts +20 -0
- package/dist/packages/bunshot-auth/src/lib/resetPassword.js +148 -0
- package/dist/packages/bunshot-auth/src/lib/roles.d.ts +9 -0
- package/dist/packages/bunshot-auth/src/lib/roles.js +93 -0
- package/dist/packages/bunshot-auth/src/lib/saml.d.ts +29 -0
- package/dist/packages/bunshot-auth/src/lib/saml.js +73 -0
- package/dist/packages/bunshot-auth/src/lib/samlRequestId.d.ts +13 -0
- package/dist/packages/bunshot-auth/src/lib/samlRequestId.js +129 -0
- package/dist/packages/bunshot-auth/src/lib/scim.d.ts +44 -0
- package/dist/packages/bunshot-auth/src/lib/scim.js +56 -0
- package/dist/packages/bunshot-auth/src/lib/securityEventWiring.d.ts +22 -0
- package/dist/packages/bunshot-auth/src/lib/securityEventWiring.js +65 -0
- package/dist/packages/bunshot-auth/src/lib/session.d.ts +45 -0
- package/dist/packages/bunshot-auth/src/lib/session.js +1211 -0
- package/dist/packages/bunshot-auth/src/lib/storeInfra.d.ts +26 -0
- package/dist/packages/bunshot-auth/src/lib/storeInfra.js +18 -0
- package/dist/packages/bunshot-auth/src/lib/suspension.d.ts +14 -0
- package/dist/packages/bunshot-auth/src/lib/suspension.js +20 -0
- package/dist/packages/bunshot-auth/src/lib/validateAdapter.d.ts +16 -0
- package/dist/packages/bunshot-auth/src/lib/validateAdapter.js +161 -0
- package/dist/packages/bunshot-auth/src/middleware/bearerAuth.d.ts +13 -0
- package/dist/packages/bunshot-auth/src/middleware/bearerAuth.js +58 -0
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/csrf.d.ts +5 -4
- package/dist/packages/bunshot-auth/src/middleware/csrf.js +138 -0
- package/dist/packages/bunshot-auth/src/middleware/identify.d.ts +4 -0
- package/dist/packages/bunshot-auth/src/middleware/identify.js +124 -0
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireMfaSetup.d.ts +2 -2
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireMfaSetup.js +10 -7
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireRole.d.ts +2 -2
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireRole.js +20 -16
- package/dist/packages/bunshot-auth/src/middleware/requireScope.d.ts +10 -0
- package/dist/packages/bunshot-auth/src/middleware/requireScope.js +25 -0
- package/dist/packages/bunshot-auth/src/middleware/requireStepUp.d.ts +18 -0
- package/dist/packages/bunshot-auth/src/middleware/requireStepUp.js +30 -0
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireVerifiedEmail.d.ts +2 -2
- package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireVerifiedEmail.js +7 -6
- package/dist/packages/bunshot-auth/src/middleware/scimAuth.d.ts +8 -0
- package/dist/packages/bunshot-auth/src/middleware/scimAuth.js +29 -0
- package/dist/packages/bunshot-auth/src/middleware/userAuth.d.ts +3 -0
- package/dist/packages/bunshot-auth/src/middleware/userAuth.js +6 -0
- package/dist/{models → packages/bunshot-auth/src/models}/AuthUser.d.ts +19 -8
- package/dist/packages/bunshot-auth/src/models/AuthUser.js +53 -0
- package/dist/packages/bunshot-auth/src/models/Group.d.ts +19 -0
- package/dist/packages/bunshot-auth/src/models/Group.js +22 -0
- package/dist/{models → packages/bunshot-auth/src/models}/GroupMembership.d.ts +6 -8
- package/dist/packages/bunshot-auth/src/models/GroupMembership.js +19 -0
- package/dist/packages/bunshot-auth/src/models/M2MClient.d.ts +18 -0
- package/dist/packages/bunshot-auth/src/models/M2MClient.js +18 -0
- package/dist/packages/bunshot-auth/src/models/TenantRole.d.ts +13 -0
- package/dist/packages/bunshot-auth/src/models/TenantRole.js +17 -0
- package/dist/packages/bunshot-auth/src/plugin.d.ts +4 -0
- package/dist/packages/bunshot-auth/src/plugin.js +274 -0
- package/dist/packages/bunshot-auth/src/routes/auth.d.ts +15 -0
- package/dist/packages/bunshot-auth/src/routes/auth.js +1624 -0
- package/dist/packages/bunshot-auth/src/routes/groups.d.ts +4 -0
- package/dist/packages/bunshot-auth/src/routes/groups.js +481 -0
- package/dist/packages/bunshot-auth/src/routes/m2m.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/routes/m2m.js +145 -0
- package/dist/packages/bunshot-auth/src/routes/mfa.d.ts +6 -0
- package/dist/packages/bunshot-auth/src/routes/mfa.js +991 -0
- package/dist/packages/bunshot-auth/src/routes/oauth.d.ts +3 -0
- package/dist/packages/bunshot-auth/src/routes/oauth.js +1727 -0
- package/dist/packages/bunshot-auth/src/routes/oidc.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/routes/oidc.js +84 -0
- package/dist/packages/bunshot-auth/src/routes/organizations.d.ts +3 -0
- package/dist/packages/bunshot-auth/src/routes/organizations.js +741 -0
- package/dist/packages/bunshot-auth/src/routes/passkey.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/routes/passkey.js +199 -0
- package/dist/packages/bunshot-auth/src/routes/saml.d.ts +2 -0
- package/dist/packages/bunshot-auth/src/routes/saml.js +226 -0
- package/dist/packages/bunshot-auth/src/routes/scim.d.ts +3 -0
- package/dist/packages/bunshot-auth/src/routes/scim.js +588 -0
- package/dist/packages/bunshot-auth/src/runtime.d.ts +52 -0
- package/dist/packages/bunshot-auth/src/runtime.js +11 -0
- package/dist/{schemas → packages/bunshot-auth/src/schemas}/auth.d.ts +4 -5
- package/dist/packages/bunshot-auth/src/schemas/auth.js +24 -0
- package/dist/packages/bunshot-auth/src/schemas/error.d.ts +10 -0
- package/dist/packages/bunshot-auth/src/schemas/error.js +10 -0
- package/dist/packages/bunshot-auth/src/schemas/success.d.ts +10 -0
- package/dist/packages/bunshot-auth/src/schemas/success.js +10 -0
- package/dist/packages/bunshot-auth/src/services/auth.d.ts +39 -0
- package/dist/packages/bunshot-auth/src/services/auth.js +378 -0
- package/dist/{services → packages/bunshot-auth/src/services}/mfa.d.ts +41 -17
- package/dist/{services → packages/bunshot-auth/src/services}/mfa.js +259 -183
- package/dist/packages/bunshot-auth/src/testing.d.ts +31 -0
- package/dist/packages/bunshot-auth/src/testing.js +23 -0
- package/dist/packages/bunshot-auth/src/types/adapter.d.ts +1 -0
- package/dist/packages/bunshot-auth/src/types/adapter.js +1 -0
- package/dist/packages/bunshot-auth/src/types/config.d.ts +152 -0
- package/dist/packages/bunshot-auth/src/types/config.js +179 -0
- package/dist/{routes → packages/bunshot-auth/src/types}/groups.d.ts +2 -3
- package/dist/packages/bunshot-auth/src/types/groups.js +1 -0
- package/dist/packages/bunshot-auth/src/types/oauthCode.d.ts +6 -0
- package/dist/packages/bunshot-auth/src/types/oauthCode.js +1 -0
- package/dist/packages/bunshot-auth/src/types/oauthReauth.d.ts +13 -0
- package/dist/packages/bunshot-auth/src/types/oauthReauth.js +1 -0
- package/dist/packages/bunshot-auth/src/types/redis.d.ts +1 -0
- package/dist/packages/bunshot-auth/src/types/redis.js +1 -0
- package/dist/packages/bunshot-auth/src/types/saml.d.ts +10 -0
- package/dist/packages/bunshot-auth/src/types/saml.js +1 -0
- package/dist/packages/bunshot-auth/src/types/session.d.ts +18 -0
- package/dist/packages/bunshot-auth/src/types/session.js +1 -0
- package/dist/packages/bunshot-auth/src/types/store.d.ts +1 -0
- package/dist/packages/bunshot-auth/src/types/store.js +1 -0
- package/dist/packages/bunshot-core/src/adminProvider.d.ts +95 -0
- package/dist/packages/bunshot-core/src/adminProvider.js +1 -0
- package/dist/packages/bunshot-core/src/auditLog.d.ts +34 -0
- package/dist/packages/bunshot-core/src/auditLog.js +1 -0
- package/dist/packages/bunshot-core/src/auth-adapter.d.ts +227 -0
- package/dist/packages/bunshot-core/src/auth-adapter.js +4 -0
- package/dist/packages/bunshot-core/src/authVariables.d.ts +14 -0
- package/dist/packages/bunshot-core/src/authVariables.js +4 -0
- package/dist/packages/bunshot-core/src/cache.d.ts +12 -0
- package/dist/packages/bunshot-core/src/cache.js +21 -0
- package/dist/packages/bunshot-core/src/captcha.d.ts +16 -0
- package/dist/packages/bunshot-core/src/captcha.js +1 -0
- package/dist/packages/bunshot-core/src/clearRegistry.d.ts +6 -0
- package/dist/packages/bunshot-core/src/clearRegistry.js +17 -0
- package/dist/packages/bunshot-core/src/clientIp.d.ts +3 -0
- package/dist/packages/bunshot-core/src/clientIp.js +45 -0
- package/dist/packages/bunshot-core/src/configLock.d.ts +4 -0
- package/dist/packages/bunshot-core/src/configLock.js +7 -0
- package/dist/packages/bunshot-core/src/configValidation.d.ts +22 -0
- package/dist/packages/bunshot-core/src/configValidation.js +39 -0
- package/dist/packages/bunshot-core/src/constants.js +10 -0
- package/dist/packages/bunshot-core/src/context/bunshotContext.d.ts +232 -0
- package/dist/packages/bunshot-core/src/context/bunshotContext.js +1 -0
- package/dist/packages/bunshot-core/src/context/contextAccess.d.ts +3 -0
- package/dist/packages/bunshot-core/src/context/contextAccess.js +16 -0
- package/dist/packages/bunshot-core/src/context/contextStore.d.ts +16 -0
- package/dist/packages/bunshot-core/src/context/contextStore.js +31 -0
- package/dist/packages/bunshot-core/src/context/frameworkConfig.d.ts +38 -0
- package/dist/packages/bunshot-core/src/context/frameworkConfig.js +1 -0
- package/dist/packages/bunshot-core/src/context/index.d.ts +4 -0
- package/dist/packages/bunshot-core/src/context/index.js +2 -0
- package/dist/packages/bunshot-core/src/context.d.ts +40 -0
- package/dist/packages/bunshot-core/src/context.js +35 -0
- package/dist/packages/bunshot-core/src/coreContracts.d.ts +47 -0
- package/dist/packages/bunshot-core/src/coreContracts.js +1 -0
- package/dist/packages/bunshot-core/src/coreRegistrar.d.ts +6 -0
- package/dist/packages/bunshot-core/src/coreRegistrar.js +42 -0
- package/dist/{lib → packages/bunshot-core/src}/createRoute.d.ts +4 -30
- package/dist/{lib → packages/bunshot-core/src}/createRoute.js +39 -88
- package/dist/packages/bunshot-core/src/cronRegistry.d.ts +11 -0
- package/dist/packages/bunshot-core/src/cronRegistry.js +1 -0
- package/dist/packages/bunshot-core/src/crypto.d.ts +43 -0
- package/dist/packages/bunshot-core/src/crypto.js +74 -0
- package/dist/packages/bunshot-core/src/csrf.d.ts +8 -0
- package/dist/packages/bunshot-core/src/csrf.js +1 -0
- package/dist/packages/bunshot-core/src/defaults/defaultFingerprint.d.ts +7 -0
- package/dist/packages/bunshot-core/src/defaults/defaultFingerprint.js +19 -0
- package/dist/packages/bunshot-core/src/defaults/memoryCacheAdapter.d.ts +6 -0
- package/dist/packages/bunshot-core/src/defaults/memoryCacheAdapter.js +40 -0
- package/dist/packages/bunshot-core/src/defaults/memoryRateLimit.d.ts +6 -0
- package/dist/packages/bunshot-core/src/defaults/memoryRateLimit.js +24 -0
- package/dist/packages/bunshot-core/src/emailTemplates.d.ts +5 -0
- package/dist/packages/bunshot-core/src/emailTemplates.js +10 -0
- package/dist/packages/bunshot-core/src/errors.d.ts +13 -0
- package/dist/packages/bunshot-core/src/errors.js +22 -0
- package/dist/packages/bunshot-core/src/eventBus.d.ts +270 -0
- package/dist/packages/bunshot-core/src/eventBus.js +143 -0
- package/dist/packages/bunshot-core/src/idempotency.d.ts +18 -0
- package/dist/packages/bunshot-core/src/idempotency.js +1 -0
- package/dist/packages/bunshot-core/src/index.d.ts +60 -0
- package/dist/packages/bunshot-core/src/index.js +34 -0
- package/dist/packages/bunshot-core/src/mail.d.ts +14 -0
- package/dist/packages/bunshot-core/src/mail.js +8 -0
- package/dist/packages/bunshot-core/src/memoryEviction.d.ts +24 -0
- package/dist/packages/bunshot-core/src/memoryEviction.js +52 -0
- package/dist/packages/bunshot-core/src/pagination.d.ts +45 -0
- package/dist/packages/bunshot-core/src/pagination.js +61 -0
- package/dist/packages/bunshot-core/src/permissions.d.ts +64 -0
- package/dist/packages/bunshot-core/src/permissions.js +27 -0
- package/dist/packages/bunshot-core/src/plugin.d.ts +44 -0
- package/dist/packages/bunshot-core/src/plugin.js +1 -0
- package/dist/packages/bunshot-core/src/rateLimit.d.ts +5 -0
- package/dist/packages/bunshot-core/src/rateLimit.js +18 -0
- package/dist/packages/bunshot-core/src/redis.d.ts +21 -0
- package/dist/packages/bunshot-core/src/redis.js +1 -0
- package/dist/packages/bunshot-core/src/routeAuth.d.ts +5 -0
- package/dist/packages/bunshot-core/src/routeAuth.js +11 -0
- package/dist/packages/bunshot-core/src/routeOverrides.d.ts +24 -0
- package/dist/packages/bunshot-core/src/routeOverrides.js +25 -0
- package/dist/packages/bunshot-core/src/routerAdapter.d.ts +6 -0
- package/dist/packages/bunshot-core/src/routerAdapter.js +56 -0
- package/dist/packages/bunshot-core/src/secrets.d.ts +48 -0
- package/dist/packages/bunshot-core/src/secrets.js +8 -0
- package/dist/packages/bunshot-core/src/signing.d.ts +41 -0
- package/dist/packages/bunshot-core/src/signing.js +1 -0
- package/dist/packages/bunshot-core/src/sse.d.ts +36 -0
- package/dist/packages/bunshot-core/src/sse.js +1 -0
- package/dist/packages/bunshot-core/src/storageAdapter.js +1 -0
- package/dist/packages/bunshot-core/src/storeInfra.d.ts +44 -0
- package/dist/packages/bunshot-core/src/storeInfra.js +18 -0
- package/dist/packages/bunshot-core/src/storeType.d.ts +7 -0
- package/dist/packages/bunshot-core/src/storeType.js +1 -0
- package/dist/packages/bunshot-core/src/testing.d.ts +1 -0
- package/dist/packages/bunshot-core/src/testing.js +1 -0
- package/dist/packages/bunshot-core/src/uploadRegistry.d.ts +23 -0
- package/dist/packages/bunshot-core/src/uploadRegistry.js +4 -0
- package/dist/packages/bunshot-core/src/userResolver.d.ts +5 -0
- package/dist/packages/bunshot-core/src/userResolver.js +14 -0
- package/dist/packages/bunshot-core/src/wsMessages.d.ts +42 -0
- package/dist/packages/bunshot-core/src/wsMessages.js +4 -0
- package/dist/packages/bunshot-permissions/src/adapters/memory.d.ts +7 -0
- package/dist/packages/bunshot-permissions/src/adapters/memory.js +73 -0
- package/dist/packages/bunshot-permissions/src/index.d.ts +10 -0
- package/dist/packages/bunshot-permissions/src/index.js +5 -0
- package/dist/packages/bunshot-permissions/src/lib/bootstrap.d.ts +7 -0
- package/dist/packages/bunshot-permissions/src/lib/bootstrap.js +12 -0
- package/dist/packages/bunshot-permissions/src/lib/evaluator.d.ts +10 -0
- package/dist/packages/bunshot-permissions/src/lib/evaluator.js +165 -0
- package/dist/packages/bunshot-permissions/src/lib/registry.d.ts +2 -0
- package/dist/packages/bunshot-permissions/src/lib/registry.js +31 -0
- package/dist/packages/bunshot-permissions/src/lib/validation.d.ts +1 -0
- package/dist/packages/bunshot-permissions/src/lib/validation.js +1 -0
- package/dist/packages/bunshot-permissions/src/types/adapter.d.ts +1 -0
- package/dist/packages/bunshot-permissions/src/types/adapter.js +1 -0
- package/dist/packages/bunshot-permissions/src/types/evaluator.d.ts +1 -0
- package/dist/packages/bunshot-permissions/src/types/evaluator.js +1 -0
- package/dist/packages/bunshot-permissions/src/types/models.d.ts +1 -0
- package/dist/packages/bunshot-permissions/src/types/models.js +1 -0
- package/dist/packages/bunshot-permissions/src/types/registry.d.ts +1 -0
- package/dist/packages/bunshot-permissions/src/types/registry.js +1 -0
- package/dist/packages/bunshot-postgres/src/adapter.d.ts +6 -0
- package/dist/packages/bunshot-postgres/src/adapter.js +794 -0
- package/dist/packages/bunshot-postgres/src/connection.d.ts +15 -0
- package/dist/packages/bunshot-postgres/src/connection.js +16 -0
- package/dist/packages/bunshot-postgres/src/index.d.ts +4 -0
- package/dist/packages/bunshot-postgres/src/index.js +2 -0
- package/dist/packages/bunshot-postgres/src/schema.d.ts +997 -0
- package/dist/packages/bunshot-postgres/src/schema.js +105 -0
- package/dist/src/app.d.ts +230 -0
- package/dist/src/app.js +182 -0
- package/dist/src/cli/commands/init.d.ts +10 -0
- package/dist/src/cli/commands/init.js +709 -0
- package/dist/src/cli/index.d.ts +1 -0
- package/dist/src/cli/index.js +3 -0
- package/dist/src/entrypoints/mongo.d.ts +6 -0
- package/dist/src/entrypoints/mongo.js +4 -0
- package/dist/src/entrypoints/queue.d.ts +2 -0
- package/dist/src/entrypoints/queue.js +1 -0
- package/dist/src/entrypoints/redis.d.ts +1 -0
- package/dist/src/entrypoints/redis.js +1 -0
- package/dist/{adapters → src/framework/adapters}/localStorage.d.ts +1 -1
- package/dist/{adapters → src/framework/adapters}/localStorage.js +23 -8
- package/dist/src/framework/adapters/memoryStorage.d.ts +2 -0
- package/dist/src/framework/adapters/memoryStorage.js +45 -0
- package/dist/{adapters → src/framework/adapters}/s3Storage.d.ts +1 -1
- package/dist/{adapters → src/framework/adapters}/s3Storage.js +12 -12
- package/dist/src/framework/admin/bunshotAccess.d.ts +2 -0
- package/dist/src/framework/admin/bunshotAccess.js +23 -0
- package/dist/src/framework/admin/bunshotUsers.d.ts +2 -0
- package/dist/src/framework/admin/bunshotUsers.js +103 -0
- package/dist/src/framework/admin/index.d.ts +7 -0
- package/dist/src/framework/admin/index.js +21 -0
- package/dist/src/framework/boundaryAdapters/cacheFactories.d.ts +13 -0
- package/dist/src/framework/boundaryAdapters/cacheFactories.js +86 -0
- package/dist/src/framework/boundaryAdapters/index.d.ts +2 -0
- package/dist/src/framework/boundaryAdapters/index.js +1 -0
- package/dist/src/framework/boundaryAdapters.d.ts +17 -0
- package/dist/src/framework/boundaryAdapters.js +62 -0
- package/dist/src/framework/buildContext.d.ts +33 -0
- package/dist/src/framework/buildContext.js +119 -0
- package/dist/src/framework/config/schema.d.ts +447 -0
- package/dist/src/framework/config/schema.js +528 -0
- package/dist/src/framework/createInfrastructure.d.ts +76 -0
- package/dist/src/framework/createInfrastructure.js +221 -0
- package/dist/src/framework/lib/auditLog.d.ts +23 -0
- package/dist/src/framework/lib/auditLog.js +416 -0
- package/dist/src/framework/lib/captcha.d.ts +11 -0
- package/dist/src/framework/lib/captcha.js +40 -0
- package/dist/{lib → src/framework/lib}/createDtoMapper.js +4 -4
- package/dist/src/framework/lib/createRoute.d.ts +1 -0
- package/dist/src/framework/lib/createRoute.js +2 -0
- package/dist/{lib → src/framework/lib}/idempotency.d.ts +2 -6
- package/dist/src/framework/lib/idempotency.js +74 -0
- package/dist/src/framework/lib/logger.d.ts +3 -0
- package/dist/src/framework/lib/logger.js +14 -0
- package/dist/src/framework/lib/metrics.d.ts +34 -0
- package/dist/{lib → src/framework/lib}/metrics.js +49 -57
- package/dist/src/framework/lib/pagination.d.ts +42 -0
- package/dist/src/framework/lib/pagination.js +51 -0
- package/dist/src/framework/lib/redisTransport.d.ts +38 -0
- package/dist/src/framework/lib/redisTransport.js +107 -0
- package/dist/src/framework/lib/resolveUserId.d.ts +2 -0
- package/dist/src/framework/lib/resolveUserId.js +5 -0
- package/dist/src/framework/lib/sseCollision.d.ts +6 -0
- package/dist/src/framework/lib/sseCollision.js +26 -0
- package/dist/src/framework/lib/storageAdapter.d.ts +1 -0
- package/dist/src/framework/lib/storageAdapter.js +1 -0
- package/dist/{lib → src/framework/lib}/stripUnreferencedSchemas.js +4 -4
- package/dist/src/framework/lib/tenant.d.ts +21 -0
- package/dist/src/framework/lib/tenant.js +70 -0
- package/dist/{lib → src/framework/lib}/upload.d.ts +14 -9
- package/dist/src/framework/lib/upload.js +132 -0
- package/dist/src/framework/lib/uploadRegistry.d.ts +23 -0
- package/dist/src/framework/lib/uploadRegistry.js +34 -0
- package/dist/{lib → src/framework/lib}/validate.d.ts +1 -1
- package/dist/{lib → src/framework/lib}/validate.js +2 -2
- package/dist/src/framework/lib/ws.d.ts +19 -0
- package/dist/src/framework/lib/ws.js +130 -0
- package/dist/src/framework/lib/wsHeartbeat.d.ts +12 -0
- package/dist/src/framework/lib/wsHeartbeat.js +53 -0
- package/dist/src/framework/lib/wsMessages.d.ts +25 -0
- package/dist/src/framework/lib/wsMessages.js +45 -0
- package/dist/src/framework/lib/wsNamespace.d.ts +17 -0
- package/dist/src/framework/lib/wsNamespace.js +19 -0
- package/dist/src/framework/lib/wsPresence.d.ts +17 -0
- package/dist/src/framework/lib/wsPresence.js +84 -0
- package/dist/src/framework/lib/wsTransport.d.ts +38 -0
- package/dist/src/framework/lib/wsTransport.js +9 -0
- package/dist/{lib → src/framework/lib}/zodToMongoose.d.ts +1 -1
- package/dist/{lib → src/framework/lib}/zodToMongoose.js +11 -11
- package/dist/{middleware → src/framework/middleware}/auditLog.d.ts +4 -3
- package/dist/src/framework/middleware/auditLog.js +42 -0
- package/dist/{middleware → src/framework/middleware}/botProtection.d.ts +2 -2
- package/dist/{middleware → src/framework/middleware}/botProtection.js +8 -9
- package/dist/src/framework/middleware/cacheResponse.d.ts +35 -0
- package/dist/src/framework/middleware/cacheResponse.js +126 -0
- package/dist/src/framework/middleware/captcha.d.ts +9 -0
- package/dist/src/framework/middleware/captcha.js +37 -0
- package/dist/{middleware → src/framework/middleware}/errorHandler.d.ts +1 -1
- package/dist/src/framework/middleware/errorHandler.js +16 -0
- package/dist/src/framework/middleware/index.js +1 -0
- package/dist/{middleware → src/framework/middleware}/logger.d.ts +1 -1
- package/dist/src/framework/middleware/metrics.d.ts +12 -0
- package/dist/src/framework/middleware/metrics.js +26 -0
- package/dist/{middleware → src/framework/middleware}/rateLimit.d.ts +2 -2
- package/dist/src/framework/middleware/rateLimit.js +22 -0
- package/dist/src/framework/middleware/requestId.d.ts +3 -0
- package/dist/{middleware → src/framework/middleware}/requestId.js +2 -2
- package/dist/{middleware → src/framework/middleware}/requestLogger.d.ts +3 -3
- package/dist/{middleware → src/framework/middleware}/requestLogger.js +17 -12
- package/dist/{middleware → src/framework/middleware}/requestSigning.d.ts +2 -2
- package/dist/{middleware → src/framework/middleware}/requestSigning.js +18 -19
- package/dist/src/framework/middleware/tenant.d.ts +14 -0
- package/dist/{middleware → src/framework/middleware}/tenant.js +31 -27
- package/dist/src/framework/middleware/upload.d.ts +5 -0
- package/dist/{middleware → src/framework/middleware}/upload.js +4 -4
- package/dist/{middleware → src/framework/middleware}/webhookAuth.d.ts +3 -3
- package/dist/{middleware → src/framework/middleware}/webhookAuth.js +11 -11
- package/dist/src/framework/models/AuditLog.d.ts +21 -0
- package/dist/src/framework/models/AuditLog.js +31 -0
- package/dist/src/framework/mountMiddleware.d.ts +91 -0
- package/dist/src/framework/mountMiddleware.js +128 -0
- package/dist/src/framework/mountOptionalEndpoints.d.ts +103 -0
- package/dist/src/framework/mountOptionalEndpoints.js +47 -0
- package/dist/src/framework/mountRoutes.d.ts +21 -0
- package/dist/src/framework/mountRoutes.js +144 -0
- package/dist/src/framework/persistence/cronRegistry.d.ts +28 -0
- package/dist/src/framework/persistence/cronRegistry.js +139 -0
- package/dist/src/framework/persistence/idempotency.d.ts +26 -0
- package/dist/src/framework/persistence/idempotency.js +178 -0
- package/dist/src/framework/persistence/index.d.ts +6 -0
- package/dist/src/framework/persistence/index.js +8 -0
- package/dist/src/framework/persistence/storeInfra.d.ts +9 -0
- package/dist/src/framework/persistence/storeInfra.js +1 -0
- package/dist/src/framework/persistence/uploadRegistry.d.ts +35 -0
- package/dist/src/framework/persistence/uploadRegistry.js +235 -0
- package/dist/src/framework/persistence/wsMessages.d.ts +22 -0
- package/dist/src/framework/persistence/wsMessages.js +296 -0
- package/dist/src/framework/preloadSchemas.d.ts +24 -0
- package/dist/src/framework/preloadSchemas.js +42 -0
- package/dist/src/framework/registerBoundaryAdapters.d.ts +23 -0
- package/dist/src/framework/registerBoundaryAdapters.js +46 -0
- package/dist/src/framework/routes/admin.d.ts +9 -0
- package/dist/src/framework/routes/admin.js +361 -0
- package/dist/src/framework/routes/health.d.ts +1 -0
- package/dist/src/framework/routes/health.js +21 -0
- package/dist/src/framework/routes/home.d.ts +1 -0
- package/dist/src/framework/routes/home.js +18 -0
- package/dist/src/framework/routes/jobs.d.ts +3 -0
- package/dist/src/framework/routes/jobs.js +315 -0
- package/dist/src/framework/routes/metrics.d.ts +10 -0
- package/dist/src/framework/routes/metrics.js +57 -0
- package/dist/src/framework/routes/uploads.d.ts +14 -0
- package/dist/src/framework/routes/uploads.js +262 -0
- package/dist/src/framework/runPluginLifecycle.d.ts +27 -0
- package/dist/src/framework/runPluginLifecycle.js +121 -0
- package/dist/src/framework/secrets/frameworkSecretSchema.d.ts +58 -0
- package/dist/src/framework/secrets/frameworkSecretSchema.js +20 -0
- package/dist/src/framework/secrets/index.d.ts +9 -0
- package/dist/src/framework/secrets/index.js +7 -0
- package/dist/src/framework/secrets/providers/envProvider.d.ts +15 -0
- package/dist/src/framework/secrets/providers/envProvider.js +18 -0
- package/dist/src/framework/secrets/providers/fileProvider.d.ts +8 -0
- package/dist/src/framework/secrets/providers/fileProvider.js +82 -0
- package/dist/src/framework/secrets/providers/ssmProvider.d.ts +20 -0
- package/dist/src/framework/secrets/providers/ssmProvider.js +127 -0
- package/dist/src/framework/secrets/resolveSecretBundle.d.ts +53 -0
- package/dist/src/framework/secrets/resolveSecretBundle.js +84 -0
- package/dist/src/framework/secrets/resolveSecrets.d.ts +18 -0
- package/dist/src/framework/secrets/resolveSecrets.js +34 -0
- package/dist/src/framework/sse/index.d.ts +21 -0
- package/dist/src/framework/sse/index.js +109 -0
- package/dist/src/framework/ws/index.d.ts +11 -0
- package/dist/src/framework/ws/index.js +8 -0
- package/dist/src/index.d.ts +87 -0
- package/dist/src/index.js +58 -0
- package/dist/src/lib/appConfig.d.ts +7 -0
- package/dist/src/lib/appConfig.js +27 -0
- package/dist/src/lib/appMeta.d.ts +7 -0
- package/dist/src/lib/appMeta.js +3 -0
- package/dist/src/lib/authConfig.d.ts +532 -0
- package/dist/src/lib/authConfig.js +179 -0
- package/dist/{lib → src/lib}/context.d.ts +6 -7
- package/dist/{lib → src/lib}/context.js +5 -5
- package/dist/src/lib/logger.d.ts +1 -0
- package/dist/src/lib/logger.js +1 -0
- package/dist/src/lib/mongo.d.ts +58 -0
- package/dist/src/lib/mongo.js +96 -0
- package/dist/src/lib/queue.d.ts +72 -0
- package/dist/src/lib/queue.js +152 -0
- package/dist/src/lib/redis.d.ts +28 -0
- package/dist/src/lib/redis.js +72 -0
- package/dist/{lib → src/lib}/signing.d.ts +2 -2
- package/dist/src/lib/signing.js +210 -0
- package/dist/src/lib/signingConfig.d.ts +40 -0
- package/dist/src/lib/signingConfig.js +28 -0
- package/dist/src/server.d.ts +146 -0
- package/dist/src/server.js +469 -0
- package/dist/src/shared/lib/HttpError.d.ts +1 -0
- package/dist/src/shared/lib/HttpError.js +2 -0
- package/dist/src/shared/lib/constants.d.ts +10 -0
- package/dist/src/shared/lib/crypto.d.ts +43 -0
- package/dist/src/shared/lib/crypto.js +74 -0
- package/dist/src/shared/lib/signing.d.ts +52 -0
- package/dist/{lib → src/shared/lib}/signing.js +40 -10
- package/dist/src/testing.d.ts +34 -0
- package/dist/src/testing.js +93 -0
- package/package.json +62 -25
- package/dist/adapters/memoryAuth.d.ts +0 -46
- package/dist/adapters/memoryAuth.js +0 -634
- package/dist/adapters/memoryStorage.d.ts +0 -3
- package/dist/adapters/memoryStorage.js +0 -44
- package/dist/adapters/mongoAuth.d.ts +0 -2
- package/dist/adapters/mongoAuth.js +0 -307
- package/dist/adapters/sqliteAuth.d.ts +0 -49
- package/dist/adapters/sqliteAuth.js +0 -707
- package/dist/app.d.ts +0 -456
- package/dist/app.js +0 -548
- package/dist/entrypoints/mongo.d.ts +0 -5
- package/dist/entrypoints/mongo.js +0 -4
- package/dist/entrypoints/queue.d.ts +0 -2
- package/dist/entrypoints/queue.js +0 -1
- package/dist/entrypoints/redis.d.ts +0 -1
- package/dist/entrypoints/redis.js +0 -1
- package/dist/index.d.ts +0 -98
- package/dist/index.js +0 -77
- package/dist/lib/HttpError.d.ts +0 -9
- package/dist/lib/HttpError.js +0 -14
- package/dist/lib/appConfig.d.ts +0 -162
- package/dist/lib/appConfig.js +0 -83
- package/dist/lib/auditLog.d.ts +0 -52
- package/dist/lib/auditLog.js +0 -201
- package/dist/lib/authAdapter.d.ts +0 -176
- package/dist/lib/authAdapter.js +0 -7
- package/dist/lib/authRateLimit.d.ts +0 -13
- package/dist/lib/authRateLimit.js +0 -81
- package/dist/lib/clientIp.d.ts +0 -14
- package/dist/lib/crypto.d.ts +0 -11
- package/dist/lib/crypto.js +0 -22
- package/dist/lib/deletionCancelToken.d.ts +0 -12
- package/dist/lib/deletionCancelToken.js +0 -88
- package/dist/lib/emailVerification.d.ts +0 -13
- package/dist/lib/emailVerification.js +0 -86
- package/dist/lib/fingerprint.js +0 -36
- package/dist/lib/idempotency.js +0 -182
- package/dist/lib/jwt.d.ts +0 -2
- package/dist/lib/jwt.js +0 -24
- package/dist/lib/logger.d.ts +0 -1
- package/dist/lib/logger.js +0 -7
- package/dist/lib/metrics.d.ts +0 -14
- package/dist/lib/mfaChallenge.d.ts +0 -42
- package/dist/lib/mfaChallenge.js +0 -293
- package/dist/lib/mongo.d.ts +0 -39
- package/dist/lib/mongo.js +0 -124
- package/dist/lib/oauth.d.ts +0 -40
- package/dist/lib/oauth.js +0 -101
- package/dist/lib/oauthCode.d.ts +0 -15
- package/dist/lib/oauthCode.js +0 -90
- package/dist/lib/pagination.d.ts +0 -119
- package/dist/lib/pagination.js +0 -166
- package/dist/lib/queue.d.ts +0 -37
- package/dist/lib/queue.js +0 -117
- package/dist/lib/redis.d.ts +0 -9
- package/dist/lib/redis.js +0 -61
- package/dist/lib/resetPassword.d.ts +0 -12
- package/dist/lib/resetPassword.js +0 -91
- package/dist/lib/roles.d.ts +0 -7
- package/dist/lib/roles.js +0 -49
- package/dist/lib/session.d.ts +0 -39
- package/dist/lib/session.js +0 -535
- package/dist/lib/tenant.d.ts +0 -15
- package/dist/lib/tenant.js +0 -65
- package/dist/lib/upload.js +0 -87
- package/dist/lib/ws.d.ts +0 -22
- package/dist/lib/ws.js +0 -89
- package/dist/lib/wsHeartbeat.d.ts +0 -12
- package/dist/lib/wsHeartbeat.js +0 -57
- package/dist/lib/wsMessages.d.ts +0 -40
- package/dist/lib/wsMessages.js +0 -330
- package/dist/lib/wsPresence.d.ts +0 -25
- package/dist/lib/wsPresence.js +0 -99
- package/dist/middleware/auditLog.js +0 -39
- package/dist/middleware/bearerAuth.d.ts +0 -2
- package/dist/middleware/bearerAuth.js +0 -11
- package/dist/middleware/cacheResponse.d.ts +0 -15
- package/dist/middleware/cacheResponse.js +0 -178
- package/dist/middleware/csrf.js +0 -125
- package/dist/middleware/errorHandler.js +0 -13
- package/dist/middleware/identify.d.ts +0 -3
- package/dist/middleware/identify.js +0 -95
- package/dist/middleware/index.js +0 -1
- package/dist/middleware/metrics.d.ts +0 -9
- package/dist/middleware/metrics.js +0 -26
- package/dist/middleware/rateLimit.js +0 -22
- package/dist/middleware/requestId.d.ts +0 -3
- package/dist/middleware/tenant.d.ts +0 -5
- package/dist/middleware/upload.d.ts +0 -5
- package/dist/middleware/userAuth.d.ts +0 -3
- package/dist/middleware/userAuth.js +0 -6
- package/dist/models/AuditLog.d.ts +0 -30
- package/dist/models/AuditLog.js +0 -39
- package/dist/models/AuthUser.js +0 -48
- package/dist/models/Group.d.ts +0 -21
- package/dist/models/Group.js +0 -28
- package/dist/models/GroupMembership.js +0 -25
- package/dist/models/TenantRole.d.ts +0 -15
- package/dist/models/TenantRole.js +0 -23
- package/dist/routes/auth.d.ts +0 -11
- package/dist/routes/auth.js +0 -605
- package/dist/routes/groups.js +0 -346
- package/dist/routes/health.d.ts +0 -1
- package/dist/routes/health.js +0 -22
- package/dist/routes/home.d.ts +0 -1
- package/dist/routes/home.js +0 -16
- package/dist/routes/jobs.d.ts +0 -2
- package/dist/routes/jobs.js +0 -272
- package/dist/routes/metrics.d.ts +0 -7
- package/dist/routes/metrics.js +0 -52
- package/dist/routes/mfa.d.ts +0 -5
- package/dist/routes/mfa.js +0 -620
- package/dist/routes/oauth.d.ts +0 -2
- package/dist/routes/oauth.js +0 -514
- package/dist/routes/uploads.d.ts +0 -2
- package/dist/routes/uploads.js +0 -135
- package/dist/schemas/auth.js +0 -30
- package/dist/server.d.ts +0 -57
- package/dist/server.js +0 -112
- package/dist/services/auth.d.ts +0 -27
- package/dist/services/auth.js +0 -159
- package/dist/ws/index.d.ts +0 -10
- package/dist/ws/index.js +0 -38
- package/docs/sections/adding-middleware/full.md +0 -35
- package/docs/sections/adding-models/full.md +0 -125
- package/docs/sections/adding-models/overview.md +0 -13
- package/docs/sections/adding-routes/full.md +0 -182
- package/docs/sections/adding-routes/overview.md +0 -23
- package/docs/sections/auth-flow/full.md +0 -779
- package/docs/sections/auth-flow/overview.md +0 -10
- package/docs/sections/auth-security-examples/full.md +0 -365
- package/docs/sections/authentication/full.md +0 -130
- package/docs/sections/authentication/overview.md +0 -5
- package/docs/sections/cli/full.md +0 -42
- package/docs/sections/configuration/full.md +0 -172
- package/docs/sections/configuration/overview.md +0 -18
- package/docs/sections/configuration-example/full.md +0 -117
- package/docs/sections/configuration-example/overview.md +0 -30
- package/docs/sections/documentation/full.md +0 -171
- package/docs/sections/environment-variables/full.md +0 -55
- package/docs/sections/exports/full.md +0 -123
- package/docs/sections/extending-context/full.md +0 -59
- package/docs/sections/header.md +0 -3
- package/docs/sections/installation/full.md +0 -6
- package/docs/sections/jobs/full.md +0 -140
- package/docs/sections/jobs/overview.md +0 -15
- package/docs/sections/logging/full.md +0 -83
- package/docs/sections/metrics/full.md +0 -127
- package/docs/sections/mongodb-connections/full.md +0 -45
- package/docs/sections/mongodb-connections/overview.md +0 -7
- package/docs/sections/multi-tenancy/full.md +0 -66
- package/docs/sections/multi-tenancy/overview.md +0 -15
- package/docs/sections/oauth/full.md +0 -189
- package/docs/sections/oauth/overview.md +0 -16
- package/docs/sections/package-development/full.md +0 -7
- package/docs/sections/pagination/full.md +0 -93
- package/docs/sections/peer-dependencies/full.md +0 -47
- package/docs/sections/quick-start/full.md +0 -43
- package/docs/sections/response-caching/full.md +0 -117
- package/docs/sections/response-caching/overview.md +0 -13
- package/docs/sections/roles/full.md +0 -225
- package/docs/sections/roles/overview.md +0 -14
- package/docs/sections/running-without-redis/full.md +0 -16
- package/docs/sections/running-without-redis-or-mongodb/full.md +0 -60
- package/docs/sections/signing/full.md +0 -203
- package/docs/sections/stack/full.md +0 -10
- package/docs/sections/uploads/full.md +0 -199
- package/docs/sections/versioning/full.md +0 -85
- package/docs/sections/webhook-auth/full.md +0 -100
- package/docs/sections/websocket/full.md +0 -184
- package/docs/sections/websocket/overview.md +0 -5
- package/docs/sections/websocket-rooms/full.md +0 -102
- package/docs/sections/websocket-rooms/overview.md +0 -5
- /package/dist/{lib/storageAdapter.js → packages/bunshot-admin/src/types/env.js} +0 -0
- /package/dist/{lib → packages/bunshot-auth/src/lib}/fingerprint.d.ts +0 -0
- /package/dist/{lib → packages/bunshot-core/src}/constants.d.ts +0 -0
- /package/dist/{lib → packages/bunshot-core/src}/storageAdapter.d.ts +0 -0
- /package/dist/{lib → src/framework/lib}/createDtoMapper.d.ts +0 -0
- /package/dist/{lib → src/framework/lib}/stripUnreferencedSchemas.d.ts +0 -0
- /package/dist/{middleware → src/framework/middleware}/cors.d.ts +0 -0
- /package/dist/{middleware → src/framework/middleware}/cors.js +0 -0
- /package/dist/{middleware → src/framework/middleware}/index.d.ts +0 -0
- /package/dist/{middleware → src/framework/middleware}/logger.js +0 -0
- /package/dist/{lib → src/shared/lib}/constants.js +0 -0
package/dist/routes/auth.js
DELETED
|
@@ -1,605 +0,0 @@
|
|
|
1
|
-
import { createRoute, withSecurity } from "../lib/createRoute";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { setCookie, getCookie, deleteCookie } from "hono/cookie";
|
|
4
|
-
import * as AuthService from "../services/auth";
|
|
5
|
-
import { makeRegisterSchema, makeLoginSchema, resetPasswordSchema } from "../schemas/auth";
|
|
6
|
-
import { COOKIE_TOKEN, HEADER_USER_TOKEN, COOKIE_REFRESH_TOKEN, HEADER_REFRESH_TOKEN } from "../lib/constants";
|
|
7
|
-
import { userAuth } from "../middleware/userAuth";
|
|
8
|
-
import { isLimited, trackAttempt, bustAuthLimit } from "../lib/authRateLimit";
|
|
9
|
-
import { getAuthAdapter } from "../lib/authAdapter";
|
|
10
|
-
import { createRouter } from "../lib/context";
|
|
11
|
-
import { getVerificationToken, deleteVerificationToken, createVerificationToken } from "../lib/emailVerification";
|
|
12
|
-
import { createResetToken, consumeResetToken } from "../lib/resetPassword";
|
|
13
|
-
import { createDeletionCancelToken, consumeDeletionCancelToken } from "../lib/deletionCancelToken";
|
|
14
|
-
import { getRefreshTokenExpiry, getAccessTokenExpiry, getCsrfEnabled, getAppName } from "../lib/appConfig";
|
|
15
|
-
import { refreshCsrfToken, clearCsrfToken } from "../middleware/csrf";
|
|
16
|
-
import { getUserSessions, deleteSession, deleteUserSessions } from "../lib/session";
|
|
17
|
-
import { getClientIp } from "../lib/clientIp";
|
|
18
|
-
const isProd = process.env.NODE_ENV === "production";
|
|
19
|
-
const TokenResponse = z.object({
|
|
20
|
-
token: z.string().describe("JWT session token. Also set as an HttpOnly session cookie. Empty string when mfaRequired is true."),
|
|
21
|
-
userId: z.string().describe("Unique user ID."),
|
|
22
|
-
email: z.string().optional().describe("User's email address (present when primaryField is 'email')."),
|
|
23
|
-
emailVerified: z.boolean().optional().describe("Whether the email address has been verified (present when emailVerification is configured)."),
|
|
24
|
-
googleLinked: z.boolean().optional().describe("Whether a Google OAuth account is linked to this user."),
|
|
25
|
-
refreshToken: z.string().optional().describe("Refresh token (present when refreshTokens is configured). Also set as an HttpOnly cookie."),
|
|
26
|
-
mfaRequired: z.boolean().optional().describe("When true, complete MFA via POST /auth/mfa/verify before accessing the API."),
|
|
27
|
-
mfaToken: z.string().optional().describe("MFA challenge token. Pass to POST /auth/mfa/verify with a TOTP or recovery code."),
|
|
28
|
-
mfaMethods: z.array(z.string()).optional().describe("Available MFA methods when mfaRequired is true (e.g., 'totp', 'emailOtp', 'webauthn')."),
|
|
29
|
-
webauthnOptions: z.record(z.string(), z.unknown()).optional().describe("WebAuthn assertion options (present when mfaMethods includes 'webauthn'). Pass directly to navigator.credentials.get()."),
|
|
30
|
-
}).openapi("TokenResponse");
|
|
31
|
-
const ErrorResponse = z.object({ error: z.string().describe("Human-readable error message.") }).openapi("ErrorResponse");
|
|
32
|
-
const tags = ["Auth"];
|
|
33
|
-
const cookieOptions = (maxAge) => ({
|
|
34
|
-
httpOnly: true,
|
|
35
|
-
secure: isProd,
|
|
36
|
-
sameSite: "Lax",
|
|
37
|
-
path: "/",
|
|
38
|
-
maxAge: maxAge ?? 60 * 60 * 24 * 7, // 7 days
|
|
39
|
-
});
|
|
40
|
-
export const createAuthRouter = ({ primaryField, emailVerification, passwordReset, rateLimit, accountDeletion, refreshTokens }) => {
|
|
41
|
-
const router = createRouter();
|
|
42
|
-
const RegisterSchema = makeRegisterSchema(primaryField);
|
|
43
|
-
const LoginSchema = makeLoginSchema(primaryField);
|
|
44
|
-
const fieldLabel = primaryField.charAt(0).toUpperCase() + primaryField.slice(1);
|
|
45
|
-
const alreadyRegisteredMsg = `${fieldLabel} already registered`;
|
|
46
|
-
// Resolve limits with defaults
|
|
47
|
-
const loginOpts = { windowMs: rateLimit?.login?.windowMs ?? 15 * 60 * 1000, max: rateLimit?.login?.max ?? 10 };
|
|
48
|
-
const registerOpts = { windowMs: rateLimit?.register?.windowMs ?? 60 * 60 * 1000, max: rateLimit?.register?.max ?? 5 };
|
|
49
|
-
const verifyOpts = { windowMs: rateLimit?.verifyEmail?.windowMs ?? 15 * 60 * 1000, max: rateLimit?.verifyEmail?.max ?? 10 };
|
|
50
|
-
const resendOpts = { windowMs: rateLimit?.resendVerification?.windowMs ?? 60 * 60 * 1000, max: rateLimit?.resendVerification?.max ?? 3 };
|
|
51
|
-
const forgotOpts = { windowMs: rateLimit?.forgotPassword?.windowMs ?? 15 * 60 * 1000, max: rateLimit?.forgotPassword?.max ?? 5 };
|
|
52
|
-
const resetOpts = { windowMs: rateLimit?.resetPassword?.windowMs ?? 15 * 60 * 1000, max: rateLimit?.resetPassword?.max ?? 10 };
|
|
53
|
-
router.openapi(createRoute({
|
|
54
|
-
method: "post",
|
|
55
|
-
path: "/auth/register",
|
|
56
|
-
summary: "Register a new account",
|
|
57
|
-
description: "Creates a new user account and returns a JWT session token. The token is also set as an HttpOnly session cookie. Rate-limited by IP.",
|
|
58
|
-
tags,
|
|
59
|
-
request: { body: { content: { "application/json": { schema: RegisterSchema } }, description: "Registration credentials." } },
|
|
60
|
-
responses: {
|
|
61
|
-
201: { content: { "application/json": { schema: TokenResponse } }, description: "Account created. Returns a session token." },
|
|
62
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Validation error (e.g. missing field, password too short)." },
|
|
63
|
-
409: { content: { "application/json": { schema: ErrorResponse } }, description: alreadyRegisteredMsg },
|
|
64
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many registration attempts from this IP. Try again later." },
|
|
65
|
-
},
|
|
66
|
-
}), async (c) => {
|
|
67
|
-
const ip = getClientIp(c);
|
|
68
|
-
if (await trackAttempt(`register:${ip}`, registerOpts)) {
|
|
69
|
-
return c.json({ error: "Too many registration attempts. Try again later." }, 429);
|
|
70
|
-
}
|
|
71
|
-
const body = c.req.valid("json");
|
|
72
|
-
const identifier = body[primaryField];
|
|
73
|
-
const metadata = {
|
|
74
|
-
ipAddress: ip !== "unknown" ? ip : undefined,
|
|
75
|
-
userAgent: c.req.header("user-agent") ?? undefined,
|
|
76
|
-
};
|
|
77
|
-
const result = await AuthService.register(identifier, body.password, metadata);
|
|
78
|
-
setCookie(c, COOKIE_TOKEN, result.token, cookieOptions(refreshTokens ? getAccessTokenExpiry() : undefined));
|
|
79
|
-
if (result.refreshToken) {
|
|
80
|
-
setCookie(c, COOKIE_REFRESH_TOKEN, result.refreshToken, cookieOptions(getRefreshTokenExpiry()));
|
|
81
|
-
}
|
|
82
|
-
if (getCsrfEnabled())
|
|
83
|
-
refreshCsrfToken(c);
|
|
84
|
-
return c.json(result, 201);
|
|
85
|
-
});
|
|
86
|
-
router.openapi(createRoute({
|
|
87
|
-
method: "post",
|
|
88
|
-
path: "/auth/login",
|
|
89
|
-
summary: "Log in",
|
|
90
|
-
description: "Authenticates with credentials and returns a JWT session token. The token is also set as an HttpOnly session cookie. Failed attempts are rate-limited per identifier.",
|
|
91
|
-
tags,
|
|
92
|
-
request: { body: { content: { "application/json": { schema: LoginSchema } }, description: "Login credentials." } },
|
|
93
|
-
responses: {
|
|
94
|
-
200: { content: { "application/json": { schema: TokenResponse } }, description: "Authenticated. Returns a session token." },
|
|
95
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "Invalid credentials." },
|
|
96
|
-
403: { content: { "application/json": { schema: ErrorResponse } }, description: "Email not verified. Verification is required before login." },
|
|
97
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many failed login attempts for this identifier. Try again later." },
|
|
98
|
-
},
|
|
99
|
-
}), async (c) => {
|
|
100
|
-
const body = c.req.valid("json");
|
|
101
|
-
const identifier = body[primaryField];
|
|
102
|
-
const limitKey = `login:${identifier}`;
|
|
103
|
-
if (await isLimited(limitKey, loginOpts)) {
|
|
104
|
-
return c.json({ error: "Too many failed login attempts. Try again later." }, 429);
|
|
105
|
-
}
|
|
106
|
-
const metadata = {
|
|
107
|
-
ipAddress: getClientIp(c),
|
|
108
|
-
userAgent: c.req.header("user-agent") ?? undefined,
|
|
109
|
-
};
|
|
110
|
-
try {
|
|
111
|
-
const result = await AuthService.login(identifier, body.password, metadata);
|
|
112
|
-
await bustAuthLimit(limitKey); // success — clear failure count
|
|
113
|
-
if (!result.mfaRequired) {
|
|
114
|
-
setCookie(c, COOKIE_TOKEN, result.token, cookieOptions(refreshTokens ? getAccessTokenExpiry() : undefined));
|
|
115
|
-
if (result.refreshToken) {
|
|
116
|
-
setCookie(c, COOKIE_REFRESH_TOKEN, result.refreshToken, cookieOptions(getRefreshTokenExpiry()));
|
|
117
|
-
}
|
|
118
|
-
if (getCsrfEnabled())
|
|
119
|
-
refreshCsrfToken(c);
|
|
120
|
-
}
|
|
121
|
-
return c.json(result, 200);
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
await trackAttempt(limitKey, loginOpts); // failure — count it
|
|
125
|
-
throw err;
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
router.use("/auth/me", userAuth);
|
|
129
|
-
router.openapi(withSecurity(createRoute({
|
|
130
|
-
method: "get",
|
|
131
|
-
path: "/auth/me",
|
|
132
|
-
summary: "Get current user",
|
|
133
|
-
description: "Returns the authenticated user's profile. Requires a valid session via cookie or x-user-token header.",
|
|
134
|
-
tags,
|
|
135
|
-
responses: {
|
|
136
|
-
200: {
|
|
137
|
-
content: {
|
|
138
|
-
"application/json": {
|
|
139
|
-
schema: z.object({
|
|
140
|
-
userId: z.string().describe("Unique user ID."),
|
|
141
|
-
email: z.string().optional().describe("User's email address."),
|
|
142
|
-
emailVerified: z.boolean().optional().describe("Whether the email address has been verified."),
|
|
143
|
-
googleLinked: z.boolean().optional().describe("Whether a Google OAuth account is linked."),
|
|
144
|
-
}),
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
description: "Authenticated user's profile.",
|
|
148
|
-
},
|
|
149
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "No valid session." },
|
|
150
|
-
},
|
|
151
|
-
}), { cookieAuth: [] }, { userToken: [] }), async (c) => {
|
|
152
|
-
const authUserId = c.get("authUserId");
|
|
153
|
-
const adapter = getAuthAdapter();
|
|
154
|
-
const user = adapter.getUser ? await adapter.getUser(authUserId) : null;
|
|
155
|
-
const googleLinked = user?.providerIds?.some((id) => id.startsWith("google:")) ?? false;
|
|
156
|
-
return c.json({ userId: authUserId, email: user?.email, emailVerified: user?.emailVerified, googleLinked }, 200);
|
|
157
|
-
});
|
|
158
|
-
// ---------------------------------------------------------------------------
|
|
159
|
-
// Account deletion
|
|
160
|
-
// ---------------------------------------------------------------------------
|
|
161
|
-
const deleteAccountOpts = { windowMs: rateLimit?.deleteAccount?.windowMs ?? 60 * 60 * 1000, max: rateLimit?.deleteAccount?.max ?? 3 };
|
|
162
|
-
router.openapi(withSecurity(createRoute({
|
|
163
|
-
method: "delete",
|
|
164
|
-
path: "/auth/me",
|
|
165
|
-
summary: "Delete account",
|
|
166
|
-
description: "Permanently deletes the authenticated user's account. Requires password confirmation for credential accounts. MFA is not required — the password serves as the identity check. Revokes all active sessions.",
|
|
167
|
-
tags,
|
|
168
|
-
request: {
|
|
169
|
-
body: {
|
|
170
|
-
content: {
|
|
171
|
-
"application/json": {
|
|
172
|
-
schema: z.object({
|
|
173
|
-
password: z.string().optional().describe("Current password. Required for credential accounts, optional for OAuth-only accounts."),
|
|
174
|
-
}),
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
description: "Password confirmation.",
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
responses: {
|
|
181
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Account deleted." },
|
|
182
|
-
202: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Account deletion has been scheduled." },
|
|
183
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Password is required for credential accounts." },
|
|
184
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "Invalid password or no valid session." },
|
|
185
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many deletion attempts. Try again later." },
|
|
186
|
-
501: { content: { "application/json": { schema: ErrorResponse } }, description: "The configured auth adapter does not support deleteUser." },
|
|
187
|
-
},
|
|
188
|
-
}), { cookieAuth: [] }, { userToken: [] }), async (c) => {
|
|
189
|
-
const authUserId = c.get("authUserId");
|
|
190
|
-
if (await trackAttempt(`deleteaccount:${authUserId}`, deleteAccountOpts)) {
|
|
191
|
-
return c.json({ error: "Too many deletion attempts. Try again later." }, 429);
|
|
192
|
-
}
|
|
193
|
-
const adapter = getAuthAdapter();
|
|
194
|
-
if (!adapter.deleteUser) {
|
|
195
|
-
return c.json({ error: "Auth adapter does not support deleteUser" }, 501);
|
|
196
|
-
}
|
|
197
|
-
const { password } = c.req.valid("json");
|
|
198
|
-
// Verify password for credential accounts
|
|
199
|
-
if (password) {
|
|
200
|
-
const user = adapter.getUser ? await adapter.getUser(authUserId) : null;
|
|
201
|
-
const email = user?.email;
|
|
202
|
-
if (email) {
|
|
203
|
-
const findFn = adapter.findByIdentifier ?? adapter.findByEmail.bind(adapter);
|
|
204
|
-
const found = await findFn(email);
|
|
205
|
-
if (found && !(await Bun.password.verify(password, found.passwordHash))) {
|
|
206
|
-
return c.json({ error: "Invalid password" }, 401);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
else if (adapter.hasPassword && await adapter.hasPassword(authUserId)) {
|
|
211
|
-
return c.json({ error: "Password is required to delete a credential account" }, 400);
|
|
212
|
-
}
|
|
213
|
-
// Call onBeforeDelete hook
|
|
214
|
-
if (accountDeletion?.onBeforeDelete) {
|
|
215
|
-
await accountDeletion.onBeforeDelete(authUserId);
|
|
216
|
-
}
|
|
217
|
-
// Queued deletion via BullMQ
|
|
218
|
-
if (accountDeletion?.queued) {
|
|
219
|
-
const { createQueue } = await import("../lib/queue");
|
|
220
|
-
const appName = getAppName();
|
|
221
|
-
const queue = createQueue(`${appName}:account-deletions`);
|
|
222
|
-
const delayMs = (accountDeletion.gracePeriod ?? 0) * 1000;
|
|
223
|
-
const job = await queue.add("delete-account", { userId: authUserId }, {
|
|
224
|
-
delay: delayMs,
|
|
225
|
-
attempts: 3,
|
|
226
|
-
backoff: { type: "exponential", delay: 1000 },
|
|
227
|
-
removeOnComplete: true,
|
|
228
|
-
removeOnFail: 100,
|
|
229
|
-
});
|
|
230
|
-
await queue.close();
|
|
231
|
-
// Revoke sessions immediately so the user is logged out
|
|
232
|
-
await deleteUserSessions(authUserId);
|
|
233
|
-
if (accountDeletion.gracePeriod && accountDeletion.onDeletionScheduled) {
|
|
234
|
-
const user = adapter.getUser ? await adapter.getUser(authUserId) : null;
|
|
235
|
-
const email = user?.email ?? "";
|
|
236
|
-
if (email) {
|
|
237
|
-
const cancelToken = await createDeletionCancelToken(authUserId, job.id, accountDeletion.gracePeriod);
|
|
238
|
-
await accountDeletion.onDeletionScheduled(authUserId, email, cancelToken);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
deleteCookie(c, COOKIE_TOKEN, { path: "/" });
|
|
242
|
-
return c.json({ message: "Account deletion scheduled" }, 202);
|
|
243
|
-
}
|
|
244
|
-
// Synchronous deletion (default)
|
|
245
|
-
await deleteUserSessions(authUserId);
|
|
246
|
-
await adapter.deleteUser(authUserId);
|
|
247
|
-
if (accountDeletion?.onAfterDelete) {
|
|
248
|
-
await accountDeletion.onAfterDelete(authUserId);
|
|
249
|
-
}
|
|
250
|
-
deleteCookie(c, COOKIE_TOKEN, { path: "/" });
|
|
251
|
-
return c.json({ message: "Account deleted" }, 200);
|
|
252
|
-
});
|
|
253
|
-
router.use("/auth/set-password", userAuth);
|
|
254
|
-
router.openapi(withSecurity(createRoute({
|
|
255
|
-
method: "post",
|
|
256
|
-
path: "/auth/set-password",
|
|
257
|
-
summary: "Set or update password",
|
|
258
|
-
description: "Sets or updates the password for the authenticated user. Useful for OAuth-only users who want to add a password. Requires a valid session.",
|
|
259
|
-
tags,
|
|
260
|
-
request: { body: { content: { "application/json": { schema: z.object({ password: z.string().min(8).describe("New password. Minimum 8 characters.") }) } }, description: "New password." } },
|
|
261
|
-
responses: {
|
|
262
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Password updated successfully." },
|
|
263
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Validation error (e.g. password too short)." },
|
|
264
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "No valid session." },
|
|
265
|
-
501: { content: { "application/json": { schema: ErrorResponse } }, description: "The configured auth adapter does not support setPassword." },
|
|
266
|
-
},
|
|
267
|
-
}), { cookieAuth: [] }, { userToken: [] }), async (c) => {
|
|
268
|
-
const adapter = getAuthAdapter();
|
|
269
|
-
if (!adapter.setPassword) {
|
|
270
|
-
return c.json({ error: "Auth adapter does not support setPassword" }, 501);
|
|
271
|
-
}
|
|
272
|
-
const { password } = c.req.valid("json");
|
|
273
|
-
const authUserId = c.get("authUserId");
|
|
274
|
-
const passwordHash = await Bun.password.hash(password);
|
|
275
|
-
await adapter.setPassword(authUserId, passwordHash);
|
|
276
|
-
return c.json({ message: "Password updated" }, 200);
|
|
277
|
-
});
|
|
278
|
-
router.openapi(createRoute({
|
|
279
|
-
method: "post",
|
|
280
|
-
path: "/auth/logout",
|
|
281
|
-
summary: "Log out",
|
|
282
|
-
description: "Invalidates the current session and clears the session cookie. Safe to call even without an active session.",
|
|
283
|
-
tags,
|
|
284
|
-
responses: {
|
|
285
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Logged out. Session is invalidated and cookie is cleared." },
|
|
286
|
-
},
|
|
287
|
-
}), async (c) => {
|
|
288
|
-
const token = getCookie(c, COOKIE_TOKEN) ?? c.req.header(HEADER_USER_TOKEN) ?? null;
|
|
289
|
-
await AuthService.logout(token);
|
|
290
|
-
deleteCookie(c, COOKIE_TOKEN, { path: "/" });
|
|
291
|
-
deleteCookie(c, COOKIE_REFRESH_TOKEN, { path: "/" });
|
|
292
|
-
if (getCsrfEnabled())
|
|
293
|
-
clearCsrfToken(c);
|
|
294
|
-
return c.json({ message: "Logged out" }, 200);
|
|
295
|
-
});
|
|
296
|
-
// Email verification routes — only mounted when emailVerification is configured and primaryField is "email"
|
|
297
|
-
if (emailVerification && primaryField === "email") {
|
|
298
|
-
router.openapi(createRoute({
|
|
299
|
-
method: "post",
|
|
300
|
-
path: "/auth/verify-email",
|
|
301
|
-
summary: "Verify email address",
|
|
302
|
-
description: "Consumes a single-use email verification token and marks the account as verified. The token is delivered by the `emailVerification.onSend` callback configured in CreateAppConfig. Rate-limited by IP.",
|
|
303
|
-
tags,
|
|
304
|
-
request: { body: { content: { "application/json": { schema: z.object({ token: z.string().describe("Single-use verification token received via email.") }) } }, description: "Verification token." } },
|
|
305
|
-
responses: {
|
|
306
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Email verified successfully." },
|
|
307
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Invalid or expired verification token." },
|
|
308
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many verification attempts from this IP. Try again later." },
|
|
309
|
-
},
|
|
310
|
-
}), async (c) => {
|
|
311
|
-
const ip = getClientIp(c);
|
|
312
|
-
if (await trackAttempt(`verify:${ip}`, verifyOpts)) {
|
|
313
|
-
return c.json({ error: "Too many verification attempts. Try again later." }, 429);
|
|
314
|
-
}
|
|
315
|
-
const { token } = c.req.valid("json");
|
|
316
|
-
const adapter = getAuthAdapter();
|
|
317
|
-
const entry = await getVerificationToken(token);
|
|
318
|
-
if (!entry)
|
|
319
|
-
return c.json({ error: "Invalid or expired verification token" }, 400);
|
|
320
|
-
if (adapter.setEmailVerified)
|
|
321
|
-
await adapter.setEmailVerified(entry.userId, true);
|
|
322
|
-
await deleteVerificationToken(token);
|
|
323
|
-
return c.json({ message: "Email verified" }, 200);
|
|
324
|
-
});
|
|
325
|
-
router.openapi(createRoute({
|
|
326
|
-
method: "post",
|
|
327
|
-
path: "/auth/resend-verification",
|
|
328
|
-
summary: "Resend verification email",
|
|
329
|
-
description: "Authenticates with credentials and sends a new verification email. Always returns 200 for valid credentials regardless of verification status, to prevent user enumeration. Rate-limited per identifier. Does not require a session.",
|
|
330
|
-
tags,
|
|
331
|
-
request: { body: { content: { "application/json": { schema: LoginSchema } }, description: "Login credentials to identify the account." } },
|
|
332
|
-
responses: {
|
|
333
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Verification email sent, or account is already verified (indistinguishable by design)." },
|
|
334
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "No email address on file for this account." },
|
|
335
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "Invalid credentials." },
|
|
336
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many resend attempts for this identifier. Try again later." },
|
|
337
|
-
501: { content: { "application/json": { schema: ErrorResponse } }, description: "The configured auth adapter does not support email verification." },
|
|
338
|
-
},
|
|
339
|
-
}), async (c) => {
|
|
340
|
-
const adapter = getAuthAdapter();
|
|
341
|
-
if (!adapter.getEmailVerified || !adapter.getUser) {
|
|
342
|
-
return c.json({ error: "Auth adapter does not support email verification" }, 501);
|
|
343
|
-
}
|
|
344
|
-
const body = c.req.valid("json");
|
|
345
|
-
const identifier = body[primaryField];
|
|
346
|
-
if (await trackAttempt(`resend:${identifier}`, resendOpts)) {
|
|
347
|
-
return c.json({ error: "Too many resend attempts. Try again later." }, 429);
|
|
348
|
-
}
|
|
349
|
-
const findFn = adapter.findByIdentifier ?? adapter.findByEmail.bind(adapter);
|
|
350
|
-
const user = await findFn(identifier);
|
|
351
|
-
if (!user || !(await Bun.password.verify(body.password, user.passwordHash))) {
|
|
352
|
-
return c.json({ error: "Invalid credentials" }, 401);
|
|
353
|
-
}
|
|
354
|
-
const alreadyVerified = await adapter.getEmailVerified(user.id);
|
|
355
|
-
// Return 200 (not 400) to avoid revealing whether the account is verified —
|
|
356
|
-
// distinguishing verified vs unverified would let attackers confirm valid credentials.
|
|
357
|
-
if (alreadyVerified)
|
|
358
|
-
return c.json({ message: "Verification email sent if not already verified" }, 200);
|
|
359
|
-
const fullUser = await adapter.getUser(user.id);
|
|
360
|
-
if (!fullUser?.email)
|
|
361
|
-
return c.json({ error: "No email address on file" }, 400);
|
|
362
|
-
const verificationToken = await createVerificationToken(user.id, fullUser.email);
|
|
363
|
-
await emailVerification.onSend(fullUser.email, verificationToken);
|
|
364
|
-
return c.json({ message: "Verification email sent" }, 200);
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
// Password reset routes — only mounted when passwordReset is configured and primaryField is "email"
|
|
368
|
-
if (passwordReset && primaryField === "email") {
|
|
369
|
-
router.openapi(createRoute({
|
|
370
|
-
method: "post",
|
|
371
|
-
path: "/auth/forgot-password",
|
|
372
|
-
summary: "Request password reset",
|
|
373
|
-
description: "Sends a password reset email if the address is registered. Always returns 200 regardless of whether the address exists, to prevent email enumeration. Rate-limited by both IP and email address.",
|
|
374
|
-
tags,
|
|
375
|
-
request: { body: { content: { "application/json": { schema: z.object({ email: z.string().email().describe("Email address to send the reset link to.") }) } }, description: "Email address for the account to reset." } },
|
|
376
|
-
responses: {
|
|
377
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Request received. A reset email will be sent if the address is registered." },
|
|
378
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Validation error (e.g. not a valid email address)." },
|
|
379
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many attempts from this IP or for this email address. Try again later." },
|
|
380
|
-
},
|
|
381
|
-
}), async (c) => {
|
|
382
|
-
const ip = getClientIp(c);
|
|
383
|
-
const { email } = c.req.valid("json");
|
|
384
|
-
// Rate-limit by both IP and email to prevent distributed email-bombing
|
|
385
|
-
const ipLimited = await trackAttempt(`forgot:ip:${ip}`, forgotOpts);
|
|
386
|
-
const emailLimited = await trackAttempt(`forgot:email:${email}`, forgotOpts);
|
|
387
|
-
if (ipLimited || emailLimited) {
|
|
388
|
-
return c.json({ error: "Too many attempts. Try again later." }, 429);
|
|
389
|
-
}
|
|
390
|
-
const adapter = getAuthAdapter();
|
|
391
|
-
const user = await adapter.findByEmail(email);
|
|
392
|
-
// Fire-and-forget: the response does not wait for token creation or email sending,
|
|
393
|
-
// which reduces obvious timing differences between registered and unregistered emails.
|
|
394
|
-
const msg = { message: "If that email is registered, a password reset link has been sent." };
|
|
395
|
-
if (user) {
|
|
396
|
-
void (async () => {
|
|
397
|
-
try {
|
|
398
|
-
const token = await createResetToken(user.id, email);
|
|
399
|
-
await passwordReset.onSend(email, token);
|
|
400
|
-
}
|
|
401
|
-
catch (err) {
|
|
402
|
-
console.error("Failed to send password reset email:", err);
|
|
403
|
-
}
|
|
404
|
-
})();
|
|
405
|
-
}
|
|
406
|
-
return c.json(msg, 200);
|
|
407
|
-
});
|
|
408
|
-
router.openapi(createRoute({
|
|
409
|
-
method: "post",
|
|
410
|
-
path: "/auth/reset-password",
|
|
411
|
-
summary: "Reset password",
|
|
412
|
-
description: "Consumes a single-use reset token and sets a new password. All active sessions are revoked after a successful reset to invalidate any stolen JWTs. Rate-limited by IP.",
|
|
413
|
-
tags,
|
|
414
|
-
request: {
|
|
415
|
-
body: {
|
|
416
|
-
content: {
|
|
417
|
-
"application/json": {
|
|
418
|
-
schema: z.object({
|
|
419
|
-
token: z.string().describe("Single-use reset token received via email."),
|
|
420
|
-
password: resetPasswordSchema().describe("New password."),
|
|
421
|
-
}),
|
|
422
|
-
},
|
|
423
|
-
},
|
|
424
|
-
description: "Reset token and new password.",
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
responses: {
|
|
428
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Password reset. All sessions have been revoked." },
|
|
429
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Validation error, or the reset token is invalid or expired." },
|
|
430
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many reset attempts from this IP. Try again later." },
|
|
431
|
-
501: { content: { "application/json": { schema: ErrorResponse } }, description: "The configured auth adapter does not support setPassword." },
|
|
432
|
-
},
|
|
433
|
-
}), async (c) => {
|
|
434
|
-
const ip = getClientIp(c);
|
|
435
|
-
if (await trackAttempt(`reset:${ip}`, resetOpts)) {
|
|
436
|
-
return c.json({ error: "Too many attempts. Try again later." }, 429);
|
|
437
|
-
}
|
|
438
|
-
const { token, password } = c.req.valid("json");
|
|
439
|
-
// consumeResetToken atomically gets and deletes — prevents concurrent replay
|
|
440
|
-
const entry = await consumeResetToken(token);
|
|
441
|
-
if (!entry)
|
|
442
|
-
return c.json({ error: "Invalid or expired reset token" }, 400);
|
|
443
|
-
const adapter = getAuthAdapter();
|
|
444
|
-
if (!adapter.setPassword) {
|
|
445
|
-
return c.json({ error: "Auth adapter does not support setPassword" }, 501);
|
|
446
|
-
}
|
|
447
|
-
const passwordHash = await Bun.password.hash(password);
|
|
448
|
-
await adapter.setPassword(entry.userId, passwordHash);
|
|
449
|
-
// Revoke all sessions so stolen JWTs can't stay valid after a reset
|
|
450
|
-
const sessions = await getUserSessions(entry.userId);
|
|
451
|
-
await Promise.all(sessions.map((s) => deleteSession(s.sessionId)));
|
|
452
|
-
return c.json({ message: "Password reset successfully" }, 200);
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
// ---------------------------------------------------------------------------
|
|
456
|
-
// Refresh token route — only mounted when refreshTokens is configured
|
|
457
|
-
// ---------------------------------------------------------------------------
|
|
458
|
-
if (refreshTokens) {
|
|
459
|
-
const RefreshResponse = z.object({
|
|
460
|
-
token: z.string().describe("New short-lived JWT access token."),
|
|
461
|
-
refreshToken: z.string().describe("New refresh token (rotation). The previous token is valid for a short grace window."),
|
|
462
|
-
userId: z.string().describe("Unique user ID."),
|
|
463
|
-
}).openapi("RefreshResponse");
|
|
464
|
-
router.openapi(createRoute({
|
|
465
|
-
method: "post",
|
|
466
|
-
path: "/auth/refresh",
|
|
467
|
-
summary: "Refresh access token",
|
|
468
|
-
description: "Exchanges a valid refresh token for a new access token and rotated refresh token. The old refresh token remains valid for a short grace window to handle network drops. If a previously rotated token is reused after the grace window, the entire session is invalidated (token theft detection).",
|
|
469
|
-
tags,
|
|
470
|
-
request: {
|
|
471
|
-
body: {
|
|
472
|
-
content: {
|
|
473
|
-
"application/json": {
|
|
474
|
-
schema: z.object({
|
|
475
|
-
refreshToken: z.string().optional().describe("Refresh token. Can also be sent via the refresh_token cookie or x-refresh-token header."),
|
|
476
|
-
}),
|
|
477
|
-
},
|
|
478
|
-
},
|
|
479
|
-
description: "Refresh token (optional if sent via cookie or header).",
|
|
480
|
-
},
|
|
481
|
-
},
|
|
482
|
-
responses: {
|
|
483
|
-
200: { content: { "application/json": { schema: RefreshResponse } }, description: "New access and refresh tokens." },
|
|
484
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "Invalid or expired refresh token, or session invalidated due to token theft detection." },
|
|
485
|
-
429: { content: { "application/json": { schema: ErrorResponse } }, description: "Too many refresh attempts. Try again later." },
|
|
486
|
-
},
|
|
487
|
-
}), async (c) => {
|
|
488
|
-
const ip = getClientIp(c);
|
|
489
|
-
if (await trackAttempt(`refresh:ip:${ip}`, { max: 30, windowMs: 60_000 })) {
|
|
490
|
-
return c.json({ error: "Too many refresh attempts. Try again later." }, 429);
|
|
491
|
-
}
|
|
492
|
-
const body = c.req.valid("json");
|
|
493
|
-
const rt = body.refreshToken ?? getCookie(c, COOKIE_REFRESH_TOKEN) ?? c.req.header(HEADER_REFRESH_TOKEN) ?? null;
|
|
494
|
-
if (!rt) {
|
|
495
|
-
return c.json({ error: "Refresh token is required" }, 401);
|
|
496
|
-
}
|
|
497
|
-
const result = await AuthService.refresh(rt);
|
|
498
|
-
setCookie(c, COOKIE_TOKEN, result.token, cookieOptions(getAccessTokenExpiry()));
|
|
499
|
-
setCookie(c, COOKIE_REFRESH_TOKEN, result.refreshToken, cookieOptions(getRefreshTokenExpiry()));
|
|
500
|
-
return c.json(result, 200);
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
// ---------------------------------------------------------------------------
|
|
504
|
-
// Account deletion cancellation — only mounted when queued: true + gracePeriod > 0
|
|
505
|
-
// ---------------------------------------------------------------------------
|
|
506
|
-
if (accountDeletion?.queued && accountDeletion.gracePeriod) {
|
|
507
|
-
router.openapi(createRoute({
|
|
508
|
-
method: "post",
|
|
509
|
-
path: "/auth/cancel-deletion",
|
|
510
|
-
summary: "Cancel scheduled account deletion",
|
|
511
|
-
description: "Cancels a pending queued account deletion using the cancel token sent via the onDeletionScheduled callback. Must be called before the grace period expires.",
|
|
512
|
-
tags,
|
|
513
|
-
request: {
|
|
514
|
-
body: {
|
|
515
|
-
content: {
|
|
516
|
-
"application/json": {
|
|
517
|
-
schema: z.object({
|
|
518
|
-
token: z.string().describe("Cancel token received in the deletion scheduled notification."),
|
|
519
|
-
}),
|
|
520
|
-
},
|
|
521
|
-
},
|
|
522
|
-
description: "Cancel token.",
|
|
523
|
-
},
|
|
524
|
-
},
|
|
525
|
-
responses: {
|
|
526
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Account deletion cancelled." },
|
|
527
|
-
400: { content: { "application/json": { schema: ErrorResponse } }, description: "Invalid or expired cancel token." },
|
|
528
|
-
},
|
|
529
|
-
}), async (c) => {
|
|
530
|
-
const { token } = c.req.valid("json");
|
|
531
|
-
const entry = await consumeDeletionCancelToken(token);
|
|
532
|
-
if (!entry)
|
|
533
|
-
return c.json({ error: "Invalid or expired cancel token" }, 400);
|
|
534
|
-
// Remove the pending BullMQ job
|
|
535
|
-
try {
|
|
536
|
-
const { createQueue } = await import("../lib/queue");
|
|
537
|
-
const appName = getAppName();
|
|
538
|
-
const queue = createQueue(`${appName}:account-deletions`);
|
|
539
|
-
const job = await queue.getJob(entry.jobId);
|
|
540
|
-
if (job)
|
|
541
|
-
await job.remove();
|
|
542
|
-
await queue.close();
|
|
543
|
-
}
|
|
544
|
-
catch {
|
|
545
|
-
// Job may have already executed — that's an error case but we still consumed the token
|
|
546
|
-
}
|
|
547
|
-
return c.json({ message: "Account deletion cancelled" }, 200);
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
// ---------------------------------------------------------------------------
|
|
551
|
-
// Session management
|
|
552
|
-
// ---------------------------------------------------------------------------
|
|
553
|
-
const SessionInfoSchema = z.object({
|
|
554
|
-
sessionId: z.string().describe("Unique session identifier (UUID)."),
|
|
555
|
-
createdAt: z.number().describe("Unix timestamp (ms) when the session was created."),
|
|
556
|
-
lastActiveAt: z.number().describe("Unix timestamp (ms) of the most recent authenticated request (updated when trackLastActive is enabled)."),
|
|
557
|
-
expiresAt: z.number().describe("Unix timestamp (ms) when the session expires."),
|
|
558
|
-
ipAddress: z.string().optional().describe("IP address of the client at session creation."),
|
|
559
|
-
userAgent: z.string().optional().describe("User-agent string of the client at session creation."),
|
|
560
|
-
isActive: z.boolean().describe("Whether the session is currently valid and unexpired."),
|
|
561
|
-
}).openapi("SessionInfo");
|
|
562
|
-
router.use("/auth/sessions", userAuth);
|
|
563
|
-
router.use("/auth/sessions/*", userAuth);
|
|
564
|
-
router.openapi(withSecurity(createRoute({
|
|
565
|
-
method: "get",
|
|
566
|
-
path: "/auth/sessions",
|
|
567
|
-
summary: "List sessions",
|
|
568
|
-
description: "Returns all sessions for the authenticated user. Includes inactive sessions when `sessionPolicy.includeInactiveSessions` is enabled. Requires a valid session.",
|
|
569
|
-
tags,
|
|
570
|
-
responses: {
|
|
571
|
-
200: {
|
|
572
|
-
content: { "application/json": { schema: z.object({ sessions: z.array(SessionInfoSchema) }) } },
|
|
573
|
-
description: "Sessions belonging to the authenticated user.",
|
|
574
|
-
},
|
|
575
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "No valid session." },
|
|
576
|
-
},
|
|
577
|
-
}), { cookieAuth: [] }, { userToken: [] }), async (c) => {
|
|
578
|
-
const userId = c.get("authUserId");
|
|
579
|
-
const sessions = await getUserSessions(userId);
|
|
580
|
-
return c.json({ sessions }, 200);
|
|
581
|
-
});
|
|
582
|
-
router.openapi(withSecurity(createRoute({
|
|
583
|
-
method: "delete",
|
|
584
|
-
path: "/auth/sessions/{sessionId}",
|
|
585
|
-
summary: "Revoke a session",
|
|
586
|
-
description: "Revokes a specific session by ID. Users can only revoke their own sessions. Useful for 'sign out of other devices' flows. Requires a valid session.",
|
|
587
|
-
tags,
|
|
588
|
-
request: { params: z.object({ sessionId: z.string().describe("UUID of the session to revoke.") }) },
|
|
589
|
-
responses: {
|
|
590
|
-
200: { content: { "application/json": { schema: z.object({ message: z.string() }) } }, description: "Session revoked successfully." },
|
|
591
|
-
401: { content: { "application/json": { schema: ErrorResponse } }, description: "No valid session." },
|
|
592
|
-
404: { content: { "application/json": { schema: ErrorResponse } }, description: "Session not found or does not belong to the authenticated user." },
|
|
593
|
-
},
|
|
594
|
-
}), { cookieAuth: [] }, { userToken: [] }), async (c) => {
|
|
595
|
-
const userId = c.get("authUserId");
|
|
596
|
-
const { sessionId } = c.req.valid("param");
|
|
597
|
-
const sessions = await getUserSessions(userId);
|
|
598
|
-
const session = sessions.find((s) => s.sessionId === sessionId);
|
|
599
|
-
if (!session)
|
|
600
|
-
return c.json({ error: "Session not found" }, 404);
|
|
601
|
-
await deleteSession(sessionId);
|
|
602
|
-
return c.json({ message: "Session revoked" }, 200);
|
|
603
|
-
});
|
|
604
|
-
return router;
|
|
605
|
-
};
|