mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-27 12:36:14 +01:00
move attachment sharing logic to service
This commit is contained in:
parent
43c0cbce45
commit
4165a78277
@ -28,8 +28,6 @@ export abstract class CipherService {
|
|||||||
saveWithServer: (cipher: Cipher) => Promise<any>;
|
saveWithServer: (cipher: Cipher) => Promise<any>;
|
||||||
shareWithServer: (cipher: CipherView, organizationId: string, collectionIds: string[]) => Promise<any>;
|
shareWithServer: (cipher: CipherView, organizationId: string, collectionIds: string[]) => Promise<any>;
|
||||||
shareManyWithServer: (ciphers: CipherView[], organizationId: string, collectionIds: string[]) => Promise<any>;
|
shareManyWithServer: (ciphers: CipherView[], organizationId: string, collectionIds: string[]) => Promise<any>;
|
||||||
shareAttachmentWithServer: (attachmentView: AttachmentView, cipherId: string,
|
|
||||||
organizationId: string) => Promise<any>;
|
|
||||||
saveAttachmentWithServer: (cipher: Cipher, unencryptedFile: any, admin?: boolean) => Promise<Cipher>;
|
saveAttachmentWithServer: (cipher: Cipher, unencryptedFile: any, admin?: boolean) => Promise<Cipher>;
|
||||||
saveAttachmentRawWithServer: (cipher: Cipher, filename: string, data: ArrayBuffer,
|
saveAttachmentRawWithServer: (cipher: Cipher, filename: string, data: ArrayBuffer,
|
||||||
admin?: boolean) => Promise<Cipher>;
|
admin?: boolean) => Promise<Cipher>;
|
||||||
|
@ -65,23 +65,14 @@ export class ShareComponent implements OnInit {
|
|||||||
const cipherDomain = await this.cipherService.get(this.cipherId);
|
const cipherDomain = await this.cipherService.get(this.cipherId);
|
||||||
const cipherView = await cipherDomain.decrypt();
|
const cipherView = await cipherDomain.decrypt();
|
||||||
|
|
||||||
const attachmentPromises: Array<Promise<any>> = [];
|
|
||||||
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);
|
const checkedCollectionIds = this.collections.filter((c) => (c as any).checked).map((c) => c.id);
|
||||||
try {
|
try {
|
||||||
this.formPromise = Promise.all(attachmentPromises).then(async () => {
|
this.formPromise = this.cipherService.shareWithServer(cipherView, this.organizationId,
|
||||||
await this.cipherService.shareWithServer(cipherView, this.organizationId, checkedCollectionIds);
|
checkedCollectionIds).then(async () => {
|
||||||
this.onSharedCipher.emit();
|
this.onSharedCipher.emit();
|
||||||
this.platformUtilsService.eventTrack('Shared Cipher');
|
this.platformUtilsService.eventTrack('Shared Cipher');
|
||||||
this.platformUtilsService.showToast('success', null, this.i18nService.t('sharedItem'));
|
this.platformUtilsService.showToast('success', null, this.i18nService.t('sharedItem'));
|
||||||
});
|
});
|
||||||
await this.formPromise;
|
await this.formPromise;
|
||||||
} catch { }
|
} catch { }
|
||||||
}
|
}
|
||||||
|
@ -461,6 +461,14 @@ export class CipherService implements CipherServiceAbstraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async shareWithServer(cipher: CipherView, organizationId: string, collectionIds: string[]): Promise<any> {
|
async shareWithServer(cipher: CipherView, organizationId: string, collectionIds: string[]): Promise<any> {
|
||||||
|
const attachmentPromises: Array<Promise<any>> = [];
|
||||||
|
if (cipher.attachments != null) {
|
||||||
|
cipher.attachments.forEach((attachment) => {
|
||||||
|
attachmentPromises.push(this.shareAttachmentWithServer(attachment, cipher.id, organizationId));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await Promise.all(attachmentPromises);
|
||||||
|
|
||||||
cipher.organizationId = organizationId;
|
cipher.organizationId = organizationId;
|
||||||
cipher.collectionIds = collectionIds;
|
cipher.collectionIds = collectionIds;
|
||||||
const encCipher = await this.encrypt(cipher);
|
const encCipher = await this.encrypt(cipher);
|
||||||
@ -488,43 +496,6 @@ export class CipherService implements CipherServiceAbstraction {
|
|||||||
await this.upsert(encCiphers.map((c) => c.toCipherData(userId)));
|
await this.upsert(encCiphers.map((c) => c.toCipherData(userId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async shareAttachmentWithServer(attachmentView: AttachmentView, cipherId: string,
|
|
||||||
organizationId: string): Promise<any> {
|
|
||||||
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<Cipher> {
|
saveAttachmentWithServer(cipher: Cipher, unencryptedFile: any, admin = false): Promise<Cipher> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
@ -772,6 +743,41 @@ export class CipherService implements CipherServiceAbstraction {
|
|||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
|
private async shareAttachmentWithServer(attachmentView: AttachmentView, cipherId: string,
|
||||||
|
organizationId: string): Promise<any> {
|
||||||
|
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<V extends View, D extends Domain>(model: V, obj: D,
|
private async encryptObjProperty<V extends View, D extends Domain>(model: V, obj: D,
|
||||||
map: any, key: SymmetricCryptoKey): Promise<void> {
|
map: any, key: SymmetricCryptoKey): Promise<void> {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
Loading…
Reference in New Issue
Block a user