diff --git a/jslib b/jslib index 4ca7a9709e..8448b48cd7 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 4ca7a9709e9ccd0e67ce09309ae605f2057bf089 +Subproject commit 8448b48cd7c65c3d7891bc00246e27777daaeb58 diff --git a/package-lock.json b/package-lock.json index 3bbfa2b8e0..94b938506f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -172,9 +172,9 @@ "dev": true }, "@types/lunr": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.1.5.tgz", - "integrity": "sha512-esk3CG25hRtHsVHm+LOjiSFYdw8be3uIY653WUwR43Bro914HSimPgPpqgajkhTJ0awK3RQfaIxP7zvbtCpcyg==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.1.6.tgz", + "integrity": "sha512-Bz6fUhX1llTa7ygQJN3ttoVkkrpW7xxSEP7D7OYFO/FCBKqKqruRUZtJzTtYA0GkQX13lxU5u+8LuCviJlAXkQ==", "dev": true }, "@types/node": { @@ -6273,9 +6273,9 @@ } }, "lunr": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.1.6.tgz", - "integrity": "sha512-ydJpB8CX8cZ/VE+KMaYaFcZ6+o2LruM6NG76VXdflYTgluvVemz1lW4anE+pyBbLvxJHZdvD1Jy/fOqdzAEJog==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.1.tgz", + "integrity": "sha1-ETYWorYC3cEJMqe/ik5uV+v+zfI=" }, "magic-string": { "version": "0.22.5", diff --git a/package.json b/package.json index 0fd8d026fd..af32ef1075 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@angular/compiler-cli": "5.2.0", "@ngtools/webpack": "1.10.2", "@types/jquery": "^3.3.2", - "@types/lunr": "2.1.5", + "@types/lunr": "^2.1.6", "@types/node": "8.0.19", "@types/node-forge": "0.6.10", "@types/papaparse": "4.1.33", @@ -73,7 +73,7 @@ "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", "font-awesome": "4.7.0", "jquery": "3.3.1", - "lunr": "2.1.6", + "lunr": "2.3.1", "mousetrap": "1.6.1", "ngx-infinite-scroll": "0.8.4", "node-forge": "0.7.1", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0b6cbca59b..7216722e75 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -33,6 +33,7 @@ import { I18nService } from 'jslib/abstractions/i18n.service'; import { LockService } from 'jslib/abstractions/lock.service'; import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SearchService } from 'jslib/abstractions/search.service'; import { SettingsService } from 'jslib/abstractions/settings.service'; import { SyncService } from 'jslib/abstractions/sync.service'; import { TokenService } from 'jslib/abstractions/token.service'; @@ -70,7 +71,7 @@ export class AppComponent implements OnDestroy, OnInit { private platformUtilsService: PlatformUtilsService, private ngZone: NgZone, private lockService: LockService, private storageService: StorageService, private cryptoService: CryptoService, private collectionService: CollectionService, - private routerService: RouterService) { } + private routerService: RouterService, private searchService: SearchService) { } ngOnInit() { this.ngZone.runOutsideAngular(() => { @@ -157,6 +158,7 @@ export class AppComponent implements OnDestroy, OnInit { this.passwordGenerationService.clear(), ]); + this.searchService.clearIndex(); this.authService.logOut(async () => { this.analytics.eventTrack.next({ action: 'Logged Out' }); if (expired) { diff --git a/src/app/organizations/vault/ciphers.component.ts b/src/app/organizations/vault/ciphers.component.ts index bae26e3ba3..b8cc84ce79 100644 --- a/src/app/organizations/vault/ciphers.component.ts +++ b/src/app/organizations/vault/ciphers.component.ts @@ -11,6 +11,7 @@ import { ApiService } from 'jslib/abstractions/api.service'; import { CipherService } from 'jslib/abstractions/cipher.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SearchService } from 'jslib/abstractions/search.service'; import { CipherData } from 'jslib/models/data/cipherData'; import { Cipher } from 'jslib/models/domain/cipher'; @@ -29,10 +30,13 @@ export class CiphersComponent extends BaseCiphersComponent { organization: Organization; accessEvents = false; - constructor(cipherService: CipherService, analytics: Angulartics2, + protected allCiphers: CipherView[] = []; + + constructor(searchService: SearchService, analytics: Angulartics2, toasterService: ToasterService, i18nService: I18nService, - platformUtilsService: PlatformUtilsService, private apiService: ApiService) { - super(cipherService, analytics, toasterService, i18nService, platformUtilsService); + platformUtilsService: PlatformUtilsService, cipherService: CipherService, + private apiService: ApiService) { + super(searchService, analytics, toasterService, i18nService, platformUtilsService, cipherService); } async load(filter: (cipher: CipherView) => boolean = null) { @@ -60,12 +64,24 @@ export class CiphersComponent extends BaseCiphersComponent { this.loaded = true; } - applyFilter(filter: (cipher: CipherView) => boolean = null) { + async applyFilter(filter: (cipher: CipherView) => boolean = null) { if (this.organization.isAdmin) { - super.applyFilter(filter); + await super.applyFilter(filter); } else { const f = (c: CipherView) => c.organizationId === this.organization.id && (filter == null || filter(c)); - super.applyFilter(f); + await super.applyFilter(f); + } + } + + search(timeout: number = null) { + if (!this.organization.isAdmin) { + return super.search(timeout); + } + this.searchPending = false; + if (this.searchText == null || this.searchText.trim().length < 2) { + this.ciphers = this.allCiphers; + } else { + this.ciphers = this.searchService.searchCiphersBasic(this.allCiphers, this.searchText); } } diff --git a/src/app/organizations/vault/vault.component.ts b/src/app/organizations/vault/vault.component.ts index de6eebb321..0f784df4a8 100644 --- a/src/app/organizations/vault/vault.component.ts +++ b/src/app/organizations/vault/vault.component.ts @@ -139,6 +139,7 @@ export class VaultComponent implements OnInit { filterSearchText(searchText: string) { this.ciphersComponent.searchText = searchText; + this.ciphersComponent.search(200); } editCipherAttachments(cipher: CipherView) { diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts index 79885e922b..dd46704cd3 100644 --- a/src/app/services/services.module.ts +++ b/src/app/services/services.module.ts @@ -39,6 +39,7 @@ import { FolderService } from 'jslib/services/folder.service'; import { ImportService } from 'jslib/services/import.service'; import { LockService } from 'jslib/services/lock.service'; import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service'; +import { SearchService } from 'jslib/services/search.service'; import { SettingsService } from 'jslib/services/settings.service'; import { StateService } from 'jslib/services/state.service'; import { SyncService } from 'jslib/services/sync.service'; @@ -67,6 +68,7 @@ import { PasswordGenerationService as PasswordGenerationServiceAbstraction, } from 'jslib/abstractions/passwordGeneration.service'; import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib/abstractions/platformUtils.service'; +import { SearchService as SearchServiceAbstraction } from 'jslib/abstractions/search.service'; import { SettingsService as SettingsServiceAbstraction } from 'jslib/abstractions/settings.service'; import { StateService as StateServiceAbstraction } from 'jslib/abstractions/state.service'; import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service'; @@ -93,13 +95,15 @@ const apiService = new ApiService(tokenService, platformUtilsService, const environmentService = new EnvironmentService(apiService, storageService); const userService = new UserService(tokenService, storageService); const settingsService = new SettingsService(userService, storageService); +export let searchService: SearchService = null; const cipherService = new CipherService(cryptoService, userService, settingsService, - apiService, storageService, i18nService, platformUtilsService); + apiService, storageService, i18nService, platformUtilsService, () => searchService); const folderService = new FolderService(cryptoService, userService, apiService, storageService, i18nService, cipherService); const collectionService = new CollectionService(cryptoService, userService, storageService, i18nService); +searchService = new SearchService(cipherService, platformUtilsService); const lockService = new LockService(cipherService, folderService, collectionService, - cryptoService, platformUtilsService, storageService, messagingService, null); + cryptoService, platformUtilsService, storageService, messagingService, searchService, null); const syncService = new SyncService(userService, apiService, settingsService, folderService, cipherService, cryptoService, collectionService, storageService, messagingService, async (expired: boolean) => messagingService.send('logout', { expired: expired })); @@ -188,6 +192,7 @@ export function initFactory(): Function { { provide: StorageServiceAbstraction, useValue: storageService }, { provide: StateServiceAbstraction, useValue: stateService }, { provide: ExportServiceAbstraction, useValue: exportService }, + { provide: SearchServiceAbstraction, useValue: searchService }, { provide: ImportServiceAbstraction, useValue: importService }, { provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService }, { diff --git a/src/app/vault/ciphers.component.html b/src/app/vault/ciphers.component.html index fd3d90ad51..9c60fcd15d 100644 --- a/src/app/vault/ciphers.component.html +++ b/src/app/vault/ciphers.component.html @@ -1,7 +1,7 @@ - - + +
- + @@ -52,7 +52,7 @@
-
+

{{'noItemsInList' | i18n}}

diff --git a/src/app/vault/ciphers.component.ts b/src/app/vault/ciphers.component.ts index f987c9b9cd..6f8f536374 100644 --- a/src/app/vault/ciphers.component.ts +++ b/src/app/vault/ciphers.component.ts @@ -12,6 +12,7 @@ import { Angulartics2 } from 'angulartics2'; import { CipherService } from 'jslib/abstractions/cipher.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { SearchService } from 'jslib/abstractions/search.service'; import { CiphersComponent as BaseCiphersComponent } from 'jslib/angular/components/ciphers.component'; @@ -38,10 +39,10 @@ export class CiphersComponent extends BaseCiphersComponent implements OnDestroy private searchPipe: SearchCiphersPipe; - constructor(cipherService: CipherService, protected analytics: Angulartics2, + constructor(searchService: SearchService, protected analytics: Angulartics2, protected toasterService: ToasterService, protected i18nService: I18nService, - protected platformUtilsService: PlatformUtilsService) { - super(cipherService); + protected platformUtilsService: PlatformUtilsService, protected cipherService: CipherService) { + super(searchService); this.searchPipe = new SearchCiphersPipe(platformUtilsService); } diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts index a6f11a166f..45ff9f41b8 100644 --- a/src/app/vault/vault.component.ts +++ b/src/app/vault/vault.component.ts @@ -167,6 +167,7 @@ export class VaultComponent implements OnInit { filterSearchText(searchText: string) { this.ciphersComponent.searchText = searchText; + this.ciphersComponent.search(200); } async editCipherAttachments(cipher: CipherView) {