Skip to content

Commit

Permalink
refactor(util/host-rules): Strict null checks for host rules (#12868)
Browse files Browse the repository at this point in the history
Co-authored-by: Rhys Arkins <rhys@arkins.net>
  • Loading branch information
zharinov and rarkins committed Nov 28, 2021
1 parent 04d1612 commit f4dbff9
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 26 deletions.
72 changes: 47 additions & 25 deletions lib/util/host-rules.ts
@@ -1,3 +1,4 @@
import is from '@sindresorhus/is';
import merge from 'deepmerge';
import { logger } from '../logger';
import { HostRule } from '../types';
Expand All @@ -7,27 +8,41 @@ import { parseUrl, validateUrl } from './url';

let hostRules: HostRule[] = [];

const legacyHostFields = ['hostName', 'domainName', 'baseUrl'];
interface LegacyHostRule {
hostName?: string;
domainName?: string;
baseUrl?: string;
}

export function add(params: HostRule): void {
const rule = clone(params);
const matchedFields = legacyHostFields.filter((field) => rule[field]);
if (matchedFields.length) {
if (rule.matchHost || matchedFields.length > 1) {
throw new Error(
`hostRules cannot contain more than one host-matching field - use "matchHost" only.`
);
}
const field = matchedFields[0];
logger.warn({ field }, 'Legacy hostRules field needs migrating');
rule.matchHost = rule[field];
delete rule[field];
function migrateRule(rule: LegacyHostRule & HostRule): HostRule {
const cloned: LegacyHostRule & HostRule = clone(rule);
delete cloned.hostName;
delete cloned.domainName;
delete cloned.baseUrl;
const result: HostRule = cloned;

const { matchHost } = result;
const { hostName, domainName, baseUrl } = rule;
const hostValues = [matchHost, hostName, domainName, baseUrl].filter(Boolean);
if (hostValues.length === 1) {
const [matchHost] = hostValues;
result.matchHost = matchHost;
} else if (hostValues.length > 1) {
throw new Error(
`hostRules cannot contain more than one host-matching field - use "matchHost" only.`
);
}

const confidentialFields = ['password', 'token'];
return result;
}

export function add(params: HostRule): void {
const rule = migrateRule(params);

const confidentialFields: (keyof HostRule)[] = ['password', 'token'];
if (rule.matchHost) {
const parsedUrl = parseUrl(rule.matchHost);
rule.resolvedHost = parsedUrl?.hostname || rule.matchHost;
rule.resolvedHost = parsedUrl?.hostname ?? rule.matchHost;
confidentialFields.forEach((field) => {
if (rule[field]) {
logger.debug(
Expand All @@ -38,7 +53,7 @@ export function add(params: HostRule): void {
}
confidentialFields.forEach((field) => {
const secret = rule[field];
if (secret && secret.length > 3) {
if (is.string(secret) && secret.length > 3) {
sanitize.add(secret);
}
});
Expand All @@ -61,26 +76,30 @@ function isEmptyRule(rule: HostRule): boolean {
}

function isHostTypeRule(rule: HostRule): boolean {
return rule.hostType && !rule.resolvedHost;
return !!rule.hostType && !rule.resolvedHost;
}

function isHostOnlyRule(rule: HostRule): boolean {
return !rule.hostType && !!rule.matchHost;
}

function isMultiRule(rule: HostRule): boolean {
return rule.hostType && !!rule.resolvedHost;
return !!rule.hostType && !!rule.resolvedHost;
}

function matchesHostType(rule: HostRule, search: HostRuleSearch): boolean {
return rule.hostType === search.hostType;
}

function matchesHost(rule: HostRule, search: HostRuleSearch): boolean {
if (validateUrl(rule.matchHost)) {
// istanbul ignore if
if (!rule.matchHost) {
return false;
}
if (search.url && validateUrl(rule.matchHost)) {
return search.url.startsWith(rule.matchHost);
}
const parsedUrl = parseUrl(search.url);
const parsedUrl = search.url ? parseUrl(search.url) : null;
if (!parsedUrl?.hostname) {
return false;
}
Expand Down Expand Up @@ -132,10 +151,13 @@ export function find(search: HostRuleSearch): HostRule {
}

export function hosts({ hostType }: { hostType: string }): string[] {
return hostRules
.filter((rule) => rule.hostType === hostType)
.map((rule) => rule.resolvedHost)
.filter(Boolean);
const result: string[] = [];
for (const rule of hostRules) {
if (rule.hostType === hostType && rule.resolvedHost) {
result.push(rule.resolvedHost);
}
}
return result;
}

export function findAll({ hostType }: { hostType: string }): HostRule[] {
Expand Down
2 changes: 1 addition & 1 deletion lib/util/url.ts
Expand Up @@ -77,5 +77,5 @@ export function parseUrl(url: string): URL | null {
* @returns an URL object or null
*/
export function createURLFromHostOrURL(url: string): URL | null {
return parseUrl(url) || parseUrl(`https://${url}`);
return parseUrl(url) ?? parseUrl(`https://${url}`);
}
2 changes: 2 additions & 0 deletions tsconfig.strict.json
Expand Up @@ -120,6 +120,7 @@
"./lib/util/exec/types.ts",
"./lib/util/git/config.ts",
"./lib/util/git/types.ts",
"./lib/util/host-rules.ts",
"./lib/util/html.ts",
"./lib/util/http/hooks.ts",
"./lib/util/http/types.ts",
Expand All @@ -132,6 +133,7 @@
"./lib/util/regex.ts",
"./lib/util/sanitize.ts",
"./lib/util/split.ts",
"./lib/util/url.ts",
"./lib/workers/pr/changelog/hbs-template.ts",
"./lib/workers/pr/changelog/types.ts",
"./lib/workers/repository/init/types.ts",
Expand Down

0 comments on commit f4dbff9

Please sign in to comment.