From 3dca3a429140d5b6d230c06119f3e7a864ce4069 Mon Sep 17 00:00:00 2001 From: Chris Scott Date: Wed, 10 Jul 2019 11:48:16 -0400 Subject: [PATCH] Add handlers for the Branding and Prompts API endpoints. (#70) --- src/auth0/handlers/branding.js | 32 ++ src/auth0/handlers/index.js | 6 +- src/auth0/handlers/prompts.js | 32 ++ tests/auth0/handlers/branding.tests.js | 41 +++ tests/auth0/handlers/prompts.tests.js | 41 +++ tests/auth0/validator.tests.js | 474 ++++++++++++------------- 6 files changed, 369 insertions(+), 257 deletions(-) create mode 100644 src/auth0/handlers/branding.js create mode 100644 src/auth0/handlers/prompts.js create mode 100644 tests/auth0/handlers/branding.tests.js create mode 100644 tests/auth0/handlers/prompts.tests.js diff --git a/src/auth0/handlers/branding.js b/src/auth0/handlers/branding.js new file mode 100644 index 000000000..4faf06e86 --- /dev/null +++ b/src/auth0/handlers/branding.js @@ -0,0 +1,32 @@ +import DefaultHandler from './default'; + +export const schema = { type: 'object' }; + +export default class BrandingHandler extends DefaultHandler { + constructor(options) { + super({ + ...options, + type: 'branding' + }); + } + + async getType() { + try { + return await this.client.branding.getSettings(); + } catch (err) { + if (err.statusCode === 404) return {}; + throw err; + } + } + + async processChanges(assets) { + const { branding } = assets; + + // Do nothing if not set + if (!branding) return; + + await this.client.branding.updateSettings(branding); + this.updated += 1; + this.didUpdate(branding); + } +} diff --git a/src/auth0/handlers/index.js b/src/auth0/handlers/index.js index 00971789d..530871705 100644 --- a/src/auth0/handlers/index.js +++ b/src/auth0/handlers/index.js @@ -13,6 +13,8 @@ import * as guardianFactors from './guardianFactors'; import * as guardianFactorProviders from './guardianFactorProviders'; import * as guardianFactorTemplates from './guardianFactorTemplates'; import * as roles from './roles'; +import * as branding from './branding'; +import * as prompts from './prompts'; export { rules, @@ -29,5 +31,7 @@ export { guardianFactors, guardianFactorProviders, guardianFactorTemplates, - roles + roles, + branding, + prompts }; diff --git a/src/auth0/handlers/prompts.js b/src/auth0/handlers/prompts.js new file mode 100644 index 000000000..4dc54bd0f --- /dev/null +++ b/src/auth0/handlers/prompts.js @@ -0,0 +1,32 @@ +import DefaultHandler from './default'; + +export const schema = { type: 'object' }; + +export default class PromptsHandler extends DefaultHandler { + constructor(options) { + super({ + ...options, + type: 'prompts' + }); + } + + async getType() { + try { + return await this.client.prompts.getSettings(); + } catch (err) { + if (err.statusCode === 404) return {}; + throw err; + } + } + + async processChanges(assets) { + const { prompts } = assets; + + // Do nothing if not set + if (!prompts) return; + + await this.client.prompts.updateSettings(prompts); + this.updated += 1; + this.didUpdate(prompts); + } +} diff --git a/tests/auth0/handlers/branding.tests.js b/tests/auth0/handlers/branding.tests.js new file mode 100644 index 000000000..583a8eae2 --- /dev/null +++ b/tests/auth0/handlers/branding.tests.js @@ -0,0 +1,41 @@ +const { expect } = require('chai'); +const branding = require('../../../src/auth0/handlers/branding'); + +describe('#branding handler', () => { + describe('#branding process', () => { + it('should get branding', async () => { + const auth0 = { + branding: { + getSettings: () => ({ + logo_url: 'https://example.com/logo.png' + }) + } + }; + + const handler = new branding.default({ client: auth0 }); + const data = await handler.getType(); + expect(data).to.deep.equal({ + logo_url: 'https://example.com/logo.png' + }); + }); + + it('should update branding settings', async () => { + const auth0 = { + branding: { + updateSettings: (data) => { + expect(data).to.be.an('object'); + expect(data.logo_url).to.equal('https://example.com/logo.png'); + return Promise.resolve(data); + } + } + }; + + const handler = new branding.default({ client: auth0 }); + const stageFn = Object.getPrototypeOf(handler).processChanges; + + await stageFn.apply(handler, [ + { branding: { logo_url: 'https://example.com/logo.png' } } + ]); + }); + }); +}); diff --git a/tests/auth0/handlers/prompts.tests.js b/tests/auth0/handlers/prompts.tests.js new file mode 100644 index 000000000..409f5138c --- /dev/null +++ b/tests/auth0/handlers/prompts.tests.js @@ -0,0 +1,41 @@ +const { expect } = require('chai'); +const prompts = require('../../../src/auth0/handlers/prompts'); + +describe('#prompts handler', () => { + describe('#prompts process', () => { + it('should get prompts', async () => { + const auth0 = { + prompts: { + getSettings: () => ({ + universal_login_experience: 'new' + }) + } + }; + + const handler = new prompts.default({ client: auth0 }); + const data = await handler.getType(); + expect(data).to.deep.equal({ + universal_login_experience: 'new' + }); + }); + + it('should update prompts settings', async () => { + const auth0 = { + prompts: { + updateSettings: (data) => { + expect(data).to.be.an('object'); + expect(data.universal_login_experience).to.equal('new'); + return Promise.resolve(data); + } + } + }; + + const handler = new prompts.default({ client: auth0 }); + const stageFn = Object.getPrototypeOf(handler).processChanges; + + await stageFn.apply(handler, [ + { prompts: { universal_login_experience: 'new' } } + ]); + }); + }); +}); diff --git a/tests/auth0/validator.tests.js b/tests/auth0/validator.tests.js index 21d0904dd..7949834e7 100644 --- a/tests/auth0/validator.tests.js +++ b/tests/auth0/validator.tests.js @@ -18,80 +18,96 @@ describe('#schema validation tests', () => { const checkPassed = (data, done) => { const auth0 = new Auth0(client, data, {}); - auth0.validate() - .then(passedCb(done), failedCb(done)); + auth0.validate().then(passedCb(done), failedCb(done)); }; const checkRequired = (field, data, done) => { const auth0 = new Auth0({}, data, {}); - auth0.validate() - .then(failedCb(done), passedCb(done, `should have required property '${field}'`)); + auth0 + .validate() + .then( + failedCb(done), + passedCb(done, `should have required property '${field}'`) + ); }; const checkEnum = (data, done) => { const auth0 = new Auth0({}, data, {}); - auth0.validate() - .then(failedCb(done), passedCb(done, 'should be equal to one of the allowed values')); + auth0 + .validate() + .then( + failedCb(done), + passedCb(done, 'should be equal to one of the allowed values') + ); }; + describe('#branding validate', () => { + it('should fail validation if branding is not an object', (done) => { + const data = [ { + anything: 'anything' + } ]; + + const auth0 = new Auth0({}, { branding: data }, {}); + + auth0.validate().then(failedCb(done), passedCb(done, 'should be object')); + }); + + it('should pass validation', (done) => { + const data = { + anything: 'anything' + }; + + checkPassed({ branding: data }, done); + }); + }); + describe('#clientGrants validate', () => { it('should fail validation if no "client_id" provided', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkRequired('client_id', { clientGrants: data }, done); }); it('should fail validation if no "scope" provided', (done) => { - const data = [ - { - client_id: 'client_id', - audience: 'audience' - } - ]; + const data = [ { + client_id: 'client_id', + audience: 'audience' + } ]; checkRequired('scope', { clientGrants: data }, done); }); it('should fail validation if no "audience" provided', (done) => { - const data = [ - { - client_id: 'client_id', - scope: [ 'scope' ] - } - ]; + const data = [ { + client_id: 'client_id', + scope: [ 'scope' ] + } ]; checkRequired('audience', { clientGrants: data }, done); }); it('should fail validation if bad "scope" provided', (done) => { - const data = [ - { - client_id: 'client_id', - scope: 'scope', - audience: 'audience' - } - ]; + const data = [ { + client_id: 'client_id', + scope: 'scope', + audience: 'audience' + } ]; const auth0 = new Auth0({}, { clientGrants: data }, {}); - auth0.validate() - .then(failedCb(done), passedCb(done, 'should be array')); + auth0.validate().then(failedCb(done), passedCb(done, 'should be array')); }); it('should pass validation', (done) => { - const data = [ - { - client_id: 'client_id', - scope: [ 'scope' ], - audience: 'audience' - } - ]; + const data = [ { + client_id: 'client_id', + scope: [ 'scope' ], + audience: 'audience' + } ]; checkPassed({ clientGrants: data }, done); }); @@ -99,34 +115,32 @@ describe('#schema validation tests', () => { describe('#clients validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - id: 'id' - } - ]; + const data = [ { + id: 'id' + } ]; checkRequired('name', { clients: data }, done); }); it('should fail validation if bad "name" provided', (done) => { - const data = [ - { - name: '' - } - ]; + const data = [ { + name: '' + } ]; const auth0 = new Auth0({}, { clients: data }, {}); - auth0.validate() - .then(failedCb(done), passedCb(done, 'should NOT be shorter than 1 characters')); + auth0 + .validate() + .then( + failedCb(done), + passedCb(done, 'should NOT be shorter than 1 characters') + ); }); it('should pass validation', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkPassed({ clients: data }, done); }); @@ -134,32 +148,26 @@ describe('#schema validation tests', () => { describe('#connections validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - id: 'id' - } - ]; + const data = [ { + id: 'id' + } ]; checkRequired('name', { connections: data }, done); }); it('should fail validation if no "strategy" provided', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkRequired('strategy', { connections: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'name', - strategy: 'strategy' - } - ]; + const data = [ { + name: 'name', + strategy: 'strategy' + } ]; checkPassed({ connections: data }, done); }); @@ -167,33 +175,27 @@ describe('#schema validation tests', () => { describe('#databases validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - id: 'id' - } - ]; + const data = [ { + id: 'id' + } ]; checkRequired('name', { databases: data }, done); }); it('should fail validation if bad "strategy" provided', (done) => { - const data = [ - { - name: 'name', - strategy: 'strategy' - } - ]; + const data = [ { + name: 'name', + strategy: 'strategy' + } ]; checkEnum({ databases: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'name', - options: {} - } - ]; + const data = [ { + name: 'name', + options: {} + } ]; checkPassed({ databases: data }, done); }); @@ -201,16 +203,13 @@ describe('#schema validation tests', () => { describe('#emailProvider validate', () => { it('should fail validation if emailProvider is not an object', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; const auth0 = new Auth0({}, { emailProvider: data }, {}); - auth0.validate() - .then(failedCb(done), passedCb(done, 'should be object')); + auth0.validate().then(failedCb(done), passedCb(done, 'should be object')); }); it('should pass validation', (done) => { @@ -224,33 +223,27 @@ describe('#schema validation tests', () => { describe('#emailTemplates validate', () => { it('should fail validation if no "template" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('template', { emailTemplates: data }, done); }); it('should fail validation if bad "template" provided', (done) => { - const data = [ - { - template: 'template', - body: 'body' - } - ]; + const data = [ { + template: 'template', + body: 'body' + } ]; checkEnum({ emailTemplates: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - template: 'verify_email', - body: 'body' - } - ]; + const data = [ { + template: 'verify_email', + body: 'body' + } ]; checkPassed({ emailTemplates: data }, done); }); @@ -258,54 +251,44 @@ describe('#schema validation tests', () => { describe('#guardianFactorProviders validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('name', { guardianFactorProviders: data }, done); }); it('should fail validation if no "provider" provided', (done) => { - const data = [ - { - name: 'sms' - } - ]; + const data = [ { + name: 'sms' + } ]; checkRequired('provider', { guardianFactorProviders: data }, done); }); it('should fail validation if bad "name" provided', (done) => { - const data = [ - { - name: 'name', - provider: 'provider' - } - ]; + const data = [ { + name: 'name', + provider: 'provider' + } ]; checkEnum({ guardianFactorProviders: data }, done); }); it('should fail validation if bad "provider" provided', (done) => { - const data = [ - { - name: 'sms', - provider: 'provider' - } - ]; + const data = [ { + name: 'sms', + provider: 'provider' + } ]; checkEnum({ guardianFactorProviders: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'sms', - provider: 'twilio' - } - ]; + const data = [ { + name: 'sms', + provider: 'twilio' + } ]; checkPassed({ guardianFactorProviders: data }, done); }); @@ -313,31 +296,25 @@ describe('#schema validation tests', () => { describe('#guardianFactors validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('name', { guardianFactors: data }, done); }); it('should fail validation if bad "name" provided', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkEnum({ guardianFactors: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'sms' - } - ]; + const data = [ { + name: 'sms' + } ]; checkPassed({ guardianFactors: data }, done); }); @@ -345,31 +322,25 @@ describe('#schema validation tests', () => { describe('#guardianFactorTemplates validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('name', { guardianFactorTemplates: data }, done); }); it('should fail validation if bad "name" provided', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkEnum({ guardianFactorTemplates: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'sms' - } - ]; + const data = [ { + name: 'sms' + } ]; checkPassed({ guardianFactorTemplates: data }, done); }); @@ -377,64 +348,72 @@ describe('#schema validation tests', () => { describe('#pages validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('name', { pages: data }, done); }); it('should fail validation if bad "name" provided', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkEnum({ pages: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'login' - } - ]; + const data = [ { + name: 'login' + } ]; checkPassed({ pages: data }, done); }); }); + describe('#prompts validate', () => { + it('should fail validation if prompts is not an object', (done) => { + const data = [ { + anything: 'anything' + } ]; + + const auth0 = new Auth0({}, { prompts: data }, {}); + + auth0.validate().then(failedCb(done), passedCb(done, 'should be object')); + }); + + it('should pass validation', (done) => { + const data = { + anything: 'anything' + }; + + checkPassed({ prompts: data }, done); + }); + }); + describe('#resourceServers validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('name', { resourceServers: data }, done); }); it('should fail validation if no "identifier" provided', (done) => { - const data = [ - { - name: 'name' - } - ]; + const data = [ { + name: 'name' + } ]; checkRequired('identifier', { resourceServers: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'name', - identifier: 'identifier' - } - ]; + const data = [ { + name: 'name', + identifier: 'identifier' + } ]; checkPassed({ resourceServers: data }, done); }); @@ -442,47 +421,40 @@ describe('#schema validation tests', () => { describe('#rules validate', () => { it('should fail validation if no "name" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('name', { rules: data }, done); }); it('should fail validation if bad "name" provided', (done) => { - const data = [ - { - name: '-rule-' - } - ]; + const data = [ { + name: '-rule-' + } ]; const auth0 = new Auth0({}, { rules: data }, {}); - auth0.validate() + auth0 + .validate() .then(failedCb(done), passedCb(done, 'should match pattern')); }); it('should fail validation if bad "stage" provided', (done) => { - const data = [ - { - name: 'rule', - stage: 'stage' - } - ]; + const data = [ { + name: 'rule', + stage: 'stage' + } ]; checkEnum({ rules: data }, done); }); it('should pass validation', (done) => { - const data = [ - { - name: 'name', - order: 1, - stage: 'login_failure' - } - ]; + const data = [ { + name: 'name', + order: 1, + stage: 'login_failure' + } ]; checkPassed({ rules: data }, done); }); @@ -490,46 +462,39 @@ describe('#schema validation tests', () => { describe('#rulesConfigs validate', () => { it('should fail validation if no "key" provided', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; checkRequired('key', { rulesConfigs: data }, done); }); it('should fail validation if no "value" provided', (done) => { - const data = [ - { - key: 'key' - } - ]; + const data = [ { + key: 'key' + } ]; checkRequired('value', { rulesConfigs: data }, done); }); it('should fail validation if bad "key" provided', (done) => { - const data = [ - { - key: ':-?', - value: 'value' - } - ]; + const data = [ { + key: ':-?', + value: 'value' + } ]; const auth0 = new Auth0({}, { rulesConfigs: data }, {}); - auth0.validate() + auth0 + .validate() .then(failedCb(done), passedCb(done, 'should match pattern')); }); it('should pass validation', (done) => { - const data = [ - { - key: 'key', - value: 'value' - } - ]; + const data = [ { + key: 'key', + value: 'value' + } ]; checkPassed({ rulesConfigs: data }, done); }); @@ -537,16 +502,13 @@ describe('#schema validation tests', () => { describe('#tenant validate', () => { it('should fail validation if tenant is not an object', (done) => { - const data = [ - { - anything: 'anything' - } - ]; + const data = [ { + anything: 'anything' + } ]; const auth0 = new Auth0({}, { tenant: data }, {}); - auth0.validate() - .then(failedCb(done), passedCb(done, 'should be object')); + auth0.validate().then(failedCb(done), passedCb(done, 'should be object')); }); it('should pass validation', (done) => {