From 1021f23277db5a47ae9b7be8e8021ad5005a8c10 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 12 Jun 2018 13:07:06 -0400 Subject: [PATCH] cipher collection apis --- src/abstractions/api.service.ts | 7 +- src/abstractions/cipher.service.ts | 1 + .../request/cipherCollectionsRequest.ts | 2 +- src/services/api.service.ts | 68 ++++++++++++------- src/services/cipher.service.ts | 14 +++- 5 files changed, 64 insertions(+), 28 deletions(-) diff --git a/src/abstractions/api.service.ts b/src/abstractions/api.service.ts index a1410c0fe3..4bb7a854b6 100644 --- a/src/abstractions/api.service.ts +++ b/src/abstractions/api.service.ts @@ -1,5 +1,6 @@ import { EnvironmentUrls } from '../models/domain/environmentUrls'; +import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherShareRequest } from '../models/request/cipherShareRequest'; import { FolderRequest } from '../models/request/folderRequest'; @@ -37,11 +38,13 @@ export abstract class ApiService { deleteFolder: (id: string) => Promise; postCipher: (request: CipherRequest) => Promise; putCipher: (id: string, request: CipherRequest) => Promise; - shareCipher: (id: string, request: CipherShareRequest) => Promise; deleteCipher: (id: string) => Promise; + putShareCipher: (id: string, request: CipherShareRequest) => Promise; + putCipherCollections: (id: string, request: CipherCollectionsRequest) => Promise; postCipherAttachment: (id: string, data: FormData) => Promise; - shareCipherAttachment: (id: string, attachmentId: string, data: FormData, organizationId: string) => Promise; deleteCipherAttachment: (id: string, attachmentId: string) => Promise; + postShareCipherAttachment: (id: string, attachmentId: string, data: FormData, + organizationId: string) => Promise; getSync: () => Promise; postImportDirectory: (organizationId: string, request: ImportDirectoryRequest) => Promise; } diff --git a/src/abstractions/cipher.service.ts b/src/abstractions/cipher.service.ts index d621443f1b..06e66d2df2 100644 --- a/src/abstractions/cipher.service.ts +++ b/src/abstractions/cipher.service.ts @@ -31,6 +31,7 @@ export abstract class CipherService { organizationId: string) => Promise; saveAttachmentWithServer: (cipher: Cipher, unencryptedFile: any) => Promise; saveAttachmentRawWithServer: (cipher: Cipher, filename: string, data: ArrayBuffer) => Promise; + saveCollectionsWithServer: (cipher: Cipher) => Promise; upsert: (cipher: CipherData | CipherData[]) => Promise; replace: (ciphers: { [id: string]: CipherData; }) => Promise; clear: (userId: string) => Promise; diff --git a/src/models/request/cipherCollectionsRequest.ts b/src/models/request/cipherCollectionsRequest.ts index 14718e2308..1473f4e3d6 100644 --- a/src/models/request/cipherCollectionsRequest.ts +++ b/src/models/request/cipherCollectionsRequest.ts @@ -2,6 +2,6 @@ export class CipherCollectionsRequest { collectionIds: string[]; constructor(collectionIds: string[]) { - this.collectionIds = collectionIds; + this.collectionIds = collectionIds == null ? [] : collectionIds; } } diff --git a/src/services/api.service.ts b/src/services/api.service.ts index 806ffb151c..2f2d4f8308 100644 --- a/src/services/api.service.ts +++ b/src/services/api.service.ts @@ -6,6 +6,7 @@ import { TokenService } from '../abstractions/token.service'; import { EnvironmentUrls } from '../models/domain/environmentUrls'; +import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherShareRequest } from '../models/request/cipherShareRequest'; import { FolderRequest } from '../models/request/folderRequest'; @@ -335,7 +336,25 @@ export class ApiService implements ApiServiceAbstraction { } } - async shareCipher(id: string, request: CipherShareRequest): Promise { + async deleteCipher(id: string): Promise { + const authHeader = await this.handleTokenState(); + const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id, { + cache: 'no-cache', + credentials: this.getCredentials(), + headers: new Headers({ + 'Authorization': authHeader, + 'Device-Type': this.deviceType, + }), + method: 'DELETE', + })); + + if (response.status !== 200) { + const error = await this.handleError(response, false); + return Promise.reject(error); + } + } + + async putShareCipher(id: string, request: CipherShareRequest): Promise { const authHeader = await this.handleTokenState(); const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id + '/share', { body: JSON.stringify(request), @@ -356,16 +375,19 @@ export class ApiService implements ApiServiceAbstraction { } } - async deleteCipher(id: string): Promise { + async putCipherCollections(id: string, request: CipherCollectionsRequest): Promise { const authHeader = await this.handleTokenState(); - const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id, { + const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id + '/collections', { + 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: 'DELETE', + method: 'PUT', })); if (response.status !== 200) { @@ -399,7 +421,25 @@ export class ApiService implements ApiServiceAbstraction { } } - async shareCipherAttachment(id: string, attachmentId: string, data: FormData, + async deleteCipherAttachment(id: string, attachmentId: string): Promise { + const authHeader = await this.handleTokenState(); + const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id + '/attachment/' + attachmentId, { + cache: 'no-cache', + credentials: this.getCredentials(), + headers: new Headers({ + 'Authorization': authHeader, + 'Device-Type': this.deviceType, + }), + method: 'DELETE', + })); + + if (response.status !== 200) { + const error = await this.handleError(response, false); + return Promise.reject(error); + } + } + + async postShareCipherAttachment(id: string, attachmentId: string, data: FormData, organizationId: string): Promise { const authHeader = await this.handleTokenState(); const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id + '/attachment/' + @@ -421,24 +461,6 @@ export class ApiService implements ApiServiceAbstraction { } } - async deleteCipherAttachment(id: string, attachmentId: string): Promise { - const authHeader = await this.handleTokenState(); - const response = await fetch(new Request(this.baseUrl + '/ciphers/' + id + '/attachment/' + attachmentId, { - cache: 'no-cache', - credentials: this.getCredentials(), - headers: new Headers({ - 'Authorization': authHeader, - 'Device-Type': this.deviceType, - }), - method: 'DELETE', - })); - - if (response.status !== 200) { - const error = await this.handleError(response, false); - return Promise.reject(error); - } - } - // Sync APIs async getSync(): Promise { diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index 6c89d23141..e122b45283 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -15,6 +15,7 @@ import { LoginUri } from '../models/domain/loginUri'; import { SecureNote } from '../models/domain/secureNote'; import { SymmetricCryptoKey } from '../models/domain/symmetricCryptoKey'; +import { CipherCollectionsRequest } from '../models/request/cipherCollectionsRequest'; import { CipherRequest } from '../models/request/cipherRequest'; import { CipherResponse } from '../models/response/cipherResponse'; @@ -357,7 +358,7 @@ export class CipherService implements CipherServiceAbstraction { async shareWithServer(cipher: Cipher): Promise { const request = new CipherShareRequest(cipher); - await this.apiService.shareCipher(cipher.id, request); + await this.apiService.putShareCipher(cipher.id, request); const userId = await this.userService.getUserId(); await this.upsert(cipher.toCipherData(userId)); } @@ -392,7 +393,8 @@ export class CipherService implements CipherServiceAbstraction { let response: CipherResponse; try { - response = await this.apiService.shareCipherAttachment(cipherId, attachmentView.id, fd, organizationId); + response = await this.apiService.postShareCipherAttachment(cipherId, attachmentView.id, fd, + organizationId); } catch (e) { throw new Error((e as ErrorResponse).getSingleMessage()); } @@ -450,6 +452,14 @@ export class CipherService implements CipherServiceAbstraction { return new Cipher(cData); } + async saveCollectionsWithServer(cipher: Cipher): Promise { + const request = new CipherCollectionsRequest(cipher.collectionIds); + const response = await this.apiService.putCipherCollections(cipher.id, request); + const userId = await this.userService.getUserId(); + const data = cipher.toCipherData(userId); + await this.upsert(data); + } + async upsert(cipher: CipherData | CipherData[]): Promise { const userId = await this.userService.getUserId(); let ciphers = await this.storageService.get<{ [id: string]: CipherData; }>(