From bdc06aa5a03ae5244949f6ffd91d690af1b48893 Mon Sep 17 00:00:00 2001 From: Will Vedder Date: Wed, 1 Mar 2023 13:32:04 -0500 Subject: [PATCH] DXCDT-384: Keyword preservation in auxiliary files (#758) * Renaming load to loadAssetsFromLocal * Renaming load to loadAssetsFromAuth0 * integrating into export process * Adding config interpreter * Disabling keyword replacement in certain cases * Fixing directory load * More forgiving lookup logic if properties and/or addresses do not exist * Fixing directory load again * Adding case that would have previously tripped up process * Adding e2e tests for keyword preservation * Removing old tests, updating recordings, removing console. logs * Commenting-out test to fix later on * Fixing workdirectory for e2e tests * Adding eventual cases for auxillary files * Adding TODO * Adding preqrequisite checks * Fixing test * Standardizing definitions of resource identifiers * Removing incompatible id from email templates * Readding identifiers field for resource server * Fixing email templates identifier field * Reformulating arguments into object * Adding e2e case * Init * Removing console log * Adding more robust e2e test * Updating recordings * Fixing database directory handler, test * Adding unit test cases for not replacing keywords --------- Co-authored-by: Will Vedder --- src/context/directory/handlers/branding.ts | 5 +- src/context/directory/handlers/clients.ts | 5 +- src/context/directory/handlers/connections.ts | 5 +- src/context/directory/handlers/databases.ts | 21 +- .../directory/handlers/emailTemplates.ts | 5 +- src/context/directory/handlers/pages.ts | 5 +- src/context/directory/index.ts | 5 +- src/context/yaml/handlers/branding.ts | 5 +- src/context/yaml/index.ts | 8 +- src/tools/utils.ts | 10 +- src/utils.ts | 8 +- test/e2e/e2e.test.ts | 73 ++++- ...reserve-keywords-for-directory-format.json | 257 +++++++++++++++++- ...uld-preserve-keywords-for-yaml-format.json | 257 +++++++++++++++++- .../yaml/emailTemplates/welcome_email.json | 10 - test/tools/utils.test.js | 22 +- 16 files changed, 644 insertions(+), 57 deletions(-) delete mode 100644 test/e2e/testdata/should-preserve-keywords/yaml/emailTemplates/welcome_email.json diff --git a/src/context/directory/handlers/branding.ts b/src/context/directory/handlers/branding.ts index 173ca364b..c1f67da6a 100644 --- a/src/context/directory/handlers/branding.ts +++ b/src/context/directory/handlers/branding.ts @@ -40,7 +40,10 @@ function parse(context: DirectoryContext): ParsedBranding { }); definition.body = loadFileAndReplaceKeywords( path.join(brandingTemplatesFolder, definition.body), - context.mappings + { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + } ); return definition; }, {}); diff --git a/src/context/directory/handlers/clients.ts b/src/context/directory/handlers/clients.ts index eb484fdb8..336f8e02b 100644 --- a/src/context/directory/handlers/clients.ts +++ b/src/context/directory/handlers/clients.ts @@ -36,7 +36,10 @@ function parse(context: DirectoryContext): ParsedClients { const htmlFileName = path.join(clientsFolder, client.custom_login_page); if (isFile(htmlFileName)) { - client.custom_login_page = loadFileAndReplaceKeywords(htmlFileName, context.mappings); + client.custom_login_page = loadFileAndReplaceKeywords(htmlFileName, { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }); } } diff --git a/src/context/directory/handlers/connections.ts b/src/context/directory/handlers/connections.ts index 7a341931c..4501609d9 100644 --- a/src/context/directory/handlers/connections.ts +++ b/src/context/directory/handlers/connections.ts @@ -43,7 +43,10 @@ function parse(context: DirectoryContext): ParsedConnections { `Passwordless email template purportedly located at ${htmlFileName} does not exist for connection. Ensure the existence of this file to proceed with deployment.` ); } - connection.options.email.body = loadFileAndReplaceKeywords(htmlFileName, context.mappings); + connection.options.email.body = loadFileAndReplaceKeywords(htmlFileName, { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }); } return connection; diff --git a/src/context/directory/handlers/databases.ts b/src/context/directory/handlers/databases.ts index c27e46b5b..502b20618 100644 --- a/src/context/directory/handlers/databases.ts +++ b/src/context/directory/handlers/databases.ts @@ -14,7 +14,7 @@ import { import { DirectoryHandler } from '.'; import DirectoryContext from '..'; -import { Asset, ParsedAsset } from '../../../types'; +import { Asset, KeywordMappings, ParsedAsset } from '../../../types'; type ParsedDatabases = ParsedAsset<'databases', Asset[]>; @@ -31,12 +31,15 @@ type DatabaseMetadata = { }; }; -function getDatabase(folder: string, mappings): {} { +function getDatabase( + folder: string, + mappingOpts: { mappings: KeywordMappings; disableKeywordReplacement: boolean } +): {} { const metaFile = path.join(folder, 'database.json'); const metaData: DatabaseMetadata | {} = (() => { try { - return loadJSON(metaFile, mappings); + return loadJSON(metaFile, mappingOpts); } catch (err) { log.warn(`Skipping database folder ${folder} as cannot find or read ${metaFile}`); return {}; @@ -60,15 +63,14 @@ function getDatabase(folder: string, mappings): {} { // If any customScripts configured then load content of files if (database.options.customScripts) { - Object.entries(database.options.customScripts).forEach(([name, script]) => { + Object.entries(database.options.customScripts).forEach(([name, script]: [string, string]) => { if (!constants.DATABASE_SCRIPTS.includes(name)) { // skip invalid keys in customScripts object log.warn('Skipping invalid database configuration: ' + name); } else { database.options.customScripts[name] = loadFileAndReplaceKeywords( - //@ts-ignore path.join(folder, script), - mappings + mappingOpts ); } }); @@ -87,7 +89,12 @@ function parse(context: DirectoryContext): ParsedDatabases { .filter((f) => isDirectory(f)); const databases = folders - .map((f) => getDatabase(f, context.mappings)) + .map((f) => + getDatabase(f, { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }) + ) .filter((p) => Object.keys(p).length > 1); return { diff --git a/src/context/directory/handlers/emailTemplates.ts b/src/context/directory/handlers/emailTemplates.ts index 419d84a25..0e663b0d0 100644 --- a/src/context/directory/handlers/emailTemplates.ts +++ b/src/context/directory/handlers/emailTemplates.ts @@ -41,7 +41,10 @@ function parse(context: DirectoryContext): ParsedEmailTemplates { mappings: context.mappings, disableKeywordReplacement: context.disableKeywordReplacement, }), - body: loadFileAndReplaceKeywords(html, context.mappings), + body: loadFileAndReplaceKeywords(html, { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }), }; } } diff --git a/src/context/directory/handlers/pages.ts b/src/context/directory/handlers/pages.ts index 30290dbd9..02dda133a 100644 --- a/src/context/directory/handlers/pages.ts +++ b/src/context/directory/handlers/pages.ts @@ -55,7 +55,10 @@ function parse(context: DirectoryContext): ParsedPages { mappings: context.mappings, disableKeywordReplacement: context.disableKeywordReplacement, }), - html: loadFileAndReplaceKeywords(html, context.mappings), + html: loadFileAndReplaceKeywords(html, { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }), }; }); diff --git a/src/context/directory/index.ts b/src/context/directory/index.ts index f679a7c5a..2e786d671 100644 --- a/src/context/directory/index.ts +++ b/src/context/directory/index.ts @@ -47,7 +47,10 @@ export default class DirectoryContext { // try load not relative to yaml file toLoad = f; } - return loadFileAndReplaceKeywords(toLoad, this.mappings); + return loadFileAndReplaceKeywords(toLoad, { + mappings: this.mappings, + disableKeywordReplacement: this.disableKeywordReplacement, + }); } async loadAssetsFromLocal(opts = { disableKeywordReplacement: false }): Promise { diff --git a/src/context/yaml/handlers/branding.ts b/src/context/yaml/handlers/branding.ts index 8464040c8..b3b7fbd3b 100644 --- a/src/context/yaml/handlers/branding.ts +++ b/src/context/yaml/handlers/branding.ts @@ -34,7 +34,10 @@ async function parse(context: YAMLContext): Promise { const markupFile = path.join(context.basePath, templateDefinition.body); return { template: templateDefinition.template, - body: loadFileAndReplaceKeywords(markupFile, context.mappings), + body: loadFileAndReplaceKeywords(markupFile, { + mappings: context.mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }), }; } ); diff --git a/src/context/yaml/index.ts b/src/context/yaml/index.ts index 43c75d74c..678fe01bd 100644 --- a/src/context/yaml/index.ts +++ b/src/context/yaml/index.ts @@ -18,12 +18,14 @@ export default class YAMLContext { mappings: KeywordMappings; mgmtClient: Auth0APIClient; assets: Assets; + disableKeywordReplacement: boolean; constructor(config: Config, mgmtClient) { this.configFile = config.AUTH0_INPUT_FILE; this.config = config; this.mappings = config.AUTH0_KEYWORD_REPLACE_MAPPINGS || {}; this.mgmtClient = mgmtClient; + this.disableKeywordReplacement = false; //@ts-ignore because the assets property gets filled out throughout this.assets = {}; @@ -50,11 +52,15 @@ export default class YAMLContext { // try load not relative to yaml file toLoad = f; } - return loadFileAndReplaceKeywords(path.resolve(toLoad), this.mappings); + return loadFileAndReplaceKeywords(path.resolve(toLoad), { + mappings: this.mappings, + disableKeywordReplacement: this.disableKeywordReplacement, + }); } async loadAssetsFromLocal(opts = { disableKeywordReplacement: false }) { // Allow to send object/json directly + this.disableKeywordReplacement = opts.disableKeywordReplacement; if (typeof this.configFile === 'object') { this.assets = this.configFile; } else { diff --git a/src/tools/utils.ts b/src/tools/utils.ts index 8a1e4bfcd..41b1c24c9 100644 --- a/src/tools/utils.ts +++ b/src/tools/utils.ts @@ -65,12 +65,18 @@ export function convertClientNamesToIds(names: string[], clients: Asset[]): stri return [...unresolved, ...result]; } -export function loadFileAndReplaceKeywords(file: string, mappings: KeywordMappings): string { +export function loadFileAndReplaceKeywords( + file: string, + { + mappings, + disableKeywordReplacement = false, + }: { mappings: KeywordMappings; disableKeywordReplacement: boolean } +): string { // Load file and replace keyword mappings const f = path.resolve(file); try { fs.accessSync(f, fsConstants.F_OK); - if (mappings) { + if (mappings && !disableKeywordReplacement) { return keywordReplace(fs.readFileSync(f, 'utf8'), mappings); } return fs.readFileSync(f, 'utf8'); diff --git a/src/utils.ts b/src/utils.ts index 8ba3954d3..d3ec16079 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -40,10 +40,10 @@ export function loadJSON( } ): any { try { - const content = loadFileAndReplaceKeywords( - file, - opts.disableKeywordReplacement ? {} : opts.mappings - ); + const content = loadFileAndReplaceKeywords(file, { + mappings: opts.mappings, + disableKeywordReplacement: opts.disableKeywordReplacement, + }); return JSON.parse(content); } catch (e) { throw new Error(`Error parsing JSON from metadata file: ${file}, because: ${e.message}`); diff --git a/test/e2e/e2e.test.ts b/test/e2e/e2e.test.ts index 1fbd24fcc..8d4655f71 100644 --- a/test/e2e/e2e.test.ts +++ b/test/e2e/e2e.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import path from 'path'; import fs from 'fs'; -import { copySync } from 'fs-extra'; +import { copySync, emptyDirSync } from 'fs-extra'; import { getFiles, existsMustBeDir } from '../../src/utils'; import { load as yamlLoad } from 'js-yaml'; import { setupRecording, testNameToWorkingDirectory } from './e2e-utils'; @@ -384,8 +384,32 @@ describe('keyword preservation', () => { config, }); + //Dumping without keyword preservation so we can assert that remote values will overwrite local values + await dump({ + output_folder: workDirectory, + format: 'yaml', + config: { + ...config, + AUTH0_PRESERVE_KEYWORDS: false, + }, + }); + const yamlWithoutPreservation = yamlLoad( + fs.readFileSync(path.join(workDirectory, 'tenant.yaml')) + ); + expect(yamlWithoutPreservation.tenant.friendly_name).to.equal( + 'This tenant name should be preserved' + ); + expect(yamlWithoutPreservation.tenant.support_email).to.equal('support@travel0.com'); + expect(yamlWithoutPreservation.tenant.support_url).to.equal('https://travel0.com/support'); + expect( + yamlWithoutPreservation.emailTemplates.find(({ template }) => template === 'welcome_email') + .resultUrl + ).to.equal('https://travel0.com/welcome'); + + emptyDirSync(workDirectory); copySync(`${__dirname}/testdata/should-preserve-keywords/yaml`, workDirectory); //It is necessary to copy directory contents to work directory to prevent overwriting of Git-committed files + //This dump will attempt to preserve keywords await dump({ output_folder: workDirectory, format: 'yaml', @@ -402,10 +426,10 @@ describe('keyword preservation', () => { // expect(yaml.tenant.enabled_locales).to.equal('@@LANGUAGES@@'); TODO: enable @@ARRAY@@ keyword preservation in yaml formats - // const emailTemplateHTML = fs - // .readFileSync(path.join(workDirectory, 'emailTemplates', 'welcome_email.html')) - // .toString(); - // expect(emailTemplateHTML).to.contain('##TENANT##'); TODO: enable keyword preservation in auxillary template files + const emailTemplateHTML = fs + .readFileSync(path.join(workDirectory, 'emailTemplates', 'welcome_email.html')) + .toString(); + expect(emailTemplateHTML).to.contain('##TENANT_NAME##'); recordingDone(); }); @@ -420,8 +444,39 @@ describe('keyword preservation', () => { config, }); + //Dumping without keyword preservation so we can assert that remote values will overwrite local values + await dump({ + output_folder: workDirectory, + format: 'directory', + config: { + ...config, + AUTH0_PRESERVE_KEYWORDS: false, + }, + }); + + const jsonWithoutPreservation = JSON.parse( + fs.readFileSync(path.join(workDirectory, 'tenant.json')).toString() + ); + + expect(jsonWithoutPreservation.friendly_name).to.equal('This tenant name should be preserved'); + expect(jsonWithoutPreservation.enabled_locales).to.deep.equal(['en', 'es']); + expect(jsonWithoutPreservation.support_email).to.equal('support@travel0.com'); + expect(jsonWithoutPreservation.support_url).to.equal('https://travel0.com/support'); + + const emailTemplateJsonWithoutPreservation = JSON.parse( + fs.readFileSync(path.join(workDirectory, 'emails', 'welcome_email.json')).toString() + ); + + expect(emailTemplateJsonWithoutPreservation.resultUrl).to.equal('https://travel0.com/welcome'); + + expect( + fs.readFileSync(path.join(workDirectory, 'emails', 'welcome_email.html')).toString() + ).to.contain('This tenant name should be preserved'); + + emptyDirSync(workDirectory); copySync(`${__dirname}/testdata/should-preserve-keywords/directory`, workDirectory); //It is necessary to copy directory contents to work directory to prevent overwriting of Git-committed files + //This dump will attempt to preserve keywords await dump({ output_folder: workDirectory, format: 'directory', @@ -442,10 +497,10 @@ describe('keyword preservation', () => { expect(emailTemplateJson.resultUrl).to.equal('https://##DOMAIN##/welcome'); expect(emailTemplateJson.subject).to.not.equal('##THIS_SHOULD_NOT_BE_PRESERVED##'); - // const emailTemplateHTML = fs - // .readFileSync(path.join(workDirectory, 'emailTemplates', 'welcome_email.html')) - // .toString(); - // expect(emailTemplateHTML).to.contain('##TENANT##'); TODO: enable keyword preservation in auxillary template files + const emailTemplateHTML = fs + .readFileSync(path.join(workDirectory, 'emailTemplates', 'welcome_email.html')) + .toString(); + expect(emailTemplateHTML).to.contain('##TENANT_NAME##'); recordingDone(); }); diff --git a/test/e2e/recordings/should-preserve-keywords-for-directory-format.json b/test/e2e/recordings/should-preserve-keywords-for-directory-format.json index 1ed3bd535..4a899f95b 100644 --- a/test/e2e/recordings/should-preserve-keywords-for-directory-format.json +++ b/test/e2e/recordings/should-preserve-keywords-for-directory-format.json @@ -251,6 +251,129 @@ "rawHeaders": [], "responseIsBinary": false }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/change_password", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/verify_email", + "body": "", + "status": 200, + "response": { + "template": "verify_email", + "body": "\n \n \n \n \n
\n \n \n \n
\n \n \n

\n\n

Welcome to {{ application.name}}!

\n\n

\n Thank you for signing up. Please verify your email address by clicking the following\n link:\n

\n\n

Confirm my account

\n\n

\n If you are having any issues with your account, please don’t hesitate to contact us\n by replying to this mail.\n

\n\n
\n Haha!!!\n
\n\n {{ application.name }}\n\n

\n
\n \n If you did not make this request, please contact us by replying to this mail.\n

\n
\n \n \n \n
\n \n\n", + "from": "", + "subject": "", + "syntax": "liquid", + "urlLifetimeInSeconds": 432000, + "enabled": true + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/mfa_oob_code", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/reset_email", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/password_reset", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/verify_email_by_code", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/enrollment_email", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/user_invitation", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", @@ -288,7 +411,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/verify_email_by_code", + "path": "/api/v2/email-templates/stolen_credentials", "body": "", "status": 404, "response": { @@ -303,7 +426,78 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/password_reset", + "path": "/api/v2/tenants/settings", + "body": "", + "status": 200, + "response": { + "allowed_logout_urls": [ + "https://travel0.com/logoutCallback" + ], + "change_password": { + "enabled": true, + "html": "Change Password\n" + }, + "enabled_locales": [ + "en", + "es" + ], + "error_page": { + "html": "Error Page\n", + "show_log_link": false, + "url": "https://mycompany.org/error" + }, + "flags": { + "allow_changing_enable_sso": false, + "allow_legacy_delegation_grant_types": true, + "allow_legacy_ro_grant_types": true, + "change_pwd_flow_v1": false, + "disable_impersonation": true, + "enable_apis_section": false, + "enable_client_connections": false, + "enable_custom_domain_in_emails": false, + "enable_dynamic_client_registration": false, + "enable_legacy_logs_search_v2": false, + "enable_public_signup_user_exists_error": true, + "enable_sso": true, + "new_universal_login_experience_enabled": true, + "universal_login": true, + "use_scope_descriptions_for_consent": false, + "revoke_refresh_token_grant": false, + "disable_clickjack_protection_headers": false, + "enable_pipeline2": false + }, + "friendly_name": "This tenant name should be preserved", + "guardian_mfa_page": { + "enabled": true, + "html": "MFA\n" + }, + "idle_session_lifetime": 1, + "picture_url": "https://upload.wikimedia.org/wikipedia/commons/0/0d/Grandmas_marathon_finishers.png", + "sandbox_version": "12", + "session_lifetime": 3.0166666666666666, + "support_email": "support@travel0.com", + "support_url": "https://travel0.com/support", + "universal_login": { + "colors": { + "primary": "#F8F8F2", + "page_background": "#222221" + } + }, + "session_cookie": { + "mode": "non-persistent" + }, + "sandbox_versions_available": [ + "16", + "12" + ] + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/blocked_account", "body": "", "status": 404, "response": { @@ -318,7 +512,41 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/user_invitation", + "path": "/api/v2/email-templates/verify_email_by_code", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/welcome_email", + "body": "", + "status": 200, + "response": { + "template": "welcome_email", + "body": "\n \n

Welcome to This tenant name should be preserved!

\n \n\n", + "from": "", + "resultUrl": "https://travel0.com/welcome", + "subject": "Welcome", + "syntax": "liquid", + "urlLifetimeInSeconds": 3600, + "enabled": false + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/reset_email", "body": "", "status": 404, "response": { @@ -348,7 +576,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/change_password", + "path": "/api/v2/email-templates/mfa_oob_code", "body": "", "status": 404, "response": { @@ -378,7 +606,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/mfa_oob_code", + "path": "/api/v2/email-templates/change_password", "body": "", "status": 404, "response": { @@ -393,7 +621,22 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/reset_email", + "path": "/api/v2/email-templates/password_reset", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/user_invitation", "body": "", "status": 404, "response": { @@ -423,4 +666,4 @@ "rawHeaders": [], "responseIsBinary": false } -] +] \ No newline at end of file diff --git a/test/e2e/recordings/should-preserve-keywords-for-yaml-format.json b/test/e2e/recordings/should-preserve-keywords-for-yaml-format.json index 62c58b53b..9b0d06b8e 100644 --- a/test/e2e/recordings/should-preserve-keywords-for-yaml-format.json +++ b/test/e2e/recordings/should-preserve-keywords-for-yaml-format.json @@ -275,6 +275,36 @@ "rawHeaders": [], "responseIsBinary": false }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/reset_email", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/blocked_account", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", @@ -293,7 +323,71 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/reset_email", + "path": "/api/v2/email-templates/enrollment_email", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/verify_email_by_code", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/password_reset", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/welcome_email", + "body": "", + "status": 200, + "response": { + "template": "welcome_email", + "body": "\n \n

Welcome to This tenant name should be preserved!

\n \n\n", + "from": "", + "resultUrl": "https://travel0.com/welcome", + "subject": "Welcome", + "syntax": "liquid", + "urlLifetimeInSeconds": 3600, + "enabled": false + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/user_invitation", "body": "", "status": 404, "response": { @@ -323,6 +417,125 @@ "rawHeaders": [], "responseIsBinary": false }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/mfa_oob_code", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/change_password", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/tenants/settings", + "body": "", + "status": 200, + "response": { + "allowed_logout_urls": [ + "https://travel0.com/logoutCallback" + ], + "change_password": { + "enabled": true, + "html": "Change Password\n" + }, + "enabled_locales": [ + "en", + "es" + ], + "error_page": { + "html": "Error Page\n", + "show_log_link": false, + "url": "https://mycompany.org/error" + }, + "flags": { + "allow_changing_enable_sso": false, + "allow_legacy_delegation_grant_types": true, + "allow_legacy_ro_grant_types": true, + "change_pwd_flow_v1": false, + "disable_impersonation": true, + "enable_apis_section": false, + "enable_client_connections": false, + "enable_custom_domain_in_emails": false, + "enable_dynamic_client_registration": false, + "enable_legacy_logs_search_v2": false, + "enable_public_signup_user_exists_error": true, + "enable_sso": true, + "new_universal_login_experience_enabled": true, + "universal_login": true, + "use_scope_descriptions_for_consent": false, + "revoke_refresh_token_grant": false, + "disable_clickjack_protection_headers": false, + "enable_pipeline2": false + }, + "friendly_name": "This tenant name should be preserved", + "guardian_mfa_page": { + "enabled": true, + "html": "MFA\n" + }, + "idle_session_lifetime": 1, + "picture_url": "https://unsplash.com/photos/8v1T2SCM6Ek", + "sandbox_version": "12", + "session_lifetime": 3.0166666666666666, + "support_email": "support@travel0.com", + "support_url": "https://travel0.com/support", + "universal_login": { + "colors": { + "primary": "#F8F8F2", + "page_background": "#222221" + } + }, + "session_cookie": { + "mode": "non-persistent" + }, + "sandbox_versions_available": [ + "16", + "12" + ] + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/verify_email", + "body": "", + "status": 200, + "response": { + "template": "verify_email", + "body": "\n \n \n \n \n
\n \n \n \n
\n \n \n

\n\n

Welcome to {{ application.name}}!

\n\n

\n Thank you for signing up. Please verify your email address by clicking the following\n link:\n

\n\n

Confirm my account

\n\n

\n If you are having any issues with your account, please don’t hesitate to contact us\n by replying to this mail.\n

\n\n
\n Haha!!!\n
\n\n {{ application.name }}\n\n

\n
\n \n If you did not make this request, please contact us by replying to this mail.\n

\n
\n \n \n \n
\n \n\n", + "from": "", + "subject": "", + "syntax": "liquid", + "urlLifetimeInSeconds": 432000, + "enabled": true + }, + "rawHeaders": [], + "responseIsBinary": false + }, { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", @@ -341,7 +554,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/enrollment_email", + "path": "/api/v2/email-templates/blocked_account", "body": "", "status": 404, "response": { @@ -356,7 +569,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/change_password", + "path": "/api/v2/email-templates/reset_email", "body": "", "status": 404, "response": { @@ -371,7 +584,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/mfa_oob_code", + "path": "/api/v2/email-templates/stolen_credentials", "body": "", "status": 404, "response": { @@ -386,7 +599,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/user_invitation", + "path": "/api/v2/email-templates/change_password", "body": "", "status": 404, "response": { @@ -417,6 +630,36 @@ "rawHeaders": [], "responseIsBinary": false }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/enrollment_email", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, + { + "scope": "https://deploy-cli-dev.eu.auth0.com:443", + "method": "GET", + "path": "/api/v2/email-templates/user_invitation", + "body": "", + "status": 404, + "response": { + "statusCode": 404, + "error": "Not Found", + "message": "The template does not exist.", + "errorCode": "inexistent_email_template" + }, + "rawHeaders": [], + "responseIsBinary": false + }, { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", @@ -435,7 +678,7 @@ { "scope": "https://deploy-cli-dev.eu.auth0.com:443", "method": "GET", - "path": "/api/v2/email-templates/blocked_account", + "path": "/api/v2/email-templates/mfa_oob_code", "body": "", "status": 404, "response": { @@ -447,4 +690,4 @@ "rawHeaders": [], "responseIsBinary": false } -] +] \ No newline at end of file diff --git a/test/e2e/testdata/should-preserve-keywords/yaml/emailTemplates/welcome_email.json b/test/e2e/testdata/should-preserve-keywords/yaml/emailTemplates/welcome_email.json deleted file mode 100644 index f58bcbf42..000000000 --- a/test/e2e/testdata/should-preserve-keywords/yaml/emailTemplates/welcome_email.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "template": "welcome_email", - "body": "./welcome_email.html", - "from": "", - "resultUrl": "https://example.com/welcome", - "subject": "Welcome", - "syntax": "liquid", - "urlLifetimeInSeconds": 3600, - "enabled": false -} diff --git a/test/tools/utils.test.js b/test/tools/utils.test.js index 13f57aae8..d937a66ea 100644 --- a/test/tools/utils.test.js +++ b/test/tools/utils.test.js @@ -1,5 +1,6 @@ import path from 'path'; import { expect } from 'chai'; +import { readFileSync } from 'fs'; import jsYaml from 'js-yaml'; import * as utils from '../../src/tools/utils'; import constants from '../../src/tools/constants'; @@ -30,15 +31,30 @@ const expectations = { }; describe('#utils', function () { - it('should load file', () => { + it('should load file and replace keywords', () => { const file = path.resolve(__dirname, 'test.file.json'); - const loaded = utils.loadFileAndReplaceKeywords(file, mappings); + const loaded = utils.loadFileAndReplaceKeywords(file, { + mappings, + disableKeywordReplacement: false, + }); expect(JSON.parse(loaded)).to.deep.equal(expectations); }); + it('should load file and not replace keywords', () => { + const file = path.resolve(__dirname, 'test.file.json'); + const loaded = utils.loadFileAndReplaceKeywords(file, { + mappings, + disableKeywordReplacement: true, + }); + expect(loaded).to.deep.equal(readFileSync(file).toString()); + }); + it('should throw error if cannot load file', () => { expect(function () { - utils.loadFileAndReplaceKeywords('notexist.json', mappings); + utils.loadFileAndReplaceKeywords('notexist.json', { + mappings, + disableKeywordReplacement: context.disableKeywordReplacement, + }); }).to.throw(/Unable to load file.*/); });