Skip to content

Commit

Permalink
Merge pull request #671 from auth0/DXCDT-237-undefined-html-page-temp…
Browse files Browse the repository at this point in the history
…late

DXCDT-237: Fixing undefined HTML page template writing
  • Loading branch information
willvedd authored Oct 19, 2022
2 parents 5b05483 + 5e40a29 commit 79686dd
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 35 deletions.
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"yargs": "^15.3.1"
},
"devDependencies": {
"@types/fs-extra": "^9.0.13",
"@types/lodash": "^4.14.185",
"@types/mocha": "^9.1.0",
"@types/nconf": "^0.10.3",
Expand Down
3 changes: 2 additions & 1 deletion src/context/directory/handlers/databases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,14 @@ async function dump(context: DirectoryContext): Promise<void> {
// customScripts option only written if there are scripts
...(database.options.customScripts && {
customScripts: Object.entries(database.options.customScripts)
//@ts-ignore
//@ts-ignore because we'll fix this in subsequent PR
.sort(sortCustomScripts)
.reduce((scripts, [name, script]) => {
// Dump custom script to file
const scriptName = sanitize(`${name}.js`);
const scriptFile = path.join(dbFolder, scriptName);
log.info(`Writing ${scriptFile}`);
//@ts-ignore because we'll fix this in subsequent PR
fs.writeFileSync(scriptFile, script);
scripts[name] = `./${scriptName}`;
return scripts;
Expand Down
18 changes: 8 additions & 10 deletions src/context/directory/handlers/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import log from '../../../logger';
import { getFiles, existsMustBeDir, dumpJSON, loadJSON } from '../../../utils';
import { DirectoryHandler } from '.';
import DirectoryContext from '..';
import { Asset, ParsedAsset } from '../../../types';
import { ParsedAsset } from '../../../types';
import { Page } from '../../../tools/auth0/handlers/pages';

type ParsedPages = ParsedAsset<'pages', Asset[]>;
type ParsedPages = ParsedAsset<'pages', Page[]>;

function parse(context: DirectoryContext): ParsedPages {
const pagesFolder = path.join(context.filePath, constants.PAGES_DIRECTORY);
Expand All @@ -29,7 +30,7 @@ function parse(context: DirectoryContext): ParsedPages {
return acc;
}, {});

const pages = Object.keys(sorted).flatMap((key): Asset[] => {
const pages = Object.keys(sorted).flatMap((key): Page[] => {
const { meta, html } = sorted[key];
if (!meta) {
log.warn(`Skipping pages file ${html} as missing the corresponding '.json' file`);
Expand Down Expand Up @@ -60,24 +61,21 @@ function parse(context: DirectoryContext): ParsedPages {
async function dump(context: DirectoryContext): Promise<void> {
const pages = context.assets.pages;

if (!pages) return; // Skip, nothing to dump
if (!pages) return;

// Create Pages folder
const pagesFolder = path.join(context.filePath, constants.PAGES_DIRECTORY);
fs.ensureDirSync(pagesFolder);

pages.forEach((page) => {
var metadata = { ...page };
const metadata = { ...page };

if (page.name !== 'error_page' || page.html !== undefined) {
// Dump template html to file
if (page.html !== undefined) {
const htmlFile = path.join(pagesFolder, `${page.name}.html`);
log.info(`Writing ${htmlFile}`);
fs.writeFileSync(htmlFile || '', page.html);
fs.writeFileSync(htmlFile, page.html);
metadata.html = `./${page.name}.html`;
}

// Dump page metadata
const pageFile = path.join(pagesFolder, `${page.name}.json`);
dumpJSON(pageFile, metadata);
});
Expand Down
2 changes: 2 additions & 0 deletions src/context/yaml/handlers/databases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ async function dump(context: YAMLContext): Promise<ParsedDatabases> {
// customScripts option only written if there are scripts
...(database.options.customScripts && {
customScripts: Object.entries(database.options.customScripts)
//@ts-ignore because we'll fix this in subsequent PR
.sort(sortCustomScripts)
.reduce((scripts, [name, script]) => {
// Create Database folder
Expand All @@ -69,6 +70,7 @@ async function dump(context: YAMLContext): Promise<ParsedDatabases> {
const scriptName = sanitize(name);
const scriptFile = path.join(dbFolder, `${scriptName}.js`);
log.info(`Writing ${scriptFile}`);
//@ts-ignore because we'll fix this in subsequent PR
fs.writeFileSync(scriptFile, script);
scripts[name] = `./databases/${dbName}/${scriptName}.js`;
return scripts;
Expand Down
11 changes: 5 additions & 6 deletions src/context/yaml/handlers/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import fs from 'fs-extra';
import log from '../../../logger';
import { YAMLHandler } from '.';
import YAMLContext from '..';
import { Asset, ParsedAsset } from '../../../types';
import { ParsedAsset } from '../../../types';
import { Page } from '../../../tools/auth0/handlers/pages';

type ParsedPages = ParsedAsset<'pages', Asset[]>;
type ParsedPages = ParsedAsset<'pages', Page[]>;

async function parse(context: YAMLContext): Promise<ParsedPages> {
// Load the HTML file for each page
Expand All @@ -31,19 +32,17 @@ async function dump(context: YAMLContext): Promise<ParsedPages> {
return { pages: null };
}

// Create Pages folder
const pagesFolder = path.join(context.basePath, 'pages');
fs.ensureDirSync(pagesFolder);

pages = pages.map((page) => {
if (page.name === 'error_page' && page.html === undefined) {
if (page.html === undefined) {
return page;
}

// Dump html to file
const htmlFile = path.join(pagesFolder, `${page.name}.html`);
log.info(`Writing ${htmlFile}`);
fs.writeFileSync(htmlFile, page.html || '');
fs.writeFileSync(htmlFile, page.html);
return {
...page,
html: `./pages/${page.name}.html`,
Expand Down
8 changes: 8 additions & 0 deletions src/tools/auth0/handlers/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ export const pageNameMap = {
error_page: 'error_page',
};

export type Page = {
show_log_link?: boolean;
name: string;
enabled?: boolean;
html?: string;
url?: string;
};

// With this schema, we can only validate property types but not valid properties on per type basis
export const schema = {
type: 'array',
Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from './tools/auth0/handlers/prompts';
import { Tenant } from './tools/auth0/handlers/tenant';
import { Theme } from './tools/auth0/handlers/themes';
import { Page } from './tools/auth0/handlers/pages';

type SharedPaginationParams = {
checkpoint?: boolean;
Expand Down Expand Up @@ -234,7 +235,7 @@ export type Assets = Partial<{
logStreams: Asset[] | null;
migrations: Asset[] | null;
organizations: Asset[] | null;
pages: Asset[] | null;
pages: Page[] | null;
prompts: Prompts | null;
resourceServers: Asset[] | null;
roles: Asset[] | null;
Expand Down
21 changes: 8 additions & 13 deletions test/context/directory/pages.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,11 @@ describe('#directory context pages', () => {

context.assets.pages = [
{ html: htmlValidation, name: 'login' },
{ html: htmlValidation, name: 'password_reset' },
{ enabled: false, html: htmlValidation, name: 'guardian_multifactor' },
{ enabled: false, html: htmlValidation, name: 'password_reset' },
{ name: 'guardian_multifactor' }, // No `html` property defined
{
html: htmlValidation,
name: 'error_page',
url: errorPageUrl,
url: errorPageUrl, // URL defined instead of `html` property
show_log_link: false,
},
];
Expand All @@ -137,29 +136,25 @@ describe('#directory context pages', () => {
expect(loadJSON(path.join(pagesFolder, 'password_reset.json'))).to.deep.equal({
html: './password_reset.html',
name: 'password_reset',
enabled: false,
});
expect(fs.readFileSync(path.join(pagesFolder, 'password_reset.html'), 'utf8')).to.deep.equal(
htmlValidation
);

expect(loadJSON(path.join(pagesFolder, 'guardian_multifactor.json'))).to.deep.equal({
html: './guardian_multifactor.html',
name: 'guardian_multifactor',
enabled: false,
});
expect(
fs.readFileSync(path.join(pagesFolder, 'guardian_multifactor.html'), 'utf8')
).to.deep.equal(htmlValidation);
// eslint-disable-next-line no-unused-expressions
expect(fs.existsSync(path.join(pagesFolder, 'guardian_multifactor.html'), 'utf8')).to.be.false; // Should not dump template with no HTML

expect(loadJSON(path.join(pagesFolder, 'error_page.json'))).to.deep.equal({
html: './error_page.html',
name: 'error_page',
url: errorPageUrl,
show_log_link: false,
});
expect(fs.readFileSync(path.join(pagesFolder, 'error_page.html'), 'utf8')).to.deep.equal(
htmlValidation
);
// eslint-disable-next-line no-unused-expressions
expect(fs.existsSync(path.join(pagesFolder, 'error_page.html'), 'utf8')).to.be.false; // Should not dump template with no HTML
});

it('should dump empty error page even if HTML is not set', async () => {
Expand Down
6 changes: 2 additions & 4 deletions test/context/yaml/pages.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,22 +145,20 @@ describe('#YAML context pages', () => {
);

context.assets.pages = [
{ html: undefined, name: 'login' }, // HTML property is not defined here
{ name: 'login' }, // HTML property is not defined here
];

const dumped = await handler.dump(context);
expect(dumped).to.deep.equal({
pages: [
{
html: './pages/login.html',
name: 'login',
},
],
});

const pagesFolder = path.join(dir, 'pages');
expect(fs.readFileSync(path.join(pagesFolder, 'login.html'), 'utf8')).to.deep.equal('');
expect(fs.readdirSync(pagesFolder).length).to.equal(1);
expect(fs.readdirSync(pagesFolder).length).to.equal(0);
});

it('should dump error_page with html undefined', async () => {
Expand Down

0 comments on commit 79686dd

Please sign in to comment.