diff --git a/src/abstractions/cipher.service.ts b/src/abstractions/cipher.service.ts index 71fa641228d..7a0fab508fe 100644 --- a/src/abstractions/cipher.service.ts +++ b/src/abstractions/cipher.service.ts @@ -28,8 +28,6 @@ export abstract class CipherService { saveWithServer: (cipher: Cipher) => Promise; shareWithServer: (cipher: CipherView, organizationId: string, collectionIds: string[]) => Promise; shareManyWithServer: (ciphers: CipherView[], organizationId: string, collectionIds: string[]) => Promise; - shareAttachmentWithServer: (attachmentView: AttachmentView, cipherId: string, - organizationId: string) => Promise; saveAttachmentWithServer: (cipher: Cipher, unencryptedFile: any, admin?: boolean) => Promise; saveAttachmentRawWithServer: (cipher: Cipher, filename: string, data: ArrayBuffer, admin?: boolean) => Promise; diff --git a/src/angular/components/share.component.ts b/src/angular/components/share.component.ts index 0bd64784fbb..d0c7dea4fa5 100644 --- a/src/angular/components/share.component.ts +++ b/src/angular/components/share.component.ts @@ -65,23 +65,14 @@ export class ShareComponent implements OnInit { const cipherDomain = await this.cipherService.get(this.cipherId); const cipherView = await cipherDomain.decrypt(); - const attachmentPromises: Array> = []; - if (cipherView.attachments != null) { - for (const attachment of cipherView.attachments) { - const promise = this.cipherService.shareAttachmentWithServer(attachment, cipherView.id, - this.organizationId); - attachmentPromises.push(promise); - } - } - const checkedCollectionIds = this.collections.filter((c) => (c as any).checked).map((c) => c.id); try { - this.formPromise = Promise.all(attachmentPromises).then(async () => { - await this.cipherService.shareWithServer(cipherView, this.organizationId, checkedCollectionIds); - this.onSharedCipher.emit(); - this.platformUtilsService.eventTrack('Shared Cipher'); - this.platformUtilsService.showToast('success', null, this.i18nService.t('sharedItem')); - }); + this.formPromise = this.cipherService.shareWithServer(cipherView, this.organizationId, + checkedCollectionIds).then(async () => { + this.onSharedCipher.emit(); + this.platformUtilsService.eventTrack('Shared Cipher'); + this.platformUtilsService.showToast('success', null, this.i18nService.t('sharedItem')); + }); await this.formPromise; } catch { } } diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index 6cff911e34b..257d59b4a6c 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -461,6 +461,14 @@ export class CipherService implements CipherServiceAbstraction { } async shareWithServer(cipher: CipherView, organizationId: string, collectionIds: string[]): Promise { + const attachmentPromises: Array> = []; + if (cipher.attachments != null) { + cipher.attachments.forEach((attachment) => { + attachmentPromises.push(this.shareAttachmentWithServer(attachment, cipher.id, organizationId)); + }); + } + await Promise.all(attachmentPromises); + cipher.organizationId = organizationId; cipher.collectionIds = collectionIds; const encCipher = await this.encrypt(cipher); @@ -488,43 +496,6 @@ export class CipherService implements CipherServiceAbstraction { await this.upsert(encCiphers.map((c) => c.toCipherData(userId))); } - async shareAttachmentWithServer(attachmentView: AttachmentView, cipherId: string, - organizationId: string): Promise { - const attachmentResponse = await fetch(new Request(attachmentView.url, { cache: 'no-cache' })); - if (attachmentResponse.status !== 200) { - throw Error('Failed to download attachment: ' + attachmentResponse.status.toString()); - } - - const buf = await attachmentResponse.arrayBuffer(); - const decBuf = await this.cryptoService.decryptFromBytes(buf, null); - const key = await this.cryptoService.getOrgKey(organizationId); - const encData = await this.cryptoService.encryptToBytes(decBuf, key); - const encFileName = await this.cryptoService.encrypt(attachmentView.fileName, key); - - const fd = new FormData(); - try { - const blob = new Blob([encData], { type: 'application/octet-stream' }); - fd.append('data', blob, encFileName.encryptedString); - } catch (e) { - if (Utils.isNode && !Utils.isBrowser) { - fd.append('data', Buffer.from(encData) as any, { - filepath: encFileName.encryptedString, - contentType: 'application/octet-stream', - } as any); - } else { - throw e; - } - } - - let response: CipherResponse; - try { - response = await this.apiService.postShareCipherAttachment(cipherId, attachmentView.id, fd, - organizationId); - } catch (e) { - throw new Error((e as ErrorResponse).getSingleMessage()); - } - } - saveAttachmentWithServer(cipher: Cipher, unencryptedFile: any, admin = false): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); @@ -772,6 +743,41 @@ export class CipherService implements CipherServiceAbstraction { // Helpers + private async shareAttachmentWithServer(attachmentView: AttachmentView, cipherId: string, + organizationId: string): Promise { + const attachmentResponse = await fetch(new Request(attachmentView.url, { cache: 'no-cache' })); + if (attachmentResponse.status !== 200) { + throw Error('Failed to download attachment: ' + attachmentResponse.status.toString()); + } + + const buf = await attachmentResponse.arrayBuffer(); + const decBuf = await this.cryptoService.decryptFromBytes(buf, null); + const key = await this.cryptoService.getOrgKey(organizationId); + const encData = await this.cryptoService.encryptToBytes(decBuf, key); + const encFileName = await this.cryptoService.encrypt(attachmentView.fileName, key); + + const fd = new FormData(); + try { + const blob = new Blob([encData], { type: 'application/octet-stream' }); + fd.append('data', blob, encFileName.encryptedString); + } catch (e) { + if (Utils.isNode && !Utils.isBrowser) { + fd.append('data', Buffer.from(encData) as any, { + filepath: encFileName.encryptedString, + contentType: 'application/octet-stream', + } as any); + } else { + throw e; + } + } + + try { + await this.apiService.postShareCipherAttachment(cipherId, attachmentView.id, fd, organizationId); + } catch (e) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } + } + private async encryptObjProperty(model: V, obj: D, map: any, key: SymmetricCryptoKey): Promise { const promises = [];