diff --git a/src/abstractions/cipher.service.ts b/src/abstractions/cipher.service.ts index 339ca0a4617..ca4d29af1ed 100644 --- a/src/abstractions/cipher.service.ts +++ b/src/abstractions/cipher.service.ts @@ -26,8 +26,10 @@ export abstract class CipherService { defaultMatch?: UriMatchType) => Promise; getAllFromApiForOrganization: (organizationId: string) => Promise; getLastUsedForUrl: (url: string) => Promise; + getLastLaunchedForUrl: (url: string) => Promise; getNextCipherForUrl: (url: string) => Promise; updateLastUsedDate: (id: string) => Promise; + updateLastLaunchedDate: (id: string) => Promise; saveNeverDomain: (domain: string) => Promise; saveWithServer: (cipher: Cipher) => Promise; shareWithServer: (cipher: CipherView, organizationId: string, collectionIds: string[]) => Promise; diff --git a/src/models/domain/sortedCiphersCache.ts b/src/models/domain/sortedCiphersCache.ts index 9f11f73db78..e4e22ee9eef 100644 --- a/src/models/domain/sortedCiphersCache.ts +++ b/src/models/domain/sortedCiphersCache.ts @@ -23,6 +23,10 @@ export class SortedCiphersCache { return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getLastUsed() : null; } + getLastLaunched(url: string) { + return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getLastLaunched() : null; + } + getNext(url: string) { this.resetTimer(url); return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getNext() : null; @@ -52,6 +56,11 @@ class Ciphers { return this.ciphers[this.lastUsedIndex]; } + getLastLaunched() { + const sortedCiphers = this.ciphers.sort((x, y) => y.localData?.lastLaunched?.valueOf() - x.localData?.lastLaunched?.valueOf()); + return sortedCiphers[0]; + } + getNext() { const nextIndex = (this.lastUsedIndex + 1) % this.ciphers.length; this.lastUsedIndex = nextIndex; diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index 1942628898b..0095c4773a1 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -445,11 +445,15 @@ export class CipherService implements CipherServiceAbstraction { } async getLastUsedForUrl(url: string): Promise { - return this.getCipherForUrl(url, true); + return this.getCipherForUrl(url, true, false); + } + + async getLastLaunchedForUrl(url: string): Promise { + return this.getCipherForUrl(url, false, true); } async getNextCipherForUrl(url: string): Promise { - return this.getCipherForUrl(url, false); + return this.getCipherForUrl(url, false, false); } async updateLastUsedDate(id: string): Promise { @@ -481,6 +485,35 @@ export class CipherService implements CipherServiceAbstraction { } } + async updateLastLaunchedDate(id: string): Promise { + let ciphersLocalData = await this.storageService.get(Keys.localData); + if (!ciphersLocalData) { + ciphersLocalData = {}; + } + + if (ciphersLocalData[id]) { + ciphersLocalData[id].lastLaunched = new Date().getTime(); + } else { + ciphersLocalData[id] = { + lastUsedDate: new Date().getTime(), + }; + } + + await this.storageService.save(Keys.localData, ciphersLocalData); + + if (this.decryptedCipherCache == null) { + return; + } + + for (let i = 0; i < this.decryptedCipherCache.length; i++) { + const cached = this.decryptedCipherCache[i]; + if (cached.id === id) { + cached.localData = ciphersLocalData[id]; + break; + } + } + } + async saveNeverDomain(domain: string): Promise { if (domain == null) { return; @@ -1009,7 +1042,7 @@ export class CipherService implements CipherServiceAbstraction { } } - private async getCipherForUrl(url: string, lastUsed: boolean): Promise { + private async getCipherForUrl(url: string, lastUsed: boolean, lastLaunched: boolean): Promise { if (!this.sortedCiphersCache.isCached(url)) { const ciphers = await this.getAllDecryptedForUrl(url); if (!ciphers) { @@ -1018,6 +1051,13 @@ export class CipherService implements CipherServiceAbstraction { this.sortedCiphersCache.addCiphers(url, ciphers); } - return lastUsed ? this.sortedCiphersCache.getLastUsed(url) : this.sortedCiphersCache.getNext(url); + if (lastLaunched) { + return this.sortedCiphersCache.getLastLaunched(url); + } else if (lastUsed) { + return this.sortedCiphersCache.getLastUsed(url); + } + else { + return this.sortedCiphersCache.getNext(url); + } } }