From cfad521ea8ef205abe774907d8f7a243b3adaf10 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Wed, 13 Jun 2018 00:02:15 -0400 Subject: [PATCH] bulk share apis --- src/abstractions/api.service.ts | 2 ++ src/abstractions/cipher.service.ts | 3 ++- src/models/request/cipherBulkShareRequest.ts | 18 +++++++++++++ src/services/api.service.ts | 22 ++++++++++++++++ src/services/cipher.service.ts | 27 +++++++++++++++++--- 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/models/request/cipherBulkShareRequest.ts diff --git a/src/abstractions/api.service.ts b/src/abstractions/api.service.ts index c9c7792076..2032cebe04 100644 --- a/src/abstractions/api.service.ts +++ b/src/abstractions/api.service.ts @@ -2,6 +2,7 @@ import { EnvironmentUrls } from '../models/domain/environmentUrls'; import { CipherBulkDeleteRequest } from '../models/request/cipherBulkDeleteRequest'; import { CipherBulkMoveRequest } from '../models/request/cipherBulkMoveRequest'; +import { CipherBulkShareRequest } from '../models/request/cipherBulkShareRequest'; import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherShareRequest } from '../models/request/cipherShareRequest'; @@ -44,6 +45,7 @@ export abstract class ApiService { deleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise; putMoveCiphers: (request: CipherBulkMoveRequest) => Promise; putShareCipher: (id: string, request: CipherShareRequest) => Promise; + putShareCiphers: (request: CipherBulkShareRequest) => Promise; putCipherCollections: (id: string, request: CipherCollectionsRequest) => Promise; postCipherAttachment: (id: string, data: FormData) => Promise; deleteCipherAttachment: (id: string, attachmentId: string) => Promise; diff --git a/src/abstractions/cipher.service.ts b/src/abstractions/cipher.service.ts index edcc6479f5..c1072e484d 100644 --- a/src/abstractions/cipher.service.ts +++ b/src/abstractions/cipher.service.ts @@ -26,7 +26,8 @@ export abstract class CipherService { updateLastUsedDate: (id: string) => Promise; saveNeverDomain: (domain: string) => Promise; saveWithServer: (cipher: Cipher) => Promise; - shareWithServer: (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) => Promise; diff --git a/src/models/request/cipherBulkShareRequest.ts b/src/models/request/cipherBulkShareRequest.ts new file mode 100644 index 0000000000..a4dede2875 --- /dev/null +++ b/src/models/request/cipherBulkShareRequest.ts @@ -0,0 +1,18 @@ +import { CipherRequest } from './cipherRequest'; + +import { Cipher } from '../domain/cipher'; + +export class CipherBulkShareRequest { + ciphers: CipherRequest[]; + collectionIds: string[]; + + constructor(ciphers: Cipher[], collectionIds: string[]) { + if (ciphers != null) { + this.ciphers = []; + ciphers.forEach((c) => { + this.ciphers.push(new CipherRequest(c)); + }); + } + this.collectionIds = collectionIds; + } +} diff --git a/src/services/api.service.ts b/src/services/api.service.ts index 9fb8b58248..b365217fa7 100644 --- a/src/services/api.service.ts +++ b/src/services/api.service.ts @@ -8,6 +8,7 @@ import { EnvironmentUrls } from '../models/domain/environmentUrls'; import { CipherBulkDeleteRequest } from '../models/request/cipherBulkDeleteRequest'; import { CipherBulkMoveRequest } from '../models/request/cipherBulkMoveRequest'; +import { CipherBulkShareRequest } from '../models/request/cipherBulkShareRequest'; import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherShareRequest } from '../models/request/cipherShareRequest'; @@ -419,6 +420,27 @@ export class ApiService implements ApiServiceAbstraction { } } + async putShareCiphers(request: CipherBulkShareRequest): Promise { + const authHeader = await this.handleTokenState(); + const response = await fetch(new Request(this.baseUrl + '/ciphers/share', { + body: JSON.stringify(request), + cache: 'no-cache', + credentials: this.getCredentials(), + headers: new Headers({ + 'Accept': 'application/json', + 'Authorization': authHeader, + 'Content-Type': 'application/json; charset=utf-8', + 'Device-Type': this.deviceType, + }), + method: 'PUT', + })); + + if (response.status !== 200) { + const error = await this.handleError(response, false); + return Promise.reject(error); + } + } + async putCipherCollections(id: string, request: CipherCollectionsRequest): Promise { const authHeader = await this.handleTokenState(); const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id + '/collections', { diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index 523da8d33f..6b60c0bd56 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -17,6 +17,7 @@ import { SymmetricCryptoKey } from '../models/domain/symmetricCryptoKey'; import { CipherBulkDeleteRequest } from '../models/request/cipherBulkDeleteRequest'; import { CipherBulkMoveRequest } from '../models/request/cipherBulkMoveRequest'; +import { CipherBulkShareRequest } from '../models/request/cipherBulkShareRequest'; import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherShareRequest } from '../models/request/cipherShareRequest'; @@ -358,11 +359,31 @@ export class CipherService implements CipherServiceAbstraction { await this.upsert(data); } - async shareWithServer(cipher: Cipher): Promise { - const request = new CipherShareRequest(cipher); + async shareWithServer(cipher: CipherView, organizationId: string, collectionIds: string[]): Promise { + cipher.organizationId = organizationId; + cipher.collectionIds = collectionIds; + const encCipher = await this.encrypt(cipher); + const request = new CipherShareRequest(encCipher); await this.apiService.putShareCipher(cipher.id, request); const userId = await this.userService.getUserId(); - await this.upsert(cipher.toCipherData(userId)); + await this.upsert(encCipher.toCipherData(userId)); + } + + async shareManyWithServer(ciphers: CipherView[], organizationId: string, collectionIds: string[]): Promise { + const promises: Array> = []; + const encCiphers: Cipher[] = []; + for (const cipher of ciphers) { + cipher.organizationId = organizationId; + cipher.collectionIds = collectionIds; + promises.push(this.encrypt(cipher).then((c) => { + encCiphers.push(c); + })); + } + await Promise.all(promises); + const request = new CipherBulkShareRequest(encCiphers, collectionIds); + await this.apiService.putShareCiphers(request); + const userId = await this.userService.getUserId(); + await this.upsert(encCiphers.map((c) => c.toCipherData(userId))); } async shareAttachmentWithServer(attachmentView: AttachmentView, cipherId: string,