From 62c303ed1011ce379a55ead77213d3498e393242 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 12:32:28 -0400
Subject: [PATCH 1/9] Fixing management API type

---
 src/context/directory/index.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/context/directory/index.ts b/src/context/directory/index.ts
index 5fe366455..51cd700f7 100644
--- a/src/context/directory/index.ts
+++ b/src/context/directory/index.ts
@@ -9,7 +9,6 @@ import {
 } from '../../utils';
 import { Assets, Auth0APIClient, Config } from '../../types'
 
-type ManagementAPIClient = unknown// TODO: replace with a more canonical representation of the ManagementAPIClient type 
 type KeywordMappings = { [key: string]: (string | number)[] | string | number }
 
 export default class DirectoryContext {
@@ -17,7 +16,7 @@ export default class DirectoryContext {
   filePath: string;
   config: Config;
   mappings: KeywordMappings;
-  mgmtClient: ManagementAPIClient;
+  mgmtClient: Auth0APIClient;
   assets: Assets
 
   constructor(config: Config, mgmtClient: Auth0APIClient) {

From 7d6d7b49561fa4b6c240e2aff847442574e4acf3 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 13:47:54 -0400
Subject: [PATCH 2/9] Initial implementation of resource exclusion

---
 src/context/yaml/index.ts |  9 ++++++---
 src/tools/auth0/index.ts  | 11 +++++++----
 src/types.ts              | 10 ++++++----
 3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/context/yaml/index.ts b/src/context/yaml/index.ts
index fcc7d8391..f5596ec74 100644
--- a/src/context/yaml/index.ts
+++ b/src/context/yaml/index.ts
@@ -7,9 +7,9 @@ import log from '../../logger';
 import {
   isFile, toConfigFn, stripIdentifiers, formatResults, recordsSorter
 } from '../../utils';
-import handlers from './handlers';
+import handlers, { YAMLHandler } from './handlers';
 import cleanAssets from '../../readonly';
-import { Assets, Config, Auth0APIClient } from '../../types'
+import { Assets, Config, Auth0APIClient, AssetTypes } from '../../types'
 
 type KeywordMappings = { [key: string]: (string | number)[] | string | number }
 
@@ -101,7 +101,10 @@ export default class YAMLContext {
       throw new Error(`Problem loading tenant data from Auth0 ${err}${extraMessage}`);
     }
 
-    await Promise.all(Object.entries(handlers).map(async ([name, handler]) => {
+    await Promise.all(Object.entries(handlers).filter(([handlerName]: [AssetTypes, YAMLHandler<any>]) => {
+      const excludedAssetTypes = this.config.AUTH0_EXCLUDED
+      return !excludedAssetTypes.includes(handlerName)
+    }).map(async ([name, handler]) => {
       try {
         const data = await handler.dump(this);
         if (data) {
diff --git a/src/tools/auth0/index.ts b/src/tools/auth0/index.ts
index 3d698634b..6dffb4cf2 100644
--- a/src/tools/auth0/index.ts
+++ b/src/tools/auth0/index.ts
@@ -39,11 +39,14 @@ export default class Auth0 {
     this.config = config;
     this.assets = assets;
 
-    this.handlers = Object.values(handlers).map((h) => {
+    this.handlers = Object.values(handlers).map((handler) => {
       //@ts-ignore because prompts don't appear to have been universally implemented yet
-      const handler = new h.default({ client: this.client, config: this.config });
-      return handler
-    });
+      const newHandler = new handler.default({ client: this.client, config: this.config });
+      return newHandler
+    }).filter((handler) => {
+      const excludedAssetTypes = config('AUTH0_EXCLUDED')
+      return !excludedAssetTypes.includes(handler.type)
+    })
   }
 
   async runStage(stage: Stage): Promise<void> {
diff --git a/src/types.ts b/src/types.ts
index 7660ebb4b..b7040e146 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -14,22 +14,24 @@ export type Config = {
     AUTH0_CLIENT_SECRET: string
     AUTH0_INPUT_FILE: string
     AUTH0_ALLOW_DELETE: boolean
+    AUTH0_EXCLUDED: AssetTypes[]
     EXTENSION_SECRET: string
     AUTH0_ACCESS_TOKEN?: string
     AUTH0_BASE_PATH?: string
     AUTH0_AUDIENCE?: string
     AUTH0_API_MAX_RETRIES?: number
     AUTH0_KEYWORD_REPLACE_MAPPINGS?: { [key: string]: string[] | string }
+    AUTH0_EXPORT_IDENTIFIERS?: boolean
+    AUTH0_CONNECTIONS_DIRECTORY?: string
+    EXCLUDED_PROPS?: {}
+    INCLUDED_PROPS?: {}
+    // Eventually deprecate:
     AUTH0_EXCLUDED_RULES?: string[]
     AUTH0_EXCLUDED_CLIENTS?: string[]
     AUTH0_EXCLUDED_DATABASES?: string[]
     AUTH0_EXCLUDED_CONNECTIONS?: string[]
     AUTH0_EXCLUDED_RESOURCE_SERVERS?: string[]
     AUTH0_EXCLUDED_DEFAULTS?: string[]
-    AUTH0_EXPORT_IDENTIFIERS?: boolean
-    AUTH0_CONNECTIONS_DIRECTORY?: string
-    EXCLUDED_PROPS?: {}
-    INCLUDED_PROPS?: {}
 }// TODO: replace with a more accurate representation of the Config type 
 
 export type Asset = { [key: string]: any }

From 05162d191201acb6b17e29ab03de36f15adcd2bc Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 14:08:41 -0400
Subject: [PATCH 3/9] Adding protection against undefined AUTH0_EXCLUDED value,
 updating tests to pass

---
 src/context/yaml/index.ts           |   2 +-
 src/tools/auth0/index.ts            |   2 +-
 test/tools/auth0/validator.tests.js | 240 ++++++++++++++--------------
 test/utils.test.js                  |  28 ++--
 4 files changed, 138 insertions(+), 134 deletions(-)

diff --git a/src/context/yaml/index.ts b/src/context/yaml/index.ts
index f5596ec74..4bcabe289 100644
--- a/src/context/yaml/index.ts
+++ b/src/context/yaml/index.ts
@@ -102,7 +102,7 @@ export default class YAMLContext {
     }
 
     await Promise.all(Object.entries(handlers).filter(([handlerName]: [AssetTypes, YAMLHandler<any>]) => {
-      const excludedAssetTypes = this.config.AUTH0_EXCLUDED
+      const excludedAssetTypes = this.config.AUTH0_EXCLUDED || []
       return !excludedAssetTypes.includes(handlerName)
     }).map(async ([name, handler]) => {
       try {
diff --git a/src/tools/auth0/index.ts b/src/tools/auth0/index.ts
index 6dffb4cf2..9665bd384 100644
--- a/src/tools/auth0/index.ts
+++ b/src/tools/auth0/index.ts
@@ -44,7 +44,7 @@ export default class Auth0 {
       const newHandler = new handler.default({ client: this.client, config: this.config });
       return newHandler
     }).filter((handler) => {
-      const excludedAssetTypes = config('AUTH0_EXCLUDED')
+      const excludedAssetTypes = config('AUTH0_EXCLUDED') || []
       return !excludedAssetTypes.includes(handler.type)
     })
   }
diff --git a/test/tools/auth0/validator.tests.js b/test/tools/auth0/validator.tests.js
index dd43ff9a6..08385dbcb 100644
--- a/test/tools/auth0/validator.tests.js
+++ b/test/tools/auth0/validator.tests.js
@@ -2,6 +2,8 @@ import { expect } from 'chai';
 import Auth0 from '../../../src/tools/auth0';
 import constants from '../../../src/tools/constants';
 
+const mockConfigFn = () => { }
+
 describe('#schema validation tests', () => {
   const client = {
     rules: {
@@ -33,13 +35,13 @@ describe('#schema validation tests', () => {
   };
 
   const checkPassed = (data, done) => {
-    const auth0 = new Auth0(client, data, {});
+    const auth0 = new Auth0(client, data, mockConfigFn);
 
     auth0.validate().then(passedCb(done), failedCb(done));
   };
 
   const checkRequired = (field, data, done) => {
-    const auth0 = new Auth0({}, data, {});
+    const auth0 = new Auth0({}, data, mockConfigFn);
 
     auth0
       .validate()
@@ -50,7 +52,7 @@ describe('#schema validation tests', () => {
   };
 
   const checkEnum = (data, done) => {
-    const auth0 = new Auth0({}, data, {});
+    const auth0 = new Auth0({}, data, mockConfigFn);
 
     auth0
       .validate()
@@ -61,7 +63,7 @@ describe('#schema validation tests', () => {
   };
 
   const checkTypeError = (field, expectedType, data, done) => {
-    const auth0 = new Auth0({}, data, {});
+    const auth0 = new Auth0({}, data, mockConfigFn);
 
     auth0
       .validate()
@@ -73,11 +75,11 @@ describe('#schema validation tests', () => {
 
   describe('#branding validate', () => {
     it('should fail validation if branding is not an object', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { branding: data }, {});
+      const auth0 = new Auth0({}, { branding: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be object'));
     });
@@ -93,49 +95,49 @@ describe('#schema validation tests', () => {
 
   describe('#clientGrants validate', () => {
     it('should fail validation if no "client_id" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkRequired('client_id', { clientGrants: data }, done);
     });
 
     it('should fail validation if no "scope" provided', (done) => {
-      const data = [ {
+      const data = [{
         client_id: 'client_id',
         audience: 'audience'
-      } ];
+      }];
 
       checkRequired('scope', { clientGrants: data }, done);
     });
 
     it('should fail validation if no "audience" provided', (done) => {
-      const data = [ {
+      const data = [{
         client_id: 'client_id',
-        scope: [ 'scope' ]
-      } ];
+        scope: ['scope']
+      }];
 
       checkRequired('audience', { clientGrants: data }, done);
     });
 
     it('should fail validation if bad "scope" provided', (done) => {
-      const data = [ {
+      const data = [{
         client_id: 'client_id',
         scope: 'scope',
         audience: 'audience'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { clientGrants: data }, {});
+      const auth0 = new Auth0({}, { clientGrants: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be array'));
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         client_id: 'client_id',
-        scope: [ 'scope' ],
+        scope: ['scope'],
         audience: 'audience'
-      } ];
+      }];
 
       checkPassed({ clientGrants: data }, done);
     });
@@ -143,19 +145,19 @@ describe('#schema validation tests', () => {
 
   describe('#clients validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         id: 'id'
-      } ];
+      }];
 
       checkRequired('name', { clients: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: ''
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { clients: data }, {});
+      const auth0 = new Auth0({}, { clients: data }, mockConfigFn);
 
       auth0
         .validate()
@@ -166,9 +168,9 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkPassed({ clients: data }, done);
     });
@@ -176,26 +178,26 @@ describe('#schema validation tests', () => {
 
   describe('#connections validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         id: 'id'
-      } ];
+      }];
 
       checkRequired('name', { connections: data }, done);
     });
 
     it('should fail validation if no "strategy" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkRequired('strategy', { connections: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         strategy: 'strategy'
-      } ];
+      }];
 
       checkPassed({ connections: data }, done);
     });
@@ -203,27 +205,27 @@ describe('#schema validation tests', () => {
 
   describe('#databases validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         id: 'id'
-      } ];
+      }];
 
       checkRequired('name', { databases: data }, done);
     });
 
     it('should fail validation if bad "strategy" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         strategy: 'strategy'
-      } ];
+      }];
 
       checkEnum({ databases: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         options: {}
-      } ];
+      }];
 
       checkPassed({ databases: data }, done);
     });
@@ -231,11 +233,11 @@ describe('#schema validation tests', () => {
 
   describe('#emailProvider validate', () => {
     it('should fail validation if emailProvider is not an object', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { emailProvider: data }, {});
+      const auth0 = new Auth0({}, { emailProvider: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be object'));
     });
@@ -251,27 +253,27 @@ describe('#schema validation tests', () => {
 
   describe('#emailTemplates validate', () => {
     it('should fail validation if no "template" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('template', { emailTemplates: data }, done);
     });
 
     it('should fail validation if bad "template" provided', (done) => {
-      const data = [ {
+      const data = [{
         template: 'template',
         body: 'body'
-      } ];
+      }];
 
       checkEnum({ emailTemplates: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         template: 'verify_email',
         body: 'body'
-      } ];
+      }];
 
       checkPassed({ emailTemplates: data }, done);
     });
@@ -279,44 +281,44 @@ describe('#schema validation tests', () => {
 
   describe('#guardianFactorProviders validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { guardianFactorProviders: data }, done);
     });
 
     it('should fail validation if no "provider" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'sms'
-      } ];
+      }];
 
       checkRequired('provider', { guardianFactorProviders: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         provider: 'provider'
-      } ];
+      }];
 
       checkEnum({ guardianFactorProviders: data }, done);
     });
 
     it('should fail validation if bad "provider" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'sms',
         provider: 'provider'
-      } ];
+      }];
 
       checkEnum({ guardianFactorProviders: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'sms',
         provider: 'twilio'
-      } ];
+      }];
 
       checkPassed({ guardianFactorProviders: data }, done);
     });
@@ -324,26 +326,26 @@ describe('#schema validation tests', () => {
 
   describe('#guardianFactors validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { guardianFactors: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkEnum({ guardianFactors: data }, done);
     });
 
     constants.GUARDIAN_FACTORS.forEach((factorName) => {
       it(`should pass validation for ${factorName}`, (done) => {
-        const data = [ {
+        const data = [{
           name: factorName
-        } ];
+        }];
         checkPassed({ guardianFactors: data }, done);
       });
     });
@@ -351,25 +353,25 @@ describe('#schema validation tests', () => {
 
   describe('#guardianFactorTemplates validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { guardianFactorTemplates: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkEnum({ guardianFactorTemplates: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'sms'
-      } ];
+      }];
 
       checkPassed({ guardianFactorTemplates: data }, done);
     });
@@ -386,7 +388,7 @@ describe('#schema validation tests', () => {
 
     it('should pass validation', (done) => {
       const data = {
-        policies: [ 'all-applications' ]
+        policies: ['all-applications']
       };
 
       checkPassed({ guardianPolicies: data }, done);
@@ -423,7 +425,7 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = { message_types: [ 'sms', 'voice' ] };
+      const data = { message_types: ['sms', 'voice'] };
 
       checkPassed({ guardianPhoneFactorMessageTypes: data }, done);
     });
@@ -431,17 +433,17 @@ describe('#schema validation tests', () => {
 
   describe('#pages validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { pages: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkEnum({ pages: data }, done);
     });
@@ -486,11 +488,11 @@ describe('#schema validation tests', () => {
 
   describe('#prompts validate', () => {
     it('should fail validation if prompts is not an object', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { prompts: data }, {});
+      const auth0 = new Auth0({}, { prompts: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be object'));
     });
@@ -506,26 +508,26 @@ describe('#schema validation tests', () => {
 
   describe('#resourceServers validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { resourceServers: data }, done);
     });
 
     it('should fail validation if no "identifier" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name'
-      } ];
+      }];
 
       checkRequired('identifier', { resourceServers: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         identifier: 'identifier'
-      } ];
+      }];
 
       checkPassed({ resourceServers: data }, done);
     });
@@ -533,19 +535,19 @@ describe('#schema validation tests', () => {
 
   describe('#rules validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { rules: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: '-rule-'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { rules: data }, {});
+      const auth0 = new Auth0({}, { rules: data }, mockConfigFn);
 
       auth0
         .validate()
@@ -553,20 +555,20 @@ describe('#schema validation tests', () => {
     });
 
     it('should fail validation if bad "stage" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'rule',
         stage: 'stage'
-      } ];
+      }];
 
       checkEnum({ rules: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         order: 1,
         stage: 'login_failure'
-      } ];
+      }];
 
       checkPassed({ rules: data }, done);
     });
@@ -574,28 +576,28 @@ describe('#schema validation tests', () => {
 
   describe('#rulesConfigs validate', () => {
     it('should fail validation if no "key" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('key', { rulesConfigs: data }, done);
     });
 
     it('should fail validation if no "value" provided', (done) => {
-      const data = [ {
+      const data = [{
         key: 'key'
-      } ];
+      }];
 
       checkRequired('value', { rulesConfigs: data }, done);
     });
 
     it('should fail validation if bad "key" provided', (done) => {
-      const data = [ {
+      const data = [{
         key: ':-?',
         value: 'value'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { rulesConfigs: data }, {});
+      const auth0 = new Auth0({}, { rulesConfigs: data }, mockConfigFn);
 
       auth0
         .validate()
@@ -603,10 +605,10 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         key: 'key',
         value: 'value'
-      } ];
+      }];
 
       checkPassed({ rulesConfigs: data }, done);
     });
@@ -614,19 +616,19 @@ describe('#schema validation tests', () => {
 
   describe('#hooks validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
       checkRequired('name', { hooks: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: '-hook-'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { hooks: data }, {});
+      const auth0 = new Auth0({}, { hooks: data }, mockConfigFn);
 
       auth0
         .validate()
@@ -634,29 +636,29 @@ describe('#schema validation tests', () => {
     });
 
     it('should fail validation if no "triggerId" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         script: 'script content'
-      } ];
+      }];
 
       checkRequired('triggerId', { hooks: data }, done);
     });
 
     it('should fail validation if bad "triggerId" provided', (done) => {
-      const data = [ {
+      const data = [{
         name: 'rule',
         triggerId: 'invalid triggerId'
-      } ];
+      }];
 
       checkEnum({ hooks: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [ {
+      const data = [{
         name: 'name',
         script: 'script content',
         triggerId: 'post-change-password'
-      } ];
+      }];
 
       checkPassed({ hooks: data }, done);
     });
@@ -664,11 +666,11 @@ describe('#schema validation tests', () => {
 
   describe('#tenant validate', () => {
     it('should fail validation if tenant is not an object', (done) => {
-      const data = [ {
+      const data = [{
         anything: 'anything'
-      } ];
+      }];
 
-      const auth0 = new Auth0({}, { tenant: data }, {});
+      const auth0 = new Auth0({}, { tenant: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be object'));
     });
@@ -686,7 +688,7 @@ describe('#schema validation tests', () => {
     it('should fail validation if migrations is not an object', (done) => {
       const data = '';
 
-      const auth0 = new Auth0({}, { migrations: data }, {});
+      const auth0 = new Auth0({}, { migrations: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be object'));
     });
@@ -696,7 +698,7 @@ describe('#schema validation tests', () => {
         migration_flag: 'string'
       };
 
-      const auth0 = new Auth0({}, { migrations: data }, {});
+      const auth0 = new Auth0({}, { migrations: data }, mockConfigFn);
 
       auth0.validate().then(failedCb(done), passedCb(done, 'should be boolean'));
     });
diff --git a/test/utils.test.js b/test/utils.test.js
index b68b5011a..1082659cb 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -22,7 +22,9 @@ import {
   toConfigFn
 } from '../src/utils';
 
-describe('#utils', function() {
+const mockConfigFn = () => { }
+
+describe('#utils', function () {
   it('should check if directory exist', () => {
     const dirExist = path.join(testDataDir, 'utils', 'isdir');
     const dirNotExist = path.join(testDataDir, 'utils', 'notexist');
@@ -52,7 +54,7 @@ describe('#utils', function() {
     fs.writeFileSync(path.join(dir, 'test2.html'), 'junk');
     fs.writeFileSync(path.join(dir, 'other.file'), 'junk');
 
-    expect(getFiles(dir, [ '.json', '.html' ])).to.deep.equal([
+    expect(getFiles(dir, ['.json', '.html'])).to.deep.equal([
       path.join(dir, 'test1.html'),
       path.join(dir, 'test1.json'),
       path.join(dir, 'test2.html'),
@@ -91,11 +93,11 @@ describe('#utils', function() {
 
   it('should strip identifiers', () => {
     const assets = {
-      clients: [ { name: 'some client', client_id: 'test' } ],
-      rulesConfigs: [ { key: 'test', value: 'test' } ]
+      clients: [{ name: 'some client', client_id: 'test' }],
+      rulesConfigs: [{ key: 'test', value: 'test' }]
     };
 
-    const auth0 = new Auth0(mockMgmtClient(), {}, {});
+    const auth0 = new Auth0(mockMgmtClient(), {}, mockConfigFn);
 
     expect(stripIdentifiers(auth0, assets)).to.deep.equal({
       clients: [
@@ -132,7 +134,7 @@ describe('#utils', function() {
       name: 'Name',
       a: 'Alpha'
     });
-    expect(Object.keys(result)).to.deep.equal([ 'name', 'identifier', 'id', 'a', 'b', 'c', 'd' ]);
+    expect(Object.keys(result)).to.deep.equal(['name', 'identifier', 'id', 'a', 'b', 'c', 'd']);
     expect(result).to.deep.equal({
       name: 'Name',
       identifier: 'Identifier',
@@ -198,12 +200,12 @@ describe('#utils', function() {
   it('should not touch correct client arrays', () => {
     const client = {
       name: 'Default App',
-      callbacks: [ 'callback' ],
+      callbacks: ['callback'],
       allowed_clients: [],
-      allowed_logout_urls: [ 'url', 'url' ],
+      allowed_logout_urls: ['url', 'url'],
       is_first_party: true,
       oidc_conformant: false,
-      allowed_origins: [ 'origin' ]
+      allowed_origins: ['origin']
     };
 
     expect(clearClientArrays(client)).to.deep.equal(client);
@@ -264,16 +266,16 @@ describe('#utils', function() {
 
     it('should return sorted list', () => {
       expect(mapClientID2NameSorted(
-        [ 'client_id_B', 'client_id_A', 'not_found_id' ],
+        ['client_id_B', 'client_id_A', 'not_found_id'],
         knownClients
-      )).deep.equal([ 'client_A', 'client_B', 'not_found_id' ]);
+      )).deep.equal(['client_A', 'client_B', 'not_found_id']);
     });
 
     it('should return sorted list even knownClient are invalid', () => {
       expect(mapClientID2NameSorted(
-        [ 'client_id_B', 'client_id_A', 'not_found_id' ],
+        ['client_id_B', 'client_id_A', 'not_found_id'],
         null
-      )).deep.equal([ 'client_id_A', 'client_id_B', 'not_found_id' ]);
+      )).deep.equal(['client_id_A', 'client_id_B', 'not_found_id']);
     });
 
     it('should return empty list upon invalid input', () => {

From 050be2dc7329efea0e72562fcba7d3d62dd0e830 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 14:13:52 -0400
Subject: [PATCH 4/9] Fixing newly failing test cases that don't properly mock
 config function

---
 test/tools/auth0/validator.tests.js | 210 ++++++++++++++--------------
 test/utils.test.js                  |  26 ++--
 2 files changed, 118 insertions(+), 118 deletions(-)

diff --git a/test/tools/auth0/validator.tests.js b/test/tools/auth0/validator.tests.js
index 08385dbcb..364b88f63 100644
--- a/test/tools/auth0/validator.tests.js
+++ b/test/tools/auth0/validator.tests.js
@@ -2,7 +2,7 @@ import { expect } from 'chai';
 import Auth0 from '../../../src/tools/auth0';
 import constants from '../../../src/tools/constants';
 
-const mockConfigFn = () => { }
+const mockConfigFn = () => { };
 
 describe('#schema validation tests', () => {
   const client = {
@@ -75,9 +75,9 @@ describe('#schema validation tests', () => {
 
   describe('#branding validate', () => {
     it('should fail validation if branding is not an object', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { branding: data }, mockConfigFn);
 
@@ -95,37 +95,37 @@ describe('#schema validation tests', () => {
 
   describe('#clientGrants validate', () => {
     it('should fail validation if no "client_id" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkRequired('client_id', { clientGrants: data }, done);
     });
 
     it('should fail validation if no "scope" provided', (done) => {
-      const data = [{
+      const data = [ {
         client_id: 'client_id',
         audience: 'audience'
-      }];
+      } ];
 
       checkRequired('scope', { clientGrants: data }, done);
     });
 
     it('should fail validation if no "audience" provided', (done) => {
-      const data = [{
+      const data = [ {
         client_id: 'client_id',
-        scope: ['scope']
-      }];
+        scope: [ 'scope' ]
+      } ];
 
       checkRequired('audience', { clientGrants: data }, done);
     });
 
     it('should fail validation if bad "scope" provided', (done) => {
-      const data = [{
+      const data = [ {
         client_id: 'client_id',
         scope: 'scope',
         audience: 'audience'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { clientGrants: data }, mockConfigFn);
 
@@ -133,11 +133,11 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         client_id: 'client_id',
-        scope: ['scope'],
+        scope: [ 'scope' ],
         audience: 'audience'
-      }];
+      } ];
 
       checkPassed({ clientGrants: data }, done);
     });
@@ -145,17 +145,17 @@ describe('#schema validation tests', () => {
 
   describe('#clients validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         id: 'id'
-      }];
+      } ];
 
       checkRequired('name', { clients: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: ''
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { clients: data }, mockConfigFn);
 
@@ -168,9 +168,9 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkPassed({ clients: data }, done);
     });
@@ -178,26 +178,26 @@ describe('#schema validation tests', () => {
 
   describe('#connections validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         id: 'id'
-      }];
+      } ];
 
       checkRequired('name', { connections: data }, done);
     });
 
     it('should fail validation if no "strategy" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkRequired('strategy', { connections: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         strategy: 'strategy'
-      }];
+      } ];
 
       checkPassed({ connections: data }, done);
     });
@@ -205,27 +205,27 @@ describe('#schema validation tests', () => {
 
   describe('#databases validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         id: 'id'
-      }];
+      } ];
 
       checkRequired('name', { databases: data }, done);
     });
 
     it('should fail validation if bad "strategy" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         strategy: 'strategy'
-      }];
+      } ];
 
       checkEnum({ databases: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         options: {}
-      }];
+      } ];
 
       checkPassed({ databases: data }, done);
     });
@@ -233,9 +233,9 @@ describe('#schema validation tests', () => {
 
   describe('#emailProvider validate', () => {
     it('should fail validation if emailProvider is not an object', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { emailProvider: data }, mockConfigFn);
 
@@ -253,27 +253,27 @@ describe('#schema validation tests', () => {
 
   describe('#emailTemplates validate', () => {
     it('should fail validation if no "template" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('template', { emailTemplates: data }, done);
     });
 
     it('should fail validation if bad "template" provided', (done) => {
-      const data = [{
+      const data = [ {
         template: 'template',
         body: 'body'
-      }];
+      } ];
 
       checkEnum({ emailTemplates: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         template: 'verify_email',
         body: 'body'
-      }];
+      } ];
 
       checkPassed({ emailTemplates: data }, done);
     });
@@ -281,44 +281,44 @@ describe('#schema validation tests', () => {
 
   describe('#guardianFactorProviders validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { guardianFactorProviders: data }, done);
     });
 
     it('should fail validation if no "provider" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'sms'
-      }];
+      } ];
 
       checkRequired('provider', { guardianFactorProviders: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         provider: 'provider'
-      }];
+      } ];
 
       checkEnum({ guardianFactorProviders: data }, done);
     });
 
     it('should fail validation if bad "provider" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'sms',
         provider: 'provider'
-      }];
+      } ];
 
       checkEnum({ guardianFactorProviders: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'sms',
         provider: 'twilio'
-      }];
+      } ];
 
       checkPassed({ guardianFactorProviders: data }, done);
     });
@@ -326,26 +326,26 @@ describe('#schema validation tests', () => {
 
   describe('#guardianFactors validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { guardianFactors: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkEnum({ guardianFactors: data }, done);
     });
 
     constants.GUARDIAN_FACTORS.forEach((factorName) => {
       it(`should pass validation for ${factorName}`, (done) => {
-        const data = [{
+        const data = [ {
           name: factorName
-        }];
+        } ];
         checkPassed({ guardianFactors: data }, done);
       });
     });
@@ -353,25 +353,25 @@ describe('#schema validation tests', () => {
 
   describe('#guardianFactorTemplates validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { guardianFactorTemplates: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkEnum({ guardianFactorTemplates: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'sms'
-      }];
+      } ];
 
       checkPassed({ guardianFactorTemplates: data }, done);
     });
@@ -388,7 +388,7 @@ describe('#schema validation tests', () => {
 
     it('should pass validation', (done) => {
       const data = {
-        policies: ['all-applications']
+        policies: [ 'all-applications' ]
       };
 
       checkPassed({ guardianPolicies: data }, done);
@@ -425,7 +425,7 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = { message_types: ['sms', 'voice'] };
+      const data = { message_types: [ 'sms', 'voice' ] };
 
       checkPassed({ guardianPhoneFactorMessageTypes: data }, done);
     });
@@ -433,17 +433,17 @@ describe('#schema validation tests', () => {
 
   describe('#pages validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { pages: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkEnum({ pages: data }, done);
     });
@@ -488,9 +488,9 @@ describe('#schema validation tests', () => {
 
   describe('#prompts validate', () => {
     it('should fail validation if prompts is not an object', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { prompts: data }, mockConfigFn);
 
@@ -508,26 +508,26 @@ describe('#schema validation tests', () => {
 
   describe('#resourceServers validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { resourceServers: data }, done);
     });
 
     it('should fail validation if no "identifier" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name'
-      }];
+      } ];
 
       checkRequired('identifier', { resourceServers: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         identifier: 'identifier'
-      }];
+      } ];
 
       checkPassed({ resourceServers: data }, done);
     });
@@ -535,17 +535,17 @@ describe('#schema validation tests', () => {
 
   describe('#rules validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { rules: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: '-rule-'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { rules: data }, mockConfigFn);
 
@@ -555,20 +555,20 @@ describe('#schema validation tests', () => {
     });
 
     it('should fail validation if bad "stage" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'rule',
         stage: 'stage'
-      }];
+      } ];
 
       checkEnum({ rules: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         order: 1,
         stage: 'login_failure'
-      }];
+      } ];
 
       checkPassed({ rules: data }, done);
     });
@@ -576,26 +576,26 @@ describe('#schema validation tests', () => {
 
   describe('#rulesConfigs validate', () => {
     it('should fail validation if no "key" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('key', { rulesConfigs: data }, done);
     });
 
     it('should fail validation if no "value" provided', (done) => {
-      const data = [{
+      const data = [ {
         key: 'key'
-      }];
+      } ];
 
       checkRequired('value', { rulesConfigs: data }, done);
     });
 
     it('should fail validation if bad "key" provided', (done) => {
-      const data = [{
+      const data = [ {
         key: ':-?',
         value: 'value'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { rulesConfigs: data }, mockConfigFn);
 
@@ -605,10 +605,10 @@ describe('#schema validation tests', () => {
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         key: 'key',
         value: 'value'
-      }];
+      } ];
 
       checkPassed({ rulesConfigs: data }, done);
     });
@@ -616,17 +616,17 @@ describe('#schema validation tests', () => {
 
   describe('#hooks validate', () => {
     it('should fail validation if no "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       checkRequired('name', { hooks: data }, done);
     });
 
     it('should fail validation if bad "name" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: '-hook-'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { hooks: data }, mockConfigFn);
 
@@ -636,29 +636,29 @@ describe('#schema validation tests', () => {
     });
 
     it('should fail validation if no "triggerId" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         script: 'script content'
-      }];
+      } ];
 
       checkRequired('triggerId', { hooks: data }, done);
     });
 
     it('should fail validation if bad "triggerId" provided', (done) => {
-      const data = [{
+      const data = [ {
         name: 'rule',
         triggerId: 'invalid triggerId'
-      }];
+      } ];
 
       checkEnum({ hooks: data }, done);
     });
 
     it('should pass validation', (done) => {
-      const data = [{
+      const data = [ {
         name: 'name',
         script: 'script content',
         triggerId: 'post-change-password'
-      }];
+      } ];
 
       checkPassed({ hooks: data }, done);
     });
@@ -666,9 +666,9 @@ describe('#schema validation tests', () => {
 
   describe('#tenant validate', () => {
     it('should fail validation if tenant is not an object', (done) => {
-      const data = [{
+      const data = [ {
         anything: 'anything'
-      }];
+      } ];
 
       const auth0 = new Auth0({}, { tenant: data }, mockConfigFn);
 
diff --git a/test/utils.test.js b/test/utils.test.js
index 1082659cb..40b59e29a 100644
--- a/test/utils.test.js
+++ b/test/utils.test.js
@@ -22,9 +22,9 @@ import {
   toConfigFn
 } from '../src/utils';
 
-const mockConfigFn = () => { }
+const mockConfigFn = () => { };
 
-describe('#utils', function () {
+describe('#utils', function() {
   it('should check if directory exist', () => {
     const dirExist = path.join(testDataDir, 'utils', 'isdir');
     const dirNotExist = path.join(testDataDir, 'utils', 'notexist');
@@ -54,7 +54,7 @@ describe('#utils', function () {
     fs.writeFileSync(path.join(dir, 'test2.html'), 'junk');
     fs.writeFileSync(path.join(dir, 'other.file'), 'junk');
 
-    expect(getFiles(dir, ['.json', '.html'])).to.deep.equal([
+    expect(getFiles(dir, [ '.json', '.html' ])).to.deep.equal([
       path.join(dir, 'test1.html'),
       path.join(dir, 'test1.json'),
       path.join(dir, 'test2.html'),
@@ -93,8 +93,8 @@ describe('#utils', function () {
 
   it('should strip identifiers', () => {
     const assets = {
-      clients: [{ name: 'some client', client_id: 'test' }],
-      rulesConfigs: [{ key: 'test', value: 'test' }]
+      clients: [ { name: 'some client', client_id: 'test' } ],
+      rulesConfigs: [ { key: 'test', value: 'test' } ]
     };
 
     const auth0 = new Auth0(mockMgmtClient(), {}, mockConfigFn);
@@ -134,7 +134,7 @@ describe('#utils', function () {
       name: 'Name',
       a: 'Alpha'
     });
-    expect(Object.keys(result)).to.deep.equal(['name', 'identifier', 'id', 'a', 'b', 'c', 'd']);
+    expect(Object.keys(result)).to.deep.equal([ 'name', 'identifier', 'id', 'a', 'b', 'c', 'd' ]);
     expect(result).to.deep.equal({
       name: 'Name',
       identifier: 'Identifier',
@@ -200,12 +200,12 @@ describe('#utils', function () {
   it('should not touch correct client arrays', () => {
     const client = {
       name: 'Default App',
-      callbacks: ['callback'],
+      callbacks: [ 'callback' ],
       allowed_clients: [],
-      allowed_logout_urls: ['url', 'url'],
+      allowed_logout_urls: [ 'url', 'url' ],
       is_first_party: true,
       oidc_conformant: false,
-      allowed_origins: ['origin']
+      allowed_origins: [ 'origin' ]
     };
 
     expect(clearClientArrays(client)).to.deep.equal(client);
@@ -266,16 +266,16 @@ describe('#utils', function () {
 
     it('should return sorted list', () => {
       expect(mapClientID2NameSorted(
-        ['client_id_B', 'client_id_A', 'not_found_id'],
+        [ 'client_id_B', 'client_id_A', 'not_found_id' ],
         knownClients
-      )).deep.equal(['client_A', 'client_B', 'not_found_id']);
+      )).deep.equal([ 'client_A', 'client_B', 'not_found_id' ]);
     });
 
     it('should return sorted list even knownClient are invalid', () => {
       expect(mapClientID2NameSorted(
-        ['client_id_B', 'client_id_A', 'not_found_id'],
+        [ 'client_id_B', 'client_id_A', 'not_found_id' ],
         null
-      )).deep.equal(['client_id_A', 'client_id_B', 'not_found_id']);
+      )).deep.equal([ 'client_id_A', 'client_id_B', 'not_found_id' ]);
     });
 
     it('should return empty list upon invalid input', () => {

From f3c278e7842f102eaab5d028755f7517bd23125a Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 15:24:03 -0400
Subject: [PATCH 5/9] Fixing code comment

---
 src/tools/auth0/index.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/auth0/index.ts b/src/tools/auth0/index.ts
index 9665bd384..04c163895 100644
--- a/src/tools/auth0/index.ts
+++ b/src/tools/auth0/index.ts
@@ -40,7 +40,7 @@ export default class Auth0 {
     this.assets = assets;
 
     this.handlers = Object.values(handlers).map((handler) => {
-      //@ts-ignore because prompts don't appear to have been universally implemented yet
+      //@ts-ignore because class expects `type` property but gets directly injected into class constructors
       const newHandler = new handler.default({ client: this.client, config: this.config });
       return newHandler
     }).filter((handler) => {

From 0d4333321a40e9674526430756a26cb1ed9bc6b4 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 15:24:54 -0400
Subject: [PATCH 6/9] Removing newHandler intermediate value

---
 src/tools/auth0/index.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/tools/auth0/index.ts b/src/tools/auth0/index.ts
index 04c163895..379ebbd84 100644
--- a/src/tools/auth0/index.ts
+++ b/src/tools/auth0/index.ts
@@ -41,8 +41,7 @@ export default class Auth0 {
 
     this.handlers = Object.values(handlers).map((handler) => {
       //@ts-ignore because class expects `type` property but gets directly injected into class constructors
-      const newHandler = new handler.default({ client: this.client, config: this.config });
-      return newHandler
+      return new handler.default({ client: this.client, config: this.config });
     }).filter((handler) => {
       const excludedAssetTypes = config('AUTH0_EXCLUDED') || []
       return !excludedAssetTypes.includes(handler.type)

From 3c12c557aad3e002a258e9f785b25fa09bb6fce8 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 16:20:22 -0400
Subject: [PATCH 7/9] Adding auth0 class test

---
 test/tools/auth0/index.test.ts | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 test/tools/auth0/index.test.ts

diff --git a/test/tools/auth0/index.test.ts b/test/tools/auth0/index.test.ts
new file mode 100644
index 000000000..395a0f28a
--- /dev/null
+++ b/test/tools/auth0/index.test.ts
@@ -0,0 +1,34 @@
+import { expect } from 'chai';
+import Auth0 from '../../../src/tools/auth0'
+import { Auth0APIClient, Assets } from '../../../src/types'
+
+const mockEmptyClient = {} as Auth0APIClient
+const mockEmptyAssets = {} as Assets
+
+describe("#Auth0 class", () => {
+
+    describe("#resource exclusion", () => {
+        it('should exclude handlers listed in AUTH0_EXCLUDED from Auth0 class', () => {
+
+            const auth0WithoutExclusions = new Auth0(mockEmptyClient, mockEmptyAssets, () => []);
+
+            const AUTH0_EXCLUDE = ['rules', 'organizations', 'connections']
+            const auth0WithExclusions = new Auth0(mockEmptyClient, mockEmptyAssets, () => AUTH0_EXCLUDE);
+
+            expect(auth0WithoutExclusions.handlers.length).to.equal(auth0WithExclusions.handlers.length + AUTH0_EXCLUDE.length) // Number of handlers is reduced by number of exclusions
+
+            const areAllExcludedHandlersAbsent = auth0WithExclusions.handlers.some((handler) => {
+                return AUTH0_EXCLUDE.includes(handler.type)
+            })
+
+            expect(areAllExcludedHandlersAbsent).to.be.false;
+        })
+
+        it('should not exclude any handlers if AUTH0_EXCLUDED is undefined', () => {
+            const AUTH0_EXCLUDE = undefined
+            const auth0 = new Auth0(mockEmptyClient, mockEmptyAssets, () => AUTH0_EXCLUDE);
+
+            expect(auth0.handlers.length).to.be.greaterThan(0)
+        })
+    })
+})
\ No newline at end of file

From eafebdf2297e7d5b1743e32551d9db2e15e8d877 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Thu, 31 Mar 2022 16:47:41 -0400
Subject: [PATCH 8/9] Adding resource exclusion to directory handlers

---
 src/context/directory/index.ts | 11 +++++++----
 test/tools/auth0/index.test.ts | 12 ++++++------
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/context/directory/index.ts b/src/context/directory/index.ts
index 51cd700f7..bd004d027 100644
--- a/src/context/directory/index.ts
+++ b/src/context/directory/index.ts
@@ -3,11 +3,11 @@ import { loadFileAndReplaceKeywords, Auth0 } from '../../tools';
 
 import cleanAssets from '../../readonly';
 import log from '../../logger';
-import handlers from './handlers';
+import handlers, { DirectoryHandler } from './handlers';
 import {
   isDirectory, isFile, stripIdentifiers, toConfigFn
 } from '../../utils';
-import { Assets, Auth0APIClient, Config } from '../../types'
+import { Assets, Auth0APIClient, Config, AssetTypes } from '../../types'
 
 type KeywordMappings = { [key: string]: (string | number)[] | string | number }
 
@@ -78,14 +78,17 @@ export default class DirectoryContext {
     // Copy clients to be used by handlers which require converting client_id to the name
     // Must copy as the client_id will be stripped if AUTH0_EXPORT_IDENTIFIERS is false
     //@ts-ignore because assets haven't been typed yet TODO: type assets
-    this.assets.clientsOrig = [...this.assets.clients];
+    this.assets.clientsOrig = [...this.assets.clients || []];
 
     // Optionally Strip identifiers
     if (!this.config.AUTH0_EXPORT_IDENTIFIERS) {
       this.assets = stripIdentifiers(auth0, this.assets);
     }
 
-    await Promise.all(Object.entries(handlers).map(async ([name, handler]) => {
+    await Promise.all(Object.entries(handlers).filter(([handlerName]: [AssetTypes, DirectoryHandler<any>]) => {
+      const excludedAssetTypes = this.config.AUTH0_EXCLUDED || []
+      return !excludedAssetTypes.includes(handlerName)
+    }).map(async ([name, handler]) => {
       try {
         await handler.dump(this);
       } catch (err) {
diff --git a/test/tools/auth0/index.test.ts b/test/tools/auth0/index.test.ts
index 395a0f28a..699584d37 100644
--- a/test/tools/auth0/index.test.ts
+++ b/test/tools/auth0/index.test.ts
@@ -12,21 +12,21 @@ describe("#Auth0 class", () => {
 
             const auth0WithoutExclusions = new Auth0(mockEmptyClient, mockEmptyAssets, () => []);
 
-            const AUTH0_EXCLUDE = ['rules', 'organizations', 'connections']
-            const auth0WithExclusions = new Auth0(mockEmptyClient, mockEmptyAssets, () => AUTH0_EXCLUDE);
+            const AUTH0_EXCLUDED = ['rules', 'organizations', 'connections']
+            const auth0WithExclusions = new Auth0(mockEmptyClient, mockEmptyAssets, () => AUTH0_EXCLUDED);
 
-            expect(auth0WithoutExclusions.handlers.length).to.equal(auth0WithExclusions.handlers.length + AUTH0_EXCLUDE.length) // Number of handlers is reduced by number of exclusions
+            expect(auth0WithoutExclusions.handlers.length).to.equal(auth0WithExclusions.handlers.length + AUTH0_EXCLUDED.length) // Number of handlers is reduced by number of exclusions
 
             const areAllExcludedHandlersAbsent = auth0WithExclusions.handlers.some((handler) => {
-                return AUTH0_EXCLUDE.includes(handler.type)
+                return AUTH0_EXCLUDED.includes(handler.type)
             })
 
             expect(areAllExcludedHandlersAbsent).to.be.false;
         })
 
         it('should not exclude any handlers if AUTH0_EXCLUDED is undefined', () => {
-            const AUTH0_EXCLUDE = undefined
-            const auth0 = new Auth0(mockEmptyClient, mockEmptyAssets, () => AUTH0_EXCLUDE);
+            const AUTH0_EXCLUDED = undefined
+            const auth0 = new Auth0(mockEmptyClient, mockEmptyAssets, () => AUTH0_EXCLUDED);
 
             expect(auth0.handlers.length).to.be.greaterThan(0)
         })

From 6e0c95393cf3fe1c209751de9b1c651b4fe31d57 Mon Sep 17 00:00:00 2001
From: Will Vedder <willvedder@jxmqxvcv5v.myfiosgateway.com>
Date: Fri, 1 Apr 2022 13:37:10 -0400
Subject: [PATCH 9/9] Adding AUTH0_EXCLUDED to nonprimitive helper

---
 src/context/index.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/context/index.ts b/src/context/index.ts
index b66204ffb..4ddeac45d 100644
--- a/src/context/index.ts
+++ b/src/context/index.ts
@@ -17,6 +17,7 @@ const nonPrimitiveProps: (keyof Config)[] = [
   'AUTH0_EXCLUDED_CONNECTIONS',
   'AUTH0_EXCLUDED_RESOURCE_SERVERS',
   'AUTH0_EXCLUDED_DEFAULTS',
+  'AUTH0_EXCLUDED',
   'EXCLUDED_PROPS',
   'INCLUDED_PROPS'
 ];