Skip to content

Commit

Permalink
Sanitize file and folder names (#92)
Browse files Browse the repository at this point in the history
* update env var in docs. Might help with #88

* Handle filenames/directories properly fixes #81

* add tests

* linting error
  • Loading branch information
stevezau authored and fyockm committed Feb 22, 2019
1 parent 617c699 commit 78f6752
Show file tree
Hide file tree
Showing 22 changed files with 294 additions and 24 deletions.
21 changes: 21 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 @@ -39,6 +39,7 @@
"nconf": "^0.8.4",
"node-storage": "0.0.7",
"readline": "^1.3.0",
"sanitize-filename": "^1.6.1",
"superagent": "^3.5.2",
"winston": "^2.3.0",
"xregexp": "^3.1.1",
Expand Down
4 changes: 2 additions & 2 deletions src/context/directory/handlers/clientGrants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { constants } from 'auth0-source-control-extension-tools';

import log from '../../../logger';
import { getFiles, existsMustBeDir, loadJSON } from '../../../utils';
import { getFiles, existsMustBeDir, loadJSON, sanitize } from '../../../utils';

function parse(context) {
const grantsFolder = path.join(context.filePath, constants.CLIENTS_GRANTS_DIRECTORY);
Expand Down Expand Up @@ -35,7 +35,7 @@ async function dump(context) {
const found = clients.find(c => c.client_id === dumpGrant.client_id);
if (found) dumpGrant.client_id = found.name;

const name = `${dumpGrant.client_id} (${dumpGrant.audience})`.replace(/[/\\?%*:|"<>]/g, '-');
const name = sanitize(`${dumpGrant.client_id} (${dumpGrant.audience})`);
const grantFile = path.join(grantsFolder, `${name}.json`);
log.info(`Writing ${grantFile}`);
fs.writeFileSync(grantFile, JSON.stringify(dumpGrant, null, 2));
Expand Down
4 changes: 2 additions & 2 deletions src/context/directory/handlers/clients.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { constants } from 'auth0-source-control-extension-tools';

import log from '../../../logger';
import { getFiles, existsMustBeDir, loadJSON } from '../../../utils';
import { getFiles, existsMustBeDir, loadJSON, sanitize } from '../../../utils';

function parse(context) {
const clientsFolder = path.join(context.filePath, constants.CLIENTS_DIRECTORY);
Expand All @@ -29,7 +29,7 @@ async function dump(context) {
fs.ensureDirSync(clientsFolder);

clients.forEach((client) => {
const clientFile = path.join(clientsFolder, `${client.name}.json`);
const clientFile = path.join(clientsFolder, sanitize(`${client.name}.json`));
log.info(`Writing ${clientFile}`);
fs.writeFileSync(clientFile, JSON.stringify(client, null, 2));
});
Expand Down
4 changes: 2 additions & 2 deletions src/context/directory/handlers/connections.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { constants } from 'auth0-source-control-extension-tools';

import log from '../../../logger';
import { getFiles, existsMustBeDir, loadJSON } from '../../../utils';
import { getFiles, existsMustBeDir, loadJSON, sanitize } from '../../../utils';

function parse(context) {
const connectionsFolder = path.join(context.filePath, constants.CONNECTIONS_DIRECTORY);
Expand Down Expand Up @@ -41,7 +41,7 @@ async function dump(context) {
]
};

const connectionFile = path.join(connectionsFolder, `${dumpedConnection.name}.json`);
const connectionFile = path.join(connectionsFolder, sanitize(`${dumpedConnection.name}.json`));
log.info(`Writing ${connectionFile}`);
fs.writeFileSync(connectionFile, JSON.stringify(dumpedConnection, null, 2));
});
Expand Down
9 changes: 5 additions & 4 deletions src/context/directory/handlers/databases.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs-extra';
import { constants, loadFile } from 'auth0-source-control-extension-tools';

import log from '../../../logger';
import { isDirectory, existsMustBeDir, loadJSON, getFiles } from '../../../utils';
import { isDirectory, existsMustBeDir, loadJSON, getFiles, sanitize } from '../../../utils';


function getDatabase(folder, mappings) {
Expand Down Expand Up @@ -72,7 +72,7 @@ async function dump(context) {
fs.ensureDirSync(databasesFolder);

databases.forEach((database) => {
const dbFolder = path.join(databasesFolder, database.name);
const dbFolder = path.join(databasesFolder, sanitize(database.name));
fs.ensureDirSync(dbFolder);

const formatted = {
Expand All @@ -90,10 +90,11 @@ async function dump(context) {
...(database.options.customScripts && {
customScripts: Object.entries(database.options.customScripts).reduce((scripts, [ name, script ]) => {
// Dump custom script to file
const scriptFile = path.join(dbFolder, `${name}.js`);
const scriptName = sanitize(`${name}.js`);
const scriptFile = path.join(dbFolder, scriptName);
log.info(`Writing ${scriptFile}`);
fs.writeFileSync(scriptFile, script);
scripts[name] = `./${name}.js`;
scripts[name] = `./${scriptName}`;
return scripts;
}, {})
})
Expand Down
4 changes: 2 additions & 2 deletions src/context/directory/handlers/resourceServers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { constants } from 'auth0-source-control-extension-tools';

import log from '../../../logger';
import { getFiles, existsMustBeDir, loadJSON } from '../../../utils';
import { getFiles, existsMustBeDir, loadJSON, sanitize } from '../../../utils';

function parse(context) {
const resourceServersFolder = path.join(context.filePath, constants.RESOURCE_SERVERS_DIRECTORY);
Expand All @@ -29,7 +29,7 @@ async function dump(context) {
fs.ensureDirSync(resourceServersFolder);

resourceServers.forEach((resourceServer) => {
const resourceServerFile = path.join(resourceServersFolder, `${resourceServer.name}.json`);
const resourceServerFile = path.join(resourceServersFolder, sanitize(`${resourceServer.name}.json`));
log.info(`Writing ${resourceServerFile}`);
fs.writeFileSync(resourceServerFile, JSON.stringify(resourceServer, null, 2));
});
Expand Down
9 changes: 5 additions & 4 deletions src/context/directory/handlers/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'path';
import { constants } from 'auth0-source-control-extension-tools';

import log from '../../../logger';
import { getFiles, existsMustBeDir, loadJSON } from '../../../utils';
import { getFiles, existsMustBeDir, loadJSON, sanitize } from '../../../utils';


function parse(context) {
Expand Down Expand Up @@ -36,14 +36,15 @@ async function dump(context) {
fs.ensureDirSync(rulesFolder);
rules.forEach((rule) => {
// Dump script to file
const ruleJS = path.join(rulesFolder, `${rule.name}.js`);
const name = sanitize(rule.name);
const ruleJS = path.join(rulesFolder, `${name}.js`);
log.info(`Writing ${ruleJS}`);
fs.writeFileSync(ruleJS, rule.script);

// Dump template metadata
const ruleFile = path.join(rulesFolder, `${rule.name}.json`);
const ruleFile = path.join(rulesFolder, `${name}.json`);
log.info(`Writing ${ruleFile}`);
fs.writeFileSync(ruleFile, JSON.stringify({ ...rule, script: `./${rule.name}.js` }, null, 2));
fs.writeFileSync(ruleFile, JSON.stringify({ ...rule, script: `./${name}.js` }, null, 2));
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/context/directory/handlers/rulesConfigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs-extra';
import path from 'path';
import { constants } from 'auth0-source-control-extension-tools';

import { getFiles, existsMustBeDir, loadJSON } from '../../../utils';
import { getFiles, existsMustBeDir, loadJSON, sanitize } from '../../../utils';
import log from '../../../logger';

function parse(context) {
Expand All @@ -29,7 +29,7 @@ async function dump(context) {
fs.ensureDirSync(ruleConfigsFolder);

rulesConfigs.forEach((rulesConfig) => {
const ruleConfigFile = path.join(ruleConfigsFolder, `${rulesConfig.key}.json`);
const ruleConfigFile = path.join(ruleConfigsFolder, sanitize(`${rulesConfig.key}.json`));
log.info(`Writing ${ruleConfigFile}`);
fs.writeFileSync(ruleConfigFile, JSON.stringify({
value: '******',
Expand Down
9 changes: 6 additions & 3 deletions src/context/yaml/handlers/databases.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs-extra';
import path from 'path';

import { sanitize } from '../../../utils';
import log from '../../../logger';


Expand Down Expand Up @@ -53,14 +54,16 @@ async function dump(context) {
...(database.options.customScripts && {
customScripts: Object.entries(database.options.customScripts).reduce((scripts, [ name, script ]) => {
// Create Database folder
const dbFolder = path.join(context.basePath, 'databases', database.name);
const dbName = sanitize(database.name);
const dbFolder = path.join(context.basePath, 'databases', sanitize(dbName));
fs.ensureDirSync(dbFolder);

// Dump custom script to file
const scriptFile = path.join(dbFolder, `${name}.js`);
const scriptName = sanitize(name);
const scriptFile = path.join(dbFolder, `${scriptName}.js`);
log.info(`Writing ${scriptFile}`);
fs.writeFileSync(scriptFile, script);
scripts[name] = `./databases/${database.name}/${name}.js`;
scripts[name] = `./databases/${dbName}/${scriptName}.js`;
return scripts;
}, {})
})
Expand Down
6 changes: 4 additions & 2 deletions src/context/yaml/handlers/rules.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';
import fs from 'fs-extra';

import { sanitize } from '../../../utils';
import log from '../../../logger';

async function parse(context) {
Expand Down Expand Up @@ -28,10 +29,11 @@ async function dump(context) {

rules = rules.map((rule) => {
// Dump rule to file
const scriptFile = path.join(rulesFolder, `${rule.name}.js`);
const scriptName = sanitize(`${rule.name}.js`);
const scriptFile = path.join(rulesFolder, scriptName);
log.info(`Writing ${scriptFile}`);
fs.writeFileSync(scriptFile, rule.script);
return { ...rule, script: `./rules/${rule.name}.js` };
return { ...rule, script: `./rules/${scriptName}` };
});
}

Expand Down
6 changes: 6 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs-extra';
import path from 'path';
import sanitizeName from 'sanitize-filename';
import { loadFile } from 'auth0-source-control-extension-tools';

export function isDirectory(f) {
Expand Down Expand Up @@ -83,3 +84,8 @@ export function stripIdentifiers(auth0, assets) {

return updated;
}


export function sanitize(str) {
return sanitizeName(str, { replacement: '-' });
}
14 changes: 14 additions & 0 deletions test/context/directory/clientGrants.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,18 @@ describe('#directory context clientGrants', () => {
const clientGrantsFolder = path.join(dir, constants.CLIENTS_GRANTS_DIRECTORY);
expect(loadJSON(path.join(clientGrantsFolder, 'My M2M (https---test.myapp.com-api-v1).json'))).to.deep.equal(context.assets.clientGrants[0]);
});

it('should dump client grants sanitized', async () => {
const dir = path.join(testDataDir, 'directory', 'clientGrantsDump');
cleanThenMkdir(dir);
const context = new Context({ AUTH0_INPUT_FILE: dir }, mockMgmtClient());

context.assets.clientGrants = [
{ audience: 'https://test.myapp.com/api/v1', client_id: 'My M2M', scope: [ 'update:account' ] }
];

await handler.dump(context);
const clientGrantsFolder = path.join(dir, constants.CLIENTS_GRANTS_DIRECTORY);
expect(loadJSON(path.join(clientGrantsFolder, 'My M2M (https---test.myapp.com-api-v1).json'))).to.deep.equal(context.assets.clientGrants[0]);
});
});
16 changes: 16 additions & 0 deletions test/context/directory/clients.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,20 @@ describe('#directory context clients', () => {
expect(loadJSON(path.join(clientFolder, 'someClient.json'))).to.deep.equal(context.assets.clients[0]);
expect(loadJSON(path.join(clientFolder, 'someClient2.json'))).to.deep.equal(context.assets.clients[1]);
});

it('should dump clients sanitized', async () => {
const dir = path.join(testDataDir, 'directory', 'clientsDump');
cleanThenMkdir(dir);
const context = new Context({ AUTH0_INPUT_FILE: dir }, mockMgmtClient());

context.assets.clients = [
{ app_type: 'spa', name: 'someClient-test' },
{ app_type: 'spa', name: 'someClient2/aa' }
];

await handler.dump(context);
const clientFolder = path.join(dir, constants.CLIENTS_DIRECTORY);
expect(loadJSON(path.join(clientFolder, 'someClient-test.json'))).to.deep.equal(context.assets.clients[0]);
expect(loadJSON(path.join(clientFolder, 'someClient2-aa.json'))).to.deep.equal(context.assets.clients[1]);
});
});
16 changes: 16 additions & 0 deletions test/context/directory/connections.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,20 @@ describe('#directory context connections', () => {
expect(loadJSON(path.join(clientFolder, 'myad-waad.json'))).to.deep.equal(context.assets.connections[0]);
expect(loadJSON(path.join(clientFolder, 'facebook.json'))).to.deep.equal(context.assets.connections[1]);
});

it('should dump connections sanitized', async () => {
const dir = path.join(testDataDir, 'directory', 'connectionsDump');
cleanThenMkdir(dir);
const context = new Context({ AUTH0_INPUT_FILE: dir }, mockMgmtClient());

context.assets.connections = [
{
name: 'my/ad-waad', strategy: 'waad', var: 'something', enabled_clients: []
}
];

await handler.dump(context);
const clientFolder = path.join(dir, constants.CONNECTIONS_DIRECTORY);
expect(loadJSON(path.join(clientFolder, 'my-ad-waad.json'))).to.deep.equal(context.assets.connections[0]);
});
});
36 changes: 36 additions & 0 deletions test/context/directory/databases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,40 @@ describe('#directory context databases', () => {
expect(fs.readFileSync(path.join(scripsFolder, 'login.js'), 'utf8')).to.deep.equal(scriptValidate);
expect(fs.readFileSync(path.join(scripsFolder, 'verify.js'), 'utf8')).to.deep.equal(scriptValidate);
});

it('should dump custom databases sanitized', async () => {
cleanThenMkdir(dbDumpDir);
const context = new Context({ AUTH0_INPUT_FILE: dbDumpDir }, mockMgmtClient());

const scriptValidate = 'function login() { var env1 = "env2"; }';
context.assets.databases = [
{
name: 'users/test',
enabled_clients: [],
options: {
customScripts: {
change_email: scriptValidate
},
enabledDatabaseCustomization: true
},
strategy: 'auth0'
}
];

await handler.dump(context);
const scripsFolder = path.join(dbDumpDir, constants.DATABASE_CONNECTIONS_DIRECTORY, 'users-test');
expect(loadJSON(path.join(scripsFolder, 'database.json'))).to.deep.equal({
name: 'users/test',
enabled_clients: [],
options: {
customScripts: {
change_email: './change_email.js'
},
enabledDatabaseCustomization: true
},
strategy: 'auth0'
});

expect(fs.readFileSync(path.join(scripsFolder, 'change_email.js'), 'utf8')).to.deep.equal(scriptValidate);
});
});
22 changes: 22 additions & 0 deletions test/context/directory/resourceServers.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,26 @@ describe('#directory context resourceServers', () => {
const resourceServersFolder = path.join(dir, constants.RESOURCE_SERVERS_DIRECTORY);
expect(loadJSON(path.join(resourceServersFolder, 'my resource.json'))).to.deep.equal(context.assets.resourceServers[0]);
});

it('should dump resource servers sanitized', async () => {
const dir = path.join(testDataDir, 'directory', 'resourceServersDump');
cleanThenMkdir(dir);
const context = new Context({ AUTH0_INPUT_FILE: dir }, mockMgmtClient());

context.assets.resourceServers = [
{
identifier: 'http://myapi.com/api',
name: 'my/test/ resource',
scopes: [
{ description: 'update account', name: 'update:account' },
{ description: 'read account', name: 'read:account' },
{ description: 'admin access', name: 'admin' }
]
}
];

await handler.dump(context);
const resourceServersFolder = path.join(dir, constants.RESOURCE_SERVERS_DIRECTORY);
expect(loadJSON(path.join(resourceServersFolder, 'my-test- resource.json'))).to.deep.equal(context.assets.resourceServers[0]);
});
});
Loading

0 comments on commit 78f6752

Please sign in to comment.