From 4ea1a5f239953a9ed5a84310e7198fb1fe4460d3 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 9 Jan 2018 22:39:43 -0500 Subject: [PATCH] move folder service to jslib --- src/abstractions/folder.service.ts | 19 ++++ src/abstractions/index.ts | 1 + src/services/folder.service.ts | 163 +++++++++++++++++++++++++++++ src/services/index.ts | 1 + 4 files changed, 184 insertions(+) create mode 100644 src/abstractions/folder.service.ts create mode 100644 src/services/folder.service.ts diff --git a/src/abstractions/folder.service.ts b/src/abstractions/folder.service.ts new file mode 100644 index 0000000000..e02323115e --- /dev/null +++ b/src/abstractions/folder.service.ts @@ -0,0 +1,19 @@ +import { FolderData } from '../models/data'; + +import { Folder } from '../models/domain'; + +export interface FolderService { + decryptedFolderCache: any[]; + + clearCache(): void; + encrypt(model: any): Promise; + get(id: string): Promise; + getAll(): Promise; + getAllDecrypted(): Promise; + saveWithServer(folder: Folder): Promise; + upsert(folder: FolderData | FolderData[]): Promise; + replace(folders: { [id: string]: FolderData; }): Promise; + clear(userId: string): Promise; + delete(id: string | string[]): Promise; + deleteWithServer(id: string): Promise; +} diff --git a/src/abstractions/index.ts b/src/abstractions/index.ts index 74062e753c..7a662f6db5 100644 --- a/src/abstractions/index.ts +++ b/src/abstractions/index.ts @@ -2,6 +2,7 @@ export { ApiService } from './api.service'; export { AppIdService } from './appId.service'; export { CryptoService } from './crypto.service'; export { EnvironmentService } from './environment.service'; +export { FolderService } from './folder.service'; export { MessagingService } from './messaging.service'; export { PasswordGenerationService } from './passwordGeneration.service'; export { PlatformUtilsService } from './platformUtils.service'; diff --git a/src/services/folder.service.ts b/src/services/folder.service.ts new file mode 100644 index 0000000000..6c51dafddc --- /dev/null +++ b/src/services/folder.service.ts @@ -0,0 +1,163 @@ +import { FolderData } from '../models/data'; + +import { Folder } from '../models/domain'; + +import { FolderRequest } from '../models/request'; + +import { FolderResponse } from '../models/response'; + +import { ApiService } from '../abstractions/api.service'; +import { CryptoService } from '../abstractions/crypto.service'; +import { FolderService as FolderServiceInterface } from '../abstractions/folder.service'; +import { StorageService } from '../abstractions/storage.service'; +import { UserService } from '../abstractions/user.service'; + +const Keys = { + foldersPrefix: 'folders_', +}; + +export class FolderService implements FolderServiceInterface { + decryptedFolderCache: any[]; + + constructor(private cryptoService: CryptoService, private userService: UserService, + private noneFolder: string, private apiService: ApiService, + private storageService: StorageService) { + } + + clearCache(): void { + this.decryptedFolderCache = null; + } + + async encrypt(model: any): Promise { + const folder = new Folder(); + folder.id = model.id; + folder.name = await this.cryptoService.encrypt(model.name); + return folder; + } + + async get(id: string): Promise { + const userId = await this.userService.getUserId(); + const folders = await this.storageService.get<{ [id: string]: FolderData; }>( + Keys.foldersPrefix + userId); + if (folders == null || !folders.hasOwnProperty(id)) { + return null; + } + + return new Folder(folders[id]); + } + + async getAll(): Promise { + const userId = await this.userService.getUserId(); + const folders = await this.storageService.get<{ [id: string]: FolderData; }>( + Keys.foldersPrefix + userId); + const response: Folder[] = []; + for (const id in folders) { + if (folders.hasOwnProperty(id)) { + response.push(new Folder(folders[id])); + } + } + return response; + } + + async getAllDecrypted(): Promise { + if (this.decryptedFolderCache != null) { + return this.decryptedFolderCache; + } + + const decFolders: any[] = [{ + id: null, + name: this.noneFolder, + }]; + + const key = await this.cryptoService.getKey(); + if (key == null) { + throw new Error('No key.'); + } + + const promises: Array> = []; + const folders = await this.getAll(); + folders.forEach((folder) => { + promises.push(folder.decrypt().then((f: any) => { + decFolders.push(f); + })); + }); + + await Promise.all(promises); + this.decryptedFolderCache = decFolders; + return this.decryptedFolderCache; + } + + async saveWithServer(folder: Folder): Promise { + const request = new FolderRequest(folder); + + let response: FolderResponse; + if (folder.id == null) { + response = await this.apiService.postFolder(request); + folder.id = response.id; + } else { + response = await this.apiService.putFolder(folder.id, request); + } + + const userId = await this.userService.getUserId(); + const data = new FolderData(response, userId); + await this.upsert(data); + } + + async upsert(folder: FolderData | FolderData[]): Promise { + const userId = await this.userService.getUserId(); + let folders = await this.storageService.get<{ [id: string]: FolderData; }>( + Keys.foldersPrefix + userId); + if (folders == null) { + folders = {}; + } + + if (folder instanceof FolderData) { + const f = folder as FolderData; + folders[f.id] = f; + } else { + (folder as FolderData[]).forEach((f) => { + folders[f.id] = f; + }); + } + + await this.storageService.save(Keys.foldersPrefix + userId, folders); + this.decryptedFolderCache = null; + } + + async replace(folders: { [id: string]: FolderData; }): Promise { + const userId = await this.userService.getUserId(); + await this.storageService.save(Keys.foldersPrefix + userId, folders); + this.decryptedFolderCache = null; + } + + async clear(userId: string): Promise { + await this.storageService.remove(Keys.foldersPrefix + userId); + this.decryptedFolderCache = null; + } + + async delete(id: string | string[]): Promise { + const userId = await this.userService.getUserId(); + const folders = await this.storageService.get<{ [id: string]: FolderData; }>( + Keys.foldersPrefix + userId); + if (folders == null) { + return; + } + + if (typeof id === 'string') { + const i = id as string; + delete folders[id]; + } else { + (id as string[]).forEach((i) => { + delete folders[i]; + }); + } + + await this.storageService.save(Keys.foldersPrefix + userId, folders); + this.decryptedFolderCache = null; + } + + async deleteWithServer(id: string): Promise { + await this.apiService.deleteFolder(id); + await this.delete(id); + } +} diff --git a/src/services/index.ts b/src/services/index.ts index bb199e0e9c..6fc897d773 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -4,6 +4,7 @@ export { ConstantsService } from './constants.service'; export { ContainerService } from './container.service'; export { CryptoService } from './crypto.service'; export { EnvironmentService } from './environment.service'; +export { FolderService } from './folder.service'; export { PasswordGenerationService } from './passwordGeneration.service'; export { TokenService } from './token.service'; export { TotpService } from './totp.service';