@contember/engine-tenant-api 2.2.0-alpha.6 → 2.2.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/development/src/TenantContainer.cjs +5 -2
  2. package/dist/development/src/TenantContainer.cjs.map +1 -1
  3. package/dist/development/src/TenantContainer.js +5 -2
  4. package/dist/development/src/TenantContainer.js.map +1 -1
  5. package/dist/development/src/model/commands/apiKey/ProlongApiKeyCommand.cjs +5 -8
  6. package/dist/development/src/model/commands/apiKey/ProlongApiKeyCommand.cjs.map +1 -1
  7. package/dist/development/src/model/commands/apiKey/ProlongApiKeyCommand.js +5 -8
  8. package/dist/development/src/model/commands/apiKey/ProlongApiKeyCommand.js.map +1 -1
  9. package/dist/development/src/model/commands/authLog/CreateAuthLogEntryCommand.cjs.map +1 -1
  10. package/dist/development/src/model/commands/authLog/CreateAuthLogEntryCommand.js.map +1 -1
  11. package/dist/development/src/model/commands/idp/ClaimIdpRevalidationCommand.cjs +3 -7
  12. package/dist/development/src/model/commands/idp/ClaimIdpRevalidationCommand.cjs.map +1 -1
  13. package/dist/development/src/model/commands/idp/ClaimIdpRevalidationCommand.js +3 -7
  14. package/dist/development/src/model/commands/idp/ClaimIdpRevalidationCommand.js.map +1 -1
  15. package/dist/development/src/model/service/IDPSignInManager.cjs +23 -15
  16. package/dist/development/src/model/service/IDPSignInManager.cjs.map +1 -1
  17. package/dist/development/src/model/service/IDPSignInManager.js +23 -15
  18. package/dist/development/src/model/service/IDPSignInManager.js.map +1 -1
  19. package/dist/development/src/model/service/idp/IdpSessionRevalidator.cjs +42 -31
  20. package/dist/development/src/model/service/idp/IdpSessionRevalidator.cjs.map +1 -1
  21. package/dist/development/src/model/service/idp/IdpSessionRevalidator.js +42 -31
  22. package/dist/development/src/model/service/idp/IdpSessionRevalidator.js.map +1 -1
  23. package/dist/production/src/TenantContainer.cjs +5 -2
  24. package/dist/production/src/TenantContainer.cjs.map +1 -1
  25. package/dist/production/src/TenantContainer.js +5 -2
  26. package/dist/production/src/TenantContainer.js.map +1 -1
  27. package/dist/production/src/model/commands/apiKey/ProlongApiKeyCommand.cjs +5 -8
  28. package/dist/production/src/model/commands/apiKey/ProlongApiKeyCommand.cjs.map +1 -1
  29. package/dist/production/src/model/commands/apiKey/ProlongApiKeyCommand.js +5 -8
  30. package/dist/production/src/model/commands/apiKey/ProlongApiKeyCommand.js.map +1 -1
  31. package/dist/production/src/model/commands/authLog/CreateAuthLogEntryCommand.cjs.map +1 -1
  32. package/dist/production/src/model/commands/authLog/CreateAuthLogEntryCommand.js.map +1 -1
  33. package/dist/production/src/model/commands/idp/ClaimIdpRevalidationCommand.cjs +3 -7
  34. package/dist/production/src/model/commands/idp/ClaimIdpRevalidationCommand.cjs.map +1 -1
  35. package/dist/production/src/model/commands/idp/ClaimIdpRevalidationCommand.js +3 -7
  36. package/dist/production/src/model/commands/idp/ClaimIdpRevalidationCommand.js.map +1 -1
  37. package/dist/production/src/model/service/IDPSignInManager.cjs +23 -15
  38. package/dist/production/src/model/service/IDPSignInManager.cjs.map +1 -1
  39. package/dist/production/src/model/service/IDPSignInManager.js +23 -15
  40. package/dist/production/src/model/service/IDPSignInManager.js.map +1 -1
  41. package/dist/production/src/model/service/idp/IdpSessionRevalidator.cjs +42 -31
  42. package/dist/production/src/model/service/idp/IdpSessionRevalidator.cjs.map +1 -1
  43. package/dist/production/src/model/service/idp/IdpSessionRevalidator.js +42 -31
  44. package/dist/production/src/model/service/idp/IdpSessionRevalidator.js.map +1 -1
  45. package/dist/tests/cases/integration/mocked/sql/sqlTransaction.d.ts +5 -0
  46. package/dist/tests/cases/integration/mocked/sql/sqlTransaction.d.ts.map +1 -1
  47. package/dist/tests/cases/unit/idp/claimIdpRevalidation.test.d.ts +2 -0
  48. package/dist/tests/cases/unit/idp/claimIdpRevalidation.test.d.ts.map +1 -0
  49. package/dist/tests/src/IdPMock.d.ts.map +1 -1
  50. package/dist/tests/src/testTenant.d.ts.map +1 -1
  51. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  52. package/dist/types/TenantContainer.d.ts +2 -0
  53. package/dist/types/TenantContainer.d.ts.map +1 -1
  54. package/dist/types/model/commands/apiKey/ProlongApiKeyCommand.d.ts +5 -3
  55. package/dist/types/model/commands/apiKey/ProlongApiKeyCommand.d.ts.map +1 -1
  56. package/dist/types/model/commands/authLog/CreateAuthLogEntryCommand.d.ts +1 -0
  57. package/dist/types/model/commands/authLog/CreateAuthLogEntryCommand.d.ts.map +1 -1
  58. package/dist/types/model/commands/idp/ClaimIdpRevalidationCommand.d.ts.map +1 -1
  59. package/dist/types/model/service/IDPSignInManager.d.ts +3 -1
  60. package/dist/types/model/service/IDPSignInManager.d.ts.map +1 -1
  61. package/dist/types/model/service/idp/IdpSessionRevalidator.d.ts +3 -1
  62. package/dist/types/model/service/idp/IdpSessionRevalidator.d.ts.map +1 -1
  63. package/dist/types/tsconfig.tsbuildinfo +1 -1
  64. package/package.json +12 -12
  65. package/src/TenantContainer.ts +7 -2
  66. package/src/model/commands/apiKey/ProlongApiKeyCommand.ts +10 -11
  67. package/src/model/commands/authLog/CreateAuthLogEntryCommand.ts +1 -0
  68. package/src/model/commands/idp/ClaimIdpRevalidationCommand.ts +8 -7
  69. package/src/model/service/IDPSignInManager.ts +26 -14
  70. package/src/model/service/idp/IdpSessionRevalidator.ts +43 -28
  71. package/tests/cases/integration/mocked/signInIdpMutation.test.ts +100 -1
  72. package/tests/cases/integration/mocked/sql/sqlTransaction.ts +16 -0
  73. package/tests/cases/unit/apiKey/prolongApiKeyCommand.test.ts +19 -9
  74. package/tests/cases/unit/idp/claimIdpRevalidation.test.ts +50 -0
  75. package/tests/cases/unit/idp/idpSessionRevalidator.test.ts +37 -4
  76. package/tests/src/IdPMock.ts +2 -0
  77. package/tests/src/testTenant.ts +1 -0
@@ -151,7 +151,10 @@ class TenantContainerFactory {
151
151
  idpRegistry.registerHandler("facebook", new FacebookProvider());
152
152
  idpRegistry.registerHandler("apple", new AppleProvider());
153
153
  return idpRegistry;
154
- }).addService("idpClaimSyncService", ({ projectSchemaResolver }) => new IDPClaimSyncService(projectSchemaResolver)).addService("idpSessionRevalidator", ({ idpRegistry, idpClaimSyncService }) => new IdpSessionRevalidator(idpRegistry, idpClaimSyncService)).addService("backchannelLogoutManager", ({ idpRegistry }) => new BackchannelLogoutManager(idpRegistry)).addService("unpersistedApiKeyManager", () => UnpersistedApiKeyManager.createForRootTokens({
154
+ }).addService("idpClaimSyncService", ({ projectSchemaResolver }) => new IDPClaimSyncService(projectSchemaResolver)).addService(
155
+ "idpSessionRevalidator",
156
+ ({ idpRegistry, idpClaimSyncService }) => new IdpSessionRevalidator(idpRegistry, idpClaimSyncService, args.logger)
157
+ ).addService("backchannelLogoutManager", ({ idpRegistry }) => new BackchannelLogoutManager(idpRegistry)).addService("unpersistedApiKeyManager", () => UnpersistedApiKeyManager.createForRootTokens({
155
158
  tokens: args.tenantCredentials.rootTokens,
156
159
  tokenHashes: args.tenantCredentials.rootTokenHashes
157
160
  })).addService(
@@ -178,7 +181,7 @@ class TenantContainerFactory {
178
181
  ({ userMailer, projectManager, emailValidator, apiKeyManager, permissionContextFactory }) => new EmailChangeManager(userMailer, projectManager, emailValidator, apiKeyManager, permissionContextFactory)
179
182
  ).addService(
180
183
  "idpSignInManager",
181
- ({ apiKeyManager, idpRegistry, idpClaimSyncService }) => new IDPSignInManager(apiKeyManager, idpRegistry, idpClaimSyncService)
184
+ ({ apiKeyManager, idpRegistry, idpClaimSyncService }) => new IDPSignInManager(apiKeyManager, idpRegistry, idpClaimSyncService, args.logger)
182
185
  ).addService("idpManager", ({ idpRegistry, projectSchemaResolver }) => new IDPManager(idpRegistry, projectSchemaResolver)).addService("personIdentityProviderManager", () => new PersonIdentityProviderManager()).addService("otpAuthenticator", ({ providers }) => new OtpAuthenticator(providers)).addService("otpManager", ({ otpAuthenticator, providers }) => new OtpManager(otpAuthenticator, providers)).addService("backupCodeManager", ({ providers, userMailer }) => new BackupCodeManager(userMailer, providers)).addService("emailOtpManager", ({ userMailer, providers, rateLimiter }) => new EmailOtpManager(userMailer, providers, rateLimiter)).addService("authPolicyManager", ({ projectManager }) => new AuthPolicyManager(projectManager)).addService(
183
186
  "signInManager",
184
187
  ({ apiKeyManager, providers, otpManager, backupCodeManager, emailOtpManager, authPolicyResolver, loginRiskAnalyzer, userMailer }) => new SignInManager(
@@ -1 +1 @@
1
- {"version":3,"file":"TenantContainer.js","sources":["../../../../packages/engine-tenant-api/src/TenantContainer.ts"],"sourcesContent":["import { AccessEvaluator, Authorizator } from '@contember/authorization'\nimport { Connection, DatabaseConfig } from '@contember/database'\nimport { Builder } from '@contember/dic'\nimport {\n\tAclSchemaAccessNodeFactory,\n\tApiKeyManager,\n\tApiKeyService,\n\tAppleProvider,\n\tAuthPolicyManager,\n\tAuthPolicyResolver,\n\tBackchannelLogoutManager,\n\tBackupCodeManager,\n\tCaptchaValidator,\n\tDatabaseContext,\n\tEmailChangeManager,\n\tEmailOtpManager,\n\tEmailValidator,\n\tEmailVerificationManager,\n\tFacebookProvider,\n\tHCaptchaProvider,\n\tIdentity,\n\tIdentityFactory,\n\tIDPClaimSyncService,\n\tIDPHandlerRegistry,\n\tIDPManager,\n\tIdpSessionRevalidator,\n\tIDPSignInManager,\n\tInviteManager,\n\tLoginRiskAnalyzer,\n\tMailTemplateManager,\n\tMembershipValidator,\n\tOIDCProvider,\n\tOtpAuthenticator,\n\tOtpManager,\n\tPanelAccessResolver,\n\tPasswordChangeManager,\n\tPasswordResetManager,\n\tPermissionContextFactory,\n\tPermissionsFactory,\n\tPersonAccessManager,\n\tPersonIdentityProviderManager,\n\tPersonManager,\n\tProjectInitializer,\n\tProjectManager,\n\tProjectMemberManager,\n\tProjectSchemaResolver,\n\tProjectScopeFactory,\n\tProviders,\n\tRateLimiter,\n\tRecaptchaV3Provider,\n\tRolesManager,\n\tSecretsManager,\n\tSignInManager,\n\tSignOutManager,\n\tSignUpManager,\n\tTurnstileProvider,\n\tUnpersistedApiKeyManager,\n\tUserMailer,\n} from './model/index.js'\nimport { HibpChecker, HttpHibpChecker, NoopHibpChecker } from './model/service/HibpChecker.js'\nimport {\n\tAddIDPMutationResolver,\n\tAddProjectMemberMutationResolver,\n\tChangePasswordMutationResolver,\n\tChangeProfileMutationResolver,\n\tCreateApiKeyMutationResolver,\n\tCreateProjectMutationResolver,\n\tDisableApiKeyMutationResolver,\n\tDisableIDPMutationResolver,\n\tDisconnectMyIdentityProviderMutationResolver,\n\tEmailOtpMutationResolver,\n\tEmailVerificationMutationResolver,\n\tEnableIDPMutationResolver,\n\tIdentityGlobalRolesMutationResolver,\n\tIdentityTypeResolver,\n\tIDPMutationResolver,\n\tInviteMutationResolver,\n\tMailTemplateMutationResolver,\n\tMeQueryResolver,\n\tOtpMutationResolver,\n\tPersonQueryResolver,\n\tPersonTypeResolver,\n\tProjectMembersQueryResolver,\n\tProjectQueryResolver,\n\tProjectTypeResolver,\n\tRegenerateBackupCodesMutationResolver,\n\tRemoveProjectMemberMutationResolver,\n\tResetPasswordMutationResolver,\n\tResolverFactory,\n\tSetProjectSecretMutationResolver,\n\tSignInMutationResolver,\n\tSignOutMutationResolver,\n\tSignUpMutationResolver,\n\tTenantResolverContextFactory,\n\tUpdateProjectMemberMutationResolver,\n\tUpdateProjectMutationResolver,\n} from './resolvers/index.js'\nimport * as Schema from './schema/index.js'\nimport { createMailer, MailerOptions, TemplateRenderer } from './utils/index.js'\nimport { IdentityFetcher } from './bridges/system/IdentityFetcher.js'\nimport { SignInResponseFactory } from './resolvers/responseHelpers/SignInResponseFactory.js'\nimport { IDPQueryResolver } from './resolvers/query/IDPQueryResolver.js'\nimport { UpdateIDPMutationResolver } from './resolvers/mutation/idp/UpdateIDPMutationResolver.js'\nimport { TenantCredentials, TenantMigrationsRunner } from './migrations/index.js'\nimport { DisablePersonMutationResolver } from './resolvers/mutation/person/DisablePersonMutationResolver.js'\nimport { EnablePersonMutationResolver } from './resolvers/mutation/person/EnablePersonMutationResolver.js'\nimport { ForceSignOutMutationResolver } from './resolvers/mutation/person/ForceSignOutMutationResolver.js'\nimport { RevokeSessionMutationResolver } from './resolvers/mutation/person/RevokeSessionMutationResolver.js'\nimport { MailTemplateQueryResolver } from './resolvers/query/MailTemplateQueryResolver.js'\nimport { ConfigurationManager } from './model/service/ConfigurationManager.js'\nimport { ConfigurationMutationResolver } from './resolvers/mutation/configuration/ConfigurationMutationResolver.js'\nimport { ConfigurationQueryResolver } from './resolvers/query/ConfigurationQueryResolver.js'\nimport { AuthPolicyMutationResolver } from './resolvers/mutation/configuration/AuthPolicyMutationResolver.js'\nimport { AuthPolicyQueryResolver } from './resolvers/query/AuthPolicyQueryResolver.js'\nimport { ResetPersonMfaMutationResolver } from './resolvers/mutation/person/ResetPersonMfaMutationResolver.js'\nimport { AuthLogQueryResolver } from './resolvers/query/AuthLogQueryResolver.js'\nimport { ApiKeyQueryResolver } from './resolvers/query/ApiKeyQueryResolver.js'\nimport { PasswordlessMutationResolver } from './resolvers/mutation/person/PasswordlessMutationResolver.js'\nimport { PasswordlessSignInManager } from './model/service/PasswordlessSignInManager.js'\nimport { TogglePasswordlessMutationResolver } from './resolvers/mutation/person/TogglePasswordlessMutationResolver.js'\nimport { PasswordStrengthValidator } from './model/service/PasswordStrengthValidator.js'\nimport { AuthLogService } from './model/service/AuthLogService.js'\n\nexport interface TenantContainer {\n\tprojectMemberManager: ProjectMemberManager\n\tapiKeyManager: ApiKeyManager\n\tbackchannelLogoutManager: BackchannelLogoutManager\n\tsignUpManager: SignUpManager\n\tprojectManager: ProjectManager\n\tpanelAccessResolver: PanelAccessResolver\n\tresolvers: Schema.Resolvers\n\tresolverContextFactory: TenantResolverContextFactory\n\tauthorizator: Authorizator<Identity>\n\tidentityFetcher: IdentityFetcher\n\tdatabaseContext: DatabaseContext\n\treadDatabaseContext: DatabaseContext\n\tmigrationsRunner: TenantMigrationsRunner\n\tconnection: Connection.ConnectionType\n\treadConnection: Connection.ConnectionType\n}\n\nexport interface TenantContainerArgs {\n\tconnection: Connection.ConnectionType\n\treadConnection: Connection.ConnectionType\n\tdbCredentials: DatabaseConfig\n\tmailOptions: MailerOptions\n\tprojectSchemaResolver: ProjectSchemaResolver\n\tprojectInitializer: ProjectInitializer\n\ttenantCredentials: TenantCredentials\n\tcryptoProviders: Pick<Providers, 'encrypt' | 'decrypt' | 'encryptionEnabled'>\n}\n\nexport class TenantContainerFactory {\n\tconstructor(\n\t\tprivate readonly providers: Omit<Providers, 'encrypt' | 'decrypt' | 'encryptionEnabled'>,\n\t) {}\n\n\tcreate(args: TenantContainerArgs): TenantContainer {\n\t\treturn this.createBuilder(args)\n\t\t\t.build()\n\t\t\t.pick(\n\t\t\t\t'apiKeyManager',\n\t\t\t\t'backchannelLogoutManager',\n\t\t\t\t'projectMemberManager',\n\t\t\t\t'projectManager',\n\t\t\t\t'panelAccessResolver',\n\t\t\t\t'signUpManager',\n\t\t\t\t'resolvers',\n\t\t\t\t'authorizator',\n\t\t\t\t'resolverContextFactory',\n\t\t\t\t'identityFetcher',\n\t\t\t\t'databaseContext',\n\t\t\t\t'readDatabaseContext',\n\t\t\t\t'migrationsRunner',\n\t\t\t\t'connection',\n\t\t\t\t'readConnection',\n\t\t\t)\n\t}\n\n\tcreateBuilder(args: TenantContainerArgs) {\n\t\treturn new Builder({})\n\t\t\t.addService('providers', () => ({ ...this.providers, ...args.cryptoProviders }))\n\t\t\t.addService('mailer', () => createMailer(args.mailOptions))\n\t\t\t.addService('projectSchemaResolver', () => args.projectSchemaResolver)\n\t\t\t.addService('templateRenderer', () => new TemplateRenderer())\n\t\t\t.addService('accessEvaluator', ({}) => new AccessEvaluator.PermissionEvaluator(new PermissionsFactory().create()))\n\t\t\t.addService('authorizator', ({ accessEvaluator }) => new Authorizator.Default(accessEvaluator))\n\t\t\t.addService('userMailer', ({ mailer, templateRenderer }) => new UserMailer(mailer, templateRenderer))\n\t\t\t.addService('apiKeyService', () => new ApiKeyService())\n\t\t\t.addService('authPolicyResolver', () => new AuthPolicyResolver())\n\t\t\t.addService('panelAccessResolver', ({ providers }) => new PanelAccessResolver(providers))\n\t\t\t.addService('authLogService', () => new AuthLogService())\n\t\t\t.addService('loginRiskAnalyzer', ({ providers }) => new LoginRiskAnalyzer(providers.hash))\n\t\t\t.addService('idpRegistry', () => {\n\t\t\t\tconst idpRegistry = new IDPHandlerRegistry()\n\t\t\t\tidpRegistry.registerHandler('oidc', new OIDCProvider())\n\t\t\t\tidpRegistry.registerHandler('facebook', new FacebookProvider())\n\t\t\t\tidpRegistry.registerHandler('apple', new AppleProvider())\n\t\t\t\treturn idpRegistry\n\t\t\t})\n\t\t\t.addService('idpClaimSyncService', ({ projectSchemaResolver }) => new IDPClaimSyncService(projectSchemaResolver))\n\t\t\t.addService('idpSessionRevalidator', ({ idpRegistry, idpClaimSyncService }) => new IdpSessionRevalidator(idpRegistry, idpClaimSyncService))\n\t\t\t.addService('backchannelLogoutManager', ({ idpRegistry }) => new BackchannelLogoutManager(idpRegistry))\n\t\t\t.addService('unpersistedApiKeyManager', () =>\n\t\t\t\tUnpersistedApiKeyManager.createForRootTokens({\n\t\t\t\t\ttokens: args.tenantCredentials.rootTokens,\n\t\t\t\t\ttokenHashes: args.tenantCredentials.rootTokenHashes,\n\t\t\t\t}))\n\t\t\t.addService(\n\t\t\t\t'apiKeyManager',\n\t\t\t\t({ apiKeyService, authPolicyResolver, authLogService, unpersistedApiKeyManager, idpSessionRevalidator }) =>\n\t\t\t\t\tnew ApiKeyManager(apiKeyService, authPolicyResolver, authLogService, unpersistedApiKeyManager, idpSessionRevalidator),\n\t\t\t)\n\t\t\t.addService('signOutManager', ({ apiKeyManager, idpRegistry }) => new SignOutManager(apiKeyManager, idpRegistry))\n\t\t\t.addService('emailValidator', () => new EmailValidator())\n\t\t\t.addService('hibpChecker', (): HibpChecker => new HttpHibpChecker())\n\t\t\t.addService('noopHibpChecker', (): HibpChecker => new NoopHibpChecker())\n\t\t\t.addService('passwordStrengthValidator', ({ hibpChecker }) => new PasswordStrengthValidator(hibpChecker))\n\t\t\t.addService('captchaValidator', () =>\n\t\t\t\tnew CaptchaValidator({\n\t\t\t\t\tturnstile: new TurnstileProvider(),\n\t\t\t\t\thcaptcha: new HCaptchaProvider(),\n\t\t\t\t\trecaptchaV3: new RecaptchaV3Provider(),\n\t\t\t\t}))\n\t\t\t.addService('rateLimiter', ({ providers }) => new RateLimiter(providers))\n\t\t\t.addService(\n\t\t\t\t'signUpManager',\n\t\t\t\t({ emailValidator, passwordStrengthValidator }) => new SignUpManager(emailValidator, passwordStrengthValidator),\n\t\t\t)\n\t\t\t.addService('passwordChangeManager', ({ providers, passwordStrengthValidator }) => new PasswordChangeManager(providers, passwordStrengthValidator))\n\t\t\t.addService('projectMemberManager', () => new ProjectMemberManager())\n\t\t\t.addService('identityFactory', ({ projectMemberManager }) => new IdentityFactory(projectMemberManager))\n\t\t\t.addService('projectScopeFactory', () => new ProjectScopeFactory(new AclSchemaAccessNodeFactory()))\n\t\t\t.addService(\n\t\t\t\t'permissionContextFactory',\n\t\t\t\t({ authorizator, identityFactory, projectScopeFactory, projectSchemaResolver }) =>\n\t\t\t\t\tnew PermissionContextFactory(authorizator, identityFactory, projectScopeFactory, projectSchemaResolver),\n\t\t\t)\n\t\t\t.addService('secretManager', ({ providers }) => new SecretsManager(providers))\n\t\t\t.addService('projectManager', ({ secretManager, apiKeyService }) => new ProjectManager(secretManager, args.projectInitializer, apiKeyService))\n\t\t\t.addService('personAccessManager', ({ apiKeyManager }) => new PersonAccessManager(apiKeyManager))\n\t\t\t.addService('personManager', ({ emailValidator }) => new PersonManager(emailValidator))\n\t\t\t.addService(\n\t\t\t\t'passwordResetManager',\n\t\t\t\t({ userMailer, projectManager, passwordStrengthValidator }) => new PasswordResetManager(userMailer, projectManager, passwordStrengthValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailVerificationManager',\n\t\t\t\t({ userMailer, projectManager }) => new EmailVerificationManager(userMailer, projectManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailChangeManager',\n\t\t\t\t({ userMailer, projectManager, emailValidator, apiKeyManager, permissionContextFactory }) =>\n\t\t\t\t\tnew EmailChangeManager(userMailer, projectManager, emailValidator, apiKeyManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'idpSignInManager',\n\t\t\t\t({ apiKeyManager, idpRegistry, idpClaimSyncService }) => new IDPSignInManager(apiKeyManager, idpRegistry, idpClaimSyncService),\n\t\t\t)\n\t\t\t.addService('idpManager', ({ idpRegistry, projectSchemaResolver }) => new IDPManager(idpRegistry, projectSchemaResolver))\n\t\t\t.addService('personIdentityProviderManager', () => new PersonIdentityProviderManager())\n\t\t\t.addService('otpAuthenticator', ({ providers }) => new OtpAuthenticator(providers))\n\t\t\t.addService('otpManager', ({ otpAuthenticator, providers }) => new OtpManager(otpAuthenticator, providers))\n\t\t\t.addService('backupCodeManager', ({ providers, userMailer }) => new BackupCodeManager(userMailer, providers))\n\t\t\t.addService('emailOtpManager', ({ userMailer, providers, rateLimiter }) => new EmailOtpManager(userMailer, providers, rateLimiter))\n\t\t\t.addService('authPolicyManager', ({ projectManager }) => new AuthPolicyManager(projectManager))\n\t\t\t.addService(\n\t\t\t\t'signInManager',\n\t\t\t\t({ apiKeyManager, providers, otpManager, backupCodeManager, emailOtpManager, authPolicyResolver, loginRiskAnalyzer, userMailer }) =>\n\t\t\t\t\tnew SignInManager(\n\t\t\t\t\t\tapiKeyManager,\n\t\t\t\t\t\tproviders,\n\t\t\t\t\t\totpManager,\n\t\t\t\t\t\tbackupCodeManager,\n\t\t\t\t\t\temailOtpManager,\n\t\t\t\t\t\tauthPolicyResolver,\n\t\t\t\t\t\tloginRiskAnalyzer,\n\t\t\t\t\t\tuserMailer,\n\t\t\t\t\t),\n\t\t\t)\n\t\t\t.addService('membershipValidator', ({ projectSchemaResolver }) => new MembershipValidator(projectSchemaResolver))\n\t\t\t.addService('inviteManager', ({ providers, userMailer, projectSchemaResolver }) => new InviteManager(providers, userMailer, projectSchemaResolver))\n\t\t\t.addService('mailTemplateManager', () => new MailTemplateManager())\n\t\t\t.addService('rolesManager', () => new RolesManager())\n\t\t\t.addService('configurationManager', () => new ConfigurationManager())\n\t\t\t.addService(\n\t\t\t\t'passwordlessSignInManager',\n\t\t\t\t({ apiKeyManager, userMailer, projectManager, otpManager, backupCodeManager }) =>\n\t\t\t\t\tnew PasswordlessSignInManager(apiKeyManager, userMailer, projectManager, otpManager, backupCodeManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'identityTypeResolver',\n\t\t\t\t({ projectMemberManager, projectManager, permissionContextFactory }) =>\n\t\t\t\t\tnew IdentityTypeResolver(projectMemberManager, projectManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'projectTypeResolver',\n\t\t\t\t({ projectMemberManager, projectSchemaResolver, secretManager }) =>\n\t\t\t\t\tnew ProjectTypeResolver(projectMemberManager, projectSchemaResolver, secretManager),\n\t\t\t)\n\t\t\t.addService('personTypeResolver', ({ personIdentityProviderManager }) => new PersonTypeResolver(personIdentityProviderManager))\n\t\t\t.addService(\n\t\t\t\t'signInResponseFactory',\n\t\t\t\t({ permissionContextFactory, identityTypeResolver }) => new SignInResponseFactory(permissionContextFactory, identityTypeResolver),\n\t\t\t)\n\t\t\t.addService('meQueryResolver', () => new MeQueryResolver())\n\t\t\t.addService(\n\t\t\t\t'personQueryResolver',\n\t\t\t\t({ personManager, projectManager, projectMemberManager }) => new PersonQueryResolver(personManager, projectManager, projectMemberManager),\n\t\t\t)\n\t\t\t.addService('idpQueryResolver', ({ idpManager }) => new IDPQueryResolver(idpManager))\n\t\t\t.addService('projectQueryResolver', ({ projectManager }) => new ProjectQueryResolver(projectManager))\n\t\t\t.addService(\n\t\t\t\t'projectMembersQueryResolver',\n\t\t\t\t({ projectManager, projectMemberManager }) => new ProjectMembersQueryResolver(projectManager, projectMemberManager),\n\t\t\t)\n\t\t\t.addService('mailTemplateQueryResolver', () => new MailTemplateQueryResolver())\n\t\t\t.addService(\n\t\t\t\t'signUpMutationResolver',\n\t\t\t\t({ signUpManager, apiKeyManager, captchaValidator, rateLimiter, emailVerificationManager, permissionContextFactory }) =>\n\t\t\t\t\tnew SignUpMutationResolver(signUpManager, apiKeyManager, captchaValidator, rateLimiter, emailVerificationManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'signInMutationResolver',\n\t\t\t\t({ signInManager, signInResponseFactory, rateLimiter }) => new SignInMutationResolver(signInManager, signInResponseFactory, rateLimiter),\n\t\t\t)\n\t\t\t.addService('signOutMutationResolver', ({ signOutManager }) => new SignOutMutationResolver(signOutManager))\n\t\t\t.addService(\n\t\t\t\t'changeProfileMutationResolver',\n\t\t\t\t({ personManager, emailChangeManager, permissionContextFactory }) =>\n\t\t\t\t\tnew ChangeProfileMutationResolver(personManager, emailChangeManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailVerificationMutationResolver',\n\t\t\t\t({ emailVerificationManager, permissionContextFactory, captchaValidator, rateLimiter }) =>\n\t\t\t\t\tnew EmailVerificationMutationResolver(emailVerificationManager, permissionContextFactory, captchaValidator, rateLimiter),\n\t\t\t)\n\t\t\t.addService('changePasswordMutationResolver', ({ passwordChangeManager }) => new ChangePasswordMutationResolver(passwordChangeManager))\n\t\t\t.addService(\n\t\t\t\t'resetPasswordMutationResolver',\n\t\t\t\t({ passwordResetManager, permissionContextFactory, captchaValidator, rateLimiter }) =>\n\t\t\t\t\tnew ResetPasswordMutationResolver(passwordResetManager, permissionContextFactory, captchaValidator, rateLimiter),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'inviteMutationResolver',\n\t\t\t\t({ inviteManager, projectManager, membershipValidator }) => new InviteMutationResolver(inviteManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'addProjectMemberMutationResolver',\n\t\t\t\t({ projectMemberManager, projectManager, membershipValidator }) =>\n\t\t\t\t\tnew AddProjectMemberMutationResolver(projectMemberManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'updateProjectMemberMutationResolver',\n\t\t\t\t({ projectMemberManager, projectManager, membershipValidator }) =>\n\t\t\t\t\tnew UpdateProjectMemberMutationResolver(projectMemberManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'removeProjectMemberMutationResolver',\n\t\t\t\t({ projectMemberManager, projectManager }) => new RemoveProjectMemberMutationResolver(projectMemberManager, projectManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'createApiKeyMutationResolver',\n\t\t\t\t({ apiKeyManager, projectManager, membershipValidator }) => new CreateApiKeyMutationResolver(apiKeyManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService('disableApiKeyMutationResolver', ({ apiKeyManager }) => new DisableApiKeyMutationResolver(apiKeyManager))\n\t\t\t.addService(\n\t\t\t\t'otpMutationResolver',\n\t\t\t\t({ otpManager, backupCodeManager, authPolicyResolver }) => new OtpMutationResolver(otpManager, backupCodeManager, authPolicyResolver),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailOtpMutationResolver',\n\t\t\t\t({ emailOtpManager, backupCodeManager, authPolicyResolver }) =>\n\t\t\t\t\tnew EmailOtpMutationResolver(emailOtpManager, backupCodeManager, authPolicyResolver),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'regenerateBackupCodesMutationResolver',\n\t\t\t\t({ backupCodeManager }) => new RegenerateBackupCodesMutationResolver(backupCodeManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'mailTemplateMutationResolver',\n\t\t\t\t({ projectManager, mailTemplateManager }) => new MailTemplateMutationResolver(projectManager, mailTemplateManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'idpMutationResolver',\n\t\t\t\t({ idpSignInManager, signInResponseFactory }) => new IDPMutationResolver(idpSignInManager, signInResponseFactory),\n\t\t\t)\n\t\t\t.addService('registerIdpMutationResolver', ({ idpManager }) => new AddIDPMutationResolver(idpManager))\n\t\t\t.addService('updateIdpMutationResolver', ({ idpManager }) => new UpdateIDPMutationResolver(idpManager))\n\t\t\t.addService('disableIdpMutationResolver', ({ idpManager }) => new DisableIDPMutationResolver(idpManager))\n\t\t\t.addService('enableIdpMutationResolver', ({ idpManager }) => new EnableIDPMutationResolver(idpManager))\n\t\t\t.addService(\n\t\t\t\t'disconnectMyIdentityProviderMutationResolver',\n\t\t\t\t({ personIdentityProviderManager }) => new DisconnectMyIdentityProviderMutationResolver(personIdentityProviderManager),\n\t\t\t)\n\t\t\t.addService('createProjectMutationResolver', ({ projectManager }) => new CreateProjectMutationResolver(projectManager))\n\t\t\t.addService(\n\t\t\t\t'disablePersonMutationResolver',\n\t\t\t\t({ personAccessManager, personManager }) => new DisablePersonMutationResolver(personAccessManager, personManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'enablePersonMutationResolver',\n\t\t\t\t({ personAccessManager, personManager }) => new EnablePersonMutationResolver(personAccessManager, personManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'forceSignOutMutationResolver',\n\t\t\t\t({ apiKeyManager, personManager, userMailer }) => new ForceSignOutMutationResolver(apiKeyManager, personManager, userMailer),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'resetPersonMfaMutationResolver',\n\t\t\t\t({ personManager, backupCodeManager }) => new ResetPersonMfaMutationResolver(personManager, backupCodeManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'revokeSessionMutationResolver',\n\t\t\t\t({ apiKeyManager }) => new RevokeSessionMutationResolver(apiKeyManager),\n\t\t\t)\n\t\t\t.addService('updateProjectMutationResolver', ({ projectManager }) => new UpdateProjectMutationResolver(projectManager))\n\t\t\t.addService(\n\t\t\t\t'setProjectSecretMutationResolver',\n\t\t\t\t({ projectManager, secretManager }) => new SetProjectSecretMutationResolver(projectManager, secretManager),\n\t\t\t)\n\t\t\t.addService('identityGlobalRolesMutationResolver', ({ rolesManager }) => new IdentityGlobalRolesMutationResolver(rolesManager))\n\t\t\t.addService('configurationMutationResolver', ({ configurationManager }) => new ConfigurationMutationResolver(configurationManager))\n\t\t\t.addService('configurationQueryResolver', ({ configurationManager }) => new ConfigurationQueryResolver(configurationManager))\n\t\t\t.addService('authPolicyMutationResolver', ({ authPolicyManager }) => new AuthPolicyMutationResolver(authPolicyManager))\n\t\t\t.addService('authPolicyQueryResolver', ({ authPolicyManager }) => new AuthPolicyQueryResolver(authPolicyManager))\n\t\t\t.addService('authLogQueryResolver', () => new AuthLogQueryResolver())\n\t\t\t.addService('apiKeyQueryResolver', () => new ApiKeyQueryResolver())\n\t\t\t.addService(\n\t\t\t\t'passwordlessMutationResolver',\n\t\t\t\t({ passwordlessSignInManager, signInResponseFactory, captchaValidator, rateLimiter }) =>\n\t\t\t\t\tnew PasswordlessMutationResolver(passwordlessSignInManager, signInResponseFactory, captchaValidator, rateLimiter),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'togglePasswordlessMutationResolver',\n\t\t\t\t({ configurationManager, personManager }) => new TogglePasswordlessMutationResolver(configurationManager, personManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'resolverContextFactory',\n\t\t\t\t({ permissionContextFactory, authLogService, loginRiskAnalyzer }) =>\n\t\t\t\t\tnew TenantResolverContextFactory(permissionContextFactory, authLogService, loginRiskAnalyzer),\n\t\t\t)\n\t\t\t.addService('resolvers', container => new ResolverFactory(container).create())\n\t\t\t.addService('connection', () => args.connection)\n\t\t\t.addService('readConnection', () => args.readConnection)\n\t\t\t.addService(\n\t\t\t\t'databaseContext',\n\t\t\t\t({ connection, providers }) => new DatabaseContext(connection.createClient('tenant', { module: 'tenant' }), providers),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'readDatabaseContext',\n\t\t\t\t({ readConnection, providers }) => new DatabaseContext(readConnection.createClient('tenant', { module: 'tenant' }), providers),\n\t\t\t)\n\t\t\t.addService('identityFetcher', ({ databaseContext }) => new IdentityFetcher(databaseContext.client))\n\t\t\t.addService('migrationsRunner', ({ providers }) => new TenantMigrationsRunner(args.dbCredentials, 'tenant', args.tenantCredentials, providers))\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TenantContainer.js","sources":["../../../../packages/engine-tenant-api/src/TenantContainer.ts"],"sourcesContent":["import { Logger } from '@contember/logger'\nimport { AccessEvaluator, Authorizator } from '@contember/authorization'\nimport { Connection, DatabaseConfig } from '@contember/database'\nimport { Builder } from '@contember/dic'\nimport {\n\tAclSchemaAccessNodeFactory,\n\tApiKeyManager,\n\tApiKeyService,\n\tAppleProvider,\n\tAuthPolicyManager,\n\tAuthPolicyResolver,\n\tBackchannelLogoutManager,\n\tBackupCodeManager,\n\tCaptchaValidator,\n\tDatabaseContext,\n\tEmailChangeManager,\n\tEmailOtpManager,\n\tEmailValidator,\n\tEmailVerificationManager,\n\tFacebookProvider,\n\tHCaptchaProvider,\n\tIdentity,\n\tIdentityFactory,\n\tIDPClaimSyncService,\n\tIDPHandlerRegistry,\n\tIDPManager,\n\tIdpSessionRevalidator,\n\tIDPSignInManager,\n\tInviteManager,\n\tLoginRiskAnalyzer,\n\tMailTemplateManager,\n\tMembershipValidator,\n\tOIDCProvider,\n\tOtpAuthenticator,\n\tOtpManager,\n\tPanelAccessResolver,\n\tPasswordChangeManager,\n\tPasswordResetManager,\n\tPermissionContextFactory,\n\tPermissionsFactory,\n\tPersonAccessManager,\n\tPersonIdentityProviderManager,\n\tPersonManager,\n\tProjectInitializer,\n\tProjectManager,\n\tProjectMemberManager,\n\tProjectSchemaResolver,\n\tProjectScopeFactory,\n\tProviders,\n\tRateLimiter,\n\tRecaptchaV3Provider,\n\tRolesManager,\n\tSecretsManager,\n\tSignInManager,\n\tSignOutManager,\n\tSignUpManager,\n\tTurnstileProvider,\n\tUnpersistedApiKeyManager,\n\tUserMailer,\n} from './model/index.js'\nimport { HibpChecker, HttpHibpChecker, NoopHibpChecker } from './model/service/HibpChecker.js'\nimport {\n\tAddIDPMutationResolver,\n\tAddProjectMemberMutationResolver,\n\tChangePasswordMutationResolver,\n\tChangeProfileMutationResolver,\n\tCreateApiKeyMutationResolver,\n\tCreateProjectMutationResolver,\n\tDisableApiKeyMutationResolver,\n\tDisableIDPMutationResolver,\n\tDisconnectMyIdentityProviderMutationResolver,\n\tEmailOtpMutationResolver,\n\tEmailVerificationMutationResolver,\n\tEnableIDPMutationResolver,\n\tIdentityGlobalRolesMutationResolver,\n\tIdentityTypeResolver,\n\tIDPMutationResolver,\n\tInviteMutationResolver,\n\tMailTemplateMutationResolver,\n\tMeQueryResolver,\n\tOtpMutationResolver,\n\tPersonQueryResolver,\n\tPersonTypeResolver,\n\tProjectMembersQueryResolver,\n\tProjectQueryResolver,\n\tProjectTypeResolver,\n\tRegenerateBackupCodesMutationResolver,\n\tRemoveProjectMemberMutationResolver,\n\tResetPasswordMutationResolver,\n\tResolverFactory,\n\tSetProjectSecretMutationResolver,\n\tSignInMutationResolver,\n\tSignOutMutationResolver,\n\tSignUpMutationResolver,\n\tTenantResolverContextFactory,\n\tUpdateProjectMemberMutationResolver,\n\tUpdateProjectMutationResolver,\n} from './resolvers/index.js'\nimport * as Schema from './schema/index.js'\nimport { createMailer, MailerOptions, TemplateRenderer } from './utils/index.js'\nimport { IdentityFetcher } from './bridges/system/IdentityFetcher.js'\nimport { SignInResponseFactory } from './resolvers/responseHelpers/SignInResponseFactory.js'\nimport { IDPQueryResolver } from './resolvers/query/IDPQueryResolver.js'\nimport { UpdateIDPMutationResolver } from './resolvers/mutation/idp/UpdateIDPMutationResolver.js'\nimport { TenantCredentials, TenantMigrationsRunner } from './migrations/index.js'\nimport { DisablePersonMutationResolver } from './resolvers/mutation/person/DisablePersonMutationResolver.js'\nimport { EnablePersonMutationResolver } from './resolvers/mutation/person/EnablePersonMutationResolver.js'\nimport { ForceSignOutMutationResolver } from './resolvers/mutation/person/ForceSignOutMutationResolver.js'\nimport { RevokeSessionMutationResolver } from './resolvers/mutation/person/RevokeSessionMutationResolver.js'\nimport { MailTemplateQueryResolver } from './resolvers/query/MailTemplateQueryResolver.js'\nimport { ConfigurationManager } from './model/service/ConfigurationManager.js'\nimport { ConfigurationMutationResolver } from './resolvers/mutation/configuration/ConfigurationMutationResolver.js'\nimport { ConfigurationQueryResolver } from './resolvers/query/ConfigurationQueryResolver.js'\nimport { AuthPolicyMutationResolver } from './resolvers/mutation/configuration/AuthPolicyMutationResolver.js'\nimport { AuthPolicyQueryResolver } from './resolvers/query/AuthPolicyQueryResolver.js'\nimport { ResetPersonMfaMutationResolver } from './resolvers/mutation/person/ResetPersonMfaMutationResolver.js'\nimport { AuthLogQueryResolver } from './resolvers/query/AuthLogQueryResolver.js'\nimport { ApiKeyQueryResolver } from './resolvers/query/ApiKeyQueryResolver.js'\nimport { PasswordlessMutationResolver } from './resolvers/mutation/person/PasswordlessMutationResolver.js'\nimport { PasswordlessSignInManager } from './model/service/PasswordlessSignInManager.js'\nimport { TogglePasswordlessMutationResolver } from './resolvers/mutation/person/TogglePasswordlessMutationResolver.js'\nimport { PasswordStrengthValidator } from './model/service/PasswordStrengthValidator.js'\nimport { AuthLogService } from './model/service/AuthLogService.js'\n\nexport interface TenantContainer {\n\tprojectMemberManager: ProjectMemberManager\n\tapiKeyManager: ApiKeyManager\n\tbackchannelLogoutManager: BackchannelLogoutManager\n\tsignUpManager: SignUpManager\n\tprojectManager: ProjectManager\n\tpanelAccessResolver: PanelAccessResolver\n\tresolvers: Schema.Resolvers\n\tresolverContextFactory: TenantResolverContextFactory\n\tauthorizator: Authorizator<Identity>\n\tidentityFetcher: IdentityFetcher\n\tdatabaseContext: DatabaseContext\n\treadDatabaseContext: DatabaseContext\n\tmigrationsRunner: TenantMigrationsRunner\n\tconnection: Connection.ConnectionType\n\treadConnection: Connection.ConnectionType\n}\n\nexport interface TenantContainerArgs {\n\tconnection: Connection.ConnectionType\n\treadConnection: Connection.ConnectionType\n\tdbCredentials: DatabaseConfig\n\tmailOptions: MailerOptions\n\tprojectSchemaResolver: ProjectSchemaResolver\n\tprojectInitializer: ProjectInitializer\n\ttenantCredentials: TenantCredentials\n\tcryptoProviders: Pick<Providers, 'encrypt' | 'decrypt' | 'encryptionEnabled'>\n\tlogger: Logger\n}\n\nexport class TenantContainerFactory {\n\tconstructor(\n\t\tprivate readonly providers: Omit<Providers, 'encrypt' | 'decrypt' | 'encryptionEnabled'>,\n\t) {}\n\n\tcreate(args: TenantContainerArgs): TenantContainer {\n\t\treturn this.createBuilder(args)\n\t\t\t.build()\n\t\t\t.pick(\n\t\t\t\t'apiKeyManager',\n\t\t\t\t'backchannelLogoutManager',\n\t\t\t\t'projectMemberManager',\n\t\t\t\t'projectManager',\n\t\t\t\t'panelAccessResolver',\n\t\t\t\t'signUpManager',\n\t\t\t\t'resolvers',\n\t\t\t\t'authorizator',\n\t\t\t\t'resolverContextFactory',\n\t\t\t\t'identityFetcher',\n\t\t\t\t'databaseContext',\n\t\t\t\t'readDatabaseContext',\n\t\t\t\t'migrationsRunner',\n\t\t\t\t'connection',\n\t\t\t\t'readConnection',\n\t\t\t)\n\t}\n\n\tcreateBuilder(args: TenantContainerArgs) {\n\t\treturn new Builder({})\n\t\t\t.addService('providers', () => ({ ...this.providers, ...args.cryptoProviders }))\n\t\t\t.addService('mailer', () => createMailer(args.mailOptions))\n\t\t\t.addService('projectSchemaResolver', () => args.projectSchemaResolver)\n\t\t\t.addService('templateRenderer', () => new TemplateRenderer())\n\t\t\t.addService('accessEvaluator', ({}) => new AccessEvaluator.PermissionEvaluator(new PermissionsFactory().create()))\n\t\t\t.addService('authorizator', ({ accessEvaluator }) => new Authorizator.Default(accessEvaluator))\n\t\t\t.addService('userMailer', ({ mailer, templateRenderer }) => new UserMailer(mailer, templateRenderer))\n\t\t\t.addService('apiKeyService', () => new ApiKeyService())\n\t\t\t.addService('authPolicyResolver', () => new AuthPolicyResolver())\n\t\t\t.addService('panelAccessResolver', ({ providers }) => new PanelAccessResolver(providers))\n\t\t\t.addService('authLogService', () => new AuthLogService())\n\t\t\t.addService('loginRiskAnalyzer', ({ providers }) => new LoginRiskAnalyzer(providers.hash))\n\t\t\t.addService('idpRegistry', () => {\n\t\t\t\tconst idpRegistry = new IDPHandlerRegistry()\n\t\t\t\tidpRegistry.registerHandler('oidc', new OIDCProvider())\n\t\t\t\tidpRegistry.registerHandler('facebook', new FacebookProvider())\n\t\t\t\tidpRegistry.registerHandler('apple', new AppleProvider())\n\t\t\t\treturn idpRegistry\n\t\t\t})\n\t\t\t.addService('idpClaimSyncService', ({ projectSchemaResolver }) => new IDPClaimSyncService(projectSchemaResolver))\n\t\t\t.addService(\n\t\t\t\t'idpSessionRevalidator',\n\t\t\t\t({ idpRegistry, idpClaimSyncService }) => new IdpSessionRevalidator(idpRegistry, idpClaimSyncService, args.logger),\n\t\t\t)\n\t\t\t.addService('backchannelLogoutManager', ({ idpRegistry }) => new BackchannelLogoutManager(idpRegistry))\n\t\t\t.addService('unpersistedApiKeyManager', () =>\n\t\t\t\tUnpersistedApiKeyManager.createForRootTokens({\n\t\t\t\t\ttokens: args.tenantCredentials.rootTokens,\n\t\t\t\t\ttokenHashes: args.tenantCredentials.rootTokenHashes,\n\t\t\t\t}))\n\t\t\t.addService(\n\t\t\t\t'apiKeyManager',\n\t\t\t\t({ apiKeyService, authPolicyResolver, authLogService, unpersistedApiKeyManager, idpSessionRevalidator }) =>\n\t\t\t\t\tnew ApiKeyManager(apiKeyService, authPolicyResolver, authLogService, unpersistedApiKeyManager, idpSessionRevalidator),\n\t\t\t)\n\t\t\t.addService('signOutManager', ({ apiKeyManager, idpRegistry }) => new SignOutManager(apiKeyManager, idpRegistry))\n\t\t\t.addService('emailValidator', () => new EmailValidator())\n\t\t\t.addService('hibpChecker', (): HibpChecker => new HttpHibpChecker())\n\t\t\t.addService('noopHibpChecker', (): HibpChecker => new NoopHibpChecker())\n\t\t\t.addService('passwordStrengthValidator', ({ hibpChecker }) => new PasswordStrengthValidator(hibpChecker))\n\t\t\t.addService('captchaValidator', () =>\n\t\t\t\tnew CaptchaValidator({\n\t\t\t\t\tturnstile: new TurnstileProvider(),\n\t\t\t\t\thcaptcha: new HCaptchaProvider(),\n\t\t\t\t\trecaptchaV3: new RecaptchaV3Provider(),\n\t\t\t\t}))\n\t\t\t.addService('rateLimiter', ({ providers }) => new RateLimiter(providers))\n\t\t\t.addService(\n\t\t\t\t'signUpManager',\n\t\t\t\t({ emailValidator, passwordStrengthValidator }) => new SignUpManager(emailValidator, passwordStrengthValidator),\n\t\t\t)\n\t\t\t.addService('passwordChangeManager', ({ providers, passwordStrengthValidator }) => new PasswordChangeManager(providers, passwordStrengthValidator))\n\t\t\t.addService('projectMemberManager', () => new ProjectMemberManager())\n\t\t\t.addService('identityFactory', ({ projectMemberManager }) => new IdentityFactory(projectMemberManager))\n\t\t\t.addService('projectScopeFactory', () => new ProjectScopeFactory(new AclSchemaAccessNodeFactory()))\n\t\t\t.addService(\n\t\t\t\t'permissionContextFactory',\n\t\t\t\t({ authorizator, identityFactory, projectScopeFactory, projectSchemaResolver }) =>\n\t\t\t\t\tnew PermissionContextFactory(authorizator, identityFactory, projectScopeFactory, projectSchemaResolver),\n\t\t\t)\n\t\t\t.addService('secretManager', ({ providers }) => new SecretsManager(providers))\n\t\t\t.addService('projectManager', ({ secretManager, apiKeyService }) => new ProjectManager(secretManager, args.projectInitializer, apiKeyService))\n\t\t\t.addService('personAccessManager', ({ apiKeyManager }) => new PersonAccessManager(apiKeyManager))\n\t\t\t.addService('personManager', ({ emailValidator }) => new PersonManager(emailValidator))\n\t\t\t.addService(\n\t\t\t\t'passwordResetManager',\n\t\t\t\t({ userMailer, projectManager, passwordStrengthValidator }) => new PasswordResetManager(userMailer, projectManager, passwordStrengthValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailVerificationManager',\n\t\t\t\t({ userMailer, projectManager }) => new EmailVerificationManager(userMailer, projectManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailChangeManager',\n\t\t\t\t({ userMailer, projectManager, emailValidator, apiKeyManager, permissionContextFactory }) =>\n\t\t\t\t\tnew EmailChangeManager(userMailer, projectManager, emailValidator, apiKeyManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'idpSignInManager',\n\t\t\t\t({ apiKeyManager, idpRegistry, idpClaimSyncService }) => new IDPSignInManager(apiKeyManager, idpRegistry, idpClaimSyncService, args.logger),\n\t\t\t)\n\t\t\t.addService('idpManager', ({ idpRegistry, projectSchemaResolver }) => new IDPManager(idpRegistry, projectSchemaResolver))\n\t\t\t.addService('personIdentityProviderManager', () => new PersonIdentityProviderManager())\n\t\t\t.addService('otpAuthenticator', ({ providers }) => new OtpAuthenticator(providers))\n\t\t\t.addService('otpManager', ({ otpAuthenticator, providers }) => new OtpManager(otpAuthenticator, providers))\n\t\t\t.addService('backupCodeManager', ({ providers, userMailer }) => new BackupCodeManager(userMailer, providers))\n\t\t\t.addService('emailOtpManager', ({ userMailer, providers, rateLimiter }) => new EmailOtpManager(userMailer, providers, rateLimiter))\n\t\t\t.addService('authPolicyManager', ({ projectManager }) => new AuthPolicyManager(projectManager))\n\t\t\t.addService(\n\t\t\t\t'signInManager',\n\t\t\t\t({ apiKeyManager, providers, otpManager, backupCodeManager, emailOtpManager, authPolicyResolver, loginRiskAnalyzer, userMailer }) =>\n\t\t\t\t\tnew SignInManager(\n\t\t\t\t\t\tapiKeyManager,\n\t\t\t\t\t\tproviders,\n\t\t\t\t\t\totpManager,\n\t\t\t\t\t\tbackupCodeManager,\n\t\t\t\t\t\temailOtpManager,\n\t\t\t\t\t\tauthPolicyResolver,\n\t\t\t\t\t\tloginRiskAnalyzer,\n\t\t\t\t\t\tuserMailer,\n\t\t\t\t\t),\n\t\t\t)\n\t\t\t.addService('membershipValidator', ({ projectSchemaResolver }) => new MembershipValidator(projectSchemaResolver))\n\t\t\t.addService('inviteManager', ({ providers, userMailer, projectSchemaResolver }) => new InviteManager(providers, userMailer, projectSchemaResolver))\n\t\t\t.addService('mailTemplateManager', () => new MailTemplateManager())\n\t\t\t.addService('rolesManager', () => new RolesManager())\n\t\t\t.addService('configurationManager', () => new ConfigurationManager())\n\t\t\t.addService(\n\t\t\t\t'passwordlessSignInManager',\n\t\t\t\t({ apiKeyManager, userMailer, projectManager, otpManager, backupCodeManager }) =>\n\t\t\t\t\tnew PasswordlessSignInManager(apiKeyManager, userMailer, projectManager, otpManager, backupCodeManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'identityTypeResolver',\n\t\t\t\t({ projectMemberManager, projectManager, permissionContextFactory }) =>\n\t\t\t\t\tnew IdentityTypeResolver(projectMemberManager, projectManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'projectTypeResolver',\n\t\t\t\t({ projectMemberManager, projectSchemaResolver, secretManager }) =>\n\t\t\t\t\tnew ProjectTypeResolver(projectMemberManager, projectSchemaResolver, secretManager),\n\t\t\t)\n\t\t\t.addService('personTypeResolver', ({ personIdentityProviderManager }) => new PersonTypeResolver(personIdentityProviderManager))\n\t\t\t.addService(\n\t\t\t\t'signInResponseFactory',\n\t\t\t\t({ permissionContextFactory, identityTypeResolver }) => new SignInResponseFactory(permissionContextFactory, identityTypeResolver),\n\t\t\t)\n\t\t\t.addService('meQueryResolver', () => new MeQueryResolver())\n\t\t\t.addService(\n\t\t\t\t'personQueryResolver',\n\t\t\t\t({ personManager, projectManager, projectMemberManager }) => new PersonQueryResolver(personManager, projectManager, projectMemberManager),\n\t\t\t)\n\t\t\t.addService('idpQueryResolver', ({ idpManager }) => new IDPQueryResolver(idpManager))\n\t\t\t.addService('projectQueryResolver', ({ projectManager }) => new ProjectQueryResolver(projectManager))\n\t\t\t.addService(\n\t\t\t\t'projectMembersQueryResolver',\n\t\t\t\t({ projectManager, projectMemberManager }) => new ProjectMembersQueryResolver(projectManager, projectMemberManager),\n\t\t\t)\n\t\t\t.addService('mailTemplateQueryResolver', () => new MailTemplateQueryResolver())\n\t\t\t.addService(\n\t\t\t\t'signUpMutationResolver',\n\t\t\t\t({ signUpManager, apiKeyManager, captchaValidator, rateLimiter, emailVerificationManager, permissionContextFactory }) =>\n\t\t\t\t\tnew SignUpMutationResolver(signUpManager, apiKeyManager, captchaValidator, rateLimiter, emailVerificationManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'signInMutationResolver',\n\t\t\t\t({ signInManager, signInResponseFactory, rateLimiter }) => new SignInMutationResolver(signInManager, signInResponseFactory, rateLimiter),\n\t\t\t)\n\t\t\t.addService('signOutMutationResolver', ({ signOutManager }) => new SignOutMutationResolver(signOutManager))\n\t\t\t.addService(\n\t\t\t\t'changeProfileMutationResolver',\n\t\t\t\t({ personManager, emailChangeManager, permissionContextFactory }) =>\n\t\t\t\t\tnew ChangeProfileMutationResolver(personManager, emailChangeManager, permissionContextFactory),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailVerificationMutationResolver',\n\t\t\t\t({ emailVerificationManager, permissionContextFactory, captchaValidator, rateLimiter }) =>\n\t\t\t\t\tnew EmailVerificationMutationResolver(emailVerificationManager, permissionContextFactory, captchaValidator, rateLimiter),\n\t\t\t)\n\t\t\t.addService('changePasswordMutationResolver', ({ passwordChangeManager }) => new ChangePasswordMutationResolver(passwordChangeManager))\n\t\t\t.addService(\n\t\t\t\t'resetPasswordMutationResolver',\n\t\t\t\t({ passwordResetManager, permissionContextFactory, captchaValidator, rateLimiter }) =>\n\t\t\t\t\tnew ResetPasswordMutationResolver(passwordResetManager, permissionContextFactory, captchaValidator, rateLimiter),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'inviteMutationResolver',\n\t\t\t\t({ inviteManager, projectManager, membershipValidator }) => new InviteMutationResolver(inviteManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'addProjectMemberMutationResolver',\n\t\t\t\t({ projectMemberManager, projectManager, membershipValidator }) =>\n\t\t\t\t\tnew AddProjectMemberMutationResolver(projectMemberManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'updateProjectMemberMutationResolver',\n\t\t\t\t({ projectMemberManager, projectManager, membershipValidator }) =>\n\t\t\t\t\tnew UpdateProjectMemberMutationResolver(projectMemberManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'removeProjectMemberMutationResolver',\n\t\t\t\t({ projectMemberManager, projectManager }) => new RemoveProjectMemberMutationResolver(projectMemberManager, projectManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'createApiKeyMutationResolver',\n\t\t\t\t({ apiKeyManager, projectManager, membershipValidator }) => new CreateApiKeyMutationResolver(apiKeyManager, projectManager, membershipValidator),\n\t\t\t)\n\t\t\t.addService('disableApiKeyMutationResolver', ({ apiKeyManager }) => new DisableApiKeyMutationResolver(apiKeyManager))\n\t\t\t.addService(\n\t\t\t\t'otpMutationResolver',\n\t\t\t\t({ otpManager, backupCodeManager, authPolicyResolver }) => new OtpMutationResolver(otpManager, backupCodeManager, authPolicyResolver),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'emailOtpMutationResolver',\n\t\t\t\t({ emailOtpManager, backupCodeManager, authPolicyResolver }) =>\n\t\t\t\t\tnew EmailOtpMutationResolver(emailOtpManager, backupCodeManager, authPolicyResolver),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'regenerateBackupCodesMutationResolver',\n\t\t\t\t({ backupCodeManager }) => new RegenerateBackupCodesMutationResolver(backupCodeManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'mailTemplateMutationResolver',\n\t\t\t\t({ projectManager, mailTemplateManager }) => new MailTemplateMutationResolver(projectManager, mailTemplateManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'idpMutationResolver',\n\t\t\t\t({ idpSignInManager, signInResponseFactory }) => new IDPMutationResolver(idpSignInManager, signInResponseFactory),\n\t\t\t)\n\t\t\t.addService('registerIdpMutationResolver', ({ idpManager }) => new AddIDPMutationResolver(idpManager))\n\t\t\t.addService('updateIdpMutationResolver', ({ idpManager }) => new UpdateIDPMutationResolver(idpManager))\n\t\t\t.addService('disableIdpMutationResolver', ({ idpManager }) => new DisableIDPMutationResolver(idpManager))\n\t\t\t.addService('enableIdpMutationResolver', ({ idpManager }) => new EnableIDPMutationResolver(idpManager))\n\t\t\t.addService(\n\t\t\t\t'disconnectMyIdentityProviderMutationResolver',\n\t\t\t\t({ personIdentityProviderManager }) => new DisconnectMyIdentityProviderMutationResolver(personIdentityProviderManager),\n\t\t\t)\n\t\t\t.addService('createProjectMutationResolver', ({ projectManager }) => new CreateProjectMutationResolver(projectManager))\n\t\t\t.addService(\n\t\t\t\t'disablePersonMutationResolver',\n\t\t\t\t({ personAccessManager, personManager }) => new DisablePersonMutationResolver(personAccessManager, personManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'enablePersonMutationResolver',\n\t\t\t\t({ personAccessManager, personManager }) => new EnablePersonMutationResolver(personAccessManager, personManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'forceSignOutMutationResolver',\n\t\t\t\t({ apiKeyManager, personManager, userMailer }) => new ForceSignOutMutationResolver(apiKeyManager, personManager, userMailer),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'resetPersonMfaMutationResolver',\n\t\t\t\t({ personManager, backupCodeManager }) => new ResetPersonMfaMutationResolver(personManager, backupCodeManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'revokeSessionMutationResolver',\n\t\t\t\t({ apiKeyManager }) => new RevokeSessionMutationResolver(apiKeyManager),\n\t\t\t)\n\t\t\t.addService('updateProjectMutationResolver', ({ projectManager }) => new UpdateProjectMutationResolver(projectManager))\n\t\t\t.addService(\n\t\t\t\t'setProjectSecretMutationResolver',\n\t\t\t\t({ projectManager, secretManager }) => new SetProjectSecretMutationResolver(projectManager, secretManager),\n\t\t\t)\n\t\t\t.addService('identityGlobalRolesMutationResolver', ({ rolesManager }) => new IdentityGlobalRolesMutationResolver(rolesManager))\n\t\t\t.addService('configurationMutationResolver', ({ configurationManager }) => new ConfigurationMutationResolver(configurationManager))\n\t\t\t.addService('configurationQueryResolver', ({ configurationManager }) => new ConfigurationQueryResolver(configurationManager))\n\t\t\t.addService('authPolicyMutationResolver', ({ authPolicyManager }) => new AuthPolicyMutationResolver(authPolicyManager))\n\t\t\t.addService('authPolicyQueryResolver', ({ authPolicyManager }) => new AuthPolicyQueryResolver(authPolicyManager))\n\t\t\t.addService('authLogQueryResolver', () => new AuthLogQueryResolver())\n\t\t\t.addService('apiKeyQueryResolver', () => new ApiKeyQueryResolver())\n\t\t\t.addService(\n\t\t\t\t'passwordlessMutationResolver',\n\t\t\t\t({ passwordlessSignInManager, signInResponseFactory, captchaValidator, rateLimiter }) =>\n\t\t\t\t\tnew PasswordlessMutationResolver(passwordlessSignInManager, signInResponseFactory, captchaValidator, rateLimiter),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'togglePasswordlessMutationResolver',\n\t\t\t\t({ configurationManager, personManager }) => new TogglePasswordlessMutationResolver(configurationManager, personManager),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'resolverContextFactory',\n\t\t\t\t({ permissionContextFactory, authLogService, loginRiskAnalyzer }) =>\n\t\t\t\t\tnew TenantResolverContextFactory(permissionContextFactory, authLogService, loginRiskAnalyzer),\n\t\t\t)\n\t\t\t.addService('resolvers', container => new ResolverFactory(container).create())\n\t\t\t.addService('connection', () => args.connection)\n\t\t\t.addService('readConnection', () => args.readConnection)\n\t\t\t.addService(\n\t\t\t\t'databaseContext',\n\t\t\t\t({ connection, providers }) => new DatabaseContext(connection.createClient('tenant', { module: 'tenant' }), providers),\n\t\t\t)\n\t\t\t.addService(\n\t\t\t\t'readDatabaseContext',\n\t\t\t\t({ readConnection, providers }) => new DatabaseContext(readConnection.createClient('tenant', { module: 'tenant' }), providers),\n\t\t\t)\n\t\t\t.addService('identityFetcher', ({ databaseContext }) => new IdentityFetcher(databaseContext.client))\n\t\t\t.addService('migrationsRunner', ({ providers }) => new TenantMigrationsRunner(args.dbCredentials, 'tenant', args.tenantCredentials, providers))\n\t}\n}\n"],"names":[],"mappings":"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"}
@@ -28,7 +28,7 @@ class ProlongApiKeyCommand {
28
28
  }
29
29
  const requestIp = this.requestInfo?.ip || null;
30
30
  const requestUserAgent = this.requestInfo?.userAgent || null;
31
- const updateTracking = this.shouldUpdateTracking(now, requestIp, requestUserAgent);
31
+ const updateTracking = this.shouldUpdateTracking(now);
32
32
  if (!updateExpiration && !updateTracking) {
33
33
  return;
34
34
  }
@@ -44,18 +44,15 @@ class ProlongApiKeyCommand {
44
44
  const qb = Database.UpdateBuilder.create().table("api_key").where({ id: this.id }).values(values);
45
45
  await qb.execute(db);
46
46
  }
47
- shouldUpdateTracking(now, requestIp, requestUserAgent) {
47
+ shouldUpdateTracking(now) {
48
48
  if (!this.requestInfo) {
49
49
  return false;
50
50
  }
51
- const last = this.tracking;
52
- if (!last || last.lastUsedAt === null) {
51
+ const lastUsedAt = this.tracking?.lastUsedAt;
52
+ if (!lastUsedAt) {
53
53
  return true;
54
54
  }
55
- if (requestIp !== last.lastIp || requestUserAgent !== last.lastUserAgent) {
56
- return true;
57
- }
58
- return now.getTime() - last.lastUsedAt.getTime() >= PROLONG_THROTTLE_MS;
55
+ return now.getTime() - lastUsedAt.getTime() >= PROLONG_THROTTLE_MS;
59
56
  }
60
57
  }
61
58
  exports.PROLONG_THROTTLE_MS = PROLONG_THROTTLE_MS;
@@ -1 +1 @@
1
- {"version":3,"file":"ProlongApiKeyCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/apiKey/ProlongApiKeyCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { ApiKey } from '../../type/index.js'\nimport { ApiKeyHelper } from './ApiKeyHelper.js'\nimport { QueryBuilder, UpdateBuilder } from '@contember/database'\n\n/**\n * Tracking writes (`last_used_at`) are throttled to at most once per this window, so\n * an idle check must add this slack to avoid prematurely expiring an active session\n * whose `last_used_at` is intentionally stale (see {@link ApiKeyManager.verifyAndProlong}).\n */\nexport const PROLONG_THROTTLE_MS = 60_000\n\nexport interface ApiKeyRequestInfo {\n\tip?: string\n\tuserAgent?: string\n}\n\nexport interface ApiKeyTrackingState {\n\tlastIp: string | null\n\tlastUserAgent: string | null\n\tlastUsedAt: Date | null\n}\n\nexport class ProlongApiKeyCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly type: ApiKey.Type,\n\t\tprivate readonly expiration: number | null,\n\t\tprivate readonly currentExpiration: Date | null,\n\t\tprivate readonly requestInfo?: ApiKeyRequestInfo,\n\t\tprivate readonly tracking?: ApiKeyTrackingState,\n\t\tprivate readonly maxExpiresAt?: Date | null,\n\t) {}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tlet newExpiration = ApiKeyHelper.getExpiration(providers, this.type, this.expiration)\n\t\t// A19: clamp the sliding window at the absolute cap snapshotted at sign-in.\n\t\t// NULL maxExpiresAt = today's uncapped sliding window.\n\t\tif (newExpiration !== null && this.maxExpiresAt && newExpiration.getTime() > this.maxExpiresAt.getTime()) {\n\t\t\tnewExpiration = this.maxExpiresAt\n\t\t}\n\t\tconst now = providers.now()\n\n\t\tlet updateExpiration = newExpiration !== null\n\t\tif (updateExpiration && this.currentExpiration && newExpiration !== null) {\n\t\t\tconst prolongMs = newExpiration.getTime() - this.currentExpiration.getTime()\n\t\t\tif (prolongMs > 0 && prolongMs < PROLONG_THROTTLE_MS) {\n\t\t\t\tupdateExpiration = false\n\t\t\t}\n\t\t}\n\n\t\tconst requestIp = this.requestInfo?.ip || null\n\t\tconst requestUserAgent = this.requestInfo?.userAgent || null\n\t\tconst updateTracking = this.shouldUpdateTracking(now, requestIp, requestUserAgent)\n\n\t\tif (!updateExpiration && !updateTracking) {\n\t\t\treturn\n\t\t}\n\n\t\tconst values: QueryBuilder.Values = {}\n\t\tif (updateExpiration && newExpiration !== null) {\n\t\t\tvalues.expires_at = newExpiration\n\t\t}\n\t\tif (updateTracking) {\n\t\t\tvalues.last_ip = requestIp\n\t\t\tvalues.last_user_agent = requestUserAgent\n\t\t\tvalues.last_used_at = now\n\t\t}\n\n\t\tconst qb = UpdateBuilder.create()\n\t\t\t.table('api_key')\n\t\t\t.where({ id: this.id })\n\t\t\t.values(values)\n\t\tawait qb.execute(db)\n\t}\n\n\tprivate shouldUpdateTracking(now: Date, requestIp: string | null, requestUserAgent: string | null): boolean {\n\t\tif (!this.requestInfo) {\n\t\t\treturn false\n\t\t}\n\t\tconst last = this.tracking\n\t\tif (!last || last.lastUsedAt === null) {\n\t\t\treturn true\n\t\t}\n\t\tif (requestIp !== last.lastIp || requestUserAgent !== last.lastUserAgent) {\n\t\t\treturn true\n\t\t}\n\t\treturn now.getTime() - last.lastUsedAt.getTime() >= PROLONG_THROTTLE_MS\n\t}\n}\n"],"names":["ApiKeyHelper","UpdateBuilder"],"mappings":";;;;AAUO,MAAM,sBAAsB;AAa5B,MAAM,qBAA8C;AAAA,EAC1D,YACkB,IACA,MACA,YACA,mBACA,aACA,UACA,cAChB;AAPgB,SAAA,KAAA;AACA,SAAA,OAAA;AACA,SAAA,aAAA;AACA,SAAA,oBAAA;AACA,SAAA,cAAA;AACA,SAAA,WAAA;AACA,SAAA,eAAA;AAAA,EACf;AAAA,EAEH,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,QAAI,gBAAgBA,aAAAA,aAAa,cAAc,WAAW,KAAK,MAAM,KAAK,UAAU;AAGpF,QAAI,kBAAkB,QAAQ,KAAK,gBAAgB,cAAc,YAAY,KAAK,aAAa,WAAW;AACzG,sBAAgB,KAAK;AAAA,IACtB;AACA,UAAM,MAAM,UAAU,IAAA;AAEtB,QAAI,mBAAmB,kBAAkB;AACzC,QAAI,oBAAoB,KAAK,qBAAqB,kBAAkB,MAAM;AACzE,YAAM,YAAY,cAAc,QAAA,IAAY,KAAK,kBAAkB,QAAA;AACnE,UAAI,YAAY,KAAK,YAAY,qBAAqB;AACrD,2BAAmB;AAAA,MACpB;AAAA,IACD;AAEA,UAAM,YAAY,KAAK,aAAa,MAAM;AAC1C,UAAM,mBAAmB,KAAK,aAAa,aAAa;AACxD,UAAM,iBAAiB,KAAK,qBAAqB,KAAK,WAAW,gBAAgB;AAEjF,QAAI,CAAC,oBAAoB,CAAC,gBAAgB;AACzC;AAAA,IACD;AAEA,UAAM,SAA8B,CAAA;AACpC,QAAI,oBAAoB,kBAAkB,MAAM;AAC/C,aAAO,aAAa;AAAA,IACrB;AACA,QAAI,gBAAgB;AACnB,aAAO,UAAU;AACjB,aAAO,kBAAkB;AACzB,aAAO,eAAe;AAAA,IACvB;AAEA,UAAM,KAAKC,SAAAA,cAAc,OAAA,EACvB,MAAM,SAAS,EACf,MAAM,EAAE,IAAI,KAAK,GAAA,CAAI,EACrB,OAAO,MAAM;AACf,UAAM,GAAG,QAAQ,EAAE;AAAA,EACpB;AAAA,EAEQ,qBAAqB,KAAW,WAA0B,kBAA0C;AAC3G,QAAI,CAAC,KAAK,aAAa;AACtB,aAAO;AAAA,IACR;AACA,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,QAAQ,KAAK,eAAe,MAAM;AACtC,aAAO;AAAA,IACR;AACA,QAAI,cAAc,KAAK,UAAU,qBAAqB,KAAK,eAAe;AACzE,aAAO;AAAA,IACR;AACA,WAAO,IAAI,QAAA,IAAY,KAAK,WAAW,aAAa;AAAA,EACrD;AACD;;;"}
1
+ {"version":3,"file":"ProlongApiKeyCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/apiKey/ProlongApiKeyCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { ApiKey } from '../../type/index.js'\nimport { ApiKeyHelper } from './ApiKeyHelper.js'\nimport { QueryBuilder, UpdateBuilder } from '@contember/database'\n\n/**\n * Tracking writes (`last_ip`, `last_user_agent`, `last_used_at`) are throttled to at most once per\n * this window, even when the IP or User-Agent changes: a key shared by several service replicas\n * alternates between their addresses, and writing every change makes its row a lock hotspot.\n * An idle check must add this slack to avoid prematurely expiring an active session whose\n * `last_used_at` is intentionally stale (see {@link ApiKeyManager.verifyAndProlong}).\n */\nexport const PROLONG_THROTTLE_MS = 60_000\n\nexport interface ApiKeyRequestInfo {\n\tip?: string\n\tuserAgent?: string\n}\n\nexport interface ApiKeyTrackingState {\n\tlastIp: string | null\n\tlastUserAgent: string | null\n\tlastUsedAt: Date | null\n}\n\nexport class ProlongApiKeyCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly type: ApiKey.Type,\n\t\tprivate readonly expiration: number | null,\n\t\tprivate readonly currentExpiration: Date | null,\n\t\tprivate readonly requestInfo?: ApiKeyRequestInfo,\n\t\tprivate readonly tracking?: ApiKeyTrackingState,\n\t\tprivate readonly maxExpiresAt?: Date | null,\n\t) {}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tlet newExpiration = ApiKeyHelper.getExpiration(providers, this.type, this.expiration)\n\t\t// A19: clamp the sliding window at the absolute cap snapshotted at sign-in.\n\t\t// NULL maxExpiresAt = today's uncapped sliding window.\n\t\tif (newExpiration !== null && this.maxExpiresAt && newExpiration.getTime() > this.maxExpiresAt.getTime()) {\n\t\t\tnewExpiration = this.maxExpiresAt\n\t\t}\n\t\tconst now = providers.now()\n\n\t\tlet updateExpiration = newExpiration !== null\n\t\tif (updateExpiration && this.currentExpiration && newExpiration !== null) {\n\t\t\tconst prolongMs = newExpiration.getTime() - this.currentExpiration.getTime()\n\t\t\tif (prolongMs > 0 && prolongMs < PROLONG_THROTTLE_MS) {\n\t\t\t\tupdateExpiration = false\n\t\t\t}\n\t\t}\n\n\t\tconst requestIp = this.requestInfo?.ip || null\n\t\tconst requestUserAgent = this.requestInfo?.userAgent || null\n\t\tconst updateTracking = this.shouldUpdateTracking(now)\n\n\t\tif (!updateExpiration && !updateTracking) {\n\t\t\treturn\n\t\t}\n\n\t\tconst values: QueryBuilder.Values = {}\n\t\tif (updateExpiration && newExpiration !== null) {\n\t\t\tvalues.expires_at = newExpiration\n\t\t}\n\t\tif (updateTracking) {\n\t\t\tvalues.last_ip = requestIp\n\t\t\tvalues.last_user_agent = requestUserAgent\n\t\t\tvalues.last_used_at = now\n\t\t}\n\n\t\tconst qb = UpdateBuilder.create()\n\t\t\t.table('api_key')\n\t\t\t.where({ id: this.id })\n\t\t\t.values(values)\n\t\tawait qb.execute(db)\n\t}\n\n\tprivate shouldUpdateTracking(now: Date): boolean {\n\t\tif (!this.requestInfo) {\n\t\t\treturn false\n\t\t}\n\t\tconst lastUsedAt = this.tracking?.lastUsedAt\n\t\tif (!lastUsedAt) {\n\t\t\treturn true\n\t\t}\n\t\treturn now.getTime() - lastUsedAt.getTime() >= PROLONG_THROTTLE_MS\n\t}\n}\n"],"names":["ApiKeyHelper","UpdateBuilder"],"mappings":";;;;AAYO,MAAM,sBAAsB;AAa5B,MAAM,qBAA8C;AAAA,EAC1D,YACkB,IACA,MACA,YACA,mBACA,aACA,UACA,cAChB;AAPgB,SAAA,KAAA;AACA,SAAA,OAAA;AACA,SAAA,aAAA;AACA,SAAA,oBAAA;AACA,SAAA,cAAA;AACA,SAAA,WAAA;AACA,SAAA,eAAA;AAAA,EACf;AAAA,EAEH,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,QAAI,gBAAgBA,aAAAA,aAAa,cAAc,WAAW,KAAK,MAAM,KAAK,UAAU;AAGpF,QAAI,kBAAkB,QAAQ,KAAK,gBAAgB,cAAc,YAAY,KAAK,aAAa,WAAW;AACzG,sBAAgB,KAAK;AAAA,IACtB;AACA,UAAM,MAAM,UAAU,IAAA;AAEtB,QAAI,mBAAmB,kBAAkB;AACzC,QAAI,oBAAoB,KAAK,qBAAqB,kBAAkB,MAAM;AACzE,YAAM,YAAY,cAAc,QAAA,IAAY,KAAK,kBAAkB,QAAA;AACnE,UAAI,YAAY,KAAK,YAAY,qBAAqB;AACrD,2BAAmB;AAAA,MACpB;AAAA,IACD;AAEA,UAAM,YAAY,KAAK,aAAa,MAAM;AAC1C,UAAM,mBAAmB,KAAK,aAAa,aAAa;AACxD,UAAM,iBAAiB,KAAK,qBAAqB,GAAG;AAEpD,QAAI,CAAC,oBAAoB,CAAC,gBAAgB;AACzC;AAAA,IACD;AAEA,UAAM,SAA8B,CAAA;AACpC,QAAI,oBAAoB,kBAAkB,MAAM;AAC/C,aAAO,aAAa;AAAA,IACrB;AACA,QAAI,gBAAgB;AACnB,aAAO,UAAU;AACjB,aAAO,kBAAkB;AACzB,aAAO,eAAe;AAAA,IACvB;AAEA,UAAM,KAAKC,SAAAA,cAAc,OAAA,EACvB,MAAM,SAAS,EACf,MAAM,EAAE,IAAI,KAAK,GAAA,CAAI,EACrB,OAAO,MAAM;AACf,UAAM,GAAG,QAAQ,EAAE;AAAA,EACpB;AAAA,EAEQ,qBAAqB,KAAoB;AAChD,QAAI,CAAC,KAAK,aAAa;AACtB,aAAO;AAAA,IACR;AACA,UAAM,aAAa,KAAK,UAAU;AAClC,QAAI,CAAC,YAAY;AAChB,aAAO;AAAA,IACR;AACA,WAAO,IAAI,QAAA,IAAY,WAAW,aAAa;AAAA,EAChD;AACD;;;"}
@@ -26,7 +26,7 @@ class ProlongApiKeyCommand {
26
26
  }
27
27
  const requestIp = this.requestInfo?.ip || null;
28
28
  const requestUserAgent = this.requestInfo?.userAgent || null;
29
- const updateTracking = this.shouldUpdateTracking(now, requestIp, requestUserAgent);
29
+ const updateTracking = this.shouldUpdateTracking(now);
30
30
  if (!updateExpiration && !updateTracking) {
31
31
  return;
32
32
  }
@@ -42,18 +42,15 @@ class ProlongApiKeyCommand {
42
42
  const qb = UpdateBuilder$1.create().table("api_key").where({ id: this.id }).values(values);
43
43
  await qb.execute(db);
44
44
  }
45
- shouldUpdateTracking(now, requestIp, requestUserAgent) {
45
+ shouldUpdateTracking(now) {
46
46
  if (!this.requestInfo) {
47
47
  return false;
48
48
  }
49
- const last = this.tracking;
50
- if (!last || last.lastUsedAt === null) {
49
+ const lastUsedAt = this.tracking?.lastUsedAt;
50
+ if (!lastUsedAt) {
51
51
  return true;
52
52
  }
53
- if (requestIp !== last.lastIp || requestUserAgent !== last.lastUserAgent) {
54
- return true;
55
- }
56
- return now.getTime() - last.lastUsedAt.getTime() >= PROLONG_THROTTLE_MS;
53
+ return now.getTime() - lastUsedAt.getTime() >= PROLONG_THROTTLE_MS;
57
54
  }
58
55
  }
59
56
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"ProlongApiKeyCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/apiKey/ProlongApiKeyCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { ApiKey } from '../../type/index.js'\nimport { ApiKeyHelper } from './ApiKeyHelper.js'\nimport { QueryBuilder, UpdateBuilder } from '@contember/database'\n\n/**\n * Tracking writes (`last_used_at`) are throttled to at most once per this window, so\n * an idle check must add this slack to avoid prematurely expiring an active session\n * whose `last_used_at` is intentionally stale (see {@link ApiKeyManager.verifyAndProlong}).\n */\nexport const PROLONG_THROTTLE_MS = 60_000\n\nexport interface ApiKeyRequestInfo {\n\tip?: string\n\tuserAgent?: string\n}\n\nexport interface ApiKeyTrackingState {\n\tlastIp: string | null\n\tlastUserAgent: string | null\n\tlastUsedAt: Date | null\n}\n\nexport class ProlongApiKeyCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly type: ApiKey.Type,\n\t\tprivate readonly expiration: number | null,\n\t\tprivate readonly currentExpiration: Date | null,\n\t\tprivate readonly requestInfo?: ApiKeyRequestInfo,\n\t\tprivate readonly tracking?: ApiKeyTrackingState,\n\t\tprivate readonly maxExpiresAt?: Date | null,\n\t) {}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tlet newExpiration = ApiKeyHelper.getExpiration(providers, this.type, this.expiration)\n\t\t// A19: clamp the sliding window at the absolute cap snapshotted at sign-in.\n\t\t// NULL maxExpiresAt = today's uncapped sliding window.\n\t\tif (newExpiration !== null && this.maxExpiresAt && newExpiration.getTime() > this.maxExpiresAt.getTime()) {\n\t\t\tnewExpiration = this.maxExpiresAt\n\t\t}\n\t\tconst now = providers.now()\n\n\t\tlet updateExpiration = newExpiration !== null\n\t\tif (updateExpiration && this.currentExpiration && newExpiration !== null) {\n\t\t\tconst prolongMs = newExpiration.getTime() - this.currentExpiration.getTime()\n\t\t\tif (prolongMs > 0 && prolongMs < PROLONG_THROTTLE_MS) {\n\t\t\t\tupdateExpiration = false\n\t\t\t}\n\t\t}\n\n\t\tconst requestIp = this.requestInfo?.ip || null\n\t\tconst requestUserAgent = this.requestInfo?.userAgent || null\n\t\tconst updateTracking = this.shouldUpdateTracking(now, requestIp, requestUserAgent)\n\n\t\tif (!updateExpiration && !updateTracking) {\n\t\t\treturn\n\t\t}\n\n\t\tconst values: QueryBuilder.Values = {}\n\t\tif (updateExpiration && newExpiration !== null) {\n\t\t\tvalues.expires_at = newExpiration\n\t\t}\n\t\tif (updateTracking) {\n\t\t\tvalues.last_ip = requestIp\n\t\t\tvalues.last_user_agent = requestUserAgent\n\t\t\tvalues.last_used_at = now\n\t\t}\n\n\t\tconst qb = UpdateBuilder.create()\n\t\t\t.table('api_key')\n\t\t\t.where({ id: this.id })\n\t\t\t.values(values)\n\t\tawait qb.execute(db)\n\t}\n\n\tprivate shouldUpdateTracking(now: Date, requestIp: string | null, requestUserAgent: string | null): boolean {\n\t\tif (!this.requestInfo) {\n\t\t\treturn false\n\t\t}\n\t\tconst last = this.tracking\n\t\tif (!last || last.lastUsedAt === null) {\n\t\t\treturn true\n\t\t}\n\t\tif (requestIp !== last.lastIp || requestUserAgent !== last.lastUserAgent) {\n\t\t\treturn true\n\t\t}\n\t\treturn now.getTime() - last.lastUsedAt.getTime() >= PROLONG_THROTTLE_MS\n\t}\n}\n"],"names":["UpdateBuilder"],"mappings":";;AAUO,MAAM,sBAAsB;AAa5B,MAAM,qBAA8C;AAAA,EAC1D,YACkB,IACA,MACA,YACA,mBACA,aACA,UACA,cAChB;AAPgB,SAAA,KAAA;AACA,SAAA,OAAA;AACA,SAAA,aAAA;AACA,SAAA,oBAAA;AACA,SAAA,cAAA;AACA,SAAA,WAAA;AACA,SAAA,eAAA;AAAA,EACf;AAAA,EAEH,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,QAAI,gBAAgB,aAAa,cAAc,WAAW,KAAK,MAAM,KAAK,UAAU;AAGpF,QAAI,kBAAkB,QAAQ,KAAK,gBAAgB,cAAc,YAAY,KAAK,aAAa,WAAW;AACzG,sBAAgB,KAAK;AAAA,IACtB;AACA,UAAM,MAAM,UAAU,IAAA;AAEtB,QAAI,mBAAmB,kBAAkB;AACzC,QAAI,oBAAoB,KAAK,qBAAqB,kBAAkB,MAAM;AACzE,YAAM,YAAY,cAAc,QAAA,IAAY,KAAK,kBAAkB,QAAA;AACnE,UAAI,YAAY,KAAK,YAAY,qBAAqB;AACrD,2BAAmB;AAAA,MACpB;AAAA,IACD;AAEA,UAAM,YAAY,KAAK,aAAa,MAAM;AAC1C,UAAM,mBAAmB,KAAK,aAAa,aAAa;AACxD,UAAM,iBAAiB,KAAK,qBAAqB,KAAK,WAAW,gBAAgB;AAEjF,QAAI,CAAC,oBAAoB,CAAC,gBAAgB;AACzC;AAAA,IACD;AAEA,UAAM,SAA8B,CAAA;AACpC,QAAI,oBAAoB,kBAAkB,MAAM;AAC/C,aAAO,aAAa;AAAA,IACrB;AACA,QAAI,gBAAgB;AACnB,aAAO,UAAU;AACjB,aAAO,kBAAkB;AACzB,aAAO,eAAe;AAAA,IACvB;AAEA,UAAM,KAAKA,gBAAc,OAAA,EACvB,MAAM,SAAS,EACf,MAAM,EAAE,IAAI,KAAK,GAAA,CAAI,EACrB,OAAO,MAAM;AACf,UAAM,GAAG,QAAQ,EAAE;AAAA,EACpB;AAAA,EAEQ,qBAAqB,KAAW,WAA0B,kBAA0C;AAC3G,QAAI,CAAC,KAAK,aAAa;AACtB,aAAO;AAAA,IACR;AACA,UAAM,OAAO,KAAK;AAClB,QAAI,CAAC,QAAQ,KAAK,eAAe,MAAM;AACtC,aAAO;AAAA,IACR;AACA,QAAI,cAAc,KAAK,UAAU,qBAAqB,KAAK,eAAe;AACzE,aAAO;AAAA,IACR;AACA,WAAO,IAAI,QAAA,IAAY,KAAK,WAAW,aAAa;AAAA,EACrD;AACD;"}
1
+ {"version":3,"file":"ProlongApiKeyCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/apiKey/ProlongApiKeyCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { ApiKey } from '../../type/index.js'\nimport { ApiKeyHelper } from './ApiKeyHelper.js'\nimport { QueryBuilder, UpdateBuilder } from '@contember/database'\n\n/**\n * Tracking writes (`last_ip`, `last_user_agent`, `last_used_at`) are throttled to at most once per\n * this window, even when the IP or User-Agent changes: a key shared by several service replicas\n * alternates between their addresses, and writing every change makes its row a lock hotspot.\n * An idle check must add this slack to avoid prematurely expiring an active session whose\n * `last_used_at` is intentionally stale (see {@link ApiKeyManager.verifyAndProlong}).\n */\nexport const PROLONG_THROTTLE_MS = 60_000\n\nexport interface ApiKeyRequestInfo {\n\tip?: string\n\tuserAgent?: string\n}\n\nexport interface ApiKeyTrackingState {\n\tlastIp: string | null\n\tlastUserAgent: string | null\n\tlastUsedAt: Date | null\n}\n\nexport class ProlongApiKeyCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly type: ApiKey.Type,\n\t\tprivate readonly expiration: number | null,\n\t\tprivate readonly currentExpiration: Date | null,\n\t\tprivate readonly requestInfo?: ApiKeyRequestInfo,\n\t\tprivate readonly tracking?: ApiKeyTrackingState,\n\t\tprivate readonly maxExpiresAt?: Date | null,\n\t) {}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tlet newExpiration = ApiKeyHelper.getExpiration(providers, this.type, this.expiration)\n\t\t// A19: clamp the sliding window at the absolute cap snapshotted at sign-in.\n\t\t// NULL maxExpiresAt = today's uncapped sliding window.\n\t\tif (newExpiration !== null && this.maxExpiresAt && newExpiration.getTime() > this.maxExpiresAt.getTime()) {\n\t\t\tnewExpiration = this.maxExpiresAt\n\t\t}\n\t\tconst now = providers.now()\n\n\t\tlet updateExpiration = newExpiration !== null\n\t\tif (updateExpiration && this.currentExpiration && newExpiration !== null) {\n\t\t\tconst prolongMs = newExpiration.getTime() - this.currentExpiration.getTime()\n\t\t\tif (prolongMs > 0 && prolongMs < PROLONG_THROTTLE_MS) {\n\t\t\t\tupdateExpiration = false\n\t\t\t}\n\t\t}\n\n\t\tconst requestIp = this.requestInfo?.ip || null\n\t\tconst requestUserAgent = this.requestInfo?.userAgent || null\n\t\tconst updateTracking = this.shouldUpdateTracking(now)\n\n\t\tif (!updateExpiration && !updateTracking) {\n\t\t\treturn\n\t\t}\n\n\t\tconst values: QueryBuilder.Values = {}\n\t\tif (updateExpiration && newExpiration !== null) {\n\t\t\tvalues.expires_at = newExpiration\n\t\t}\n\t\tif (updateTracking) {\n\t\t\tvalues.last_ip = requestIp\n\t\t\tvalues.last_user_agent = requestUserAgent\n\t\t\tvalues.last_used_at = now\n\t\t}\n\n\t\tconst qb = UpdateBuilder.create()\n\t\t\t.table('api_key')\n\t\t\t.where({ id: this.id })\n\t\t\t.values(values)\n\t\tawait qb.execute(db)\n\t}\n\n\tprivate shouldUpdateTracking(now: Date): boolean {\n\t\tif (!this.requestInfo) {\n\t\t\treturn false\n\t\t}\n\t\tconst lastUsedAt = this.tracking?.lastUsedAt\n\t\tif (!lastUsedAt) {\n\t\t\treturn true\n\t\t}\n\t\treturn now.getTime() - lastUsedAt.getTime() >= PROLONG_THROTTLE_MS\n\t}\n}\n"],"names":["UpdateBuilder"],"mappings":";;AAYO,MAAM,sBAAsB;AAa5B,MAAM,qBAA8C;AAAA,EAC1D,YACkB,IACA,MACA,YACA,mBACA,aACA,UACA,cAChB;AAPgB,SAAA,KAAA;AACA,SAAA,OAAA;AACA,SAAA,aAAA;AACA,SAAA,oBAAA;AACA,SAAA,cAAA;AACA,SAAA,WAAA;AACA,SAAA,eAAA;AAAA,EACf;AAAA,EAEH,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,QAAI,gBAAgB,aAAa,cAAc,WAAW,KAAK,MAAM,KAAK,UAAU;AAGpF,QAAI,kBAAkB,QAAQ,KAAK,gBAAgB,cAAc,YAAY,KAAK,aAAa,WAAW;AACzG,sBAAgB,KAAK;AAAA,IACtB;AACA,UAAM,MAAM,UAAU,IAAA;AAEtB,QAAI,mBAAmB,kBAAkB;AACzC,QAAI,oBAAoB,KAAK,qBAAqB,kBAAkB,MAAM;AACzE,YAAM,YAAY,cAAc,QAAA,IAAY,KAAK,kBAAkB,QAAA;AACnE,UAAI,YAAY,KAAK,YAAY,qBAAqB;AACrD,2BAAmB;AAAA,MACpB;AAAA,IACD;AAEA,UAAM,YAAY,KAAK,aAAa,MAAM;AAC1C,UAAM,mBAAmB,KAAK,aAAa,aAAa;AACxD,UAAM,iBAAiB,KAAK,qBAAqB,GAAG;AAEpD,QAAI,CAAC,oBAAoB,CAAC,gBAAgB;AACzC;AAAA,IACD;AAEA,UAAM,SAA8B,CAAA;AACpC,QAAI,oBAAoB,kBAAkB,MAAM;AAC/C,aAAO,aAAa;AAAA,IACrB;AACA,QAAI,gBAAgB;AACnB,aAAO,UAAU;AACjB,aAAO,kBAAkB;AACzB,aAAO,eAAe;AAAA,IACvB;AAEA,UAAM,KAAKA,gBAAc,OAAA,EACvB,MAAM,SAAS,EACf,MAAM,EAAE,IAAI,KAAK,GAAA,CAAI,EACrB,OAAO,MAAM;AACf,UAAM,GAAG,QAAQ,EAAE;AAAA,EACpB;AAAA,EAEQ,qBAAqB,KAAoB;AAChD,QAAI,CAAC,KAAK,aAAa;AACtB,aAAO;AAAA,IACR;AACA,UAAM,aAAa,KAAK,UAAU;AAClC,QAAI,CAAC,YAAY;AAChB,aAAO;AAAA,IACR;AACA,WAAO,IAAI,QAAA,IAAY,WAAW,aAAa;AAAA,EAChD;AACD;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CreateAuthLogEntryCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/authLog/CreateAuthLogEntryCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { AuthActionType } from '../../type/AuthLog.js'\nimport { InsertBuilder } from '@contember/database'\nimport { JSONValue } from '@contember/schema'\n\nexport class CreateAuthLogEntryCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly data: CreateAuthLogEntryCommand.Entry,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tawait InsertBuilder.create()\n\t\t\t.into('person_auth_log')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tinvoked_by_id: this.data.invokedById,\n\t\t\t\tperson_id: this.data.personId,\n\t\t\t\tperson_input_identifier: this.data.personInputIdentifier,\n\t\t\t\tperson_token_id: this.data.personTokenId,\n\t\t\t\ttype: this.data.type,\n\t\t\t\tsuccess: this.data.success,\n\t\t\t\terror_code: this.data.errorCode,\n\t\t\t\terror_message: this.data.errorMessage,\n\t\t\t\tip_address: this.data.ipAddress,\n\t\t\t\tuser_agent: this.data.userAgent,\n\t\t\t\tidentity_provider_id: this.data.identityProviderId,\n\t\t\t\tmetadata: this.data.metadata ?? {},\n\t\t\t\ttarget_person_id: this.data.targetPersonId,\n\t\t\t\tevent_data: this.data.eventData,\n\t\t\t\tgeo_country: this.data.geoCountry,\n\t\t\t\tdevice_fingerprint: this.data.deviceFingerprint,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nnamespace CreateAuthLogEntryCommand {\n\texport type Entry = {\n\t\ttype: AuthActionType\n\t\t/** The identity that initiated the action. Omit (→ NULL) when there is no acting identity, e.g. an IdP-initiated back-channel logout. */\n\t\tinvokedById?: string\n\t\tpersonInputIdentifier?: string\n\t\tpersonId?: string\n\t\tpersonTokenId?: string\n\t\tsuccess: boolean\n\t\terrorCode?: string\n\t\terrorMessage?: string\n\t\tipAddress?: string\n\t\tuserAgent?: string\n\t\tidentityProviderId?: string\n\t\tmetadata?: JSONValue\n\t\ttargetPersonId?: string\n\t\teventData?: JSONValue\n\t\t/** A03: country derived from the trusted reverse-proxy geo header, when present. */\n\t\tgeoCountry?: string\n\t\t/** A03: hash of the client user-agent (never the raw UA). */\n\t\tdeviceFingerprint?: string\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";;;AAKO,MAAM,0BAAmD;AAAA,EAC/D,YACkB,MAChB;AADgB,SAAA,OAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAMA,SAAAA,cAAc,OAAA,EAClB,KAAK,iBAAiB,EACtB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd,eAAe,KAAK,KAAK;AAAA,MACzB,WAAW,KAAK,KAAK;AAAA,MACrB,yBAAyB,KAAK,KAAK;AAAA,MACnC,iBAAiB,KAAK,KAAK;AAAA,MAC3B,MAAM,KAAK,KAAK;AAAA,MAChB,SAAS,KAAK,KAAK;AAAA,MACnB,YAAY,KAAK,KAAK;AAAA,MACtB,eAAe,KAAK,KAAK;AAAA,MACzB,YAAY,KAAK,KAAK;AAAA,MACtB,YAAY,KAAK,KAAK;AAAA,MACtB,sBAAsB,KAAK,KAAK;AAAA,MAChC,UAAU,KAAK,KAAK,YAAY,CAAA;AAAA,MAChC,kBAAkB,KAAK,KAAK;AAAA,MAC5B,YAAY,KAAK,KAAK;AAAA,MACtB,aAAa,KAAK,KAAK;AAAA,MACvB,oBAAoB,KAAK,KAAK;AAAA,IAAA,CAC9B,EACA,QAAQ,EAAE;AAAA,EACb;AACD;;"}
1
+ {"version":3,"file":"CreateAuthLogEntryCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/authLog/CreateAuthLogEntryCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { AuthActionType } from '../../type/AuthLog.js'\nimport { InsertBuilder } from '@contember/database'\nimport { JSONValue } from '@contember/schema'\n\nexport class CreateAuthLogEntryCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly data: CreateAuthLogEntryCommand.Entry,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tawait InsertBuilder.create()\n\t\t\t.into('person_auth_log')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tinvoked_by_id: this.data.invokedById,\n\t\t\t\tperson_id: this.data.personId,\n\t\t\t\tperson_input_identifier: this.data.personInputIdentifier,\n\t\t\t\tperson_token_id: this.data.personTokenId,\n\t\t\t\ttype: this.data.type,\n\t\t\t\tsuccess: this.data.success,\n\t\t\t\terror_code: this.data.errorCode,\n\t\t\t\terror_message: this.data.errorMessage,\n\t\t\t\tip_address: this.data.ipAddress,\n\t\t\t\tuser_agent: this.data.userAgent,\n\t\t\t\tidentity_provider_id: this.data.identityProviderId,\n\t\t\t\tmetadata: this.data.metadata ?? {},\n\t\t\t\ttarget_person_id: this.data.targetPersonId,\n\t\t\t\tevent_data: this.data.eventData,\n\t\t\t\tgeo_country: this.data.geoCountry,\n\t\t\t\tdevice_fingerprint: this.data.deviceFingerprint,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nnamespace CreateAuthLogEntryCommand {\n\texport type Entry = {\n\t\ttype: AuthActionType\n\t\t/** The identity that initiated the action. Omit (→ NULL) when there is no acting identity, e.g. an IdP-initiated back-channel logout. */\n\t\tinvokedById?: string\n\t\tpersonInputIdentifier?: string\n\t\tpersonId?: string\n\t\t/** A `person_token` id (password reset, e-mail verification, passwordless). FK-checked, so never an `api_key` id: put that in `eventData`. */\n\t\tpersonTokenId?: string\n\t\tsuccess: boolean\n\t\terrorCode?: string\n\t\terrorMessage?: string\n\t\tipAddress?: string\n\t\tuserAgent?: string\n\t\tidentityProviderId?: string\n\t\tmetadata?: JSONValue\n\t\ttargetPersonId?: string\n\t\teventData?: JSONValue\n\t\t/** A03: country derived from the trusted reverse-proxy geo header, when present. */\n\t\tgeoCountry?: string\n\t\t/** A03: hash of the client user-agent (never the raw UA). */\n\t\tdeviceFingerprint?: string\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";;;AAKO,MAAM,0BAAmD;AAAA,EAC/D,YACkB,MAChB;AADgB,SAAA,OAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAMA,SAAAA,cAAc,OAAA,EAClB,KAAK,iBAAiB,EACtB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd,eAAe,KAAK,KAAK;AAAA,MACzB,WAAW,KAAK,KAAK;AAAA,MACrB,yBAAyB,KAAK,KAAK;AAAA,MACnC,iBAAiB,KAAK,KAAK;AAAA,MAC3B,MAAM,KAAK,KAAK;AAAA,MAChB,SAAS,KAAK,KAAK;AAAA,MACnB,YAAY,KAAK,KAAK;AAAA,MACtB,eAAe,KAAK,KAAK;AAAA,MACzB,YAAY,KAAK,KAAK;AAAA,MACtB,YAAY,KAAK,KAAK;AAAA,MACtB,sBAAsB,KAAK,KAAK;AAAA,MAChC,UAAU,KAAK,KAAK,YAAY,CAAA;AAAA,MAChC,kBAAkB,KAAK,KAAK;AAAA,MAC5B,YAAY,KAAK,KAAK;AAAA,MACtB,aAAa,KAAK,KAAK;AAAA,MACvB,oBAAoB,KAAK,KAAK;AAAA,IAAA,CAC9B,EACA,QAAQ,EAAE;AAAA,EACb;AACD;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"CreateAuthLogEntryCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/authLog/CreateAuthLogEntryCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { AuthActionType } from '../../type/AuthLog.js'\nimport { InsertBuilder } from '@contember/database'\nimport { JSONValue } from '@contember/schema'\n\nexport class CreateAuthLogEntryCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly data: CreateAuthLogEntryCommand.Entry,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tawait InsertBuilder.create()\n\t\t\t.into('person_auth_log')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tinvoked_by_id: this.data.invokedById,\n\t\t\t\tperson_id: this.data.personId,\n\t\t\t\tperson_input_identifier: this.data.personInputIdentifier,\n\t\t\t\tperson_token_id: this.data.personTokenId,\n\t\t\t\ttype: this.data.type,\n\t\t\t\tsuccess: this.data.success,\n\t\t\t\terror_code: this.data.errorCode,\n\t\t\t\terror_message: this.data.errorMessage,\n\t\t\t\tip_address: this.data.ipAddress,\n\t\t\t\tuser_agent: this.data.userAgent,\n\t\t\t\tidentity_provider_id: this.data.identityProviderId,\n\t\t\t\tmetadata: this.data.metadata ?? {},\n\t\t\t\ttarget_person_id: this.data.targetPersonId,\n\t\t\t\tevent_data: this.data.eventData,\n\t\t\t\tgeo_country: this.data.geoCountry,\n\t\t\t\tdevice_fingerprint: this.data.deviceFingerprint,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nnamespace CreateAuthLogEntryCommand {\n\texport type Entry = {\n\t\ttype: AuthActionType\n\t\t/** The identity that initiated the action. Omit (→ NULL) when there is no acting identity, e.g. an IdP-initiated back-channel logout. */\n\t\tinvokedById?: string\n\t\tpersonInputIdentifier?: string\n\t\tpersonId?: string\n\t\tpersonTokenId?: string\n\t\tsuccess: boolean\n\t\terrorCode?: string\n\t\terrorMessage?: string\n\t\tipAddress?: string\n\t\tuserAgent?: string\n\t\tidentityProviderId?: string\n\t\tmetadata?: JSONValue\n\t\ttargetPersonId?: string\n\t\teventData?: JSONValue\n\t\t/** A03: country derived from the trusted reverse-proxy geo header, when present. */\n\t\tgeoCountry?: string\n\t\t/** A03: hash of the client user-agent (never the raw UA). */\n\t\tdeviceFingerprint?: string\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";AAKO,MAAM,0BAAmD;AAAA,EAC/D,YACkB,MAChB;AADgB,SAAA,OAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAMA,gBAAc,OAAA,EAClB,KAAK,iBAAiB,EACtB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd,eAAe,KAAK,KAAK;AAAA,MACzB,WAAW,KAAK,KAAK;AAAA,MACrB,yBAAyB,KAAK,KAAK;AAAA,MACnC,iBAAiB,KAAK,KAAK;AAAA,MAC3B,MAAM,KAAK,KAAK;AAAA,MAChB,SAAS,KAAK,KAAK;AAAA,MACnB,YAAY,KAAK,KAAK;AAAA,MACtB,eAAe,KAAK,KAAK;AAAA,MACzB,YAAY,KAAK,KAAK;AAAA,MACtB,YAAY,KAAK,KAAK;AAAA,MACtB,sBAAsB,KAAK,KAAK;AAAA,MAChC,UAAU,KAAK,KAAK,YAAY,CAAA;AAAA,MAChC,kBAAkB,KAAK,KAAK;AAAA,MAC5B,YAAY,KAAK,KAAK;AAAA,MACtB,aAAa,KAAK,KAAK;AAAA,MACvB,oBAAoB,KAAK,KAAK;AAAA,IAAA,CAC9B,EACA,QAAQ,EAAE;AAAA,EACb;AACD;"}
1
+ {"version":3,"file":"CreateAuthLogEntryCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/authLog/CreateAuthLogEntryCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\nimport { AuthActionType } from '../../type/AuthLog.js'\nimport { InsertBuilder } from '@contember/database'\nimport { JSONValue } from '@contember/schema'\n\nexport class CreateAuthLogEntryCommand implements Command<void> {\n\tconstructor(\n\t\tprivate readonly data: CreateAuthLogEntryCommand.Entry,\n\t) {\n\t}\n\n\tasync execute({ db, providers }: Command.Args): Promise<void> {\n\t\tawait InsertBuilder.create()\n\t\t\t.into('person_auth_log')\n\t\t\t.values({\n\t\t\t\tid: providers.uuid(),\n\t\t\t\tinvoked_by_id: this.data.invokedById,\n\t\t\t\tperson_id: this.data.personId,\n\t\t\t\tperson_input_identifier: this.data.personInputIdentifier,\n\t\t\t\tperson_token_id: this.data.personTokenId,\n\t\t\t\ttype: this.data.type,\n\t\t\t\tsuccess: this.data.success,\n\t\t\t\terror_code: this.data.errorCode,\n\t\t\t\terror_message: this.data.errorMessage,\n\t\t\t\tip_address: this.data.ipAddress,\n\t\t\t\tuser_agent: this.data.userAgent,\n\t\t\t\tidentity_provider_id: this.data.identityProviderId,\n\t\t\t\tmetadata: this.data.metadata ?? {},\n\t\t\t\ttarget_person_id: this.data.targetPersonId,\n\t\t\t\tevent_data: this.data.eventData,\n\t\t\t\tgeo_country: this.data.geoCountry,\n\t\t\t\tdevice_fingerprint: this.data.deviceFingerprint,\n\t\t\t})\n\t\t\t.execute(db)\n\t}\n}\n\nnamespace CreateAuthLogEntryCommand {\n\texport type Entry = {\n\t\ttype: AuthActionType\n\t\t/** The identity that initiated the action. Omit (→ NULL) when there is no acting identity, e.g. an IdP-initiated back-channel logout. */\n\t\tinvokedById?: string\n\t\tpersonInputIdentifier?: string\n\t\tpersonId?: string\n\t\t/** A `person_token` id (password reset, e-mail verification, passwordless). FK-checked, so never an `api_key` id: put that in `eventData`. */\n\t\tpersonTokenId?: string\n\t\tsuccess: boolean\n\t\terrorCode?: string\n\t\terrorMessage?: string\n\t\tipAddress?: string\n\t\tuserAgent?: string\n\t\tidentityProviderId?: string\n\t\tmetadata?: JSONValue\n\t\ttargetPersonId?: string\n\t\teventData?: JSONValue\n\t\t/** A03: country derived from the trusted reverse-proxy geo header, when present. */\n\t\tgeoCountry?: string\n\t\t/** A03: hash of the client user-agent (never the raw UA). */\n\t\tdeviceFingerprint?: string\n\t}\n}\n"],"names":["InsertBuilder"],"mappings":";AAKO,MAAM,0BAAmD;AAAA,EAC/D,YACkB,MAChB;AADgB,SAAA,OAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,IAAI,aAA0C;AAC7D,UAAMA,gBAAc,OAAA,EAClB,KAAK,iBAAiB,EACtB,OAAO;AAAA,MACP,IAAI,UAAU,KAAA;AAAA,MACd,eAAe,KAAK,KAAK;AAAA,MACzB,WAAW,KAAK,KAAK;AAAA,MACrB,yBAAyB,KAAK,KAAK;AAAA,MACnC,iBAAiB,KAAK,KAAK;AAAA,MAC3B,MAAM,KAAK,KAAK;AAAA,MAChB,SAAS,KAAK,KAAK;AAAA,MACnB,YAAY,KAAK,KAAK;AAAA,MACtB,eAAe,KAAK,KAAK;AAAA,MACzB,YAAY,KAAK,KAAK;AAAA,MACtB,YAAY,KAAK,KAAK;AAAA,MACtB,sBAAsB,KAAK,KAAK;AAAA,MAChC,UAAU,KAAK,KAAK,YAAY,CAAA;AAAA,MAChC,kBAAkB,KAAK,KAAK;AAAA,MAC5B,YAAY,KAAK,KAAK;AAAA,MACtB,aAAa,KAAK,KAAK;AAAA,MACvB,oBAAoB,KAAK,KAAK;AAAA,IAAA,CAC9B,EACA,QAAQ,EAAE;AAAA,EACb;AACD;"}
@@ -1,18 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const Database = require("@contember/database");
3
4
  class ClaimIdpRevalidationCommand {
4
5
  constructor(id, interval) {
5
6
  this.id = id;
6
7
  this.interval = interval;
7
8
  }
8
9
  async execute({ db }) {
9
- const result = await db.query(
10
- `UPDATE "idp_session"
11
- SET "last_validated_at" = now()
12
- WHERE "id" = ? AND "last_validated_at" <= now() - ?::interval`,
13
- [this.id, this.interval]
14
- );
15
- return (result.rowCount ?? 0) > 0;
10
+ const qb = Database.UpdateBuilder.create().table("idp_session").where({ id: this.id }).where((expr) => expr.raw('"last_validated_at" <= now() - ?::interval', this.interval)).values({ last_validated_at: (expr) => expr.raw("now()") });
11
+ return await qb.execute(db) > 0;
16
12
  }
17
13
  }
18
14
  exports.ClaimIdpRevalidationCommand = ClaimIdpRevalidationCommand;
@@ -1 +1 @@
1
- {"version":3,"file":"ClaimIdpRevalidationCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/ClaimIdpRevalidationCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\n\n/**\n * Atomically claim the right to re-validate a federated session: bump `last_validated_at`\n * to now() iff the throttle window has elapsed. Returns true only to the single request\n * that wins the claim, false to everyone else (still inside the window, or lost the race).\n *\n * This is both the throttle and the single-flight guard — critical for `method: 'refresh'`,\n * where two concurrent revalidations would rotate the refresh token and invalidate each\n * other. The interval is bound as a parameter and cast to `interval`, so it is injection-safe.\n */\nexport class ClaimIdpRevalidationCommand implements Command<boolean> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly interval: string,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<boolean> {\n\t\tconst result = await db.query(\n\t\t\t`UPDATE \"idp_session\"\n\t\t\t SET \"last_validated_at\" = now()\n\t\t\t WHERE \"id\" = ? AND \"last_validated_at\" <= now() - ?::interval`,\n\t\t\t[this.id, this.interval],\n\t\t)\n\t\treturn (result.rowCount ?? 0) > 0\n\t}\n}\n"],"names":[],"mappings":";;AAWO,MAAM,4BAAwD;AAAA,EACpE,YACkB,IACA,UAChB;AAFgB,SAAA,KAAA;AACA,SAAA,WAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAsC;AACrD,UAAM,SAAS,MAAM,GAAG;AAAA,MACvB;AAAA;AAAA;AAAA,MAGA,CAAC,KAAK,IAAI,KAAK,QAAQ;AAAA,IAAA;AAExB,YAAQ,OAAO,YAAY,KAAK;AAAA,EACjC;AACD;;"}
1
+ {"version":3,"file":"ClaimIdpRevalidationCommand.cjs","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/ClaimIdpRevalidationCommand.ts"],"sourcesContent":["import { UpdateBuilder } from '@contember/database'\nimport { Command } from '../Command.js'\n\n/**\n * Atomically claim the right to re-validate a federated session: bump `last_validated_at`\n * to now() iff the throttle window has elapsed. Returns true only to the single request\n * that wins the claim, false to everyone else (still inside the window, or lost the race).\n *\n * This is both the throttle and the single-flight guard — critical for `method: 'refresh'`,\n * where two concurrent revalidations would rotate the refresh token and invalidate each\n * other. The interval is bound as a parameter and cast to `interval`, so it is injection-safe.\n */\nexport class ClaimIdpRevalidationCommand implements Command<boolean> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly interval: string,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<boolean> {\n\t\tconst qb = UpdateBuilder.create()\n\t\t\t.table('idp_session')\n\t\t\t.where({ id: this.id })\n\t\t\t.where(expr => expr.raw('\"last_validated_at\" <= now() - ?::interval', this.interval))\n\t\t\t.values({ last_validated_at: expr => expr.raw('now()') })\n\n\t\treturn (await qb.execute(db)) > 0\n\t}\n}\n"],"names":["UpdateBuilder"],"mappings":";;;AAYO,MAAM,4BAAwD;AAAA,EACpE,YACkB,IACA,UAChB;AAFgB,SAAA,KAAA;AACA,SAAA,WAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAsC;AACrD,UAAM,KAAKA,SAAAA,cAAc,OAAA,EACvB,MAAM,aAAa,EACnB,MAAM,EAAE,IAAI,KAAK,GAAA,CAAI,EACrB,MAAM,CAAA,SAAQ,KAAK,IAAI,8CAA8C,KAAK,QAAQ,CAAC,EACnF,OAAO,EAAE,mBAAmB,CAAA,SAAQ,KAAK,IAAI,OAAO,GAAG;AAEzD,WAAQ,MAAM,GAAG,QAAQ,EAAE,IAAK;AAAA,EACjC;AACD;;"}
@@ -1,16 +1,12 @@
1
+ import { UpdateBuilder as UpdateBuilder$1 } from "@contember/database";
1
2
  class ClaimIdpRevalidationCommand {
2
3
  constructor(id, interval) {
3
4
  this.id = id;
4
5
  this.interval = interval;
5
6
  }
6
7
  async execute({ db }) {
7
- const result = await db.query(
8
- `UPDATE "idp_session"
9
- SET "last_validated_at" = now()
10
- WHERE "id" = ? AND "last_validated_at" <= now() - ?::interval`,
11
- [this.id, this.interval]
12
- );
13
- return (result.rowCount ?? 0) > 0;
8
+ const qb = UpdateBuilder$1.create().table("idp_session").where({ id: this.id }).where((expr) => expr.raw('"last_validated_at" <= now() - ?::interval', this.interval)).values({ last_validated_at: (expr) => expr.raw("now()") });
9
+ return await qb.execute(db) > 0;
14
10
  }
15
11
  }
16
12
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"ClaimIdpRevalidationCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/ClaimIdpRevalidationCommand.ts"],"sourcesContent":["import { Command } from '../Command.js'\n\n/**\n * Atomically claim the right to re-validate a federated session: bump `last_validated_at`\n * to now() iff the throttle window has elapsed. Returns true only to the single request\n * that wins the claim, false to everyone else (still inside the window, or lost the race).\n *\n * This is both the throttle and the single-flight guard — critical for `method: 'refresh'`,\n * where two concurrent revalidations would rotate the refresh token and invalidate each\n * other. The interval is bound as a parameter and cast to `interval`, so it is injection-safe.\n */\nexport class ClaimIdpRevalidationCommand implements Command<boolean> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly interval: string,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<boolean> {\n\t\tconst result = await db.query(\n\t\t\t`UPDATE \"idp_session\"\n\t\t\t SET \"last_validated_at\" = now()\n\t\t\t WHERE \"id\" = ? AND \"last_validated_at\" <= now() - ?::interval`,\n\t\t\t[this.id, this.interval],\n\t\t)\n\t\treturn (result.rowCount ?? 0) > 0\n\t}\n}\n"],"names":[],"mappings":"AAWO,MAAM,4BAAwD;AAAA,EACpE,YACkB,IACA,UAChB;AAFgB,SAAA,KAAA;AACA,SAAA,WAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAsC;AACrD,UAAM,SAAS,MAAM,GAAG;AAAA,MACvB;AAAA;AAAA;AAAA,MAGA,CAAC,KAAK,IAAI,KAAK,QAAQ;AAAA,IAAA;AAExB,YAAQ,OAAO,YAAY,KAAK;AAAA,EACjC;AACD;"}
1
+ {"version":3,"file":"ClaimIdpRevalidationCommand.js","sources":["../../../../../../../packages/engine-tenant-api/src/model/commands/idp/ClaimIdpRevalidationCommand.ts"],"sourcesContent":["import { UpdateBuilder } from '@contember/database'\nimport { Command } from '../Command.js'\n\n/**\n * Atomically claim the right to re-validate a federated session: bump `last_validated_at`\n * to now() iff the throttle window has elapsed. Returns true only to the single request\n * that wins the claim, false to everyone else (still inside the window, or lost the race).\n *\n * This is both the throttle and the single-flight guard — critical for `method: 'refresh'`,\n * where two concurrent revalidations would rotate the refresh token and invalidate each\n * other. The interval is bound as a parameter and cast to `interval`, so it is injection-safe.\n */\nexport class ClaimIdpRevalidationCommand implements Command<boolean> {\n\tconstructor(\n\t\tprivate readonly id: string,\n\t\tprivate readonly interval: string,\n\t) {\n\t}\n\n\tasync execute({ db }: Command.Args): Promise<boolean> {\n\t\tconst qb = UpdateBuilder.create()\n\t\t\t.table('idp_session')\n\t\t\t.where({ id: this.id })\n\t\t\t.where(expr => expr.raw('\"last_validated_at\" <= now() - ?::interval', this.interval))\n\t\t\t.values({ last_validated_at: expr => expr.raw('now()') })\n\n\t\treturn (await qb.execute(db)) > 0\n\t}\n}\n"],"names":["UpdateBuilder"],"mappings":";AAYO,MAAM,4BAAwD;AAAA,EACpE,YACkB,IACA,UAChB;AAFgB,SAAA,KAAA;AACA,SAAA,WAAA;AAAA,EAElB;AAAA,EAEA,MAAM,QAAQ,EAAE,MAAsC;AACrD,UAAM,KAAKA,gBAAc,OAAA,EACvB,MAAM,aAAa,EACnB,MAAM,EAAE,IAAI,KAAK,GAAA,CAAI,EACrB,MAAM,CAAA,SAAQ,KAAK,IAAI,8CAA8C,KAAK,QAAQ,CAAC,EACnF,OAAO,EAAE,mBAAmB,CAAA,SAAQ,KAAK,IAAI,OAAO,GAAG;AAEzD,WAAQ,MAAM,GAAG,QAAQ,EAAE,IAAK;AAAA,EACjC;AACD;"}
@@ -33,10 +33,11 @@ const CreateIdpSessionCommand = require("../commands/idp/CreateIdpSessionCommand
33
33
  const Password = require("../dtos/Password.cjs");
34
34
  const AuthLogService = require("./AuthLogService.cjs");
35
35
  class IDPSignInManager {
36
- constructor(apiKeyManager, idpRegistry, claimSyncService) {
36
+ constructor(apiKeyManager, idpRegistry, claimSyncService, logger) {
37
37
  this.apiKeyManager = apiKeyManager;
38
38
  this.idpRegistry = idpRegistry;
39
39
  this.claimSyncService = claimSyncService;
40
+ this.logger = logger;
40
41
  }
41
42
  async signInIDP(dbContext, idpSlug, responseData, expiration, requestInfo, trustForwardedInfo) {
42
43
  return dbContext.transaction(async (db) => {
@@ -96,7 +97,8 @@ class IDPSignInManager {
96
97
  let claimMappingFailed = false;
97
98
  try {
98
99
  mapping = ClaimMapping.parseClaimMapping(provider.configuration);
99
- } catch {
100
+ } catch (e) {
101
+ this.logger.warn(e, { message: "IdP sign-in: claim mapping configuration is invalid", identityProviderId: provider.id });
100
102
  claimMappingFailed = true;
101
103
  }
102
104
  let claimMappingAudit = null;
@@ -125,19 +127,25 @@ class IDPSignInManager {
125
127
  if (!hasTokens || db.providers.encryptionEnabled) {
126
128
  await db.commandBus.execute(new CreateIdpSessionCommand.CreateIdpSessionCommand(apiKeyId, provider.id, claim.idpSession));
127
129
  } else {
128
- await db.commandBus.execute(
129
- new CreateAuthLogEntryCommand.CreateAuthLogEntryCommand({
130
- type: "idp_session_revalidation_failed",
131
- invokedById: personRow.identity_id,
132
- personId: personRow.id,
133
- identityProviderId: provider.id,
134
- personTokenId: apiKeyId,
135
- success: true,
136
- errorCode: "encryption_disabled",
137
- ipAddress: requestInfo?.ip,
138
- userAgent: requestInfo?.userAgent
139
- })
140
- );
130
+ try {
131
+ await db.commandBus.transaction(
132
+ (bus) => bus.execute(
133
+ new CreateAuthLogEntryCommand.CreateAuthLogEntryCommand({
134
+ type: "idp_session_revalidation_failed",
135
+ invokedById: personRow.identity_id,
136
+ personId: personRow.id,
137
+ identityProviderId: provider.id,
138
+ success: true,
139
+ errorCode: "encryption_disabled",
140
+ ipAddress: requestInfo?.ip,
141
+ userAgent: requestInfo?.userAgent,
142
+ eventData: { apiKeyId }
143
+ })
144
+ )
145
+ );
146
+ } catch (e) {
147
+ this.logger.error(e, { message: "IdP sign-in: writing the encryption_disabled audit entry failed", identityProviderId: provider.id });
148
+ }
141
149
  }
142
150
  }
143
151
  return new Response.ResponseOk({
@@ -1 +1 @@
1
- {"version":3,"file":"IDPSignInManager.cjs","sources":["../../../../../../packages/engine-tenant-api/src/model/service/IDPSignInManager.ts"],"sourcesContent":["import { ApiKeyManager } from './apiKey/index.js'\nimport { IdentityProviderBySlugQuery, PersonByIdPQuery, PersonQuery, PersonRow } from '../queries/index.js'\nimport { IDPHandlerRegistry, IDPResponse, IDPResponseError, IDPValidationError } from './idp/index.js'\nimport { Response, ResponseError, ResponseOk } from '../utils/Response.js'\nimport { InitSignInIdpErrorCode, InitSignInIdpResult, SignInIdpErrorCode } from '../../schema/index.js'\nimport { DatabaseContext } from '../utils/index.js'\nimport { ApiKeyRequestInfo, CreateIdentityCommand, CreatePersonCommand, CreatePersonIdentityProviderIdentifierCommand } from '../commands/index.js'\nimport { CreateIdpSessionCommand } from '../commands/idp/CreateIdpSessionCommand.js'\nimport { CreateAuthLogEntryCommand } from '../commands/authLog/CreateAuthLogEntryCommand.js'\nimport { TenantRole } from '../authorization/index.js'\nimport { NoPassword } from '../dtos/index.js'\nimport { IdentityProviderRow } from '../queries/idp/types.js'\nimport { AuthLogService } from './AuthLogService.js'\nimport { ClaimMappingAudit, IDPClaimSyncService } from './idp/IDPClaimSyncService.js'\nimport { ClaimMapping, parseClaimMapping } from './idp/ClaimMapping.js'\n\nclass IDPSignInManager {\n\tconstructor(\n\t\tprivate readonly apiKeyManager: ApiKeyManager,\n\t\tprivate readonly idpRegistry: IDPHandlerRegistry,\n\t\tprivate readonly claimSyncService: IDPClaimSyncService,\n\t) {}\n\n\tasync signInIDP(\n\t\tdbContext: DatabaseContext,\n\t\tidpSlug: string,\n\t\tresponseData: unknown,\n\t\texpiration?: number,\n\t\trequestInfo?: ApiKeyRequestInfo,\n\t\ttrustForwardedInfo?: boolean,\n\t): Promise<IDPSignInManager.SignInIDPResponse> {\n\t\treturn dbContext.transaction(async (db): Promise<IDPSignInManager.SignInIDPResponse> => {\n\t\t\tconst provider = await db.queryHandler.fetch(new IdentityProviderBySlugQuery(idpSlug))\n\t\t\tif (!provider || provider.disabledAt) {\n\t\t\t\tthrow new Error('provider not found')\n\t\t\t}\n\t\t\tconst providerService = this.idpRegistry.getHandler(provider.type)\n\t\t\tconst validatedConfig = providerService.validateConfiguration(provider.configuration)\n\t\t\tlet claim: IDPResponse\n\t\t\ttry {\n\t\t\t\tclaim = await providerService.processResponse(\n\t\t\t\t\tvalidatedConfig,\n\t\t\t\t\tresponseData,\n\t\t\t\t)\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof IDPResponseError) {\n\t\t\t\t\treturn new ResponseError('INVALID_IDP_RESPONSE', e.message, {\n\t\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\t\tpersonId: undefined,\n\t\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (e instanceof IDPValidationError) {\n\t\t\t\t\treturn new ResponseError('IDP_VALIDATION_FAILED', e.message, {\n\t\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\t\tpersonId: undefined,\n\t\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tthrow e\n\t\t\t}\n\t\t\tconst resolved = await this.resolvePerson(db, claim, provider)\n\t\t\tconst personRow = resolved.person\n\n\t\t\tif (!personRow) {\n\t\t\t\t// Keep the external error generic (no account-existence leak), but\n\t\t\t\t// record the email-verification gate block distinctly in the audit\n\t\t\t\t// log — it is a takeover-grade event, not an ordinary \"not found\".\n\t\t\t\treturn new ResponseError('PERSON_NOT_FOUND', `Person ${claim.email} not found`, {\n\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\tpersonInput: claim.email,\n\t\t\t\t\t\tpersonId: resolved.blockedPersonId,\n\t\t\t\t\t\teventData: resolved.blockedReason ? { reason: resolved.blockedReason } : undefined,\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (personRow.disabled_at !== null) {\n\t\t\t\treturn new ResponseError('PERSON_DISABLED', `Person with e-mail ${claim.email} is disabled`, {\n\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\tpersonInput: claim.email,\n\t\t\t\t\t\tpersonId: personRow.id,\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// A09 — map IdP claims to project memberships. Returns a `{ before, after }` delta only\n\t\t\t// when something actually changed; the resolver emits the `idp_role_mapped` audit from it\n\t\t\t// (audit stays at the resolver layer).\n\t\t\t//\n\t\t\t// Fail-open on a MALFORMED/out-of-band `claimMapping`: parsing is caught so a bad config can\n\t\t\t// never lock the user out — sign-in proceeds without claim mapping and the resolver emits an\n\t\t\t// `idp_role_mapping_failed` marker. A DB error during the apply itself is NOT caught: it\n\t\t\t// propagates and rolls back the whole sign-in transaction, so a half-applied set of grants is\n\t\t\t// never committed (failing sign-in on an infra error is the safe outcome).\n\t\t\tlet mapping: ClaimMapping | null = null\n\t\t\tlet claimMappingFailed = false\n\t\t\ttry {\n\t\t\t\tmapping = parseClaimMapping(provider.configuration)\n\t\t\t} catch {\n\t\t\t\tclaimMappingFailed = true\n\t\t\t}\n\t\t\tlet claimMappingAudit: ClaimMappingAudit | null = null\n\t\t\tif (mapping) {\n\t\t\t\tconst syncResult = await this.claimSyncService.sync(\n\t\t\t\t\tdb,\n\t\t\t\t\tmapping,\n\t\t\t\t\tclaim,\n\t\t\t\t\t{ id: personRow.identity_id },\n\t\t\t\t\tresolved.isNewPerson === true,\n\t\t\t\t)\n\t\t\t\tclaimMappingAudit = syncResult.audit\n\t\t\t\t// The apply-time safety backstop dropped a configured rule (config-time validation was skipped, or\n\t\t\t\t// the project's ACL drifted since): surface the same fail-open marker as a malformed config, so a\n\t\t\t\t// silently-unapplied grant is visible to the operator. The resolver emits `idp_role_mapping_failed`.\n\t\t\t\tif (syncResult.droppedUnsafeRules) {\n\t\t\t\t\tclaimMappingFailed = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst { id: apiKeyId, token: sessionToken } = await this.apiKeyManager.createSessionApiKeyWithId(\n\t\t\t\tdb,\n\t\t\t\tpersonRow.identity_id,\n\t\t\t\texpiration,\n\t\t\t\trequestInfo,\n\t\t\t\ttrustForwardedInfo,\n\t\t\t)\n\n\t\t\t// Bind the federated-session state to this session so it can be re-validated\n\t\t\t// against the IdP later. Present only when the provider supports it and\n\t\t\t// revalidation is enabled on the IdP configuration (A24). Refresh tokens must be\n\t\t\t// encrypted at rest, so when no encryption key is configured we skip persisting a\n\t\t\t// token-bearing session (it would otherwise crash or store secrets in plaintext) —\n\t\t\t// the session then behaves like a plain session with no re-validation.\n\t\t\tif (claim.idpSession) {\n\t\t\t\tconst hasTokens = !!claim.idpSession.tokens && Object.keys(claim.idpSession.tokens).length > 0\n\t\t\t\tif (!hasTokens || db.providers.encryptionEnabled) {\n\t\t\t\t\tawait db.commandBus.execute(new CreateIdpSessionCommand(apiKeyId, provider.id, claim.idpSession))\n\t\t\t\t} else {\n\t\t\t\t\t// Re-validation is enabled on this IdP but no encryption key is configured, so we\n\t\t\t\t\t// won't store the token-bearing session — it silently degrades to a plain,\n\t\t\t\t\t// non-revalidated session. Audit the downgrade (errorCode `encryption_disabled`)\n\t\t\t\t\t// so the operator can see that a session they expected to be continuously\n\t\t\t\t\t// re-validated is in fact not protected, instead of failing closed at sign-in.\n\t\t\t\t\tawait db.commandBus.execute(\n\t\t\t\t\t\tnew CreateAuthLogEntryCommand({\n\t\t\t\t\t\t\ttype: 'idp_session_revalidation_failed',\n\t\t\t\t\t\t\tinvokedById: personRow.identity_id,\n\t\t\t\t\t\t\tpersonId: personRow.id,\n\t\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\t\tpersonTokenId: apiKeyId,\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\terrorCode: 'encryption_disabled',\n\t\t\t\t\t\t\tipAddress: requestInfo?.ip,\n\t\t\t\t\t\t\tuserAgent: requestInfo?.userAgent,\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new ResponseOk({\n\t\t\t\tperson: personRow,\n\t\t\t\ttoken: sessionToken,\n\t\t\t\tidpResponse: claim,\n\t\t\t\tclaimMappingAudit,\n\t\t\t\tclaimMappingFailed,\n\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\tpersonId: personRow.id,\n\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\tpersonInput: claim.email,\n\t\t\t\t}),\n\t\t\t})\n\t\t})\n\t}\n\n\tasync initSignInIDP(dbContext: DatabaseContext, idpSlug: string, data: unknown): Promise<IDPSignInManager.InitSignInIDPResponse> {\n\t\tconst provider = await dbContext.queryHandler.fetch(new IdentityProviderBySlugQuery(idpSlug))\n\t\tif (!provider || provider.disabledAt) {\n\t\t\treturn new ResponseError('PROVIDER_NOT_FOUND', `Identity provider ${idpSlug} not found`)\n\t\t}\n\t\tconst providerService = this.idpRegistry.getHandler(provider.type)\n\t\tconst validatedConfig = providerService.validateConfiguration(provider.configuration)\n\t\ttry {\n\t\t\tconst initResponse = await providerService.initAuth(validatedConfig, data)\n\n\t\t\tconst publicConfig = providerService.getPublicConfiguration\n\t\t\t\t? providerService.getPublicConfiguration(validatedConfig)\n\t\t\t\t: validatedConfig\n\n\t\t\treturn new ResponseOk({\n\t\t\t\t...initResponse,\n\t\t\t\tidpConfiguration: provider.initReturnsConfig ? publicConfig : null,\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tif (e instanceof IDPValidationError) {\n\t\t\t\treturn new ResponseError('IDP_VALIDATION_FAILED', e.message)\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tprivate async resolvePerson(db: DatabaseContext, claim: IDPResponse, provider: IdentityProviderRow): Promise<IDPSignInManager.ResolvePersonResult> {\n\t\tconst personByIdPQuery = new PersonByIdPQuery(provider.id, claim.externalIdentifier)\n\t\tconst personByIdp = await db.queryHandler.fetch(personByIdPQuery)\n\t\tif (personByIdp) {\n\t\t\treturn { person: personByIdp }\n\t\t}\n\n\t\tif (!provider.exclusive) {\n\t\t\tconst personByEmail = typeof claim.email === 'string' && claim.email\n\t\t\t\t? await db.queryHandler.fetch(PersonQuery.byEmail(claim.email))\n\t\t\t\t: null\n\t\t\tif (personByEmail) {\n\t\t\t\t// Auto-linking an IdP identity to a pre-existing local account by\n\t\t\t\t// e-mail is takeover-grade: if the provider returns an unverified\n\t\t\t\t// (or attacker-controlled) e-mail, it could hijack the account. When\n\t\t\t\t// the provider requires a verified e-mail, refuse to link — and to\n\t\t\t\t// sign in — unless the address is asserted verified. `assumeEmailVerified`\n\t\t\t\t// lets a trusted IdP that never emits the claim still satisfy the gate.\n\t\t\t\tconst emailVerified = provider.assumeEmailVerified || claim.emailVerified === true\n\t\t\t\tif (provider.requireVerifiedEmail && !emailVerified) {\n\t\t\t\t\treturn { person: null, blockedReason: 'idp_email_unverified', blockedPersonId: personByEmail.id }\n\t\t\t\t}\n\t\t\t\tawait this.saveIdpIdentifier(db, provider, claim, personByEmail)\n\t\t\t\treturn { person: personByEmail }\n\t\t\t}\n\t\t}\n\n\t\tif (provider.autoSignUp) {\n\t\t\tconst signedUpPerson = await this.signUp(db, claim, provider)\n\t\t\tawait this.saveIdpIdentifier(db, provider, claim, signedUpPerson)\n\t\t\treturn { person: signedUpPerson, isNewPerson: true }\n\t\t}\n\n\t\treturn { person: null }\n\t}\n\n\tprivate async signUp(db: DatabaseContext, { email, name, externalIdentifier }: IDPResponse, provider: IdentityProviderRow): Promise<PersonRow> {\n\t\tconst roles = [TenantRole.PERSON]\n\t\tconst identityId = await db.commandBus.execute(new CreateIdentityCommand(roles))\n\t\tconst newPerson = await db.commandBus.execute(\n\t\t\tnew CreatePersonCommand({\n\t\t\t\tidentityId,\n\t\t\t\temail: provider.exclusive ? undefined : email,\n\t\t\t\tpassword: NoPassword,\n\t\t\t\tname: name ?? email?.split('@')[0] ?? externalIdentifier,\n\t\t\t\tidpOnly: provider.exclusive,\n\t\t\t}),\n\t\t)\n\n\t\treturn {\n\t\t\t...newPerson,\n\t\t\troles,\n\t\t}\n\t}\n\n\tprivate async saveIdpIdentifier(db: DatabaseContext, provider: IdentityProviderRow, claim: IDPResponse, person: PersonRow) {\n\t\tawait db.commandBus.execute(new CreatePersonIdentityProviderIdentifierCommand(provider.id, person.id, claim.externalIdentifier))\n\t}\n}\n\nnamespace IDPSignInManager {\n\texport type ResolvePersonResult = {\n\t\treadonly person: PersonRow | null\n\t\treadonly blockedReason?: 'idp_email_unverified'\n\t\treadonly blockedPersonId?: string\n\t\t/** True when the person row was just created by auto-sign-up (drives the `sticky` claim-mapping policy). */\n\t\treadonly isNewPerson?: boolean\n\t}\n\n\texport type InitSignInIDPResponse = Response<InitSignInIdpResult, InitSignInIdpErrorCode>\n\n\tinterface SignInIDPResult {\n\t\treadonly person: PersonRow\n\t\treadonly token: string\n\t\treadonly idpResponse?: Record<string, unknown>\n\t\t/** Identity provider the sign-in went through (for the resolver's audit). */\n\t\treadonly identityProviderId?: string\n\t\t/** Claim-mapping (A09) before/after delta — present only when a mapping changed grants. */\n\t\treadonly claimMappingAudit?: ClaimMappingAudit | null\n\t\t/** True when claim mapping failed and was skipped (fail-open) — drives the `idp_role_mapping_failed` audit. */\n\t\treadonly claimMappingFailed?: boolean\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}\n\n\texport type SignInIDPResponse = Response<SignInIDPResult, SignInIdpErrorCode, {\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}>\n}\n\nexport { IDPSignInManager }\n"],"names":["IdentityProviderBySlugQuery","IDPResponseError","ResponseError","AuthLogService","IDPValidationError","parseClaimMapping","CreateIdpSessionCommand","CreateAuthLogEntryCommand","ResponseOk","PersonByIdPQuery","PersonQuery","TenantRole","CreateIdentityCommand","CreatePersonCommand","NoPassword","CreatePersonIdentityProviderIdentifierCommand"],"mappings":"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"}
1
+ {"version":3,"file":"IDPSignInManager.cjs","sources":["../../../../../../packages/engine-tenant-api/src/model/service/IDPSignInManager.ts"],"sourcesContent":["import { ApiKeyManager } from './apiKey/index.js'\nimport { IdentityProviderBySlugQuery, PersonByIdPQuery, PersonQuery, PersonRow } from '../queries/index.js'\nimport { IDPHandlerRegistry, IDPResponse, IDPResponseError, IDPValidationError } from './idp/index.js'\nimport { Response, ResponseError, ResponseOk } from '../utils/Response.js'\nimport { InitSignInIdpErrorCode, InitSignInIdpResult, SignInIdpErrorCode } from '../../schema/index.js'\nimport { DatabaseContext } from '../utils/index.js'\nimport { ApiKeyRequestInfo, CreateIdentityCommand, CreatePersonCommand, CreatePersonIdentityProviderIdentifierCommand } from '../commands/index.js'\nimport { CreateIdpSessionCommand } from '../commands/idp/CreateIdpSessionCommand.js'\nimport { CreateAuthLogEntryCommand } from '../commands/authLog/CreateAuthLogEntryCommand.js'\nimport { TenantRole } from '../authorization/index.js'\nimport { NoPassword } from '../dtos/index.js'\nimport { IdentityProviderRow } from '../queries/idp/types.js'\nimport { AuthLogService } from './AuthLogService.js'\nimport { ClaimMappingAudit, IDPClaimSyncService } from './idp/IDPClaimSyncService.js'\nimport { ClaimMapping, parseClaimMapping } from './idp/ClaimMapping.js'\nimport { Logger } from '@contember/logger'\n\nclass IDPSignInManager {\n\tconstructor(\n\t\tprivate readonly apiKeyManager: ApiKeyManager,\n\t\tprivate readonly idpRegistry: IDPHandlerRegistry,\n\t\tprivate readonly claimSyncService: IDPClaimSyncService,\n\t\tprivate readonly logger: Logger,\n\t) {}\n\n\tasync signInIDP(\n\t\tdbContext: DatabaseContext,\n\t\tidpSlug: string,\n\t\tresponseData: unknown,\n\t\texpiration?: number,\n\t\trequestInfo?: ApiKeyRequestInfo,\n\t\ttrustForwardedInfo?: boolean,\n\t): Promise<IDPSignInManager.SignInIDPResponse> {\n\t\treturn dbContext.transaction(async (db): Promise<IDPSignInManager.SignInIDPResponse> => {\n\t\t\tconst provider = await db.queryHandler.fetch(new IdentityProviderBySlugQuery(idpSlug))\n\t\t\tif (!provider || provider.disabledAt) {\n\t\t\t\tthrow new Error('provider not found')\n\t\t\t}\n\t\t\tconst providerService = this.idpRegistry.getHandler(provider.type)\n\t\t\tconst validatedConfig = providerService.validateConfiguration(provider.configuration)\n\t\t\tlet claim: IDPResponse\n\t\t\ttry {\n\t\t\t\tclaim = await providerService.processResponse(\n\t\t\t\t\tvalidatedConfig,\n\t\t\t\t\tresponseData,\n\t\t\t\t)\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof IDPResponseError) {\n\t\t\t\t\treturn new ResponseError('INVALID_IDP_RESPONSE', e.message, {\n\t\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\t\tpersonId: undefined,\n\t\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tif (e instanceof IDPValidationError) {\n\t\t\t\t\treturn new ResponseError('IDP_VALIDATION_FAILED', e.message, {\n\t\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\t\tpersonId: undefined,\n\t\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tthrow e\n\t\t\t}\n\t\t\tconst resolved = await this.resolvePerson(db, claim, provider)\n\t\t\tconst personRow = resolved.person\n\n\t\t\tif (!personRow) {\n\t\t\t\t// Keep the external error generic (no account-existence leak), but\n\t\t\t\t// record the email-verification gate block distinctly in the audit\n\t\t\t\t// log — it is a takeover-grade event, not an ordinary \"not found\".\n\t\t\t\treturn new ResponseError('PERSON_NOT_FOUND', `Person ${claim.email} not found`, {\n\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\tpersonInput: claim.email,\n\t\t\t\t\t\tpersonId: resolved.blockedPersonId,\n\t\t\t\t\t\teventData: resolved.blockedReason ? { reason: resolved.blockedReason } : undefined,\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (personRow.disabled_at !== null) {\n\t\t\t\treturn new ResponseError('PERSON_DISABLED', `Person with e-mail ${claim.email} is disabled`, {\n\t\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\tpersonInput: claim.email,\n\t\t\t\t\t\tpersonId: personRow.id,\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// A09 — map IdP claims to project memberships. Returns a `{ before, after }` delta only\n\t\t\t// when something actually changed; the resolver emits the `idp_role_mapped` audit from it\n\t\t\t// (audit stays at the resolver layer).\n\t\t\t//\n\t\t\t// Fail-open on a MALFORMED/out-of-band `claimMapping`: parsing is caught so a bad config can\n\t\t\t// never lock the user out — sign-in proceeds without claim mapping and the resolver emits an\n\t\t\t// `idp_role_mapping_failed` marker. A DB error during the apply itself is NOT caught: it\n\t\t\t// propagates and rolls back the whole sign-in transaction, so a half-applied set of grants is\n\t\t\t// never committed (failing sign-in on an infra error is the safe outcome).\n\t\t\tlet mapping: ClaimMapping | null = null\n\t\t\tlet claimMappingFailed = false\n\t\t\ttry {\n\t\t\t\tmapping = parseClaimMapping(provider.configuration)\n\t\t\t} catch (e) {\n\t\t\t\tthis.logger.warn(e, { message: 'IdP sign-in: claim mapping configuration is invalid', identityProviderId: provider.id })\n\t\t\t\tclaimMappingFailed = true\n\t\t\t}\n\t\t\tlet claimMappingAudit: ClaimMappingAudit | null = null\n\t\t\tif (mapping) {\n\t\t\t\tconst syncResult = await this.claimSyncService.sync(\n\t\t\t\t\tdb,\n\t\t\t\t\tmapping,\n\t\t\t\t\tclaim,\n\t\t\t\t\t{ id: personRow.identity_id },\n\t\t\t\t\tresolved.isNewPerson === true,\n\t\t\t\t)\n\t\t\t\tclaimMappingAudit = syncResult.audit\n\t\t\t\t// The apply-time safety backstop dropped a configured rule (config-time validation was skipped, or\n\t\t\t\t// the project's ACL drifted since): surface the same fail-open marker as a malformed config, so a\n\t\t\t\t// silently-unapplied grant is visible to the operator. The resolver emits `idp_role_mapping_failed`.\n\t\t\t\tif (syncResult.droppedUnsafeRules) {\n\t\t\t\t\tclaimMappingFailed = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst { id: apiKeyId, token: sessionToken } = await this.apiKeyManager.createSessionApiKeyWithId(\n\t\t\t\tdb,\n\t\t\t\tpersonRow.identity_id,\n\t\t\t\texpiration,\n\t\t\t\trequestInfo,\n\t\t\t\ttrustForwardedInfo,\n\t\t\t)\n\n\t\t\t// Bind the federated-session state to this session so it can be re-validated\n\t\t\t// against the IdP later. Present only when the provider supports it and\n\t\t\t// revalidation is enabled on the IdP configuration (A24). Refresh tokens must be\n\t\t\t// encrypted at rest, so when no encryption key is configured we skip persisting a\n\t\t\t// token-bearing session (it would otherwise crash or store secrets in plaintext) —\n\t\t\t// the session then behaves like a plain session with no re-validation.\n\t\t\tif (claim.idpSession) {\n\t\t\t\tconst hasTokens = !!claim.idpSession.tokens && Object.keys(claim.idpSession.tokens).length > 0\n\t\t\t\tif (!hasTokens || db.providers.encryptionEnabled) {\n\t\t\t\t\tawait db.commandBus.execute(new CreateIdpSessionCommand(apiKeyId, provider.id, claim.idpSession))\n\t\t\t\t} else {\n\t\t\t\t\t// Re-validation is enabled on this IdP but no encryption key is configured, so we\n\t\t\t\t\t// won't store the token-bearing session — it silently degrades to a plain,\n\t\t\t\t\t// non-revalidated session. Audit the downgrade (errorCode `encryption_disabled`)\n\t\t\t\t\t// so the operator can see that a session they expected to be continuously\n\t\t\t\t\t// re-validated is in fact not protected, instead of failing closed at sign-in.\n\t\t\t\t\t// Best-effort, in a savepoint: a failed insert would otherwise abort the whole\n\t\t\t\t\t// sign-in transaction, and a lost audit row must not block the sign-in.\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait db.commandBus.transaction(bus =>\n\t\t\t\t\t\t\tbus.execute(\n\t\t\t\t\t\t\t\tnew CreateAuthLogEntryCommand({\n\t\t\t\t\t\t\t\t\ttype: 'idp_session_revalidation_failed',\n\t\t\t\t\t\t\t\t\tinvokedById: personRow.identity_id,\n\t\t\t\t\t\t\t\t\tpersonId: personRow.id,\n\t\t\t\t\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\terrorCode: 'encryption_disabled',\n\t\t\t\t\t\t\t\t\tipAddress: requestInfo?.ip,\n\t\t\t\t\t\t\t\t\tuserAgent: requestInfo?.userAgent,\n\t\t\t\t\t\t\t\t\teventData: { apiKeyId },\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tthis.logger.error(e, { message: 'IdP sign-in: writing the encryption_disabled audit entry failed', identityProviderId: provider.id })\n\t\t\t\t\t\t// the savepoint is rolled back, the sign-in transaction stays usable\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new ResponseOk({\n\t\t\t\tperson: personRow,\n\t\t\t\ttoken: sessionToken,\n\t\t\t\tidpResponse: claim,\n\t\t\t\tclaimMappingAudit,\n\t\t\t\tclaimMappingFailed,\n\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t[AuthLogService.Key]: new AuthLogService.Bag({\n\t\t\t\t\tpersonId: personRow.id,\n\t\t\t\t\tidentityProviderId: provider.id,\n\t\t\t\t\tpersonInput: claim.email,\n\t\t\t\t}),\n\t\t\t})\n\t\t})\n\t}\n\n\tasync initSignInIDP(dbContext: DatabaseContext, idpSlug: string, data: unknown): Promise<IDPSignInManager.InitSignInIDPResponse> {\n\t\tconst provider = await dbContext.queryHandler.fetch(new IdentityProviderBySlugQuery(idpSlug))\n\t\tif (!provider || provider.disabledAt) {\n\t\t\treturn new ResponseError('PROVIDER_NOT_FOUND', `Identity provider ${idpSlug} not found`)\n\t\t}\n\t\tconst providerService = this.idpRegistry.getHandler(provider.type)\n\t\tconst validatedConfig = providerService.validateConfiguration(provider.configuration)\n\t\ttry {\n\t\t\tconst initResponse = await providerService.initAuth(validatedConfig, data)\n\n\t\t\tconst publicConfig = providerService.getPublicConfiguration\n\t\t\t\t? providerService.getPublicConfiguration(validatedConfig)\n\t\t\t\t: validatedConfig\n\n\t\t\treturn new ResponseOk({\n\t\t\t\t...initResponse,\n\t\t\t\tidpConfiguration: provider.initReturnsConfig ? publicConfig : null,\n\t\t\t})\n\t\t} catch (e) {\n\t\t\tif (e instanceof IDPValidationError) {\n\t\t\t\treturn new ResponseError('IDP_VALIDATION_FAILED', e.message)\n\t\t\t}\n\t\t\tthrow e\n\t\t}\n\t}\n\n\tprivate async resolvePerson(db: DatabaseContext, claim: IDPResponse, provider: IdentityProviderRow): Promise<IDPSignInManager.ResolvePersonResult> {\n\t\tconst personByIdPQuery = new PersonByIdPQuery(provider.id, claim.externalIdentifier)\n\t\tconst personByIdp = await db.queryHandler.fetch(personByIdPQuery)\n\t\tif (personByIdp) {\n\t\t\treturn { person: personByIdp }\n\t\t}\n\n\t\tif (!provider.exclusive) {\n\t\t\tconst personByEmail = typeof claim.email === 'string' && claim.email\n\t\t\t\t? await db.queryHandler.fetch(PersonQuery.byEmail(claim.email))\n\t\t\t\t: null\n\t\t\tif (personByEmail) {\n\t\t\t\t// Auto-linking an IdP identity to a pre-existing local account by\n\t\t\t\t// e-mail is takeover-grade: if the provider returns an unverified\n\t\t\t\t// (or attacker-controlled) e-mail, it could hijack the account. When\n\t\t\t\t// the provider requires a verified e-mail, refuse to link — and to\n\t\t\t\t// sign in — unless the address is asserted verified. `assumeEmailVerified`\n\t\t\t\t// lets a trusted IdP that never emits the claim still satisfy the gate.\n\t\t\t\tconst emailVerified = provider.assumeEmailVerified || claim.emailVerified === true\n\t\t\t\tif (provider.requireVerifiedEmail && !emailVerified) {\n\t\t\t\t\treturn { person: null, blockedReason: 'idp_email_unverified', blockedPersonId: personByEmail.id }\n\t\t\t\t}\n\t\t\t\tawait this.saveIdpIdentifier(db, provider, claim, personByEmail)\n\t\t\t\treturn { person: personByEmail }\n\t\t\t}\n\t\t}\n\n\t\tif (provider.autoSignUp) {\n\t\t\tconst signedUpPerson = await this.signUp(db, claim, provider)\n\t\t\tawait this.saveIdpIdentifier(db, provider, claim, signedUpPerson)\n\t\t\treturn { person: signedUpPerson, isNewPerson: true }\n\t\t}\n\n\t\treturn { person: null }\n\t}\n\n\tprivate async signUp(db: DatabaseContext, { email, name, externalIdentifier }: IDPResponse, provider: IdentityProviderRow): Promise<PersonRow> {\n\t\tconst roles = [TenantRole.PERSON]\n\t\tconst identityId = await db.commandBus.execute(new CreateIdentityCommand(roles))\n\t\tconst newPerson = await db.commandBus.execute(\n\t\t\tnew CreatePersonCommand({\n\t\t\t\tidentityId,\n\t\t\t\temail: provider.exclusive ? undefined : email,\n\t\t\t\tpassword: NoPassword,\n\t\t\t\tname: name ?? email?.split('@')[0] ?? externalIdentifier,\n\t\t\t\tidpOnly: provider.exclusive,\n\t\t\t}),\n\t\t)\n\n\t\treturn {\n\t\t\t...newPerson,\n\t\t\troles,\n\t\t}\n\t}\n\n\tprivate async saveIdpIdentifier(db: DatabaseContext, provider: IdentityProviderRow, claim: IDPResponse, person: PersonRow) {\n\t\tawait db.commandBus.execute(new CreatePersonIdentityProviderIdentifierCommand(provider.id, person.id, claim.externalIdentifier))\n\t}\n}\n\nnamespace IDPSignInManager {\n\texport type ResolvePersonResult = {\n\t\treadonly person: PersonRow | null\n\t\treadonly blockedReason?: 'idp_email_unverified'\n\t\treadonly blockedPersonId?: string\n\t\t/** True when the person row was just created by auto-sign-up (drives the `sticky` claim-mapping policy). */\n\t\treadonly isNewPerson?: boolean\n\t}\n\n\texport type InitSignInIDPResponse = Response<InitSignInIdpResult, InitSignInIdpErrorCode>\n\n\tinterface SignInIDPResult {\n\t\treadonly person: PersonRow\n\t\treadonly token: string\n\t\treadonly idpResponse?: Record<string, unknown>\n\t\t/** Identity provider the sign-in went through (for the resolver's audit). */\n\t\treadonly identityProviderId?: string\n\t\t/** Claim-mapping (A09) before/after delta — present only when a mapping changed grants. */\n\t\treadonly claimMappingAudit?: ClaimMappingAudit | null\n\t\t/** True when claim mapping failed and was skipped (fail-open) — drives the `idp_role_mapping_failed` audit. */\n\t\treadonly claimMappingFailed?: boolean\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}\n\n\texport type SignInIDPResponse = Response<SignInIDPResult, SignInIdpErrorCode, {\n\t\t[AuthLogService.Key]: AuthLogService.Bag\n\t}>\n}\n\nexport { IDPSignInManager }\n"],"names":["IdentityProviderBySlugQuery","IDPResponseError","ResponseError","AuthLogService","IDPValidationError","parseClaimMapping","CreateIdpSessionCommand","CreateAuthLogEntryCommand","ResponseOk","PersonByIdPQuery","PersonQuery","TenantRole","CreateIdentityCommand","CreatePersonCommand","NoPassword","CreatePersonIdentityProviderIdentifierCommand"],"mappings":"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"}