瀏覽代碼

fix: passing key params for backup requests (#867)

Karol Sójko 1 年之前
父節點
當前提交
07398169c8

+ 0 - 1
packages/api-gateway/src/Service/Resolver/EndpointResolver.ts

@@ -42,7 +42,6 @@ export class EndpointResolver implements EndpointResolverInterface {
     // Users Controller
     ['[PATCH]:users/:userId', 'auth.users.update'],
     ['[PUT]:users/:userUuid/attributes/credentials', 'auth.users.updateCredentials'],
-    ['[GET]:users/params', 'auth.users.getKeyParams'],
     ['[DELETE]:users/:userUuid', 'auth.users.delete'],
     ['[POST]:listed', 'auth.users.createListedAccount'],
     ['[POST]:auth', 'auth.users.register'],

+ 12 - 1
packages/auth/bin/backup.ts

@@ -21,6 +21,7 @@ import { SettingRepositoryInterface } from '../src/Domain/Setting/SettingReposit
 import { MuteFailedBackupsEmailsOption, SettingName } from '@standardnotes/settings'
 import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
 import { PermissionName } from '@standardnotes/features'
+import { GetUserKeyParams } from '../src/Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
 
 const inputArgs = process.argv.slice(2)
 const backupProvider = inputArgs[0]
@@ -31,6 +32,7 @@ const requestBackups = async (
   roleService: RoleServiceInterface,
   domainEventFactory: DomainEventFactoryInterface,
   domainEventPublisher: DomainEventPublisherInterface,
+  getUserKeyParamsUseCase: GetUserKeyParams,
 ): Promise<void> => {
   const settingName = SettingName.create(SettingName.NAMES.EmailBackupFrequency).getValue()
   const permissionName = PermissionName.DailyEmailBackup
@@ -64,11 +66,17 @@ const requestBackups = async (
               userHasEmailsMuted = emailsMutedSetting.value === muteEmailsSettingValue
             }
 
+            const keyParamsResponse = await getUserKeyParamsUseCase.execute({
+              userUuid: setting.setting_user_uuid,
+              authenticated: false,
+            })
+
             await domainEventPublisher.publish(
               domainEventFactory.createEmailBackupRequestedEvent(
                 setting.setting_user_uuid,
                 emailsMutedSetting?.uuid as string,
                 userHasEmailsMuted,
+                keyParamsResponse.keyParams,
               ),
             )
 
@@ -96,11 +104,14 @@ void container.load().then((container) => {
   const roleService: RoleServiceInterface = container.get(TYPES.Auth_RoleService)
   const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.Auth_DomainEventFactory)
   const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
+  const getUserKeyParamsUseCase: GetUserKeyParams = container.get(TYPES.Auth_GetUserKeyParams)
 
   const tracer = new OpenTelemetryTracer()
   tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'backup')
 
-  Promise.resolve(requestBackups(settingRepository, roleService, domainEventFactory, domainEventPublisher))
+  Promise.resolve(
+    requestBackups(settingRepository, roleService, domainEventFactory, domainEventPublisher, getUserKeyParamsUseCase),
+  )
     .then(() => {
       logger.info(`${backupFrequency} ${backupProvider} backup requesting complete`)
 

+ 17 - 1
packages/auth/bin/user_email_backup.ts

@@ -20,6 +20,7 @@ import { MuteFailedBackupsEmailsOption, SettingName } from '@standardnotes/setti
 import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
 import { PermissionName } from '@standardnotes/features'
 import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
+import { GetUserKeyParams } from '../src/Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
 
 const inputArgs = process.argv.slice(2)
 const backupEmail = inputArgs[0]
@@ -30,6 +31,7 @@ const requestBackups = async (
   roleService: RoleServiceInterface,
   domainEventFactory: DomainEventFactoryInterface,
   domainEventPublisher: DomainEventPublisherInterface,
+  getUserKeyParamsUseCase: GetUserKeyParams,
 ): Promise<void> => {
   const permissionName = PermissionName.DailyEmailBackup
   const muteEmailsSettingName = SettingName.NAMES.MuteFailedBackupsEmails
@@ -57,11 +59,17 @@ const requestBackups = async (
     userHasEmailsMuted = emailsMutedSetting.value === muteEmailsSettingValue
   }
 
+  const keyParamsResponse = await getUserKeyParamsUseCase.execute({
+    userUuid: user.uuid,
+    authenticated: false,
+  })
+
   await domainEventPublisher.publish(
     domainEventFactory.createEmailBackupRequestedEvent(
       user.uuid,
       emailsMutedSetting?.uuid as string,
       userHasEmailsMuted,
+      keyParamsResponse.keyParams,
     ),
   )
 
@@ -84,12 +92,20 @@ void container.load().then((container) => {
   const roleService: RoleServiceInterface = container.get(TYPES.Auth_RoleService)
   const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.Auth_DomainEventFactory)
   const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
+  const getUserKeyParamsUseCase: GetUserKeyParams = container.get(TYPES.Auth_GetUserKeyParams)
 
   const tracer = new OpenTelemetryTracer()
   tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'user_email_backup')
 
   Promise.resolve(
-    requestBackups(userRepository, settingRepository, roleService, domainEventFactory, domainEventPublisher),
+    requestBackups(
+      userRepository,
+      settingRepository,
+      roleService,
+      domainEventFactory,
+      domainEventPublisher,
+      getUserKeyParamsUseCase,
+    ),
   )
     .then(() => {
       logger.info(`Email backup requesting complete for ${backupEmail}`)

+ 58 - 24
packages/auth/src/Bootstrap/Container.ts

@@ -273,6 +273,8 @@ import { UserRemovedFromSharedVaultEventHandler } from '../Domain/Handler/UserRe
 import { DesignateSurvivor } from '../Domain/UseCase/DesignateSurvivor/DesignateSurvivor'
 import { UserDesignatedAsSurvivorInSharedVaultEventHandler } from '../Domain/Handler/UserDesignatedAsSurvivorInSharedVaultEventHandler'
 import { DisableEmailSettingBasedOnEmailSubscription } from '../Domain/UseCase/DisableEmailSettingBasedOnEmailSubscription/DisableEmailSettingBasedOnEmailSubscription'
+import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
+import { KeyParamsFactoryInterface } from '../Domain/User/KeyParamsFactoryInterface'
 
 export class ContainerConfigLoader {
   constructor(private mode: 'server' | 'worker' = 'server') {}
@@ -306,6 +308,8 @@ export class ContainerConfigLoader {
     }
     container.bind<winston.Logger>(TYPES.Auth_Logger).toConstantValue(logger)
 
+    container.bind<CryptoNode>(TYPES.Auth_CryptoNode).toConstantValue(new CryptoNode())
+
     const appDataSource = new AppDataSource({ env, runMigrations: this.mode === 'server' })
     await appDataSource.initialize()
 
@@ -367,6 +371,19 @@ export class ContainerConfigLoader {
       container.bind<SQSClient>(TYPES.Auth_SQS).toConstantValue(sqsClient)
     }
 
+    container.bind(TYPES.Auth_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
+
+    container
+      .bind<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher)
+      .toConstantValue(
+        isConfiguredForHomeServer
+          ? directCallDomainEventPublisher
+          : new SNSOpenTelemetryDomainEventPublisher(
+              container.get(TYPES.Auth_SNS),
+              container.get(TYPES.Auth_SNS_TOPIC_ARN),
+            ),
+      )
+
     // Mapping
     container
       .bind<MapperInterface<SessionTrace, TypeORMSessionTrace>>(TYPES.Auth_SessionTracePersistenceMapper)
@@ -547,7 +564,6 @@ export class ContainerConfigLoader {
     container
       .bind(TYPES.Auth_DISABLE_USER_REGISTRATION)
       .toConstantValue(env.get('DISABLE_USER_REGISTRATION', true) === 'true')
-    container.bind(TYPES.Auth_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
     container.bind(TYPES.Auth_SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
     container.bind(TYPES.Auth_SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL', true))
     container
@@ -649,6 +665,9 @@ export class ContainerConfigLoader {
     }
 
     // Services
+    container
+      .bind<SelectorInterface<ProtocolVersion>>(TYPES.Auth_ProtocolVersionSelector)
+      .toConstantValue(new DeterministicSelector<ProtocolVersion>())
     container.bind<UAParser>(TYPES.Auth_DeviceDetector).toConstantValue(new UAParser())
     container.bind<SessionService>(TYPES.Auth_SessionService).to(SessionService)
     container.bind<AuthResponseFactory20161215>(TYPES.Auth_AuthResponseFactory20161215).to(AuthResponseFactory20161215)
@@ -691,44 +710,61 @@ export class ContainerConfigLoader {
     container.bind<DomainEventFactory>(TYPES.Auth_DomainEventFactory).to(DomainEventFactory)
     container.bind<AxiosInstance>(TYPES.Auth_HTTPClient).toConstantValue(axios.create())
     container.bind<CrypterInterface>(TYPES.Auth_Crypter).to(CrypterNode)
-    container.bind<SettingServiceInterface>(TYPES.Auth_SettingService).to(SettingService)
+    container
+      .bind<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService)
+      .to(SettingsAssociationService)
+    container.bind<SettingDecrypterInterface>(TYPES.Auth_SettingDecrypter).to(SettingDecrypter)
+
+    container
+      .bind<GetUserKeyParams>(TYPES.Auth_GetUserKeyParams)
+      .toConstantValue(
+        new GetUserKeyParams(
+          container.get<KeyParamsFactoryInterface>(TYPES.Auth_KeyParamsFactory),
+          container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
+          container.get<PKCERepositoryInterface>(TYPES.Auth_PKCERepository),
+          container.get<winston.Logger>(TYPES.Auth_Logger),
+        ),
+      )
+    container
+      .bind<SettingInterpreterInterface>(TYPES.Auth_SettingInterpreter)
+      .toConstantValue(
+        new SettingInterpreter(
+          container.get<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher),
+          container.get<DomainEventFactoryInterface>(TYPES.Auth_DomainEventFactory),
+          container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
+          container.get<GetUserKeyParams>(TYPES.Auth_GetUserKeyParams),
+        ),
+      )
+
+    container
+      .bind<SettingServiceInterface>(TYPES.Auth_SettingService)
+      .toConstantValue(
+        new SettingService(
+          container.get<SettingFactoryInterface>(TYPES.Auth_SettingFactory),
+          container.get<SettingRepositoryInterface>(TYPES.Auth_SettingRepository),
+          container.get<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService),
+          container.get<SettingInterpreterInterface>(TYPES.Auth_SettingInterpreter),
+          container.get<SettingDecrypterInterface>(TYPES.Auth_SettingDecrypter),
+          container.get<winston.Logger>(TYPES.Auth_Logger),
+        ),
+      )
     container
       .bind<SubscriptionSettingServiceInterface>(TYPES.Auth_SubscriptionSettingService)
       .to(SubscriptionSettingService)
     container.bind<OfflineSettingServiceInterface>(TYPES.Auth_OfflineSettingService).to(OfflineSettingService)
-    container.bind<CryptoNode>(TYPES.Auth_CryptoNode).toConstantValue(new CryptoNode())
     container.bind<ContentDecoderInterface>(TYPES.Auth_ContenDecoder).toConstantValue(new ContentDecoder())
     container.bind<ClientServiceInterface>(TYPES.Auth_WebSocketsClientService).to(WebSocketsClientService)
     container.bind<RoleServiceInterface>(TYPES.Auth_RoleService).to(RoleService)
     container.bind<RoleToSubscriptionMapInterface>(TYPES.Auth_RoleToSubscriptionMap).to(RoleToSubscriptionMap)
-    container
-      .bind<SettingsAssociationServiceInterface>(TYPES.Auth_SettingsAssociationService)
-      .to(SettingsAssociationService)
     container
       .bind<SubscriptionSettingsAssociationServiceInterface>(TYPES.Auth_SubscriptionSettingsAssociationService)
       .to(SubscriptionSettingsAssociationService)
     container.bind<FeatureServiceInterface>(TYPES.Auth_FeatureService).to(FeatureService)
-    container.bind<SettingInterpreterInterface>(TYPES.Auth_SettingInterpreter).to(SettingInterpreter)
-    container.bind<SettingDecrypterInterface>(TYPES.Auth_SettingDecrypter).to(SettingDecrypter)
-    container
-      .bind<SelectorInterface<ProtocolVersion>>(TYPES.Auth_ProtocolVersionSelector)
-      .toConstantValue(new DeterministicSelector<ProtocolVersion>())
     container
       .bind<SelectorInterface<boolean>>(TYPES.Auth_BooleanSelector)
       .toConstantValue(new DeterministicSelector<boolean>())
     container.bind<UserSubscriptionServiceInterface>(TYPES.Auth_UserSubscriptionService).to(UserSubscriptionService)
 
-    container
-      .bind<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher)
-      .toConstantValue(
-        isConfiguredForHomeServer
-          ? directCallDomainEventPublisher
-          : new SNSOpenTelemetryDomainEventPublisher(
-              container.get(TYPES.Auth_SNS),
-              container.get(TYPES.Auth_SNS_TOPIC_ARN),
-            ),
-      )
-
     // Middleware
     container.bind<SessionMiddleware>(TYPES.Auth_SessionMiddleware).to(SessionMiddleware)
     container.bind<LockMiddleware>(TYPES.Auth_LockMiddleware).to(LockMiddleware)
@@ -881,7 +917,6 @@ export class ContainerConfigLoader {
           container.get(TYPES.Auth_SettingService),
         ),
       )
-    container.bind<GetUserKeyParams>(TYPES.Auth_GetUserKeyParams).to(GetUserKeyParams)
     container.bind<UpdateUser>(TYPES.Auth_UpdateUser).to(UpdateUser)
     container.bind<Register>(TYPES.Auth_Register).to(Register)
     container.bind<GetActiveSessionsForUser>(TYPES.Auth_GetActiveSessionsForUser).to(GetActiveSessionsForUser)
@@ -1311,7 +1346,6 @@ export class ContainerConfigLoader {
         .toConstantValue(
           new BaseUsersController(
             container.get<UpdateUser>(TYPES.Auth_UpdateUser),
-            container.get<GetUserKeyParams>(TYPES.Auth_GetUserKeyParams),
             container.get<DeleteAccount>(TYPES.Auth_DeleteAccount),
             container.get<GetUserSubscription>(TYPES.Auth_GetUserSubscription),
             container.get<ClearLoginAttempts>(TYPES.Auth_ClearLoginAttempts),

+ 3 - 0
packages/auth/src/Domain/Event/DomainEventFactory.ts

@@ -28,6 +28,7 @@ import { inject, injectable } from 'inversify'
 import TYPES from '../../Bootstrap/Types'
 import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
 import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
+import { KeyParamsData } from '@standardnotes/responses'
 
 @injectable()
 export class DomainEventFactory implements DomainEventFactoryInterface {
@@ -277,6 +278,7 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
     userUuid: string,
     muteEmailsSettingUuid: string,
     userHasEmailsMuted: boolean,
+    keyParams: KeyParamsData,
   ): EmailBackupRequestedEvent {
     return {
       type: 'EMAIL_BACKUP_REQUESTED',
@@ -292,6 +294,7 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
         userUuid,
         userHasEmailsMuted,
         muteEmailsSettingUuid,
+        keyParams,
       },
     }
   }

+ 2 - 0
packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts

@@ -21,6 +21,7 @@ import {
   TransitionRequestedEvent,
 } from '@standardnotes/domain-events'
 import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
+import { KeyParamsData } from '@standardnotes/responses'
 
 export interface DomainEventFactoryInterface {
   createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: JSONString }): WebSocketMessageRequestedEvent
@@ -41,6 +42,7 @@ export interface DomainEventFactoryInterface {
     userUuid: string,
     muteEmailsSettingUuid: string,
     userHasEmailsMuted: boolean,
+    keyParams: KeyParamsData,
   ): EmailBackupRequestedEvent
   createAccountDeletionRequestedEvent(dto: {
     userUuid: string

+ 10 - 3
packages/auth/src/Domain/Setting/SettingInterpreter.spec.ts

@@ -19,6 +19,8 @@ import { SettingDecrypterInterface } from './SettingDecrypterInterface'
 
 import { SettingInterpreter } from './SettingInterpreter'
 import { SettingRepositoryInterface } from './SettingRepositoryInterface'
+import { GetUserKeyParams } from '../UseCase/GetUserKeyParams/GetUserKeyParams'
+import { KeyParamsData } from '@standardnotes/responses'
 
 describe('SettingInterpreter', () => {
   let user: User
@@ -27,8 +29,10 @@ describe('SettingInterpreter', () => {
   let settingRepository: SettingRepositoryInterface
   let settingDecrypter: SettingDecrypterInterface
   let logger: Logger
+  let getUserKeyParams: GetUserKeyParams
 
-  const createInterpreter = () => new SettingInterpreter(domainEventPublisher, domainEventFactory, settingRepository)
+  const createInterpreter = () =>
+    new SettingInterpreter(domainEventPublisher, domainEventFactory, settingRepository, getUserKeyParams)
 
   beforeEach(() => {
     user = {
@@ -61,6 +65,9 @@ describe('SettingInterpreter', () => {
     logger.debug = jest.fn()
     logger.warn = jest.fn()
     logger.error = jest.fn()
+
+    getUserKeyParams = {} as jest.Mocked<GetUserKeyParams>
+    getUserKeyParams.execute = jest.fn().mockReturnValue({ keyParams: {} as jest.Mocked<KeyParamsData> })
   })
 
   it('should trigger session cleanup if user is disabling session user agent logging', async () => {
@@ -85,7 +92,7 @@ describe('SettingInterpreter', () => {
     )
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createEmailBackupRequestedEvent).toHaveBeenCalledWith('4-5-6', '', false)
+    expect(domainEventFactory.createEmailBackupRequestedEvent).toHaveBeenCalledWith('4-5-6', '', false, {})
   })
 
   it('should trigger backup if email backup setting is created - emails muted', async () => {
@@ -102,7 +109,7 @@ describe('SettingInterpreter', () => {
     )
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createEmailBackupRequestedEvent).toHaveBeenCalledWith('4-5-6', '6-7-8', true)
+    expect(domainEventFactory.createEmailBackupRequestedEvent).toHaveBeenCalledWith('4-5-6', '6-7-8', true, {})
   })
 
   it('should not trigger backup if email backup setting is disabled', async () => {

+ 16 - 7
packages/auth/src/Domain/Setting/SettingInterpreter.ts

@@ -6,15 +6,13 @@ import {
   MuteFailedBackupsEmailsOption,
   SettingName,
 } from '@standardnotes/settings'
-import { inject, injectable } from 'inversify'
 
-import TYPES from '../../Bootstrap/Types'
 import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
 import { User } from '../User/User'
 import { SettingInterpreterInterface } from './SettingInterpreterInterface'
 import { SettingRepositoryInterface } from './SettingRepositoryInterface'
+import { GetUserKeyParams } from '../UseCase/GetUserKeyParams/GetUserKeyParams'
 
-@injectable()
 export class SettingInterpreter implements SettingInterpreterInterface {
   private readonly emailSettingToSubscriptionRejectionLevelMap: Map<string, string> = new Map([
     [SettingName.NAMES.MuteFailedBackupsEmails, EmailLevel.LEVELS.FailedEmailBackup],
@@ -24,9 +22,10 @@ export class SettingInterpreter implements SettingInterpreterInterface {
   ])
 
   constructor(
-    @inject(TYPES.Auth_DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
-    @inject(TYPES.Auth_DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
-    @inject(TYPES.Auth_SettingRepository) private settingRepository: SettingRepositoryInterface,
+    private domainEventPublisher: DomainEventPublisherInterface,
+    private domainEventFactory: DomainEventFactoryInterface,
+    private settingRepository: SettingRepositoryInterface,
+    private getUserKeyParams: GetUserKeyParams,
   ) {}
 
   async interpretSettingUpdated(
@@ -59,8 +58,18 @@ export class SettingInterpreter implements SettingInterpreterInterface {
       muteEmailsSettingUuid = muteFailedEmailsBackupSetting.uuid
     }
 
+    const keyParamsResponse = await this.getUserKeyParams.execute({
+      authenticated: false,
+      userUuid,
+    })
+
     await this.domainEventPublisher.publish(
-      this.domainEventFactory.createEmailBackupRequestedEvent(userUuid, muteEmailsSettingUuid, userHasEmailsMuted),
+      this.domainEventFactory.createEmailBackupRequestedEvent(
+        userUuid,
+        muteEmailsSettingUuid,
+        userHasEmailsMuted,
+        keyParamsResponse.keyParams,
+      ),
     )
   }
 

+ 6 - 9
packages/auth/src/Domain/Setting/SettingService.ts

@@ -1,7 +1,6 @@
 import { SettingName } from '@standardnotes/settings'
-import { inject, injectable } from 'inversify'
 import { Logger } from 'winston'
-import TYPES from '../../Bootstrap/Types'
+
 import { User } from '../User/User'
 import { CreateOrReplaceSettingDto } from './CreateOrReplaceSettingDto'
 import { CreateOrReplaceSettingResponse } from './CreateOrReplaceSettingResponse'
@@ -14,16 +13,14 @@ import { SettingInterpreterInterface } from './SettingInterpreterInterface'
 import { SettingDecrypterInterface } from './SettingDecrypterInterface'
 import { SettingFactoryInterface } from './SettingFactoryInterface'
 
-@injectable()
 export class SettingService implements SettingServiceInterface {
   constructor(
-    @inject(TYPES.Auth_SettingFactory) private factory: SettingFactoryInterface,
-    @inject(TYPES.Auth_SettingRepository) private settingRepository: SettingRepositoryInterface,
-    @inject(TYPES.Auth_SettingsAssociationService)
+    private factory: SettingFactoryInterface,
+    private settingRepository: SettingRepositoryInterface,
     private settingsAssociationService: SettingsAssociationServiceInterface,
-    @inject(TYPES.Auth_SettingInterpreter) private settingInterpreter: SettingInterpreterInterface,
-    @inject(TYPES.Auth_SettingDecrypter) private settingDecrypter: SettingDecrypterInterface,
-    @inject(TYPES.Auth_Logger) private logger: Logger,
+    private settingInterpreter: SettingInterpreterInterface,
+    private settingDecrypter: SettingDecrypterInterface,
+    private logger: Logger,
   ) {}
 
   async applyDefaultSettingsUponRegistration(user: User): Promise<void> {

+ 8 - 10
packages/auth/src/Domain/UseCase/GetUserKeyParams/GetUserKeyParams.ts

@@ -1,24 +1,22 @@
-import { inject, injectable } from 'inversify'
-import TYPES from '../../../Bootstrap/Types'
+import { KeyParamsData } from '@standardnotes/responses'
+import { Logger } from 'winston'
+import { Username, Uuid } from '@standardnotes/domain-core'
+
 import { KeyParamsFactoryInterface } from '../../User/KeyParamsFactoryInterface'
 import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
 import { GetUserKeyParamsDTO } from './GetUserKeyParamsDTO'
 import { GetUserKeyParamsResponse } from './GetUserKeyParamsResponse'
 import { UseCaseInterface } from '../UseCaseInterface'
-import { Logger } from 'winston'
 import { User } from '../../User/User'
 import { PKCERepositoryInterface } from '../../User/PKCERepositoryInterface'
 import { GetUserKeyParamsDTOV2Challenged } from './GetUserKeyParamsDTOV2Challenged'
-import { KeyParamsData } from '@standardnotes/responses'
-import { Username, Uuid } from '@standardnotes/domain-core'
 
-@injectable()
 export class GetUserKeyParams implements UseCaseInterface {
   constructor(
-    @inject(TYPES.Auth_KeyParamsFactory) private keyParamsFactory: KeyParamsFactoryInterface,
-    @inject(TYPES.Auth_UserRepository) private userRepository: UserRepositoryInterface,
-    @inject(TYPES.Auth_PKCERepository) private pkceRepository: PKCERepositoryInterface,
-    @inject(TYPES.Auth_Logger) private logger: Logger,
+    private keyParamsFactory: KeyParamsFactoryInterface,
+    private userRepository: UserRepositoryInterface,
+    private pkceRepository: PKCERepositoryInterface,
+    private logger: Logger,
   ) {}
 
   async execute(dto: GetUserKeyParamsDTO): Promise<GetUserKeyParamsResponse> {

+ 0 - 60
packages/auth/src/Infra/InversifyExpressUtils/AnnotatedUsersController.spec.ts

@@ -8,7 +8,6 @@ import { Result, Username } from '@standardnotes/domain-core'
 import { DeleteAccount } from '../../Domain/UseCase/DeleteAccount/DeleteAccount'
 import { ChangeCredentials } from '../../Domain/UseCase/ChangeCredentials/ChangeCredentials'
 import { ClearLoginAttempts } from '../../Domain/UseCase/ClearLoginAttempts'
-import { GetUserKeyParams } from '../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
 import { GetUserSubscription } from '../../Domain/UseCase/GetUserSubscription/GetUserSubscription'
 import { IncreaseLoginAttempts } from '../../Domain/UseCase/IncreaseLoginAttempts'
 import { InviteToSharedSubscription } from '../../Domain/UseCase/InviteToSharedSubscription/InviteToSharedSubscription'
@@ -18,7 +17,6 @@ import { User } from '../../Domain/User/User'
 describe('AnnotatedUsersController', () => {
   let updateUser: UpdateUser
   let deleteAccount: DeleteAccount
-  let getUserKeyParams: GetUserKeyParams
   let getUserSubscription: GetUserSubscription
   let clearLoginAttempts: ClearLoginAttempts
   let increaseLoginAttempts: IncreaseLoginAttempts
@@ -32,7 +30,6 @@ describe('AnnotatedUsersController', () => {
   const createController = () =>
     new AnnotatedUsersController(
       updateUser,
-      getUserKeyParams,
       deleteAccount,
       getUserSubscription,
       clearLoginAttempts,
@@ -51,9 +48,6 @@ describe('AnnotatedUsersController', () => {
     user.uuid = '123'
     user.email = 'test@test.te'
 
-    getUserKeyParams = {} as jest.Mocked<GetUserKeyParams>
-    getUserKeyParams.execute = jest.fn()
-
     getUserSubscription = {} as jest.Mocked<GetUserSubscription>
     getUserSubscription.execute = jest.fn()
 
@@ -213,60 +207,6 @@ describe('AnnotatedUsersController', () => {
     expect(result.statusCode).toEqual(401)
   })
 
-  it('should get user key params', async () => {
-    request.query = {
-      email: 'test@test.te',
-      uuid: '1-2-3',
-    }
-
-    getUserKeyParams.execute = jest.fn().mockReturnValue({ foo: 'bar' })
-
-    const httpResponse = <results.JsonResult>await createController().keyParams(request)
-    const result = await httpResponse.executeAsync()
-
-    expect(getUserKeyParams.execute).toHaveBeenCalledWith({
-      email: 'test@test.te',
-      userUuid: '1-2-3',
-      authenticated: false,
-    })
-
-    expect(result.statusCode).toEqual(200)
-  })
-
-  it('should get authenticated user key params', async () => {
-    request.query = {
-      email: 'test@test.te',
-      uuid: '1-2-3',
-      authenticated: 'true',
-    }
-
-    getUserKeyParams.execute = jest.fn().mockReturnValue({ foo: 'bar' })
-
-    const httpResponse = <results.JsonResult>await createController().keyParams(request)
-    const result = await httpResponse.executeAsync()
-
-    expect(getUserKeyParams.execute).toHaveBeenCalledWith({
-      email: 'test@test.te',
-      userUuid: '1-2-3',
-      authenticated: true,
-    })
-
-    expect(result.statusCode).toEqual(200)
-  })
-
-  it('should not get user key params if email and user uuid is missing', async () => {
-    request.query = {}
-
-    getUserKeyParams.execute = jest.fn().mockReturnValue({ foo: 'bar' })
-
-    const httpResponse = <results.JsonResult>await createController().keyParams(request)
-    const result = await httpResponse.executeAsync()
-
-    expect(getUserKeyParams.execute).not.toHaveBeenCalled()
-
-    expect(result.statusCode).toEqual(400)
-  })
-
   it('should get user subscription', async () => {
     request.params.userUuid = '1-2-3'
     response.locals.user = {

+ 0 - 8
packages/auth/src/Infra/InversifyExpressUtils/AnnotatedUsersController.ts

@@ -11,7 +11,6 @@ import {
 } from 'inversify-express-utils'
 import TYPES from '../../Bootstrap/Types'
 import { DeleteAccount } from '../../Domain/UseCase/DeleteAccount/DeleteAccount'
-import { GetUserKeyParams } from '../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
 import { UpdateUser } from '../../Domain/UseCase/UpdateUser'
 import { GetUserSubscription } from '../../Domain/UseCase/GetUserSubscription/GetUserSubscription'
 import { ClearLoginAttempts } from '../../Domain/UseCase/ClearLoginAttempts'
@@ -23,7 +22,6 @@ import { BaseUsersController } from './Base/BaseUsersController'
 export class AnnotatedUsersController extends BaseUsersController {
   constructor(
     @inject(TYPES.Auth_UpdateUser) override updateUser: UpdateUser,
-    @inject(TYPES.Auth_GetUserKeyParams) override getUserKeyParams: GetUserKeyParams,
     @inject(TYPES.Auth_DeleteAccount) override doDeleteAccount: DeleteAccount,
     @inject(TYPES.Auth_GetUserSubscription) override doGetUserSubscription: GetUserSubscription,
     @inject(TYPES.Auth_ClearLoginAttempts) override clearLoginAttempts: ClearLoginAttempts,
@@ -32,7 +30,6 @@ export class AnnotatedUsersController extends BaseUsersController {
   ) {
     super(
       updateUser,
-      getUserKeyParams,
       doDeleteAccount,
       doGetUserSubscription,
       clearLoginAttempts,
@@ -46,11 +43,6 @@ export class AnnotatedUsersController extends BaseUsersController {
     return super.update(request, response)
   }
 
-  @httpGet('/params')
-  override async keyParams(request: Request): Promise<results.JsonResult> {
-    return super.keyParams(request)
-  }
-
   @httpDelete('/:userUuid', TYPES.Auth_RequiredCrossServiceTokenMiddleware)
   override async deleteAccount(request: Request, response: Response): Promise<results.JsonResult> {
     return super.deleteAccount(request, response)

+ 0 - 27
packages/auth/src/Infra/InversifyExpressUtils/Base/BaseUsersController.ts

@@ -5,7 +5,6 @@ import { BaseHttpController, results } from 'inversify-express-utils'
 import { ChangeCredentials } from '../../../Domain/UseCase/ChangeCredentials/ChangeCredentials'
 import { ClearLoginAttempts } from '../../../Domain/UseCase/ClearLoginAttempts'
 import { DeleteAccount } from '../../../Domain/UseCase/DeleteAccount/DeleteAccount'
-import { GetUserKeyParams } from '../../../Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
 import { GetUserSubscription } from '../../../Domain/UseCase/GetUserSubscription/GetUserSubscription'
 import { IncreaseLoginAttempts } from '../../../Domain/UseCase/IncreaseLoginAttempts'
 import { UpdateUser } from '../../../Domain/UseCase/UpdateUser'
@@ -14,7 +13,6 @@ import { ErrorTag } from '@standardnotes/responses'
 export class BaseUsersController extends BaseHttpController {
   constructor(
     protected updateUser: UpdateUser,
-    protected getUserKeyParams: GetUserKeyParams,
     protected doDeleteAccount: DeleteAccount,
     protected doGetUserSubscription: GetUserSubscription,
     protected clearLoginAttempts: ClearLoginAttempts,
@@ -26,7 +24,6 @@ export class BaseUsersController extends BaseHttpController {
 
     if (this.controllerContainer !== undefined) {
       this.controllerContainer.register('auth.users.update', this.update.bind(this))
-      this.controllerContainer.register('auth.users.getKeyParams', this.keyParams.bind(this))
       this.controllerContainer.register('auth.users.getSubscription', this.getSubscription.bind(this))
       this.controllerContainer.register('auth.users.updateCredentials', this.changeCredentials.bind(this))
       this.controllerContainer.register('auth.users.delete', this.deleteAccount.bind(this))
@@ -79,30 +76,6 @@ export class BaseUsersController extends BaseHttpController {
     )
   }
 
-  async keyParams(request: Request): Promise<results.JsonResult> {
-    const email = 'email' in request.query ? <string>request.query.email : undefined
-    const userUuid = 'uuid' in request.query ? <string>request.query.uuid : undefined
-
-    if (!email && !userUuid) {
-      return this.json(
-        {
-          error: {
-            message: 'Missing mandatory request query parameters.',
-          },
-        },
-        400,
-      )
-    }
-
-    const result = await this.getUserKeyParams.execute({
-      email,
-      userUuid,
-      authenticated: request.query.authenticated === 'true',
-    })
-
-    return this.json(result.keyParams)
-  }
-
   async deleteAccount(request: Request, response: Response): Promise<results.JsonResult> {
     if (request.params.userUuid !== response.locals.user.uuid) {
       return this.json(

+ 1 - 0
packages/domain-events/src/Domain/Event/EmailBackupRequestedEventPayload.ts

@@ -2,4 +2,5 @@ export interface EmailBackupRequestedEventPayload {
   userUuid: string
   userHasEmailsMuted: boolean
   muteEmailsSettingUuid: string
+  keyParams: Record<string, unknown>
 }

+ 0 - 14
packages/syncing-server/src/Bootstrap/Container.ts

@@ -47,7 +47,6 @@ import {
   DomainEventPublisherInterface,
 } from '@standardnotes/domain-events'
 import axios, { AxiosInstance } from 'axios'
-import { AuthHttpServiceInterface } from '../Domain/Auth/AuthHttpServiceInterface'
 import { ExtensionsHttpService } from '../Domain/Extension/ExtensionsHttpService'
 import { ExtensionsHttpServiceInterface } from '../Domain/Extension/ExtensionsHttpServiceInterface'
 import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
@@ -56,7 +55,6 @@ import { EmailBackupRequestedEventHandler } from '../Domain/Handler/EmailBackupR
 import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler'
 import { ItemBackupServiceInterface } from '../Domain/Item/ItemBackupServiceInterface'
 import { FSItemBackupService } from '../Infra/FS/FSItemBackupService'
-import { AuthHttpService } from '../Infra/HTTP/AuthHttpService'
 import { S3ItemBackupService } from '../Infra/S3/S3ItemBackupService'
 import {
   ControllerContainer,
@@ -1104,17 +1102,6 @@ export class ContainerConfigLoader {
       ],
     ])
     if (!isConfiguredForHomeServer) {
-      container.bind(TYPES.Sync_AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
-
-      container
-        .bind<AuthHttpServiceInterface>(TYPES.Sync_AuthHttpService)
-        .toDynamicValue((context: interfaces.Context) => {
-          return new AuthHttpService(
-            context.container.get(TYPES.Sync_HTTPClient),
-            context.container.get(TYPES.Sync_AUTH_SERVER_URL),
-          )
-        })
-
       container
         .bind<EmailBackupRequestedEventHandler>(TYPES.Sync_EmailBackupRequestedEventHandler)
         .toConstantValue(
@@ -1123,7 +1110,6 @@ export class ContainerConfigLoader {
             isSecondaryDatabaseEnabled
               ? container.get<ItemRepositoryInterface>(TYPES.Sync_MongoDBItemRepository)
               : null,
-            container.get<AuthHttpServiceInterface>(TYPES.Sync_AuthHttpService),
             container.get<ItemBackupServiceInterface>(TYPES.Sync_ItemBackupService),
             container.get<DomainEventPublisherInterface>(TYPES.Sync_DomainEventPublisher),
             container.get<DomainEventFactoryInterface>(TYPES.Sync_DomainEventFactory),

+ 0 - 2
packages/syncing-server/src/Bootstrap/Types.ts

@@ -36,7 +36,6 @@ const TYPES = {
   Sync_SQS_AWS_REGION: Symbol.for('Sync_SQS_AWS_REGION'),
   Sync_AUTH_JWT_SECRET: Symbol.for('Sync_AUTH_JWT_SECRET'),
   Sync_EXTENSIONS_SERVER_URL: Symbol.for('Sync_EXTENSIONS_SERVER_URL'),
-  Sync_AUTH_SERVER_URL: Symbol.for('Sync_AUTH_SERVER_URL'),
   Sync_S3_AWS_REGION: Symbol.for('Sync_S3_AWS_REGION'),
   Sync_S3_BACKUP_BUCKET_NAME: Symbol.for('Sync_S3_BACKUP_BUCKET_NAME'),
   Sync_EMAIL_ATTACHMENT_MAX_BYTE_SIZE: Symbol.for('Sync_EMAIL_ATTACHMENT_MAX_BYTE_SIZE'),
@@ -115,7 +114,6 @@ const TYPES = {
   Sync_SyncResponseFactory20161215: Symbol.for('Sync_SyncResponseFactory20161215'),
   Sync_SyncResponseFactory20200115: Symbol.for('Sync_SyncResponseFactory20200115'),
   Sync_SyncResponseFactoryResolver: Symbol.for('Sync_SyncResponseFactoryResolver'),
-  Sync_AuthHttpService: Symbol.for('Sync_AuthHttpService'),
   Sync_ExtensionsHttpService: Symbol.for('Sync_ExtensionsHttpService'),
   Sync_ItemBackupService: Symbol.for('Sync_ItemBackupService'),
   Sync_ItemSaveValidator: Symbol.for('Sync_ItemSaveValidator'),

+ 0 - 5
packages/syncing-server/src/Domain/Auth/AuthHttpServiceInterface.ts

@@ -1,5 +0,0 @@
-import { KeyParamsData } from '@standardnotes/responses'
-
-export interface AuthHttpServiceInterface {
-  getUserKeyParams(userUuid: string): Promise<KeyParamsData>
-}

+ 3 - 19
packages/syncing-server/src/Domain/Handler/EmailBackupRequestedEventHandler.ts

@@ -1,4 +1,3 @@
-import { KeyParamsData } from '@standardnotes/responses'
 import {
   DomainEventHandlerInterface,
   DomainEventPublisherInterface,
@@ -6,7 +5,6 @@ import {
 } from '@standardnotes/domain-events'
 import { EmailLevel } from '@standardnotes/domain-core'
 import { Logger } from 'winston'
-import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
 import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
 import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
 import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
@@ -18,7 +16,6 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
   constructor(
     private primaryItemRepository: ItemRepositoryInterface,
     private secondaryItemRepository: ItemRepositoryInterface | null,
-    private authHttpService: AuthHttpServiceInterface,
     private itemBackupService: ItemBackupServiceInterface,
     private domainEventPublisher: DomainEventPublisherInterface,
     private domainEventFactory: DomainEventFactoryInterface,
@@ -40,19 +37,6 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
     event: EmailBackupRequestedEvent,
     itemRepository: ItemRepositoryInterface,
   ): Promise<void> {
-    let authParams: KeyParamsData
-    try {
-      authParams = await this.authHttpService.getUserKeyParams(event.payload.userUuid)
-    } catch (error) {
-      this.logger.error(
-        `Could not get user key params from auth service for user ${event.payload.userUuid}: ${
-          (error as Error).message
-        }`,
-      )
-
-      return
-    }
-
     const itemQuery: ItemQuery = {
       userUuid: event.payload.userUuid,
       sortBy: 'updated_at_timestamp',
@@ -75,7 +59,7 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
 
       const bundleBackupFileNames = await this.itemBackupService.backup(
         items,
-        authParams,
+        event.payload.keyParams,
         this.emailAttachmentMaxByteSize,
       )
 
@@ -88,11 +72,11 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
     for (const backupFileName of backupFileNames) {
       await this.domainEventPublisher.publish(
         this.domainEventFactory.createEmailRequestedEvent({
-          body: getBody(authParams.identifier as string),
+          body: getBody(event.payload.keyParams.identifier as string),
           level: EmailLevel.LEVELS.System,
           messageIdentifier: 'DATA_BACKUP',
           subject: getSubject(bundleIndex++, backupFileNames.length, dateOnly),
-          userEmail: authParams.identifier as string,
+          userEmail: event.payload.keyParams.identifier as string,
           sender: 'backups@standardnotes.org',
           attachments: [
             {

+ 0 - 27
packages/syncing-server/src/Infra/HTTP/AuthHttpService.ts

@@ -1,27 +0,0 @@
-import { KeyParamsData } from '@standardnotes/responses'
-import { AxiosInstance } from 'axios'
-
-import { AuthHttpServiceInterface } from '../../Domain/Auth/AuthHttpServiceInterface'
-
-export class AuthHttpService implements AuthHttpServiceInterface {
-  constructor(
-    private httpClient: AxiosInstance,
-    private authServerUrl: string,
-  ) {}
-
-  async getUserKeyParams(userUuid: string): Promise<KeyParamsData> {
-    const keyParamsResponse = await this.httpClient.request({
-      method: 'GET',
-      timeout: 10000,
-      headers: {
-        Accept: 'application/json',
-      },
-      url: `${this.authServerUrl}/users/params?uuid=${userUuid}`,
-      validateStatus:
-        /* istanbul ignore next */
-        (status: number) => status >= 200 && status < 500,
-    })
-
-    return keyParamsResponse.data
-  }
-}