Skip to content
This repository has been archived by the owner on Feb 28, 2021. It is now read-only.

Commit

Permalink
Hooks support (#44)
Browse files Browse the repository at this point in the history
* better objects handling for mappings

* hooks support (+tests)

* Update auth-source-control-extension-tools to 4.0.3.

* 3.2.0

* Add more test criteria around hook dependencies.

* Bump extension templates version.

* Update changelog with 3.2.0 release info.

* Update auth0 version.

* Update readme for local development.

* Add scopes  to webtask.json templates.

* Remove old auth0 exclusion.

* Move auth0 client from middleware to own instance.

* Update auth0-extension dependencies with auth0 bump.

* Revert "Move auth0 client from middleware to own instance."

This reverts commit 850f968.

* Remove auth0-extension-tools from externals.

Co-authored-by: Shu Shen <[email protected]>
Co-authored-by: Shawn Mclean <[email protected]>
  • Loading branch information
3 people authored Mar 31, 2020
1 parent d39a35a commit 06f267c
Show file tree
Hide file tree
Showing 18 changed files with 1,504 additions and 321 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [3.2.0] - 2020-03-13

### auth0-bitbucket-deploy v3.2.0
### auth0-github-deploy v3.2.0
### auth0-gitlab-deploy v3.2.0
### auth0-visualstudio-deploy v3.2.0
- #### Added
- Add support for Hooks entity.

## [3.1.1] - 2020-03-06

### auth0-bitbucket-deploy v3.1.1
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ See Custom Pages configuration [here](https://auth0.com/docs/extensions/bitbucke

### Local Development

First create a `Client` in your account with `read:connections` and `read/create/update/delete:rules` access to the Auth0 Management API. Then create a `config.json` file under `./server/` containing the following settings:
First create a machine-machine `Application` in your tenant all scopes selected for the Auth0 Management API. Then create a `config.json` file under `./server/` containing the following settings:

```json
{
Expand Down
1,663 changes: 1,397 additions & 266 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 7 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "auth0-deploy-extensions",
"version": "3.1.1",
"version": "3.2.0",
"description": "Auth0 Deployment Extensions",
"engines": {
"node": "5.9.0"
Expand Down Expand Up @@ -29,10 +29,9 @@
"license": "MIT",
"auth0-extension": {
"externals": [
"auth0@2.17.0",
"auth0@2.23.0",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
Expand Down Expand Up @@ -60,7 +59,6 @@
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
Expand All @@ -81,12 +79,12 @@
},
"dependencies": {
"async": "2.1.2",
"auth0": "2.17.0",
"auth0-extension-express-tools": "^2.0.0",
"auth0-extension-tools": "1.4.0",
"auth0": "^2.23.0",
"auth0-extension-express-tools": "^2.0.1",
"auth0-extension-tools": "1.4.5",
"auth0-extension-ui": "^1.0.1",
"auth0-oauth2-express": "^1.1.8",
"auth0-source-control-extension-tools": "3.5.1",
"auth0-source-control-extension-tools": "4.0.3",
"axios": "^0.18.0",
"babel": "^6.5.2",
"babel-core": "^6.9.1",
Expand Down
9 changes: 6 additions & 3 deletions server/lib/providers/bitbucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ const getTree = (parsedRepo, branch, sha) => {
databases: getDBConnectionsTree(params),
tenant: getTreeByDir(params, ''),
rules: getTreeByDir(params, constants.RULES_DIRECTORY),
hooks: getTreeByDir(params, constants.HOOKS_DIRECTORY),
pages: getTreeByDir(params, constants.PAGES_DIRECTORY),
roles: getTreeByDir(params, constants.ROLES_DIRECTORY),
emails: getTreeByDir(params, constants.EMAIL_TEMPLATES_DIRECTORY),
Expand All @@ -122,6 +123,7 @@ const getTree = (parsedRepo, branch, sha) => {
return Promise.props(promises)
.then((result) => (_.union(
result.rules,
result.hooks,
result.databases,
result.tenant,
result.emails,
Expand Down Expand Up @@ -223,8 +225,8 @@ const downloadConfigurable = (parsedRepo, branch, name, item, shaToken) => {
/*
* Determine if we have the script, the metadata or both.
*/
const getRules = (parsedRepo, branch, files, shaToken) => {
const rules = utils.getRulesFiles(files);
const getHooksOrRules = (parsedRepo, branch, files, shaToken, dir) => {
const rules = utils.getHooksOrRulesFiles(files, dir);

// Download all rules.
return Promise.map(Object.keys(rules), (ruleName) =>
Expand Down Expand Up @@ -350,7 +352,8 @@ export function getChanges({ repository, branch, sha, mappings }) {

const promises = {
tenant: getTenant(parsedRepo, branch, files, sha),
rules: getRules(parsedRepo, branch, files, sha),
rules: getHooksOrRules(parsedRepo, branch, files, sha, constants.RULES_DIRECTORY),
hooks: getHooksOrRules(parsedRepo, branch, files, sha, constants.HOOKS_DIRECTORY),
databases: getDatabaseData(parsedRepo, branch, files, sha),
emailProvider: getEmailProvider(parsedRepo, branch, files, sha),
emailTemplates: getHtmlTemplates(parsedRepo, branch, files, sha, constants.EMAIL_TEMPLATES_DIRECTORY, constants.EMAIL_TEMPLATES_NAMES),
Expand Down
7 changes: 4 additions & 3 deletions server/lib/providers/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ const downloadRule = (repository, branch, ruleName, rule) => {
/*
* Determine if we have the script, the metadata or both.
*/
const getRules = (repository, branch, files) => {
const rules = utils.getRulesFiles(files);
const getHooksOrRules = (repository, branch, files, dir) => {
const rules = utils.getHooksOrRulesFiles(files, dir);

// Download all rules.
return Promise.map(Object.keys(rules), (ruleName) =>
Expand Down Expand Up @@ -288,7 +288,8 @@ export const getChanges = ({ repository, branch, sha, mappings }) =>
})), null, 2)}`);

const promises = {
rules: getRules(repository, branch, files),
rules: getHooksOrRules(repository, branch, files, constants.RULES_DIRECTORY),
hooks: getHooksOrRules(repository, branch, files, constants.HOOKS_DIRECTORY),
tenant: getTenant(repository, branch, files),
databases: getDatabaseData(repository, branch, files),
emailProvider: getEmailProvider(repository, branch, files),
Expand Down
9 changes: 6 additions & 3 deletions server/lib/providers/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ const getTree = (projectId, branch) => {
const promises = {
tenant: getTreeByPath(projectId, branch, ''),
rules: getTreeByPath(projectId, branch, constants.RULES_DIRECTORY),
hooks: getTreeByPath(projectId, branch, constants.HOOKS_DIRECTORY),
databases: getDBConnectionsTree(projectId, branch),
emails: getTreeByPath(projectId, branch, constants.EMAIL_TEMPLATES_DIRECTORY),
guardianFactors: getTreeByPath(projectId, branch, path.join(constants.GUARDIAN_DIRECTORY, constants.GUARDIAN_FACTORS_DIRECTORY)),
Expand All @@ -131,6 +132,7 @@ const getTree = (projectId, branch) => {
.then((result) => (_.union(
result.tenant,
result.rules,
result.hooks,
result.databases,
result.emails,
result.guardianFactors,
Expand Down Expand Up @@ -219,8 +221,8 @@ const downloadConfigurable = (projectId, branch, itemName, item) => {
/*
* Determine if we have the script, the metadata or both.
*/
const getRules = (projectId, branch, files) => {
const rules = utils.getRulesFiles(files);
const getHooksOrRules = (projectId, branch, files, dir) => {
const rules = utils.getHooksOrRulesFiles(files, dir);

// Download all rules.
return Promise.map(Object.keys(rules), (ruleName) =>
Expand Down Expand Up @@ -339,7 +341,8 @@ export const getChanges = ({ projectId, branch, mappings }) =>

const promises = {
tenant: getTenant(projectId, branch, files),
rules: getRules(projectId, branch, files),
rules: getHooksOrRules(projectId, branch, files, constants.RULES_DIRECTORY),
hooks: getHooksOrRules(projectId, branch, files, constants.HOOKS_DIRECTORY),
databases: getDatabaseData(projectId, branch, files),
emailProvider: getEmailProvider(projectId, branch, files),
emailTemplates: getHtmlTemplates(projectId, branch, files, constants.EMAIL_TEMPLATES_DIRECTORY, constants.EMAIL_TEMPLATES_NAMES),
Expand Down
7 changes: 4 additions & 3 deletions server/lib/providers/tfs-git.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ const downloadConfigurable = (repositoryId, branch, name, item) => {
/*
* Determine if we have the script, the metadata or both.
*/
const getRules = (repositoryId, branch, files) => {
const rules = utils.getRulesFiles(files);
const getHooksOrRules = (repositoryId, branch, files, dir) => {
const rules = utils.getHooksOrRulesFiles(files, dir);

// Download all rules.
return Promise.map(Object.keys(rules), (ruleName) => downloadRule(repositoryId, branch, ruleName, rules[ruleName]), { concurrency: 2 });
Expand Down Expand Up @@ -311,7 +311,8 @@ export const getChanges = ({ repositoryId, branch, mappings }) =>

const promises = {
tenant: getTenant(repositoryId, branch, files),
rules: getRules(repositoryId, branch, files),
rules: getHooksOrRules(repositoryId, branch, files, constants.RULES_DIRECTORY),
hooks: getHooksOrRules(repositoryId, branch, files, constants.HOOKS_DIRECTORY),
databases: getDatabaseData(repositoryId, branch, files),
emailProvider: getEmailProvider(repositoryId, branch, files),
emailTemplates: getHtmlTemplates(repositoryId, branch, files, constants.EMAIL_TEMPLATES_DIRECTORY, constants.EMAIL_TEMPLATES_NAMES),
Expand Down
9 changes: 6 additions & 3 deletions server/lib/providers/tfs-tfvc.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const getTree = (project, changesetId) =>
const promises = {
tenant: getConfigurableTree(project, ''),
rules: getConfigurableTree(project, constants.RULES_DIRECTORY),
hooks: getConfigurableTree(project, constants.HOOKS_DIRECTORY),
databases: getConnectionsTree(project, changesetId),
emails: getConfigurableTree(project, constants.EMAIL_TEMPLATES_DIRECTORY),
guardianFactors: getConfigurableTree(project, path.join(constants.GUARDIAN_DIRECTORY, constants.GUARDIAN_FACTORS_DIRECTORY)),
Expand All @@ -153,6 +154,7 @@ const getTree = (project, changesetId) =>
.then(result => resolve(_.union(
result.tenant,
result.rules,
result.hooks,
result.databases,
result.emails,
result.guardianFactors,
Expand Down Expand Up @@ -256,8 +258,8 @@ const downloadConfigurable = (changesetId, name, item) => {
/*
* Determine if we have the script, the metadata or both.
*/
const getRules = (changesetId, files) => {
const rules = utils.getRulesFiles(files);
const getHooksOrRules = (changesetId, files, dir) => {
const rules = utils.getHooksOrRulesFiles(files, dir);

// Download all rules.
return Promise.map(Object.keys(rules), ruleName => downloadRule(changesetId, ruleName, rules[ruleName]), { concurrency: 2 });
Expand Down Expand Up @@ -376,7 +378,8 @@ export const getChanges = ({ project, changesetId, mappings }) =>

const promises = {
tenant: getTenant(changesetId, files),
rules: getRules(changesetId, files),
rules: getHooksOrRules(changesetId, files, constants.RULES_DIRECTORY),
hooks: getHooksOrRules(changesetId, files, constants.HOOKS_DIRECTORY),
databases: getDatabaseData(changesetId, files),
emailProvider: getEmailProvider(changesetId, files),
emailTemplates: getHtmlTemplates(changesetId, files, constants.EMAIL_TEMPLATES_DIRECTORY, constants.EMAIL_TEMPLATES_NAMES),
Expand Down
23 changes: 16 additions & 7 deletions server/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ const getPrefix = () =>
/*
* Check if a file is part of the rules folder.
*/
const isRule = (file) =>
file.indexOf(`${path.join(getPrefix(), constants.RULES_DIRECTORY)}/`) === 0;
const isHookOrRule = (file, dir) =>
file.indexOf(`${path.join(getPrefix(), dir)}/`) === 0;

/*
* Check if a file is part of the database folder.
Expand Down Expand Up @@ -121,7 +121,9 @@ const validFilesOnly = (fileName) => {
return true;
} else if (isGuardianFile(fileName)) {
return true;
} else if (isRule(fileName)) {
} else if (isHookOrRule(fileName, constants.RULES_DIRECTORY)) {
return /\.(js|json)$/i.test(fileName);
} else if (isHookOrRule(fileName, constants.HOOKS_DIRECTORY)) {
return /\.(js|json)$/i.test(fileName);
} else if (isConfigurable(fileName, constants.ROLES_DIRECTORY)) {
return /\.(js|json)$/i.test(fileName);
Expand Down Expand Up @@ -241,10 +243,10 @@ const getTplFiles = (files, directory, allowedNames) => {
return templates;
};

const getRulesFiles = (files) => {
const getHooksOrRulesFiles = (files, dir) => {
const rules = {};

_.filter(files, f => isRule(f.path)).forEach(file => {
_.filter(files, f => isHookOrRule(f.path, dir)).forEach(file => {
const ruleName = path.parse(file.path).name;
rules[ruleName] = rules[ruleName] || {};

Expand Down Expand Up @@ -294,6 +296,13 @@ const unifyItem = (item, type, mappings) => {

return ({ script, name: item.name, order, stage, enabled });
}
case 'hooks': {
const meta = extractFileContent(item.metadataFile, mappings);
const script = extractFileContent(item.scriptFile, mappings, true);
const { name, enabled, triggerId, secrets = {}, dependencies = {} } = meta;

return ({ name, enabled, triggerId, secrets, dependencies, script });
}
case 'pages': {
const meta = extractFileContent(item.metadataFile, mappings);
const html = extractFileContent(item.htmlFile, mappings, true);
Expand Down Expand Up @@ -422,7 +431,7 @@ module.exports = {
unifyData,
getBaseDir,
getPrefix,
isRule,
isHookOrRule,
isDatabaseConnection,
isTemplate,
isTenantFile,
Expand All @@ -432,7 +441,7 @@ module.exports = {
getDatabaseFiles,
getConfigurablesFiles,
getTplFiles,
getRulesFiles,
getHooksOrRulesFiles,
validFilesOnly,
getOptions,
parseRepo
Expand Down
18 changes: 18 additions & 0 deletions tests/server/mocks/expected-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@ module.exports = {
stage: 'login_success'
}
],
hooks: [
{
script: 'hook1 script',
name: 'Hook-1',
triggerId: 'client-credentials',
enabled: true,
secrets: {},
dependencies: {}
},
{
script: 'hook2 script',
name: 'Hook-2',
triggerId: 'post-user-registration',
enabled: true,
secrets: { TEST: 'test' },
dependencies: { bcrypt: '1.0.0' }
}
],
databases: [
{
enabled_clients: [
Expand Down
7 changes: 7 additions & 0 deletions tests/server/mocks/repo-data-mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ module.exports = {
scriptFile: 'Rule script',
metadataFile: '{ "enabled":true }'
} ],
hooks: [ {
script: true,
metadata: true,
name: 'test-script-111',
scriptFile: 'Hook script',
metadataFile: '{ "name": "Hook", "triggerId": "client-credentials" }'
} ],
databases: [ {
name: 'Database',
settings: '{ "options": { "enabled_clients": [ "whatever" ] } }',
Expand Down
6 changes: 6 additions & 0 deletions tests/server/mocks/repo-tree-mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ module.exports = {
'rule1.json': { order: 10, enabled: false },
'rule2.js': 'rule2 script'
},
hooks: {
'hook1.js': 'hook1 script',
'hook1.json': { name: 'Hook-1', triggerId: 'client-credentials', enabled: true },
'hook2.js': 'hook2 script',
'hook2.json': { name: 'Hook-2', triggerId: 'post-user-registration', enabled: true, secrets: { TEST: 'test' }, dependencies: { bcrypt: '1.0.0' } }
},
roles: {
'role.json': {
name: 'Test role',
Expand Down
6 changes: 6 additions & 0 deletions tests/server/utils.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ describe('unifyData', () => {
expect(unified.rules[0].stage).toEqual('login_success');
expect(unified.rules[0].enabled).toEqual(true);

expect(unified.hooks).toBeAn('array');
expect(unified.hooks[0]).toBeAn('object');
expect(unified.hooks[0].script).toEqual('Hook script');
expect(unified.hooks[0].name).toEqual('Hook');
expect(unified.hooks[0].triggerId).toEqual('client-credentials');

expect(unified.databases).toBeAn('array');

expect(unified.databases[0]).toBeAn('object');
Expand Down
4 changes: 2 additions & 2 deletions webtask-templates/bitbucket.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "Bitbucket Deployments",
"name": "auth0-bitbucket-deploy",
"version": "3.1.1",
"version": "3.2.0",
"preVersion": "2.10.0",
"author": "auth0",
"description": "This extension gives Auth0 customers the possibility to deploy Hosted Pages, Rules and Custom Database Connections from Bitbucket.",
Expand All @@ -20,7 +20,7 @@
"auth0": {
"createClient": true,
"onUninstallPath": "/.extensions/on-uninstall",
"scopes": "read:client_grants create:client_grants delete:client_grants update:client_grants read:clients update:clients delete:clients create:clients read:client_keys update:client_keys delete:client_keys create:client_keys read:connections update:connections delete:connections create:connections read:resource_servers update:resource_servers delete:resource_servers create:resource_servers read:rules update:rules delete:rules create:rules read:rules_configs update:rules_configs delete:rules_configs read:email_provider update:email_provider delete:email_provider create:email_provider read:tenant_settings update:tenant_settings read:grants delete:grants read:guardian_factors update:guardian_factors read:email_templates create:email_templates update:email_templates read:roles update:roles delete:roles create:roles"
"scopes": "read:client_grants create:client_grants delete:client_grants update:client_grants read:clients update:clients delete:clients create:clients read:client_keys update:client_keys delete:client_keys create:client_keys read:connections update:connections delete:connections create:connections read:resource_servers update:resource_servers delete:resource_servers create:resource_servers read:rules update:rules delete:rules create:rules read:rules_configs update:rules_configs delete:rules_configs read:email_provider update:email_provider delete:email_provider create:email_provider read:tenant_settings update:tenant_settings read:grants delete:grants read:guardian_factors update:guardian_factors read:email_templates create:email_templates update:email_templates read:roles update:roles delete:roles create:roles read:hooks update:hooks delete:hooks create:hooks"
},
"secrets": {
"REPOSITORY": {
Expand Down
Loading

0 comments on commit 06f267c

Please sign in to comment.