From 6878ab51fb46c0904e018f440fb99246805790dd Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Wed, 18 Nov 2020 15:18:13 -0500 Subject: [PATCH] send service implementation (#708) * send service implementation * update jslib --- jslib | 2 +- src/app/send/add-edit.component.ts | 104 +++------------------------- src/app/send/send.component.ts | 22 ++---- src/app/services/services.module.ts | 7 +- 4 files changed, 21 insertions(+), 114 deletions(-) diff --git a/jslib b/jslib index 79b856cb6e..6563dccf3b 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 79b856cb6e73f126a263a0e4a61d0161828a40dd +Subproject commit 6563dccf3b444c6f2ea97efe913eaccf9d9fd502 diff --git a/src/app/send/add-edit.component.ts b/src/app/send/add-edit.component.ts index f99e13b1dc..5e08ac395f 100644 --- a/src/app/send/add-edit.component.ts +++ b/src/app/send/add-edit.component.ts @@ -11,26 +11,19 @@ import { Component } from '@angular/core'; import { SendType } from 'jslib/enums/sendType'; import { ApiService } from 'jslib/abstractions/api.service'; -import { CryptoService } from 'jslib/abstractions/crypto.service'; -import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service'; import { EnvironmentService } from 'jslib/abstractions/environment.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SendService } from 'jslib/abstractions/send.service'; import { SendView } from 'jslib/models/view/sendView'; import { SendFileView } from 'jslib/models/view/sendFileView'; import { SendTextView } from 'jslib/models/view/sendTextView'; import { Send } from 'jslib/models/domain/send'; -import { SendFile } from 'jslib/models/domain/sendFile'; -import { SendText } from 'jslib/models/domain/sendText'; import { SendData } from 'jslib/models/data/sendData'; -import { SendRequest } from 'jslib/models/request/sendRequest'; - -import { Utils } from 'jslib/misc/utils'; - @Component({ selector: 'app-send-add-edit', templateUrl: 'add-edit.component.html', @@ -57,9 +50,8 @@ export class AddEditComponent { typeOptions: any[]; constructor(private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, - private apiService: ApiService, private cryptoService: CryptoService, - private cryptoFunctionService: CryptoFunctionService, private environmentService: EnvironmentService, - private datePipe: DatePipe) { + private apiService: ApiService, private environmentService: EnvironmentService, + private datePipe: DatePipe, private sendService: SendService) { this.typeOptions = [ { name: i18nService.t('sendTypeFile'), value: SendType.File }, { name: i18nService.t('sendTypeText'), value: SendType.Text }, @@ -137,7 +129,7 @@ export class AddEditComponent { const encSend = await this.encryptSend(file); try { - this.formPromise = this.saveSend(encSend); + this.formPromise = this.sendService.saveWithServer(encSend); await this.formPromise; this.send.id = encSend[0].id; this.platformUtilsService.showToast('success', null, @@ -181,96 +173,20 @@ export class AddEditComponent { } protected async encryptSend(file: File): Promise<[Send, ArrayBuffer]> { - let fileData: ArrayBuffer = null; - const send = new Send(); - send.id = this.send.id; - send.type = this.send.type; - send.disabled = this.send.disabled; - send.maxAccessCount = this.send.maxAccessCount; - if (this.send.key == null) { - this.send.key = await this.cryptoFunctionService.randomBytes(16); - this.send.cryptoKey = await this.cryptoService.makeSendKey(this.send.key); - } - if (this.password != null) { - const passwordHash = await this.cryptoFunctionService.pbkdf2(this.password, - this.send.key, 'sha256', 100000); - send.password = Utils.fromBufferToB64(passwordHash); - } - send.key = await this.cryptoService.encrypt(this.send.key, null); - send.name = await this.cryptoService.encrypt(this.send.name, this.send.cryptoKey); - send.notes = await this.cryptoService.encrypt(this.send.notes, this.send.cryptoKey); - if (send.type === SendType.Text) { - send.text = new SendText(); - send.text.text = await this.cryptoService.encrypt(this.send.text.text, this.send.cryptoKey); - send.text.hidden = this.send.text.hidden; - } else if (send.type === SendType.File) { - send.file = new SendFile(); - if (file != null) { - fileData = await this.parseFile(send, file); - } - } + const sendData = await this.sendService.encrypt(this.send, file, this.password, null); // Parse dates try { - send.deletionDate = this.deletionDate == null ? null : new Date(this.deletionDate); + sendData[0].deletionDate = this.deletionDate == null ? null : new Date(this.deletionDate); } catch { - send.deletionDate = null; + sendData[0].deletionDate = null; } try { - send.expirationDate = this.expirationDate == null ? null : new Date(this.expirationDate); + sendData[0].expirationDate = this.expirationDate == null ? null : new Date(this.expirationDate); } catch { - send.expirationDate = null; + sendData[0].expirationDate = null; } - return [send, fileData]; - } - - protected async saveSend(sendData: [Send, ArrayBuffer]) { - const request = new SendRequest(sendData[0]); - if (sendData[0].id == null) { - if (sendData[0].type === SendType.Text) { - await this.apiService.postSend(request); - } else { - const fd = new FormData(); - try { - const blob = new Blob([sendData[1]], { type: 'application/octet-stream' }); - fd.append('model', JSON.stringify(request)); - fd.append('data', blob, sendData[0].file.fileName.encryptedString); - } catch (e) { - if (Utils.isNode && !Utils.isBrowser) { - fd.append('model', JSON.stringify(request)); - fd.append('data', Buffer.from(sendData[1]) as any, { - filepath: sendData[0].file.fileName.encryptedString, - contentType: 'application/octet-stream', - } as any); - } else { - throw e; - } - } - await this.apiService.postSendFile(fd); - } - } else { - await this.apiService.putSend(sendData[0].id, request); - } - } - - private parseFile(send: Send, file: File): Promise { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.readAsArrayBuffer(file); - reader.onload = async (evt) => { - try { - send.file.fileName = await this.cryptoService.encrypt(file.name, this.send.cryptoKey); - const fileData = await this.cryptoService.encryptToBytes(evt.target.result as ArrayBuffer, - this.send.cryptoKey); - resolve(fileData); - } catch (e) { - reject(e); - } - }; - reader.onerror = (evt) => { - reject('Error reading file.'); - }; - }); + return sendData; } } diff --git a/src/app/send/send.component.ts b/src/app/send/send.component.ts index 5daa2c7f7e..7350f95eb3 100644 --- a/src/app/send/send.component.ts +++ b/src/app/send/send.component.ts @@ -18,11 +18,7 @@ import { ApiService } from 'jslib/abstractions/api.service'; import { EnvironmentService } from 'jslib/abstractions/environment.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; -import { UserService } from 'jslib/abstractions/user.service'; - -import { SendData } from 'jslib/models/data/sendData'; - -import { Send } from 'jslib/models/domain/send'; +import { SendService } from 'jslib/abstractions/send.service'; @Component({ selector: 'app-send', @@ -51,7 +47,7 @@ export class SendComponent implements OnInit { private searchTimeout: any; - constructor(private apiService: ApiService, private userService: UserService, + constructor(private apiService: ApiService, private sendService: SendService, private i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver, private platformUtilsService: PlatformUtilsService, private environmentService: EnvironmentService) { } @@ -60,18 +56,8 @@ export class SendComponent implements OnInit { } async load(filter: (send: SendView) => boolean = null) { this.loading = true; - const userId = await this.userService.getUserId(); - const sends = await this.apiService.getSends(); - const sendsArr: SendView[] = []; - if (sends != null && sends.data != null) { - for (const res of sends.data) { - const data = new SendData(res, userId); - const send = new Send(data); - const view = await send.decrypt(); - sendsArr.push(view); - } - } - this.sends = sendsArr; + const sends = await this.sendService.getAllDecrypted(); + this.sends = sends; this.selectAll(); this.loading = false; this.loaded = true; diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts index d5892f0ff6..e8e22d06af 100644 --- a/src/app/services/services.module.ts +++ b/src/app/services/services.module.ts @@ -42,6 +42,7 @@ import { NotificationsService } from 'jslib/services/notifications.service'; import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service'; import { PolicyService } from 'jslib/services/policy.service'; import { SearchService } from 'jslib/services/search.service'; +import { SendService } from 'jslib/services/send.service'; import { SettingsService } from 'jslib/services/settings.service'; import { StateService } from 'jslib/services/state.service'; import { SyncService } from 'jslib/services/sync.service'; @@ -74,6 +75,7 @@ import { import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib/abstractions/platformUtils.service'; import { PolicyService as PolicyServiceAbstraction } from 'jslib/abstractions/policy.service'; import { SearchService as SearchServiceAbstraction } from 'jslib/abstractions/search.service'; +import { SendService as SendServiceAbstraction } from 'jslib/abstractions/send.service'; import { SettingsService as SettingsServiceAbstraction } from 'jslib/abstractions/settings.service'; import { StateService as StateServiceAbstraction } from 'jslib/abstractions/state.service'; import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service'; @@ -108,12 +110,14 @@ const folderService = new FolderService(cryptoService, userService, apiService, const collectionService = new CollectionService(cryptoService, userService, storageService, i18nService); searchService = new SearchService(cipherService); const policyService = new PolicyService(userService, storageService); +const sendService = new SendService(cryptoService, userService, apiService, storageService, + i18nService, cryptoFunctionService); const vaultTimeoutService = new VaultTimeoutService(cipherService, folderService, collectionService, cryptoService, platformUtilsService, storageService, messagingService, searchService, userService, tokenService, null, async () => messagingService.send('logout', { expired: false })); const syncService = new SyncService(userService, apiService, settingsService, folderService, cipherService, cryptoService, collectionService, storageService, messagingService, policyService, - async (expired: boolean) => messagingService.send('logout', { expired: expired })); + sendService, async (expired: boolean) => messagingService.send('logout', { expired: expired })); const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService, policyService); const totpService = new TotpService(storageService, cryptoFunctionService); const containerService = new ContainerService(cryptoService); @@ -218,6 +222,7 @@ export function initFactory(): Function { { provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService }, { provide: EventLoggingServiceAbstraction, useValue: eventLoggingService }, { provide: PolicyServiceAbstraction, useValue: policyService }, + { provide: SendServiceAbstraction, useValue: sendService }, { provide: APP_INITIALIZER, useFactory: initFactory,