From ad4c81ed844f42e45467cd4467d993d30b1f8ce0 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Fri, 2 Mar 2018 12:03:03 -0500 Subject: [PATCH] support for uri matching types to cipher service --- src/abstractions/cipher.service.ts | 4 +- src/abstractions/utils.service.ts | 1 + src/enums/uriMatchType.ts | 2 +- src/services/cipher.service.ts | 64 ++++++++++++++++++++++++------ src/services/search.service.ts | 2 +- src/services/utils.service.ts | 17 +++++++- 6 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/abstractions/cipher.service.ts b/src/abstractions/cipher.service.ts index ca00f5e609..2e344dffd8 100644 --- a/src/abstractions/cipher.service.ts +++ b/src/abstractions/cipher.service.ts @@ -20,8 +20,8 @@ export abstract class CipherService { getAll: () => Promise; getAllDecrypted: () => Promise; getAllDecryptedForGrouping: (groupingId: string, folder?: boolean) => Promise; - getAllDecryptedForDomain: (domain: string, includeOtherTypes?: CipherType[]) => Promise; - getLastUsedForDomain: (domain: string) => Promise; + getAllDecryptedForUrl: (url: string, includeOtherTypes?: CipherType[]) => Promise; + getLastUsedForUrl: (url: string) => Promise; updateLastUsedDate: (id: string) => Promise; saveNeverDomain: (domain: string) => Promise; saveWithServer: (cipher: Cipher) => Promise; diff --git a/src/abstractions/utils.service.ts b/src/abstractions/utils.service.ts index 5ef1cce54d..9dd87774b9 100644 --- a/src/abstractions/utils.service.ts +++ b/src/abstractions/utils.service.ts @@ -1,4 +1,5 @@ export abstract class UtilsService { copyToClipboard: (text: string, doc?: Document) => void; getHostname: (uriString: string) => string; + getHost: (uriString: string) => string; } diff --git a/src/enums/uriMatchType.ts b/src/enums/uriMatchType.ts index ed6b6ab54f..f42200ac95 100644 --- a/src/enums/uriMatchType.ts +++ b/src/enums/uriMatchType.ts @@ -1,6 +1,6 @@ export enum UriMatchType { BaseDomain = 0, - FullHostname = 1, + Host = 1, StartsWith = 2, Exact = 3, RegularExpression = 4, diff --git a/src/services/cipher.service.ts b/src/services/cipher.service.ts index 2c29ea9ab0..664c394c3a 100644 --- a/src/services/cipher.service.ts +++ b/src/services/cipher.service.ts @@ -1,4 +1,5 @@ import { CipherType } from '../enums/cipherType'; +import { UriMatchType } from '../enums/uriMatchType'; import { CipherData } from '../models/data/cipherData'; @@ -31,9 +32,11 @@ import { ApiService } from '../abstractions/api.service'; import { CipherService as CipherServiceAbstraction } from '../abstractions/cipher.service'; import { CryptoService } from '../abstractions/crypto.service'; import { I18nService } from '../abstractions/i18n.service'; +import { PlatformUtilsService } from '../abstractions/platformUtils.service'; import { SettingsService } from '../abstractions/settings.service'; import { StorageService } from '../abstractions/storage.service'; import { UserService } from '../abstractions/user.service'; +import { UtilsService } from '../abstractions/utils.service'; const Keys = { ciphersPrefix: 'ciphers_', @@ -46,7 +49,8 @@ export class CipherService implements CipherServiceAbstraction { constructor(private cryptoService: CryptoService, private userService: UserService, private settingsService: SettingsService, private apiService: ApiService, - private storageService: StorageService, private i18nService: I18nService) { + private storageService: StorageService, private i18nService: I18nService, + private platformUtilsService: PlatformUtilsService, private utilsService: UtilsService) { } clearCache(): void { @@ -170,11 +174,12 @@ export class CipherService implements CipherServiceAbstraction { }); } - async getAllDecryptedForDomain(domain: string, includeOtherTypes?: CipherType[]): Promise { - if (domain == null && !includeOtherTypes) { + async getAllDecryptedForUrl(url: string, includeOtherTypes?: CipherType[]): Promise { + if (url == null && !includeOtherTypes) { return Promise.resolve([]); } + const domain = this.platformUtilsService.getDomain(url); const eqDomainsPromise = domain == null ? Promise.resolve([]) : this.settingsService.getEquivalentDomains().then((eqDomains: any[][]) => { let matches: any[] = []; @@ -196,20 +201,55 @@ export class CipherService implements CipherServiceAbstraction { const ciphers = result[1]; return ciphers.filter((cipher) => { - // TODO: uris - //if (domain && cipher.type === CipherType.Login && cipher.login.domain && - // matchingDomains.indexOf(cipher.login.domain) > -1) { - // return true; - //} else if (includeOtherTypes && includeOtherTypes.indexOf(cipher.type) > -1) { - // return true; - //} + if (includeOtherTypes && includeOtherTypes.indexOf(cipher.type) > -1) { + return true; + } + + if (url != null && cipher.type === CipherType.Login && cipher.login.uris != null) { + for (let i = 0; i < cipher.login.uris.length; i++) { + const u = cipher.login.uris[i]; + if (u.uri == null) { + continue; + } + + switch (u.match) { + case null: + case undefined: + case UriMatchType.BaseDomain: + if (domain != null && u.domain != null && matchingDomains.indexOf(u.domain) > -1) { + return true; + } + case UriMatchType.Host: + const urlHost = this.utilsService.getHost(url); + if (urlHost != null && urlHost === this.utilsService.getHost(u.uri)) { + return true; + } + case UriMatchType.Exact: + if (url === u.uri) { + return true; + } + case UriMatchType.StartsWith: + if (url.startsWith(u.uri)) { + return true; + } + case UriMatchType.RegularExpression: + const regex = new RegExp(u.uri, 'i'); + if (regex.test(url)) { + return true; + } + case UriMatchType.Never: + default: + break; + } + } + } return false; }); } - async getLastUsedForDomain(domain: string): Promise { - const ciphers = await this.getAllDecryptedForDomain(domain); + async getLastUsedForUrl(url: string): Promise { + const ciphers = await this.getAllDecryptedForUrl(url); if (ciphers.length === 0) { return null; } diff --git a/src/services/search.service.ts b/src/services/search.service.ts index 3efe4a2ac4..1307d0db74 100644 --- a/src/services/search.service.ts +++ b/src/services/search.service.ts @@ -53,7 +53,7 @@ export class SearchService implements SearchServiceAbstraction { private transformQuery(query: string) { if (query.indexOf('>') === 0) { - return query.substr(1).trimLeft(); + return query.substr(1); } return '*' + query + '*'; } diff --git a/src/services/utils.service.ts b/src/services/utils.service.ts index 7f692ae191..d8312f6ab4 100644 --- a/src/services/utils.service.ts +++ b/src/services/utils.service.ts @@ -132,6 +132,16 @@ export class UtilsService implements UtilsServiceAbstraction { } static getHostname(uriString: string): string { + const url = UtilsService.getUrl(uriString); + return url != null ? url.hostname : null; + } + + static getHost(uriString: string): string { + const url = UtilsService.getUrl(uriString); + return url != null ? url.host : null; + } + + private static getUrl(uriString: string): URL { if (uriString == null) { return null; } @@ -143,8 +153,7 @@ export class UtilsService implements UtilsServiceAbstraction { if (uriString.startsWith('http://') || uriString.startsWith('https://')) { try { - const url = new URL(uriString); - return url.hostname; + return new URL(uriString); } catch (e) { } } @@ -155,6 +164,10 @@ export class UtilsService implements UtilsServiceAbstraction { return UtilsService.getHostname(uriString); } + getHost(uriString: string): string { + return UtilsService.getHost(uriString); + } + copyToClipboard(text: string, doc?: Document) { UtilsService.copyToClipboard(text, doc); }