mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
search service with lunr implementation
This commit is contained in:
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 {
|
||||
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';
|
||||
|
||||
const PwnedPasswordsApi = 'https://api.pwnedpasswords.com/range/';
|
||||
|
||||
export class AuditService {
|
||||
export class AuditService implements AuditServiceAbstraction {
|
||||
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 + '*';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user