mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-06 09:20:43 +01:00
search service with lunr implementation
This commit is contained in:
parent
e3b3e444db
commit
6aef18ee7f
10
package-lock.json
generated
10
package-lock.json
generated
@ -31,6 +31,11 @@
|
|||||||
"integrity": "sha512-BZknw3E/z3JmCLqQVANcR17okqVTPZdlxvcIz0fJiJVLUCbSH1hK3zs9r634PVSmrzAxN+n/fxlVRiYoArdOIQ==",
|
"integrity": "sha512-BZknw3E/z3JmCLqQVANcR17okqVTPZdlxvcIz0fJiJVLUCbSH1hK3zs9r634PVSmrzAxN+n/fxlVRiYoArdOIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/lunr": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-esk3CG25hRtHsVHm+LOjiSFYdw8be3uIY653WUwR43Bro914HSimPgPpqgajkhTJ0awK3RQfaIxP7zvbtCpcyg=="
|
||||||
|
},
|
||||||
"@types/marked": {
|
"@types/marked": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.3.0.tgz",
|
||||||
@ -297,6 +302,11 @@
|
|||||||
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
|
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lunr": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-ydJpB8CX8cZ/VE+KMaYaFcZ6+o2LruM6NG76VXdflYTgluvVemz1lW4anE+pyBbLvxJHZdvD1Jy/fOqdzAEJog=="
|
||||||
|
},
|
||||||
"marked": {
|
"marked": {
|
||||||
"version": "0.3.9",
|
"version": "0.3.9",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.9.tgz",
|
||||||
|
@ -33,7 +33,9 @@
|
|||||||
"typescript": "^2.7.1"
|
"typescript": "^2.7.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"lunr": "2.1.6",
|
||||||
"node-forge": "0.7.1",
|
"node-forge": "0.7.1",
|
||||||
|
"@types/lunr": "2.1.5",
|
||||||
"@types/node-forge": "0.7.1",
|
"@types/node-forge": "0.7.1",
|
||||||
"@types/webcrypto": "0.0.28"
|
"@types/webcrypto": "0.0.28"
|
||||||
}
|
}
|
||||||
|
6
src/abstractions/search.service.ts
Normal file
6
src/abstractions/search.service.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { CipherView } from '../models/view/cipherView';
|
||||||
|
|
||||||
|
export abstract class SearchService {
|
||||||
|
indexCiphers: () => Promise<void>;
|
||||||
|
searchCiphers: (query: string) => Promise<CipherView[]>;
|
||||||
|
}
|
@ -65,4 +65,12 @@ export class CipherView implements View {
|
|||||||
get hasFields(): boolean {
|
get hasFields(): boolean {
|
||||||
return this.fields && this.fields.length > 0;
|
return this.fields && this.fields.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get login_username(): string {
|
||||||
|
return this.login != null ? this.login.username : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get login_uri(): string {
|
||||||
|
return this.login != null ? this.login.uri : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
import { AuditService as AuditServiceAbstraction } from '../abstractions/audit.service';
|
||||||
import { CryptoService } from '../abstractions/crypto.service';
|
import { CryptoService } from '../abstractions/crypto.service';
|
||||||
|
|
||||||
const PwnedPasswordsApi = 'https://api.pwnedpasswords.com/range/';
|
const PwnedPasswordsApi = 'https://api.pwnedpasswords.com/range/';
|
||||||
|
|
||||||
export class AuditService {
|
export class AuditService implements AuditServiceAbstraction {
|
||||||
constructor(private cryptoService: CryptoService) {
|
constructor(private cryptoService: CryptoService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
src/services/search.service.ts
Normal file
60
src/services/search.service.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import * as lunr from 'lunr';
|
||||||
|
|
||||||
|
import { CipherView } from '../models/view/cipherView';
|
||||||
|
|
||||||
|
import { CipherService } from '../abstractions/cipher.service';
|
||||||
|
import { SearchService as SearchServiceAbstraction } from '../abstractions/search.service';
|
||||||
|
|
||||||
|
export class SearchService implements SearchServiceAbstraction {
|
||||||
|
private index: lunr.Index;
|
||||||
|
|
||||||
|
constructor(private cipherService: CipherService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
async indexCiphers(): Promise<void> {
|
||||||
|
const builder = new lunr.Builder();
|
||||||
|
builder.ref('id');
|
||||||
|
builder.field('name');
|
||||||
|
builder.field('subTitle');
|
||||||
|
builder.field('notes');
|
||||||
|
builder.field('login_username');
|
||||||
|
builder.field('login_uri');
|
||||||
|
|
||||||
|
const ciphers = await this.cipherService.getAllDecrypted();
|
||||||
|
ciphers.forEach((c) => {
|
||||||
|
builder.add(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.index = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
async searchCiphers(query: string): Promise<CipherView[]> {
|
||||||
|
const results: CipherView[] = [];
|
||||||
|
if (this.index == null) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ciphers = await this.cipherService.getAllDecrypted();
|
||||||
|
const ciphersMap = new Map<string, CipherView>();
|
||||||
|
ciphers.forEach((c) => {
|
||||||
|
ciphersMap.set(c.id, c);
|
||||||
|
});
|
||||||
|
|
||||||
|
query = this.transformQuery(query);
|
||||||
|
const searchResults = this.index.search(query);
|
||||||
|
searchResults.forEach((r) => {
|
||||||
|
if (ciphersMap.has(r.ref)) {
|
||||||
|
results.push(ciphersMap.get(r.ref));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private transformQuery(query: string) {
|
||||||
|
if (query.indexOf('>') === 0) {
|
||||||
|
return query.substr(1).trimLeft();
|
||||||
|
}
|
||||||
|
return '*' + query + '*';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user