Files
standardnotes-server/packages/syncing-server/src/Domain/Handler/EmailBackupRequestedEventHandler.ts
T
Karol SójkoandGitHub 302b624504 feat: add mechanism for determining if a user should use the primary or secondary items database (#700)
* feat(domain-core): introduce new role for users transitioning to new mechanisms

* feat: add mechanism for determining if a user should use the primary or secondary items database

* fix: add transition mode enabled switch in docker entrypoint

* fix(syncing-server): mapping roles from middleware

* fix: mongodb item repository binding

* fix: item backups service binding

* fix: passing transition mode enabled variable to docker setup
2023-08-18 16:45:10 +02:00

109 lines
3.9 KiB
TypeScript

import { KeyParamsData } from '@standardnotes/responses'
import {
DomainEventHandlerInterface,
DomainEventPublisherInterface,
EmailBackupRequestedEvent,
} 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'
import { ItemTransferCalculatorInterface } from '../Item/ItemTransferCalculatorInterface'
import { ItemQuery } from '../Item/ItemQuery'
import { getBody, getSubject } from '../Email/EmailBackupAttachmentCreated'
export class EmailBackupRequestedEventHandler implements DomainEventHandlerInterface {
constructor(
private primaryItemRepository: ItemRepositoryInterface,
private secondaryItemRepository: ItemRepositoryInterface | null,
private authHttpService: AuthHttpServiceInterface,
private itemBackupService: ItemBackupServiceInterface,
private domainEventPublisher: DomainEventPublisherInterface,
private domainEventFactory: DomainEventFactoryInterface,
private emailAttachmentMaxByteSize: number,
private itemTransferCalculator: ItemTransferCalculatorInterface,
private s3BackupBucketName: string,
private logger: Logger,
) {}
async handle(event: EmailBackupRequestedEvent): Promise<void> {
await this.requestEmailWithBackupFile(event, this.primaryItemRepository)
if (this.secondaryItemRepository) {
await this.requestEmailWithBackupFile(event, this.secondaryItemRepository)
}
}
private async requestEmailWithBackupFile(
event: EmailBackupRequestedEvent,
itemRepository: ItemRepositoryInterface,
): Promise<void> {
let authParams: KeyParamsData
try {
authParams = await this.authHttpService.getUserKeyParams({
uuid: event.payload.userUuid,
authenticated: false,
})
} catch (error) {
this.logger.warn(`Could not get user key params from auth service: ${(error as Error).message}`)
return
}
const itemQuery: ItemQuery = {
userUuid: event.payload.userUuid,
sortBy: 'updated_at_timestamp',
sortOrder: 'ASC',
deleted: false,
}
const itemContentSizeDescriptors = await itemRepository.findContentSizeForComputingTransferLimit(itemQuery)
const itemUuidBundles = await this.itemTransferCalculator.computeItemUuidBundlesToFetch(
itemContentSizeDescriptors,
this.emailAttachmentMaxByteSize,
)
const backupFileNames: string[] = []
for (const itemUuidBundle of itemUuidBundles) {
const items = await itemRepository.findAll({
uuids: itemUuidBundle,
sortBy: 'updated_at_timestamp',
sortOrder: 'ASC',
})
const bundleBackupFileNames = await this.itemBackupService.backup(
items,
authParams,
this.emailAttachmentMaxByteSize,
)
backupFileNames.push(...bundleBackupFileNames)
}
const dateOnly = new Date().toISOString().substring(0, 10)
let bundleIndex = 1
for (const backupFileName of backupFileNames) {
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailRequestedEvent({
body: getBody(authParams.identifier as string),
level: EmailLevel.LEVELS.System,
messageIdentifier: 'DATA_BACKUP',
subject: getSubject(bundleIndex++, backupFileNames.length, dateOnly),
userEmail: authParams.identifier as string,
sender: '[email protected]',
attachments: [
{
fileName: backupFileName,
filePath: this.s3BackupBucketName,
attachmentFileName: `SN-Data-${dateOnly}.txt`,
attachmentContentType: 'application/json',
},
],
}),
)
}
}
}