From 0e218922b1af9a4aae7ada06055ad5e4ca1679db Mon Sep 17 00:00:00 2001
From: Praveen Adusumilli <47391951+adusumillipraveen@users.noreply.github.com>
Date: Thu, 4 Jun 2020 14:47:56 +0100
Subject: [PATCH] fix: Add validations for aliases (#6426)

---
 .../__snapshots__/validation.spec.ts.snap     | 20 ++++++++
 lib/config/validation.spec.ts                 | 46 +++++++++++++++++++
 lib/config/validation.ts                      | 42 ++++++++++++-----
 3 files changed, 97 insertions(+), 11 deletions(-)

diff --git a/lib/config/__snapshots__/validation.spec.ts.snap b/lib/config/__snapshots__/validation.spec.ts.snap
index fc5d501d84..782e160bdc 100644
--- a/lib/config/__snapshots__/validation.spec.ts.snap
+++ b/lib/config/__snapshots__/validation.spec.ts.snap
@@ -88,6 +88,24 @@ Array [
 ]
 `;
 
+exports[`config/validation validateConfig(config) errors if aliases depth is more than 1 1`] = `
+Array [
+  Object {
+    "depName": "Configuration Error",
+    "message": "Invalid alias object configuration",
+  },
+]
+`;
+
+exports[`config/validation validateConfig(config) errors if aliases have invalid url 1`] = `
+Array [
+  Object {
+    "depName": "Configuration Error",
+    "message": "Invalid alias object configuration",
+  },
+]
+`;
+
 exports[`config/validation validateConfig(config) errors if regexManager fields are missing 1`] = `
 Array [
   Object {
@@ -150,3 +168,5 @@ Array [
   },
 ]
 `;
+
+exports[`config/validation validateConfig(config) validates valid alias objects 1`] = `Array []`;
diff --git a/lib/config/validation.spec.ts b/lib/config/validation.spec.ts
index 5c0c219b9e..73a9088b2e 100644
--- a/lib/config/validation.spec.ts
+++ b/lib/config/validation.spec.ts
@@ -336,5 +336,51 @@ describe('config/validation', () => {
       expect(warnings).toHaveLength(0);
       expect(errors).toHaveLength(0);
     });
+
+    it('validates valid alias objects', async () => {
+      const config = {
+        aliases: {
+          example1: 'http://www.example.com',
+          example2: 'https://www.example2.com/example',
+        },
+      };
+      const { warnings, errors } = await configValidation.validateConfig(
+        config
+      );
+      expect(warnings).toHaveLength(0);
+      expect(errors).toHaveLength(0);
+      expect(errors).toMatchSnapshot();
+    });
+
+    it('errors if aliases depth is more than 1', async () => {
+      const config = {
+        aliases: {
+          sample: {
+            example1: 'http://www.example.com',
+          },
+        },
+      };
+      const { warnings, errors } = await configValidation.validateConfig(
+        config
+      );
+      expect(warnings).toHaveLength(0);
+      expect(errors).toHaveLength(1);
+      expect(errors).toMatchSnapshot();
+    });
+
+    it('errors if aliases have invalid url', async () => {
+      const config = {
+        aliases: {
+          example1: 'noturl',
+          example2: 'http://www.example.com',
+        },
+      };
+      const { warnings, errors } = await configValidation.validateConfig(
+        config
+      );
+      expect(warnings).toHaveLength(0);
+      expect(errors).toHaveLength(1);
+      expect(errors).toMatchSnapshot();
+    });
   });
 });
diff --git a/lib/config/validation.ts b/lib/config/validation.ts
index 773f908ccd..db3eb7baec 100644
--- a/lib/config/validation.ts
+++ b/lib/config/validation.ts
@@ -56,6 +56,17 @@ export async function validateConfig(
     return ignoredNodes.includes(key);
   }
 
+  function validateAliasObject(key: string, val: object): boolean {
+    if (key === 'aliases') {
+      for (const value of Object.values(val)) {
+        if (!is.urlString(value)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
   for (const [key, val] of Object.entries(config)) {
     const currentPath = parentPath ? `${parentPath}.${key}` : key;
     if (
@@ -346,17 +357,26 @@ export async function validateConfig(
           }
         } else if (type === 'object' && currentPath !== 'compatibility') {
           if (is.object(val)) {
-            const ignoredObjects = options
-              .filter((option) => option.freeChoice)
-              .map((option) => option.name);
-            if (!ignoredObjects.includes(key)) {
-              const subValidation = await module.exports.validateConfig(
-                val,
-                isPreset,
-                currentPath
-              );
-              warnings = warnings.concat(subValidation.warnings);
-              errors = errors.concat(subValidation.errors);
+            if (key === 'aliases') {
+              if (!validateAliasObject(key, val)) {
+                errors.push({
+                  depName: 'Configuration Error',
+                  message: `Invalid alias object configuration`,
+                });
+              }
+            } else {
+              const ignoredObjects = options
+                .filter((option) => option.freeChoice)
+                .map((option) => option.name);
+              if (!ignoredObjects.includes(key)) {
+                const subValidation = await module.exports.validateConfig(
+                  val,
+                  isPreset,
+                  currentPath
+                );
+                warnings = warnings.concat(subValidation.warnings);
+                errors = errors.concat(subValidation.errors);
+              }
             }
           } else {
             errors.push({
-- 
GitLab