diff --git a/package-lock.json b/package-lock.json index 49ae4dd155c..d3102861662 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4595,9 +4595,9 @@ } }, "lunr": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.1.tgz", - "integrity": "sha1-ETYWorYC3cEJMqe/ik5uV+v+zfI=" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.3.tgz", + "integrity": "sha512-rlAEsgU9Bnavca2w1WJ6+6cdeHMXNyadcersyk3ZpuhgWb5HBNj8l4WwJz9PjksAhYDlpQffCVXPctOn+wCIVA==" }, "make-dir": { "version": "1.3.0", diff --git a/package.json b/package.json index 97b1a7f307b..7a35e61349d 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "form-data": "2.3.2", "keytar": "4.2.1", "lowdb": "1.0.0", - "lunr": "2.3.1", + "lunr": "2.3.3", "node-fetch": "2.1.2", "node-forge": "0.7.1", "papaparse": "4.3.5", diff --git a/src/services/search.service.ts b/src/services/search.service.ts index 59bcbe3f23a..606375ce58e 100644 --- a/src/services/search.service.ts +++ b/src/services/search.service.ts @@ -8,8 +8,7 @@ import { SearchService as SearchServiceAbstraction } from '../abstractions/searc import { DeviceType } from '../enums/deviceType'; import { FieldType } from '../enums/fieldType'; - -const IgnoredTlds = ['com', 'net', 'org', 'io', 'co', 'uk', 'au', 'nz', 'fr', 'de', 'eu', 'me', 'jp', 'cn']; +import { UriMatchType } from '../enums/uriMatchType'; export class SearchService implements SearchServiceAbstraction { private indexing = false; @@ -47,36 +46,7 @@ export class SearchService implements SearchServiceAbstraction { (builder as any).field('login.username', { extractor: (c: CipherView) => c.login != null ? c.login.username : null, }); - (builder as any).field('login.uris', { - boost: 2, - extractor: (c: CipherView) => c.login == null || !c.login.hasUris ? null : - c.login.uris.filter((u) => u.hostname != null).map((u) => u.hostname), - }); - (builder as any).field('login.uris_split', { - boost: 2, - extractor: (c: CipherView) => { - if (c.login == null || !c.login.hasUris) { - return null; - } - let uriParts: string[] = []; - c.login.uris.forEach((u) => { - if (u.hostname == null) { - return; - } - const parts = u.hostname.split('.'); - if (parts.length > 0 && parts.length <= 2) { - uriParts.push(parts[0]); - } else if (parts.length > 2) { - uriParts = uriParts.concat(parts.slice(0, parts.length - 2)); - const lastBit = parts[parts.length - 2]; - if (IgnoredTlds.indexOf(lastBit) === -1) { - uriParts.push(lastBit); - } - } - }); - return uriParts.length === 0 ? null : uriParts; - }, - }); + (builder as any).field('login.uris', { boost: 2, extractor: (c: CipherView) => this.uriExtractor(c) }); (builder as any).field('fields', { extractor: (c: CipherView) => this.fieldExtractor(c, false) }); (builder as any).field('fields_joined', { extractor: (c: CipherView) => this.fieldExtractor(c, true) }); (builder as any).field('attachments', { extractor: (c: CipherView) => this.attachmentExtractor(c, false) }); @@ -128,12 +98,11 @@ export class SearchService implements SearchServiceAbstraction { } catch { } } else { // tslint:disable-next-line - const soWild = lunr.Query.wildcard.TRAILING; + const soWild = lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING; searchResults = index.query((q) => { q.term(query, { fields: ['name'], wildcard: soWild }); q.term(query, { fields: ['subTitle'], wildcard: soWild }); q.term(query, { fields: ['login.uris'], wildcard: soWild }); - q.term(query, { fields: ['login.uris_split'], wildcard: soWild }); lunr.tokenizer(query).forEach((token) => { q.term(token.toString(), {}); }); @@ -216,4 +185,33 @@ export class SearchService implements SearchServiceAbstraction { } return joined ? attachments.join(' ') : attachments; } + + private uriExtractor(c: CipherView) { + if (c.login == null || !c.login.hasUris) { + return null; + } + const uris: string[] = []; + c.login.uris.forEach((u) => { + if (u.uri == null || u.uri === '') { + return; + } + if (u.hostname != null) { + uris.push(u.hostname); + return; + } + let uri = u.uri; + if (u.match !== UriMatchType.RegularExpression) { + const protocolIndex = uri.indexOf('://'); + if (protocolIndex > -1) { + uri = uri.substr(protocolIndex + 3); + } + const queryIndex = uri.search(/\?|&|#/); + if (queryIndex > -1) { + uri = uri.substring(0, queryIndex); + } + } + uris.push(uri); + }); + return uris.length > 0 ? uris : null; + } }