diff --git a/src/abstractions/collection.service.ts b/src/abstractions/collection.service.ts new file mode 100644 index 0000000000..e33532d3ce --- /dev/null +++ b/src/abstractions/collection.service.ts @@ -0,0 +1,16 @@ +import { CollectionData } from '../models/data/collectionData'; + +import { Collection } from '../models/domain/collection'; + +export interface CollectionService { + decryptedCollectionCache: any[]; + + clearCache(): void; + get(id: string): Promise; + getAll(): Promise; + getAllDecrypted(): Promise; + upsert(collection: CollectionData | CollectionData[]): Promise; + replace(collections: { [id: string]: CollectionData; }): Promise; + clear(userId: string): Promise; + delete(id: string | string[]): Promise; +} diff --git a/src/abstractions/index.ts b/src/abstractions/index.ts index 7ef441f0c3..893a189120 100644 --- a/src/abstractions/index.ts +++ b/src/abstractions/index.ts @@ -1,6 +1,7 @@ export { ApiService } from './api.service'; export { AppIdService } from './appId.service'; export { CipherService } from './cipher.service'; +export { CollectionService } from './collection.service'; export { CryptoService } from './crypto.service'; export { EnvironmentService } from './environment.service'; export { FolderService } from './folder.service'; diff --git a/src/services/collection.service.ts b/src/services/collection.service.ts new file mode 100644 index 0000000000..c409925cd7 --- /dev/null +++ b/src/services/collection.service.ts @@ -0,0 +1,124 @@ +import { CollectionData } from '../models/data/collectionData'; + +import { Collection } from '../models/domain/collection'; + +import { CryptoService } from '../abstractions/crypto.service'; +import { StorageService } from '../abstractions/storage.service'; +import { UserService } from '../abstractions/user.service'; + +const Keys = { + collectionsPrefix: 'collections_', +}; + +export class CollectionService { + decryptedCollectionCache: any[]; + + constructor(private cryptoService: CryptoService, private userService: UserService, + private storageService: StorageService) { + } + + clearCache(): void { + this.decryptedCollectionCache = null; + } + + async get(id: string): Promise { + const userId = await this.userService.getUserId(); + const collections = await this.storageService.get<{ [id: string]: CollectionData; }>( + Keys.collectionsPrefix + userId); + if (collections == null || !collections.hasOwnProperty(id)) { + return null; + } + + return new Collection(collections[id]); + } + + async getAll(): Promise { + const userId = await this.userService.getUserId(); + const collections = await this.storageService.get<{ [id: string]: CollectionData; }>( + Keys.collectionsPrefix + userId); + const response: Collection[] = []; + for (const id in collections) { + if (collections.hasOwnProperty(id)) { + response.push(new Collection(collections[id])); + } + } + return response; + } + + async getAllDecrypted(): Promise { + if (this.decryptedCollectionCache != null) { + return this.decryptedCollectionCache; + } + + const key = await this.cryptoService.getKey(); + if (key == null) { + throw new Error('No key.'); + } + + const decFolders: any[] = []; + 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.decryptedCollectionCache = decFolders; + return this.decryptedCollectionCache; + } + + async upsert(collection: CollectionData | CollectionData[]): Promise { + const userId = await this.userService.getUserId(); + let collections = await this.storageService.get<{ [id: string]: CollectionData; }>( + Keys.collectionsPrefix + userId); + if (collections == null) { + collections = {}; + } + + if (collection instanceof CollectionData) { + const c = collection as CollectionData; + collections[c.id] = c; + } else { + (collection as CollectionData[]).forEach((c) => { + collections[c.id] = c; + }); + } + + await this.storageService.save(Keys.collectionsPrefix + userId, collections); + this.decryptedCollectionCache = null; + } + + async replace(collections: { [id: string]: CollectionData; }): Promise { + const userId = await this.userService.getUserId(); + await this.storageService.save(Keys.collectionsPrefix + userId, collections); + this.decryptedCollectionCache = null; + } + + async clear(userId: string): Promise { + await this.storageService.remove(Keys.collectionsPrefix + userId); + this.decryptedCollectionCache = null; + } + + async delete(id: string | string[]): Promise { + const userId = await this.userService.getUserId(); + const collections = await this.storageService.get<{ [id: string]: CollectionData; }>( + Keys.collectionsPrefix + userId); + if (collections == null) { + return; + } + + if (typeof id === 'string') { + const i = id as string; + delete collections[id]; + } else { + (id as string[]).forEach((i) => { + delete collections[i]; + }); + } + + await this.storageService.save(Keys.collectionsPrefix + userId, collections); + this.decryptedCollectionCache = null; + } +} diff --git a/src/services/index.ts b/src/services/index.ts index 990af9022b..0412506aef 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,6 +1,7 @@ export { ApiService } from './api.service'; export { AppIdService } from './appId.service'; export { CipherService } from './cipher.service'; +export { CollectionService } from './collection.service'; export { ConstantsService } from './constants.service'; export { ContainerService } from './container.service'; export { CryptoService } from './crypto.service';