Sfoglia il codice sorgente

feat(syncing-server): replace one drive backup failed event with email requested

Karol Sójko 2 anni fa
parent
commit
130f90bdb6

+ 0 - 8
packages/domain-events/src/Domain/Event/DropboxBackupFailedEvent.ts

@@ -1,8 +0,0 @@
-import { DomainEventInterface } from './DomainEventInterface'
-
-import { DropboxBackupFailedEventPayload } from './DropboxBackupFailedEventPayload'
-
-export interface DropboxBackupFailedEvent extends DomainEventInterface {
-  type: 'DROPBOX_BACKUP_FAILED'
-  payload: DropboxBackupFailedEventPayload
-}

+ 0 - 5
packages/domain-events/src/Domain/Event/DropboxBackupFailedEventPayload.ts

@@ -1,5 +0,0 @@
-export interface DropboxBackupFailedEventPayload {
-  muteCloudEmailsSettingUuid: string
-  extensionSettingUuid?: string
-  email: string
-}

+ 0 - 8
packages/domain-events/src/Domain/Event/OneDriveBackupFailedEvent.ts

@@ -1,8 +0,0 @@
-import { DomainEventInterface } from './DomainEventInterface'
-
-import { OneDriveBackupFailedEventPayload } from './OneDriveBackupFailedEventPayload'
-
-export interface OneDriveBackupFailedEvent extends DomainEventInterface {
-  type: 'ONE_DRIVE_BACKUP_FAILED'
-  payload: OneDriveBackupFailedEventPayload
-}

+ 0 - 5
packages/domain-events/src/Domain/Event/OneDriveBackupFailedEventPayload.ts

@@ -1,5 +0,0 @@
-export interface OneDriveBackupFailedEventPayload {
-  muteCloudEmailsSettingUuid: string
-  extensionSettingUuid?: string
-  email: string
-}

+ 0 - 4
packages/domain-events/src/Domain/index.ts

@@ -10,8 +10,6 @@ export * from './Event/DiscountWithdrawRequestedEvent'
 export * from './Event/DiscountWithdrawRequestedEventPayload'
 export * from './Event/DomainEventInterface'
 export * from './Event/DomainEventService'
-export * from './Event/DropboxBackupFailedEvent'
-export * from './Event/DropboxBackupFailedEventPayload'
 export * from './Event/DuplicateItemSyncedEvent'
 export * from './Event/DuplicateItemSyncedEventPayload'
 export * from './Event/EmailArchiveExtensionSyncedEvent'
@@ -48,8 +46,6 @@ export * from './Event/ListedAccountRequestedEvent'
 export * from './Event/ListedAccountRequestedEventPayload'
 export * from './Event/MuteEmailsSettingChangedEvent'
 export * from './Event/MuteEmailsSettingChangedEventPayload'
-export * from './Event/OneDriveBackupFailedEvent'
-export * from './Event/OneDriveBackupFailedEventPayload'
 export * from './Event/PaymentFailedEvent'
 export * from './Event/PaymentFailedEventPayload'
 export * from './Event/PaymentSuccessEvent'

+ 2 - 4
packages/scheduler/src/Domain/Job/JobDoneInterpreter.spec.ts

@@ -2,7 +2,7 @@ import {
   DiscountApplyRequestedEvent,
   DiscountWithdrawRequestedEvent,
   DomainEventPublisherInterface,
-  EmailMessageRequestedEvent,
+  EmailRequestedEvent,
   ExitDiscountWithdrawRequestedEvent,
 } from '@standardnotes/domain-events'
 import { PredicateName } from '@standardnotes/predicates'
@@ -45,9 +45,7 @@ describe('JobDoneInterpreter', () => {
     predicateRepository.findByJobUuid = jest.fn().mockReturnValue([])
 
     domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
-    domainEventFactory.createEmailRequestedEvent = jest
-      .fn()
-      .mockReturnValue({} as jest.Mocked<EmailMessageRequestedEvent>)
+    domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
     domainEventFactory.createDiscountApplyRequestedEvent = jest
       .fn()
       .mockReturnValue({} as jest.Mocked<DiscountApplyRequestedEvent>)

+ 9 - 0
packages/syncing-server/src/Domain/Email/OneDriveBackupFailed.ts

@@ -0,0 +1,9 @@
+import { html } from './one-drive-backup-failed.html'
+
+export function getSubject(): string {
+  return 'Failed Daily Backup to OneDrive Sync'
+}
+
+export function getBody(): string {
+  return html
+}

+ 18 - 0
packages/syncing-server/src/Domain/Email/one-drive-backup-failed.html.ts

@@ -0,0 +1,18 @@
+export const html = `<p>Hello,</p>
+<p>We recently tried backing up your data to <strong>OneDrive Sync</strong>, but an issue prevented us from doing
+  so.</p>
+<p>
+  The usual cause is an expired or revoked token from your sync provider. Please follow
+  <a href='https://standardnotes.com/help/27/how-do-i-enable-dropbox-google-drive-or-onedrive-backups'>these
+    instructions</a>
+  to use CloudLink on the web or desktop Standard Notes application to uninstall then reinstall this sync provider.
+</p>
+<p>
+  We apologize for any inconvenience this may cause.
+  If you have any questions, please feel free to reply directly to this email.
+</p>
+<p>
+  Thanks,
+  <br>SN</br>
+</p>
+<a href='https://app.standardnotes.com/?settings=backups'>Mute these emails</a>`

+ 0 - 19
packages/syncing-server/src/Domain/Event/DomainEventFactory.ts

@@ -8,7 +8,6 @@ import {
   ItemDumpedEvent,
   ItemRevisionCreationRequestedEvent,
   ItemsSyncedEvent,
-  OneDriveBackupFailedEvent,
   RevisionsCopyRequestedEvent,
   RevisionsOwnershipUpdateRequestedEvent,
   UserContentSizeRecalculationRequestedEvent,
@@ -151,24 +150,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
     }
   }
 
-  createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): OneDriveBackupFailedEvent {
-    return {
-      type: 'ONE_DRIVE_BACKUP_FAILED',
-      createdAt: this.timer.getUTCDate(),
-      meta: {
-        correlation: {
-          userIdentifier: email,
-          userIdentifierType: 'email',
-        },
-        origin: DomainEventService.SyncingServer,
-      },
-      payload: {
-        muteCloudEmailsSettingUuid,
-        email,
-      },
-    }
-  }
-
   createItemsSyncedEvent(dto: {
     userUuid: string
     extensionUrl: string

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

@@ -6,7 +6,6 @@ import {
   ItemDumpedEvent,
   ItemRevisionCreationRequestedEvent,
   ItemsSyncedEvent,
-  OneDriveBackupFailedEvent,
   RevisionsCopyRequestedEvent,
   RevisionsOwnershipUpdateRequestedEvent,
   UserContentSizeRecalculationRequestedEvent,
@@ -21,7 +20,6 @@ export interface DomainEventFactoryInterface {
     body: string
     subject: string
   }): EmailRequestedEvent
-  createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): OneDriveBackupFailedEvent
   createItemsSyncedEvent(dto: {
     userUuid: string
     extensionUrl: string

+ 8 - 30
packages/syncing-server/src/Domain/Extension/ExtensionsHttpService.spec.ts

@@ -50,9 +50,6 @@ describe('ExtensionsHttpService', () => {
     domainEventPublisher.publish = jest.fn()
 
     domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
-    domainEventFactory.createDropboxBackupFailedEvent = jest.fn()
-    domainEventFactory.createGoogleDriveBackupFailedEvent = jest.fn()
-    domainEventFactory.createOneDriveBackupFailedEvent = jest.fn()
     domainEventFactory.createEmailRequestedEvent = jest.fn()
 
     contentDecoder = {} as jest.Mocked<ContentDecoderInterface>
@@ -66,7 +63,6 @@ describe('ExtensionsHttpService', () => {
       forceMute: false,
       backupFilename: 'test',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
       cloudProvider: 'DROPBOX',
     })
 
@@ -74,7 +70,6 @@ describe('ExtensionsHttpService', () => {
       data: {
         auth_params: authParams,
         backup_filename: 'test',
-        settings_id: '3-4-5',
         silent: false,
         user_uuid: '1-2-3',
       },
@@ -100,12 +95,11 @@ describe('ExtensionsHttpService', () => {
       forceMute: false,
       backupFilename: 'test',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
       cloudProvider: 'DROPBOX',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should send items to extensions server', async () => {
@@ -117,7 +111,6 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: '',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(httpClient.request).toHaveBeenCalledWith({
@@ -125,7 +118,6 @@ describe('ExtensionsHttpService', () => {
         auth_params: authParams,
         backup_filename: '',
         items: [item],
-        settings_id: '3-4-5',
         silent: false,
         user_uuid: '1-2-3',
       },
@@ -146,14 +138,12 @@ describe('ExtensionsHttpService', () => {
       forceMute: false,
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(httpClient.request).toHaveBeenCalledWith({
       data: {
         auth_params: authParams,
         backup_filename: 'backup-file',
-        settings_id: '3-4-5',
         silent: false,
         user_uuid: '1-2-3',
       },
@@ -181,11 +171,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should publish a failed Dropbox backup event if request was sent and extensions server responded not ok', async () => {
@@ -201,11 +190,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should publish a failed Google Drive backup event if request was not sent successfully', async () => {
@@ -223,11 +211,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createGoogleDriveBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should publish a failed One Drive backup event if request was not sent successfully', async () => {
@@ -245,11 +232,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createOneDriveBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should not publish a failed backup event if emailes are force muted', async () => {
@@ -267,7 +253,6 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).not.toHaveBeenCalled()
@@ -290,7 +275,6 @@ describe('ExtensionsHttpService', () => {
         items: [item],
         backupFilename: 'backup-file',
         authParams,
-        muteEmailsSettingUuid: '3-4-5',
       })
     } catch (e) {
       error = e
@@ -317,7 +301,6 @@ describe('ExtensionsHttpService', () => {
         items: [item],
         backupFilename: 'backup-file',
         authParams,
-        muteEmailsSettingUuid: '3-4-5',
       })
     } catch (e) {
       error = e
@@ -341,11 +324,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should publish a failed Google Drive backup event judging by extension url if request was not sent successfully', async () => {
@@ -363,11 +345,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createGoogleDriveBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should publish a failed One Drive backup event judging by extension url if request was not sent successfully', async () => {
@@ -385,11 +366,10 @@ describe('ExtensionsHttpService', () => {
       items: [item],
       backupFilename: 'backup-file',
       authParams,
-      muteEmailsSettingUuid: '3-4-5',
     })
 
     expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(domainEventFactory.createOneDriveBackupFailedEvent).toHaveBeenCalled()
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
   })
 
   it('should throw an error if cannot deduce extension by judging from the url', async () => {
@@ -409,7 +389,6 @@ describe('ExtensionsHttpService', () => {
         items: [item],
         backupFilename: 'backup-file',
         authParams,
-        muteEmailsSettingUuid: '3-4-5',
       })
     } catch (e) {
       error = e
@@ -435,7 +414,6 @@ describe('ExtensionsHttpService', () => {
         items: [item],
         backupFilename: 'backup-file',
         authParams,
-        muteEmailsSettingUuid: '3-4-5',
       })
     } catch (e) {
       error = e

+ 15 - 22
packages/syncing-server/src/Domain/Extension/ExtensionsHttpService.ts

@@ -13,6 +13,7 @@ import { ExtensionsHttpServiceInterface } from './ExtensionsHttpServiceInterface
 import { SendItemsToExtensionsServerDTO } from './SendItemsToExtensionsServerDTO'
 import { getBody as googleDriveBody, getSubject as googleDriveSubject } from '../Email/GoogleDriveBackupFailed'
 import { getBody as dropboxBody, getSubject as dropboxSubject } from '../Email/DropboxBackupFailed'
+import { getBody as oneDriveBody, getSubject as oneDriveSubject } from '../Email/OneDriveBackupFailed'
 
 @injectable()
 export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
@@ -32,7 +33,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
     authParams: KeyParamsData
     forceMute: boolean
     userUuid: string
-    muteEmailsSettingUuid: string
   }): Promise<void> {
     let sent = false
     try {
@@ -41,7 +41,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
         auth_params: dto.authParams,
         silent: dto.forceMute,
         user_uuid: dto.userUuid,
-        settings_id: dto.muteEmailsSettingUuid,
       }
 
       const response = await this.httpClient.request({
@@ -61,13 +60,9 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
       this.logger.error(`[${dto.userUuid}] Failed to send a request to extensions server: ${(error as Error).message}`)
     }
 
-    if (!sent && !dto.forceMute && dto.muteEmailsSettingUuid !== undefined) {
+    if (!sent && !dto.forceMute) {
       await this.domainEventPublisher.publish(
-        this.createCloudBackupFailedEventBasedOnProvider(
-          dto.cloudProvider,
-          dto.authParams.identifier as string,
-          dto.muteEmailsSettingUuid,
-        ),
+        this.createCloudBackupFailedEventBasedOnProvider(dto.cloudProvider, dto.authParams.identifier as string),
       )
     }
   }
@@ -80,7 +75,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
         auth_params: dto.authParams,
         silent: dto.forceMute,
         user_uuid: dto.userUuid,
-        settings_id: dto.muteEmailsSettingUuid,
       }
       if (dto.items !== undefined) {
         payload.items = dto.items
@@ -103,14 +97,9 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
       this.logger.error(`[${dto.userUuid}] Failed to send a request to extensions server: ${(error as Error).message}`)
     }
 
-    if (!sent && !dto.forceMute && dto.muteEmailsSettingUuid !== undefined) {
+    if (!sent && !dto.forceMute) {
       await this.domainEventPublisher.publish(
-        await this.getBackupFailedEvent(
-          dto.muteEmailsSettingUuid,
-          dto.extensionId,
-          dto.userUuid,
-          dto.authParams.identifier as string,
-        ),
+        await this.getBackupFailedEvent(dto.extensionId, dto.userUuid, dto.authParams.identifier as string),
       )
     }
   }
@@ -118,7 +107,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
   private createCloudBackupFailedEventBasedOnProvider(
     cloudProvider: 'DROPBOX' | 'GOOGLE_DRIVE' | 'ONE_DRIVE',
     email: string,
-    muteCloudEmailsSettingUuid: string,
   ): DomainEventInterface {
     switch (cloudProvider) {
       case 'DROPBOX':
@@ -138,12 +126,17 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
           subject: googleDriveSubject(),
         })
       case 'ONE_DRIVE':
-        return this.domainEventFactory.createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid, email)
+        return this.domainEventFactory.createEmailRequestedEvent({
+          userEmail: email,
+          level: EmailLevel.LEVELS.FailedCloudBackup,
+          body: oneDriveBody(),
+          messageIdentifier: 'FAILED_ONE_DRIVE_BACKUP',
+          subject: oneDriveSubject(),
+        })
     }
   }
 
   private async getBackupFailedEvent(
-    muteCloudEmailsSettingUuid: string,
     extensionId: string,
     userUuid: string,
     email: string,
@@ -156,11 +149,11 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
     const content = this.contentDecoder.decode(extension.content)
     switch (this.getExtensionName(content)) {
       case ExtensionName.Dropbox:
-        return this.createCloudBackupFailedEventBasedOnProvider('DROPBOX', muteCloudEmailsSettingUuid, email)
+        return this.createCloudBackupFailedEventBasedOnProvider('DROPBOX', email)
       case ExtensionName.GoogleDrive:
-        return this.createCloudBackupFailedEventBasedOnProvider('GOOGLE_DRIVE', muteCloudEmailsSettingUuid, email)
+        return this.createCloudBackupFailedEventBasedOnProvider('GOOGLE_DRIVE', email)
       case ExtensionName.OneDrive:
-        return this.createCloudBackupFailedEventBasedOnProvider('ONE_DRIVE', muteCloudEmailsSettingUuid, email)
+        return this.createCloudBackupFailedEventBasedOnProvider('ONE_DRIVE', email)
     }
   }
 

+ 1 - 1
packages/syncing-server/src/Domain/Extension/SendItemsToExtensionsServerDTO.ts

@@ -1,4 +1,5 @@
 import { KeyParamsData } from '@standardnotes/responses'
+
 import { Item } from '../Item/Item'
 
 export type SendItemsToExtensionsServerDTO = {
@@ -8,6 +9,5 @@ export type SendItemsToExtensionsServerDTO = {
   authParams: KeyParamsData
   forceMute: boolean
   userUuid: string
-  muteEmailsSettingUuid?: string
   items?: Array<Item>
 }