From f13322af80ee26519768ab8cd97d09ad0ba9dfe8 Mon Sep 17 00:00:00 2001 From: Patrick Malouin Date: Fri, 19 Jun 2020 17:07:44 -0400 Subject: [PATCH 1/9] feat(guardian): support for policies, selected-provider, message-types --- src/management/GuardianManager.js | 172 +++++++++ src/management/index.js | 138 +++++++ test/management/guardian.tests.js | 428 ++++++++++++++++++++- test/management/management-client.tests.js | 32 +- 4 files changed, 762 insertions(+), 8 deletions(-) diff --git a/src/management/GuardianManager.js b/src/management/GuardianManager.js index 8c443f1fa..627261d86 100644 --- a/src/management/GuardianManager.js +++ b/src/management/GuardianManager.js @@ -104,6 +104,48 @@ var GuardianManager = function(options) { guardianFactorsProvidersAuth0RestClient, options.retry ); + + /** + * Provides an abstraction layer for retrieving Guardian policies. + * + * @type {external:RestClient} + */ + var guardianPoliciesAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/policies', + clientOptions, + options.tokenProvider + ); + this.policies = new RetryRestClient(guardianPoliciesAuth0RestClient, options.retry); + + /** + * Provides an abstraction layer for retrieving a Guardian factor selected provider. + * + * @type {external:RestClient} + */ + var guardianFactorsSelectedProviderAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/:name/selected-provider', + clientOptions, + options.tokenProvider + ); + this.factorsSelectedProvider = new RetryRestClient( + guardianFactorsSelectedProviderAuth0RestClient, + options.retry + ); + + /** + * Provides an abstraction layer for retrieving Guardian factor message types. + * + * @type {external:RestClient} + */ + var guardianFactorsMessageTypesAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/:name/message-types', + clientOptions, + options.tokenProvider + ); + this.factorsMessageTypes = new RetryRestClient( + guardianFactorsMessageTypesAuth0RestClient, + options.retry + ); }; /** @@ -280,4 +322,134 @@ utils.wrapPropertyMethod(GuardianManager, 'updateFactorTemplates', 'factorsTempl */ utils.wrapPropertyMethod(GuardianManager, 'updateFactor', 'factors.update'); +/** + * Get enabled Guardian policies + * + * @method getPolicies + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.getPolicies(function (err, policies) { + * console.log(policies); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'getPolicies', 'policies.get'); + +/** + * Update enabled Guardian policies + * + * @method updatePolicies + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.updatePolicies({}, [ + * 'all-applications' + * ], function (err, policies) { + * console.log(policies); + * }); + * + * @param {Object} params Parameters. + * @param {String[]} data Policies to enable. Empty array disables all policies. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'updatePolicies', 'policies.update'); + +/** + * Get the Guardian factor's selected provider + * + * @method getFactorSelectedProvider + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.getFactorSelectedProvider({ name: 'phone' }, function (err, selectedProvider) { + * console.log(selectedProvider); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + GuardianManager, + 'getFactorSelectedProvider', + 'factorsSelectedProvider.get' +); + +/** + * Update the Guardian factor's selected provider + * + * @method updateFactorSelectedProvider + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.updateFactorSelectedProvider({ name: 'phone' }, { + * provider: 'twilio' + * }, function (err, factor) { + * console.log(factor); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} data Updated selected provider data. + * @param {String} data.provider Name of the selected provider + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + GuardianManager, + 'updateFactorSelectedProvider', + 'factorsSelectedProvider.update' +); + +/** + * Get the Guardian factor's message types + * + * @method getFactorMessageTypes + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.getFactorMessageTypes({ name: 'phone' }, function (err, messageTypes) { + * console.log(messageTypes); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'getFactorMessageTypes', 'factorsMessageTypes.get'); + +/** + * Update the Guardian factor's message types + * + * @method updateFactorMessageTypes + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.updateFactorMessageTypes({ name: 'phone' }, { + * message_types: ['sms', 'voice'] + * }, function (err, factor) { + * console.log(factor); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} data Updated selected provider data. + * @param {String[]} data.message_types Message types (only `"sms"` and `"voice"` are supported). + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'updateFactorMessageTypes', 'factorsMessageTypes.update'); + module.exports = GuardianManager; diff --git a/src/management/index.js b/src/management/index.js index 2588e7001..17094483f 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -2696,6 +2696,144 @@ utils.wrapPropertyMethod( */ utils.wrapPropertyMethod(ManagementClient, 'updateGuardianFactor', 'guardian.updateFactor'); +/** + * Get enabled Guardian policies + * + * @method getGuardianPolicies + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.getGuardianPolicies(function (err, policies) { + * console.log(policies); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'getGuardianPolicies', 'guardian.getPolicies'); + +/** + * Update enabled Guardian policies + * + * @method updateGuardianPolicies + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.updateGuardianPolicies({}, [ + * 'all-applications' + * ], function (err, policies) { + * console.log(policies); + * }); + * + * @param {Object} params Parameters. + * @param {String[]} data Policies to enable. Empty array disables all policies. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'updateGuardianPolicies', 'guardian.updatePolicies'); + +/** + * Get the Guardian factor's selected provider + * + * @method getGuardianFactorSelectedProvider + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.getGuardianFactorSelectedProvider({ name: 'phone' }, function (err, selectedProvider) { + * console.log(selectedProvider); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'getGuardianFactorSelectedProvider', + 'guardian.getFactorSelectedProvider' +); + +/** + * Update the Guardian factor's selected provider + * + * @method updateGuardianFactorSelectedProvider + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.updateGuardianFactorSelectedProvider({ name: 'phone' }, { + * provider: 'twilio' + * }, function (err, factor) { + * console.log(factor); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} data Updated selected provider data. + * @param {String} data.provider Name of the selected provider + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'updateGuardianFactorSelectedProvider', + 'guardian.updateFactorSelectedProvider' +); + +/** + * Get the Guardian factor's message types + * + * @method getGuardianFactorMessageTypes + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.getGuardianFactorMessageTypes({ name: 'phone' }, function (err, messageTypes) { + * console.log(messageTypes); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'getGuardianFactorMessageTypes', + 'guardian.getFactorMessageTypes' +); + +/** + * Update the Guardian factor's message types + * + * @method updateGuardianFactorMessageTypes + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.updateGuardianFactorMessageTypes({ name: 'phone' }, { + * message_types: ['sms', 'voice'] + * }, function (err, factor) { + * console.log(factor); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} data Updated selected provider data. + * @param {String[]} data.message_types Message types (only `"sms"` and `"voice"` are supported). + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'updateGuardianFactorMessageTypes', + 'guardian.updateFactorMessageTypes' +); + /** * Get all roles. * diff --git a/test/management/guardian.tests.js b/test/management/guardian.tests.js index b3fd95731..d680a5c12 100644 --- a/test/management/guardian.tests.js +++ b/test/management/guardian.tests.js @@ -25,7 +25,11 @@ describe('GuardianManager', function() { 'updateFactorProvider', 'getFactorTemplates', 'updateFactorTemplates', - 'updateFactor' + 'updateFactor', + 'getFactorSelectedProvider', + 'updateFactorSelectedProvider', + 'getFactorMessageTypes', + 'updateFactorMessageTypes' ]; methods.forEach(function(method) { @@ -302,7 +306,7 @@ describe('GuardianManager', function() { .catch(done.bind(null, null)); }); - it('should perform a POST request to /api/v2/guardian/factors', function(done) { + it('should perform a GET request to /api/v2/guardian/factors', function(done) { var request = this.request; this.guardian.getFactors().then(function() { @@ -368,7 +372,7 @@ describe('GuardianManager', function() { .catch(done.bind(null, null)); }); - it('should perform a POST request to /api/v2/guardian/factors/sms/twilio', function(done) { + it('should perform a GET request to /api/v2/guardian/factors/sms/twilio', function(done) { var request = this.request; this.guardian.getFactorProvider(this.params).then(function() { @@ -446,7 +450,10 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/providers/' + this.params.provider) + .put( + '/guardian/factors/' + this.params.name + '/providers/' + this.params.provider, + this.data + ) .reply(200); this.guardian.updateFactorProvider(this.params, this.data).then(function() { @@ -512,7 +519,7 @@ describe('GuardianManager', function() { .catch(done.bind(null, null)); }); - it('should perform a POST request to /api/v2/guardian/factors/sms/templates', function(done) { + it('should perform a GET request to /api/v2/guardian/factors/sms/templates', function(done) { var request = this.request; this.guardian.getFactorTemplates(this.params).then(function() { @@ -589,7 +596,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/templates') + .put('/guardian/factors/' + this.params.name + '/templates', this.data) .reply(200); this.guardian.updateFactorTemplates(this.params, this.data).then(function() { @@ -664,7 +671,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name) + .put('/guardian/factors/' + this.params.name, this.data) .reply(200); this.guardian.updateFactor(this.params, this.data).then(function() { @@ -703,4 +710,411 @@ describe('GuardianManager', function() { }); }); }); + + describe('#getPolicies', function() { + beforeEach(function() { + this.data = ['all-applications']; + + this.request = nock(API_URL) + .get('/guardian/policies') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.guardian.getPolicies(done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .getPolicies() + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request to /api/v2/guardian/policies', function(done) { + var request = this.request; + + this.guardian.getPolicies().then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/guardian/policies') + .reply(500); + + this.guardian.getPolicies().catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/guardian/policies') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.getPolicies().then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updatePolicies', function() { + beforeEach(function() { + this.params = {}; + this.data = ['all-applications']; + }); + + it('should accept a callback', function(done) { + this.guardian.updatePolicies(this.params, this.data, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .updatePolicies(this.params, this.data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a PUT request to /api/v2/guardian/policies', function(done) { + var request = nock(API_URL) + .put('/guardian/policies') + .reply(200, this.data); + + this.guardian.updatePolicies(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should include the new data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/policies', this.data) + .reply(200); + + this.guardian.updatePolicies(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/policies') + .reply(500); + + this.guardian.updatePolicies(this.params, this.data).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/policies') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.updatePolicies(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#getFactorSelectedProvider', function() { + beforeEach(function() { + this.data = { + provider: 'twilio' + }; + + this.request = nock(API_URL) + .get('/guardian/factors/phone/selected-provider') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.guardian.getFactorSelectedProvider({ name: 'phone' }, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .getFactorSelectedProvider({ name: 'phone' }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request to /api/v2/guardian/factors/phone/selected-provider', function(done) { + var request = this.request; + + this.guardian.getFactorSelectedProvider({ name: 'phone' }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/guardian/factors/phone/selected-provider') + .reply(500); + + this.guardian.getFactorSelectedProvider({ name: 'phone' }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/guardian/factors/phone/selected-provider') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.getFactorSelectedProvider({ name: 'phone' }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updateFactorSelectedProvider', function() { + beforeEach(function() { + this.params = { name: 'phone' }; + this.data = { + provider: 'twilio' + }; + }); + + it('should accept a callback', function(done) { + this.guardian.updateFactorSelectedProvider(this.params, this.data, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .updateFactorSelectedProvider(this.params, this.data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a PUT request to /api/v2/guardian/factors/phone/selected-provider', function(done) { + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/selected-provider') + .reply(200, this.data); + + this.guardian.updateFactorSelectedProvider(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should include the new data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/selected-provider', this.data) + .reply(200); + + this.guardian.updateFactorSelectedProvider(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/selected-provider') + .reply(500); + + this.guardian.updateFactorSelectedProvider(this.params, this.data).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/selected-provider') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.updateFactorSelectedProvider(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#getFactorMessageTypes', function() { + beforeEach(function() { + this.data = { + message_types: ['sms', 'voice'] + }; + + this.request = nock(API_URL) + .get('/guardian/factors/phone/message-types') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.guardian.getFactorMessageTypes({ name: 'phone' }, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .getFactorMessageTypes({ name: 'phone' }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request to /api/v2/guardian/factors/phone/message-types', function(done) { + var request = this.request; + + this.guardian.getFactorMessageTypes({ name: 'phone' }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/guardian/factors/phone/message-types') + .reply(500); + + this.guardian.getFactorMessageTypes({ name: 'phone' }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/guardian/factors/phone/message-types') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.getFactorMessageTypes({ name: 'phone' }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updateFactorMessageTypes', function() { + beforeEach(function() { + this.params = { name: 'phone' }; + this.data = { + message_types: ['sms', 'voice'] + }; + }); + + it('should accept a callback', function(done) { + this.guardian.updateFactorMessageTypes(this.params, this.data, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .updateFactorMessageTypes(this.params, this.data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a PUT request to /api/v2/guardian/factors/phone/message-types', function(done) { + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/message-types') + .reply(200, this.data); + + this.guardian.updateFactorMessageTypes(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should include the new data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/message-types', this.data) + .reply(200); + + this.guardian.updateFactorMessageTypes(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/message-types') + .reply(500); + + this.guardian.updateFactorMessageTypes(this.params, this.data).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/message-types') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.updateFactorMessageTypes(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); }); diff --git a/test/management/management-client.tests.js b/test/management/management-client.tests.js index b543799c8..09cf4ca54 100644 --- a/test/management/management-client.tests.js +++ b/test/management/management-client.tests.js @@ -299,6 +299,12 @@ describe('ManagementClient', function() { expect(client.guardian.factorsProviders.restClient.restClient.options.headers).to.contain( requestHeaders ); + expect( + client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + ).to.contain(requestHeaders); + expect( + client.guardian.factorsMessageTypes.restClient.restClient.options.headers + ).to.contain(requestHeaders); expect(client.customDomains.resource.restClient.restClient.options.headers).to.contain( requestHeaders @@ -438,6 +444,12 @@ describe('ManagementClient', function() { expect(client.guardian.factorsProviders.restClient.restClient.options.headers).to.contain( requestHeaders ); + expect( + client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + ).to.contain(requestHeaders); + expect( + client.guardian.factorsMessageTypes.restClient.restClient.options.headers + ).to.contain(requestHeaders); expect(client.customDomains.resource.restClient.restClient.options.headers).to.contain( requestHeaders @@ -575,6 +587,12 @@ describe('ManagementClient', function() { expect( client.guardian.factorsProviders.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); + expect( + client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + ).to.not.have.property('Auth0-Client'); + expect( + client.guardian.factorsMessageTypes.restClient.restClient.options.headers + ).to.not.have.property('Auth0-Client'); expect( client.customDomains.resource.restClient.restClient.options.headers @@ -715,6 +733,12 @@ describe('ManagementClient', function() { expect( client.guardian.factorsProviders.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); + expect( + client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + ).to.not.have.property('Auth0-Client'); + expect( + client.guardian.factorsMessageTypes.restClient.restClient.options.headers + ).to.not.have.property('Auth0-Client'); expect( client.customDomains.resource.restClient.restClient.options.headers @@ -866,6 +890,12 @@ describe('ManagementClient', function() { 'getGuardianFactorTemplates', 'updateGuardianFactorTemplates', 'updateGuardianFactor', + 'getGuardianPolicies', + 'updateGuardianPolicies', + 'getGuardianFactorSelectedProvider', + 'updateGuardianFactorSelectedProvider', + 'getGuardianFactorMessageTypes', + 'updateGuardianFactorMessageTypes', 'getUserBlocks', 'unblockUser', 'getUserBlocksByIdentifier', @@ -878,7 +908,7 @@ describe('ManagementClient', function() { this.client = new ManagementClient(config); }); - methods.forEach(function (method) { + methods.forEach(function(method) { it('should have a ' + method + ' method', function() { expect(this.client[method]).to.exist.to.be.an.instanceOf(Function); }); From 3b7ae920c1cfa44c15d29d2568fd7a92ca933e4f Mon Sep 17 00:00:00 2001 From: Patrick Malouin Date: Tue, 23 Jun 2020 13:45:06 -0400 Subject: [PATCH 2/9] remodel api for better dev-experience --- src/management/GuardianManager.js | 74 +++++++++---------- src/management/index.js | 50 ++++++------- test/management/guardian.tests.js | 84 +++++++++++----------- test/management/management-client.tests.js | 24 +++---- 4 files changed, 116 insertions(+), 116 deletions(-) diff --git a/src/management/GuardianManager.js b/src/management/GuardianManager.js index 627261d86..06d852507 100644 --- a/src/management/GuardianManager.js +++ b/src/management/GuardianManager.js @@ -118,32 +118,32 @@ var GuardianManager = function(options) { this.policies = new RetryRestClient(guardianPoliciesAuth0RestClient, options.retry); /** - * Provides an abstraction layer for retrieving a Guardian factor selected provider. + * Provides an abstraction layer for retrieving Guardian phone factor selected provider. * * @type {external:RestClient} */ - var guardianFactorsSelectedProviderAuth0RestClient = new Auth0RestClient( - options.baseUrl + '/guardian/factors/:name/selected-provider', + var guardianFactorsPhoneSelectedProviderAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/phone/selected-provider', clientOptions, options.tokenProvider ); - this.factorsSelectedProvider = new RetryRestClient( - guardianFactorsSelectedProviderAuth0RestClient, + this.factorsPhoneSelectedProvider = new RetryRestClient( + guardianFactorsPhoneSelectedProviderAuth0RestClient, options.retry ); /** - * Provides an abstraction layer for retrieving Guardian factor message types. + * Provides an abstraction layer for retrieving Guardian phone factor message types. * * @type {external:RestClient} */ - var guardianFactorsMessageTypesAuth0RestClient = new Auth0RestClient( - options.baseUrl + '/guardian/factors/:name/message-types', + var guardianFactorsPhoneMessageTypesAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/phone/message-types', clientOptions, options.tokenProvider ); - this.factorsMessageTypes = new RetryRestClient( - guardianFactorsMessageTypesAuth0RestClient, + this.factorsPhoneMessageTypes = new RetryRestClient( + guardianFactorsPhoneMessageTypesAuth0RestClient, options.retry ); }; @@ -361,43 +361,40 @@ utils.wrapPropertyMethod(GuardianManager, 'getPolicies', 'policies.get'); utils.wrapPropertyMethod(GuardianManager, 'updatePolicies', 'policies.update'); /** - * Get the Guardian factor's selected provider + * Get the Guardian phone factor's selected provider * - * @method getFactorSelectedProvider + * @method getPhoneFactorSelectedProvider * @memberOf module:management.GuardianManager.prototype * * @example - * management.guardian.getFactorSelectedProvider({ name: 'phone' }, function (err, selectedProvider) { + * management.guardian.getPhoneFactorSelectedProvider(function (err, selectedProvider) { * console.log(selectedProvider); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). * @param {Function} [cb] Callback function. * * @return {Promise|undefined} */ utils.wrapPropertyMethod( GuardianManager, - 'getFactorSelectedProvider', - 'factorsSelectedProvider.get' + 'getPhoneFactorSelectedProvider', + 'factorsPhoneSelectedProvider.get' ); /** - * Update the Guardian factor's selected provider + * Update the Guardian phone factor's selected provider * - * @method updateFactorSelectedProvider + * @method updatePhoneFactorSelectedProvider * @memberOf module:management.GuardianManager.prototype * * @example - * management.guardian.updateFactorSelectedProvider({ name: 'phone' }, { + * management.guardian.updatePhoneFactorSelectedProvider({}, { * provider: 'twilio' * }, function (err, factor) { * console.log(factor); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} params Parameters. * @param {Object} data Updated selected provider data. * @param {String} data.provider Name of the selected provider * @param {Function} [cb] Callback function. @@ -406,50 +403,55 @@ utils.wrapPropertyMethod( */ utils.wrapPropertyMethod( GuardianManager, - 'updateFactorSelectedProvider', - 'factorsSelectedProvider.update' + 'updatePhoneFactorSelectedProvider', + 'factorsPhoneSelectedProvider.update' ); /** - * Get the Guardian factor's message types + * Get the Guardian phone factor's message types * - * @method getFactorMessageTypes + * @method getPhoneFactorMessageTypes * @memberOf module:management.GuardianManager.prototype * * @example - * management.guardian.getFactorMessageTypes({ name: 'phone' }, function (err, messageTypes) { + * management.guardian.getPhoneFactorMessageTypes(function (err, messageTypes) { * console.log(messageTypes); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). * @param {Function} [cb] Callback function. * * @return {Promise|undefined} */ -utils.wrapPropertyMethod(GuardianManager, 'getFactorMessageTypes', 'factorsMessageTypes.get'); +utils.wrapPropertyMethod( + GuardianManager, + 'getPhoneFactorMessageTypes', + 'factorsPhoneMessageTypes.get' +); /** - * Update the Guardian factor's message types + * Update the Guardian phone factor's message types * - * @method updateFactorMessageTypes + * @method updatePhoneFactorMessageTypes * @memberOf module:management.GuardianManager.prototype * * @example - * management.guardian.updateFactorMessageTypes({ name: 'phone' }, { + * management.guardian.updatePhoneFactorMessageTypes({}, { * message_types: ['sms', 'voice'] * }, function (err, factor) { * console.log(factor); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} params Parameters. * @param {Object} data Updated selected provider data. * @param {String[]} data.message_types Message types (only `"sms"` and `"voice"` are supported). * @param {Function} [cb] Callback function. * * @return {Promise|undefined} */ -utils.wrapPropertyMethod(GuardianManager, 'updateFactorMessageTypes', 'factorsMessageTypes.update'); +utils.wrapPropertyMethod( + GuardianManager, + 'updatePhoneFactorMessageTypes', + 'factorsPhoneMessageTypes.update' +); module.exports = GuardianManager; diff --git a/src/management/index.js b/src/management/index.js index 17094483f..c329fe321 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -2735,43 +2735,40 @@ utils.wrapPropertyMethod(ManagementClient, 'getGuardianPolicies', 'guardian.getP utils.wrapPropertyMethod(ManagementClient, 'updateGuardianPolicies', 'guardian.updatePolicies'); /** - * Get the Guardian factor's selected provider + * Get the Guardian phone factor's selected provider * - * @method getGuardianFactorSelectedProvider + * @method getGuardianPhoneFactorSelectedProvider * @memberOf module:management.ManagementClient.prototype * * @example - * management.getGuardianFactorSelectedProvider({ name: 'phone' }, function (err, selectedProvider) { + * management.getGuardianPhoneFactorSelectedProvider(function (err, selectedProvider) { * console.log(selectedProvider); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). * @param {Function} [cb] Callback function. * * @return {Promise|undefined} */ utils.wrapPropertyMethod( ManagementClient, - 'getGuardianFactorSelectedProvider', - 'guardian.getFactorSelectedProvider' + 'getGuardianPhoneFactorSelectedProvider', + 'guardian.getPhoneFactorSelectedProvider' ); /** - * Update the Guardian factor's selected provider + * Update the Guardian phone factor's selected provider * - * @method updateGuardianFactorSelectedProvider + * @method updateGuardianPhoneFactorSelectedProvider * @memberOf module:management.ManagementClient.prototype * * @example - * management.updateGuardianFactorSelectedProvider({ name: 'phone' }, { + * management.updateGuardianPhoneFactorSelectedProvider({}, { * provider: 'twilio' * }, function (err, factor) { * console.log(factor); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} params Parameters. * @param {Object} data Updated selected provider data. * @param {String} data.provider Name of the selected provider * @param {Function} [cb] Callback function. @@ -2780,48 +2777,45 @@ utils.wrapPropertyMethod( */ utils.wrapPropertyMethod( ManagementClient, - 'updateGuardianFactorSelectedProvider', - 'guardian.updateFactorSelectedProvider' + 'updateGuardianPhoneFactorSelectedProvider', + 'guardian.updatePhoneFactorSelectedProvider' ); /** - * Get the Guardian factor's message types + * Get the Guardian phone factor's message types * - * @method getGuardianFactorMessageTypes + * @method getGuardianPhoneFactorMessageTypes * @memberOf module:management.ManagementClient.prototype * * @example - * management.getGuardianFactorMessageTypes({ name: 'phone' }, function (err, messageTypes) { + * management.getGuardianPhoneFactorMessageTypes(function (err, messageTypes) { * console.log(messageTypes); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). * @param {Function} [cb] Callback function. * * @return {Promise|undefined} */ utils.wrapPropertyMethod( ManagementClient, - 'getGuardianFactorMessageTypes', - 'guardian.getFactorMessageTypes' + 'getGuardianPhoneFactorMessageTypes', + 'guardian.getPhoneFactorMessageTypes' ); /** - * Update the Guardian factor's message types + * Update the Guardian phone factor's message types * - * @method updateGuardianFactorMessageTypes + * @method updateGuardianPhoneFactorMessageTypes * @memberOf module:management.ManagementClient.prototype * * @example - * management.updateGuardianFactorMessageTypes({ name: 'phone' }, { + * management.updateGuardianPhoneFactorMessageTypes({}, { * message_types: ['sms', 'voice'] * }, function (err, factor) { * console.log(factor); * }); * - * @param {Object} params Factor provider parameters. - * @param {String} params.name Factor name (only `"phone"` is supported). + * @param {Object} params Parameters. * @param {Object} data Updated selected provider data. * @param {String[]} data.message_types Message types (only `"sms"` and `"voice"` are supported). * @param {Function} [cb] Callback function. @@ -2830,8 +2824,8 @@ utils.wrapPropertyMethod( */ utils.wrapPropertyMethod( ManagementClient, - 'updateGuardianFactorMessageTypes', - 'guardian.updateFactorMessageTypes' + 'updateGuardianPhoneFactorMessageTypes', + 'guardian.updatePhoneFactorMessageTypes' ); /** diff --git a/test/management/guardian.tests.js b/test/management/guardian.tests.js index d680a5c12..5f76591e7 100644 --- a/test/management/guardian.tests.js +++ b/test/management/guardian.tests.js @@ -26,10 +26,10 @@ describe('GuardianManager', function() { 'getFactorTemplates', 'updateFactorTemplates', 'updateFactor', - 'getFactorSelectedProvider', - 'updateFactorSelectedProvider', - 'getFactorMessageTypes', - 'updateFactorMessageTypes' + 'getPhoneFactorSelectedProvider', + 'updatePhoneFactorSelectedProvider', + 'getPhoneFactorMessageTypes', + 'updatePhoneFactorMessageTypes' ]; methods.forEach(function(method) { @@ -844,7 +844,7 @@ describe('GuardianManager', function() { }); }); - describe('#getFactorSelectedProvider', function() { + describe('#getPhoneFactorSelectedProvider', function() { beforeEach(function() { this.data = { provider: 'twilio' @@ -856,12 +856,12 @@ describe('GuardianManager', function() { }); it('should accept a callback', function(done) { - this.guardian.getFactorSelectedProvider({ name: 'phone' }, done.bind(null, null)); + this.guardian.getPhoneFactorSelectedProvider(done.bind(null, null)); }); it('should return a promise if no callback is given', function(done) { this.guardian - .getFactorSelectedProvider({ name: 'phone' }) + .getPhoneFactorSelectedProvider() .then(done.bind(null, null)) .catch(done.bind(null, null)); }); @@ -869,7 +869,7 @@ describe('GuardianManager', function() { it('should perform a GET request to /api/v2/guardian/factors/phone/selected-provider', function(done) { var request = this.request; - this.guardian.getFactorSelectedProvider({ name: 'phone' }).then(function() { + this.guardian.getPhoneFactorSelectedProvider().then(function() { expect(request.isDone()).to.be.true; done(); @@ -883,7 +883,7 @@ describe('GuardianManager', function() { .get('/guardian/factors/phone/selected-provider') .reply(500); - this.guardian.getFactorSelectedProvider({ name: 'phone' }).catch(function(err) { + this.guardian.getPhoneFactorSelectedProvider().catch(function(err) { expect(err).to.exist; done(); @@ -898,7 +898,7 @@ describe('GuardianManager', function() { .matchHeader('Authorization', 'Bearer ' + this.token) .reply(200); - this.guardian.getFactorSelectedProvider({ name: 'phone' }).then(function() { + this.guardian.getPhoneFactorSelectedProvider().then(function() { expect(request.isDone()).to.be.true; done(); @@ -906,31 +906,35 @@ describe('GuardianManager', function() { }); }); - describe('#updateFactorSelectedProvider', function() { + describe('#updatePhoneFactorSelectedProvider', function() { beforeEach(function() { - this.params = { name: 'phone' }; + this.params = {}; this.data = { provider: 'twilio' }; }); it('should accept a callback', function(done) { - this.guardian.updateFactorSelectedProvider(this.params, this.data, done.bind(null, null)); + this.guardian.updatePhoneFactorSelectedProvider( + this.params, + this.data, + done.bind(null, null) + ); }); it('should return a promise if no callback is given', function(done) { this.guardian - .updateFactorSelectedProvider(this.params, this.data) + .updatePhoneFactorSelectedProvider(this.params, this.data) .then(done.bind(null, null)) .catch(done.bind(null, null)); }); it('should perform a PUT request to /api/v2/guardian/factors/phone/selected-provider', function(done) { var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/selected-provider') + .put('/guardian/factors/phone/selected-provider') .reply(200, this.data); - this.guardian.updateFactorSelectedProvider(this.params, this.data).then(function() { + this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).then(function() { expect(request.isDone()).to.be.true; done(); @@ -941,10 +945,10 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/selected-provider', this.data) + .put('/guardian/factors/phone/selected-provider', this.data) .reply(200); - this.guardian.updateFactorSelectedProvider(this.params, this.data).then(function() { + this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).then(function() { expect(request.isDone()).to.be.true; done(); @@ -955,10 +959,10 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/selected-provider') + .put('/guardian/factors/phone/selected-provider') .reply(500); - this.guardian.updateFactorSelectedProvider(this.params, this.data).catch(function(err) { + this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).catch(function(err) { expect(err).to.exist; done(); @@ -969,11 +973,11 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/selected-provider') + .put('/guardian/factors/phone/selected-provider') .matchHeader('Authorization', 'Bearer ' + this.token) .reply(200); - this.guardian.updateFactorSelectedProvider(this.params, this.data).then(function() { + this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).then(function() { expect(request.isDone()).to.be.true; done(); @@ -981,7 +985,7 @@ describe('GuardianManager', function() { }); }); - describe('#getFactorMessageTypes', function() { + describe('#getPhoneFactorMessageTypes', function() { beforeEach(function() { this.data = { message_types: ['sms', 'voice'] @@ -993,12 +997,12 @@ describe('GuardianManager', function() { }); it('should accept a callback', function(done) { - this.guardian.getFactorMessageTypes({ name: 'phone' }, done.bind(null, null)); + this.guardian.getPhoneFactorMessageTypes(done.bind(null, null)); }); it('should return a promise if no callback is given', function(done) { this.guardian - .getFactorMessageTypes({ name: 'phone' }) + .getPhoneFactorMessageTypes() .then(done.bind(null, null)) .catch(done.bind(null, null)); }); @@ -1006,7 +1010,7 @@ describe('GuardianManager', function() { it('should perform a GET request to /api/v2/guardian/factors/phone/message-types', function(done) { var request = this.request; - this.guardian.getFactorMessageTypes({ name: 'phone' }).then(function() { + this.guardian.getPhoneFactorMessageTypes().then(function() { expect(request.isDone()).to.be.true; done(); @@ -1020,7 +1024,7 @@ describe('GuardianManager', function() { .get('/guardian/factors/phone/message-types') .reply(500); - this.guardian.getFactorMessageTypes({ name: 'phone' }).catch(function(err) { + this.guardian.getPhoneFactorMessageTypes().catch(function(err) { expect(err).to.exist; done(); @@ -1035,7 +1039,7 @@ describe('GuardianManager', function() { .matchHeader('Authorization', 'Bearer ' + this.token) .reply(200); - this.guardian.getFactorMessageTypes({ name: 'phone' }).then(function() { + this.guardian.getPhoneFactorMessageTypes().then(function() { expect(request.isDone()).to.be.true; done(); @@ -1043,31 +1047,31 @@ describe('GuardianManager', function() { }); }); - describe('#updateFactorMessageTypes', function() { + describe('#updatePhoneFactorMessageTypes', function() { beforeEach(function() { - this.params = { name: 'phone' }; + this.params = {}; this.data = { message_types: ['sms', 'voice'] }; }); it('should accept a callback', function(done) { - this.guardian.updateFactorMessageTypes(this.params, this.data, done.bind(null, null)); + this.guardian.updatePhoneFactorMessageTypes(this.params, this.data, done.bind(null, null)); }); it('should return a promise if no callback is given', function(done) { this.guardian - .updateFactorMessageTypes(this.params, this.data) + .updatePhoneFactorMessageTypes(this.params, this.data) .then(done.bind(null, null)) .catch(done.bind(null, null)); }); it('should perform a PUT request to /api/v2/guardian/factors/phone/message-types', function(done) { var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/message-types') + .put('/guardian/factors/phone/message-types') .reply(200, this.data); - this.guardian.updateFactorMessageTypes(this.params, this.data).then(function() { + this.guardian.updatePhoneFactorMessageTypes(this.params, this.data).then(function() { expect(request.isDone()).to.be.true; done(); @@ -1078,10 +1082,10 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/message-types', this.data) + .put('/guardian/factors/phone/message-types', this.data) .reply(200); - this.guardian.updateFactorMessageTypes(this.params, this.data).then(function() { + this.guardian.updatePhoneFactorMessageTypes(this.params, this.data).then(function() { expect(request.isDone()).to.be.true; done(); @@ -1092,10 +1096,10 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/message-types') + .put('/guardian/factors/phone/message-types') .reply(500); - this.guardian.updateFactorMessageTypes(this.params, this.data).catch(function(err) { + this.guardian.updatePhoneFactorMessageTypes(this.params, this.data).catch(function(err) { expect(err).to.exist; done(); @@ -1106,11 +1110,11 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/' + this.params.name + '/message-types') + .put('/guardian/factors/phone/message-types') .matchHeader('Authorization', 'Bearer ' + this.token) .reply(200); - this.guardian.updateFactorMessageTypes(this.params, this.data).then(function() { + this.guardian.updatePhoneFactorMessageTypes(this.params, this.data).then(function() { expect(request.isDone()).to.be.true; done(); diff --git a/test/management/management-client.tests.js b/test/management/management-client.tests.js index 09cf4ca54..34a108e79 100644 --- a/test/management/management-client.tests.js +++ b/test/management/management-client.tests.js @@ -300,10 +300,10 @@ describe('ManagementClient', function() { requestHeaders ); expect( - client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + client.guardian.factorsPhoneSelectedProvider.restClient.restClient.options.headers ).to.contain(requestHeaders); expect( - client.guardian.factorsMessageTypes.restClient.restClient.options.headers + client.guardian.factorsPhoneMessageTypes.restClient.restClient.options.headers ).to.contain(requestHeaders); expect(client.customDomains.resource.restClient.restClient.options.headers).to.contain( @@ -445,10 +445,10 @@ describe('ManagementClient', function() { requestHeaders ); expect( - client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + client.guardian.factorsPhoneSelectedProvider.restClient.restClient.options.headers ).to.contain(requestHeaders); expect( - client.guardian.factorsMessageTypes.restClient.restClient.options.headers + client.guardian.factorsPhoneMessageTypes.restClient.restClient.options.headers ).to.contain(requestHeaders); expect(client.customDomains.resource.restClient.restClient.options.headers).to.contain( @@ -588,10 +588,10 @@ describe('ManagementClient', function() { client.guardian.factorsProviders.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); expect( - client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + client.guardian.factorsPhoneSelectedProvider.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); expect( - client.guardian.factorsMessageTypes.restClient.restClient.options.headers + client.guardian.factorsPhoneMessageTypes.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); expect( @@ -734,10 +734,10 @@ describe('ManagementClient', function() { client.guardian.factorsProviders.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); expect( - client.guardian.factorsSelectedProvider.restClient.restClient.options.headers + client.guardian.factorsPhoneSelectedProvider.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); expect( - client.guardian.factorsMessageTypes.restClient.restClient.options.headers + client.guardian.factorsPhoneMessageTypes.restClient.restClient.options.headers ).to.not.have.property('Auth0-Client'); expect( @@ -892,10 +892,10 @@ describe('ManagementClient', function() { 'updateGuardianFactor', 'getGuardianPolicies', 'updateGuardianPolicies', - 'getGuardianFactorSelectedProvider', - 'updateGuardianFactorSelectedProvider', - 'getGuardianFactorMessageTypes', - 'updateGuardianFactorMessageTypes', + 'getGuardianPhoneFactorSelectedProvider', + 'updateGuardianPhoneFactorSelectedProvider', + 'getGuardianPhoneFactorMessageTypes', + 'updateGuardianPhoneFactorMessageTypes', 'getUserBlocks', 'unblockUser', 'getUserBlocksByIdentifier', From f5330bb19d7f2a1321377961f07a871224669c3a Mon Sep 17 00:00:00 2001 From: Patrick Malouin Date: Thu, 25 Jun 2020 17:08:37 -0400 Subject: [PATCH 3/9] switch from /phone/selected-provider to /sms/selected-provider --- src/management/GuardianManager.js | 2 +- test/management/guardian.tests.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/management/GuardianManager.js b/src/management/GuardianManager.js index 06d852507..e5125d3b5 100644 --- a/src/management/GuardianManager.js +++ b/src/management/GuardianManager.js @@ -123,7 +123,7 @@ var GuardianManager = function(options) { * @type {external:RestClient} */ var guardianFactorsPhoneSelectedProviderAuth0RestClient = new Auth0RestClient( - options.baseUrl + '/guardian/factors/phone/selected-provider', + options.baseUrl + '/guardian/factors/sms/selected-provider', clientOptions, options.tokenProvider ); diff --git a/test/management/guardian.tests.js b/test/management/guardian.tests.js index 5f76591e7..cb1113be1 100644 --- a/test/management/guardian.tests.js +++ b/test/management/guardian.tests.js @@ -851,7 +851,7 @@ describe('GuardianManager', function() { }; this.request = nock(API_URL) - .get('/guardian/factors/phone/selected-provider') + .get('/guardian/factors/sms/selected-provider') .reply(200, this.data); }); @@ -866,7 +866,7 @@ describe('GuardianManager', function() { .catch(done.bind(null, null)); }); - it('should perform a GET request to /api/v2/guardian/factors/phone/selected-provider', function(done) { + it('should perform a GET request to /api/v2/guardian/factors/sms/selected-provider', function(done) { var request = this.request; this.guardian.getPhoneFactorSelectedProvider().then(function() { @@ -880,7 +880,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .get('/guardian/factors/phone/selected-provider') + .get('/guardian/factors/sms/selected-provider') .reply(500); this.guardian.getPhoneFactorSelectedProvider().catch(function(err) { @@ -894,7 +894,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .get('/guardian/factors/phone/selected-provider') + .get('/guardian/factors/sms/selected-provider') .matchHeader('Authorization', 'Bearer ' + this.token) .reply(200); @@ -929,9 +929,9 @@ describe('GuardianManager', function() { .catch(done.bind(null, null)); }); - it('should perform a PUT request to /api/v2/guardian/factors/phone/selected-provider', function(done) { + it('should perform a PUT request to /api/v2/guardian/factors/sms/selected-provider', function(done) { var request = nock(API_URL) - .put('/guardian/factors/phone/selected-provider') + .put('/guardian/factors/sms/selected-provider') .reply(200, this.data); this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).then(function() { @@ -945,7 +945,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/phone/selected-provider', this.data) + .put('/guardian/factors/sms/selected-provider', this.data) .reply(200); this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).then(function() { @@ -959,7 +959,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/phone/selected-provider') + .put('/guardian/factors/sms/selected-provider') .reply(500); this.guardian.updatePhoneFactorSelectedProvider(this.params, this.data).catch(function(err) { @@ -973,7 +973,7 @@ describe('GuardianManager', function() { nock.cleanAll(); var request = nock(API_URL) - .put('/guardian/factors/phone/selected-provider') + .put('/guardian/factors/sms/selected-provider') .matchHeader('Authorization', 'Bearer ' + this.token) .reply(200); From cebdc365b2512aff657d9feca5419c00e2241d14 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Fri, 26 Jun 2020 14:30:43 -0400 Subject: [PATCH 4/9] feat(mgirations): adds migrations manager --- src/management/MigrationsManager.js | 109 +++++++++++++ src/management/index.js | 54 +++++++ test/management/migrations.tests.js | 230 ++++++++++++++++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 src/management/MigrationsManager.js create mode 100644 test/management/migrations.tests.js diff --git a/src/management/MigrationsManager.js b/src/management/MigrationsManager.js new file mode 100644 index 000000000..862423a39 --- /dev/null +++ b/src/management/MigrationsManager.js @@ -0,0 +1,109 @@ +var ArgumentError = require('rest-facade').ArgumentError; +var Auth0RestClient = require('../Auth0RestClient'); +var RetryRestClient = require('../RetryRestClient'); + +/** + * @class + * Abstracts interaction with the migrations endpoint. + * @constructor + * @memberOf module:management + * + * @param {Object} options The client options. + * @param {String} options.baseUrl The URL of the API. + * @param {Object} [options.headers] Headers to be included in all requests. + * @param {Object} [options.retry] Retry Policy Config + */ +var MigrationsManager = function(options) { + if (options === null || typeof options !== 'object') { + throw new ArgumentError('Must provide manager options'); + } + + if (options.baseUrl === null || options.baseUrl === undefined) { + throw new ArgumentError('Must provide a base URL for the API'); + } + + if ('string' !== typeof options.baseUrl || options.baseUrl.length === 0) { + throw new ArgumentError('The provided base URL is invalid'); + } + + var clientOptions = { + errorFormatter: { message: 'message', name: 'error' }, + headers: options.headers, + query: { repeatParams: false } + }; + + /** + * Provides an abstraction layer for consuming the + * {@link https://auth0.com/docs/api/v2#!/Stats Stats endpoint}. + * + * @type {external:RestClient} + */ + var auth0RestClient = new Auth0RestClient( + options.baseUrl + '/migrations', + clientOptions, + options.tokenProvider + ); + this.resource = new RetryRestClient(auth0RestClient, options.retry); +}; + +/** + * Update the tenant migrations. + * + * @method updateMigrations + * @memberOf module:management.MigrationsManager.prototype + * + * @example + * management.tmigrations.updateMigrations(data, function (err) { + * if (err) { + * // Handle error. + * } + * }); + * + * @param {Object} data The tenant migrations to be updated + * @param {Object} data.flags The tenant migrations flags to be updated + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +MigrationsManager.prototype.updateMigrations = function(data, cb) { + if (cb && cb instanceof Function) { + return this.resource.patch({}, data, cb); + } + + // Return a promise. + return this.resource.patch({}, data); +}; + +/** + * Get the tenant migrations. + * + * @method getMigrations + * @memberOf module:management.MIgrationsManager.prototype + * + * @example + * management.migrations.getMigrations(function (err, settings) { + * if (err) { + * // Handle error. + * } + * + * console.log(settings); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +MigrationsManager.prototype.getMigrations = function(data, cb) { + if (data instanceof Function && !cb) { + cb = data; + data = {}; + } + if (cb && cb instanceof Function) { + return this.resource.get(data, cb); + } + + // Return a promise. + return this.resource.get(data); +}; + +module.exports = MigrationsManager; diff --git a/src/management/index.js b/src/management/index.js index 2588e7001..ea938768d 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -32,6 +32,7 @@ var CustomDomainsManager = require('./CustomDomainsManager'); var RolesManager = require('./RolesManager'); var HooksManager = require('./HooksManager'); var BrandingManager = require('./BrandingManager'); +var MigrationsManager = require('./MigrationsManager'); var BASE_URL_FORMAT = 'https://%s/api/v2'; var MANAGEMENT_API_AUD_FORMAT = 'https://%s/api/v2/'; @@ -327,6 +328,13 @@ var ManagementClient = function(options) { * @type {HooksManager} */ this.branding = new BrandingManager(managerOptions); + + /** + * ManagementClient migrationss manager. + * + * @type {MigrationsManager} + */ + this.migrations = new MigrationsManager(managerOptions); }; /** @@ -3212,4 +3220,50 @@ utils.wrapPropertyMethod(ManagementClient, 'updateBrandingSettings', 'branding.u */ utils.wrapPropertyMethod(ManagementClient, 'getBrandingSettings', 'branding.getSettings'); +/** + * Update the tenant migrations. + * + * @method updateMigrations + * @memberOf module:management.ManagementClient.prototype + * + * @example + * data = { flags: { migration: true } }; + * management.updateMigrations(data, function (err, migrations) { + * if (err) { + * // Handle error. + * } + * + * // Updated migrations flags + * console.log(migrations.flags); + * }); + * + * @param {Object} data Updated migrations data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'updateMigrations', 'migrations.updateMigrations'); + +/** + * Get migrations flags + * + * @method getMigrations + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.getMigrations(function (err, migrations) { + * if (err) { + * // Handle error. + * } + * + * // Migration flags + * console.log(migrations.flags); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'getMigrations', 'migrations.getMigrations'); + module.exports = ManagementClient; diff --git a/test/management/migrations.tests.js b/test/management/migrations.tests.js new file mode 100644 index 000000000..5a6db82d9 --- /dev/null +++ b/test/management/migrations.tests.js @@ -0,0 +1,230 @@ +var expect = require('chai').expect; +var nock = require('nock'); + +var SRC_DIR = '../../src'; +var API_URL = 'https://tenants.auth0.com'; + +var MigrationsManager = require(SRC_DIR + '/management/MigrationsManager'); +var ArgumentError = require('rest-facade').ArgumentError; + +describe('MigrationsManager', function() { + before(function() { + this.token = 'TOKEN'; + this.migrations = new MigrationsManager({ + headers: { authorization: 'Bearer ' + this.token }, + baseUrl: API_URL + }); + }); + + describe('instance', function() { + var methods = ['updateMigrations', 'getMigrations']; + + methods.forEach(function(method) { + it('should have a ' + method + ' method', function() { + expect(this.migrations[method]).to.exist.to.be.an.instanceOf(Function); + }); + }); + }); + + describe('#constructor', function() { + it('should error when no options are provided', function() { + expect(MigrationsManager).to.throw(ArgumentError, 'Must provide manager options'); + }); + + it('should throw an error when no base URL is provided', function() { + var manager = MigrationsManager.bind(null, {}); + + expect(manager).to.throw(ArgumentError, 'Must provide a base URL for the API'); + }); + + it('should throw an error when the base URL is invalid', function() { + var manager = MigrationsManager.bind(null, { baseUrl: '' }); + + expect(manager).to.throw(ArgumentError, 'The provided base URL is invalid'); + }); + }); + + describe('#getMigrations', function() { + beforeEach(function() { + this.request = nock(API_URL) + .get('/migrations') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.migrations.getMigrations(function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.migrations + .getMigrations() + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/migrations') + .reply(500); + + this.migrations.getMigrations().catch(function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should pass the body of the response to the "then" handler', function(done) { + nock.cleanAll(); + + var data = { flags: { migration_flag: true } }; + var request = nock(API_URL) + .get('/migrations') + .reply(200, data); + + this.migrations.getMigrations().then(function(migrations) { + expect(migrations).to.be.an('object'); + + expect(migrations).to.have.nested.property('flags.migration_flag', true); + + done(); + }); + }); + + it('should perform a GET request to /api/v2/migrations', function(done) { + var request = this.request; + + this.migrations.getMigrations().then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/migrations') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.migrations.getMigrations().then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should pass the parameters in the query-string', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/migrations') + .query({ + any: 'test' + }) + .reply(200); + + this.migrations.getMigrations({ any: 'test' }).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + }); + + describe('#updateMigrations', function() { + var data = { + flags: { + migration: false + } + }; + + beforeEach(function() { + this.request = nock(API_URL) + .patch('/migrations') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.migrations.updateMigrations(data, function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.migrations + .updateMigrations(data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/migrations') + .reply(500); + + this.migrations.updateMigrations(data).catch(function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should perform a PATCH request to /api/v2migrations', function(done) { + var request = this.request; + + this.migrations.updateMigrations(data).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should pass the data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/migrations', data) + .reply(200); + + this.migrations.updateMigrations(data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass the body of the response to the "then" handler', function(done) { + nock.cleanAll(); + + var result = { flags: { migration_flag: true } }; + var request = nock(API_URL) + .patch('/migrations') + .reply(200, result); + + this.migrations.updateMigrations(data).then(function(migrations) { + expect(migrations).to.be.an('object'); + + expect(migrations).to.have.nested.property('flags.migration_flag', true); + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/migrations') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.migrations.updateMigrations(data).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + }); +}); From f87cbb0f66084fa547df097cc0118c39b8c483c8 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Tue, 30 Jun 2020 11:59:54 -0400 Subject: [PATCH 5/9] Update src/management/index.js Co-authored-by: Fady Makram --- src/management/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/management/index.js b/src/management/index.js index ea938768d..6b43095e5 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -330,7 +330,7 @@ var ManagementClient = function(options) { this.branding = new BrandingManager(managerOptions); /** - * ManagementClient migrationss manager. + * ManagementClient migrations manager. * * @type {MigrationsManager} */ From 4df261b27f3e55b5fcd07248f78c9c95d85db151 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Tue, 30 Jun 2020 12:00:01 -0400 Subject: [PATCH 6/9] Update src/management/MigrationsManager.js Co-authored-by: Fady Makram --- src/management/MigrationsManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/management/MigrationsManager.js b/src/management/MigrationsManager.js index 862423a39..ba87215df 100644 --- a/src/management/MigrationsManager.js +++ b/src/management/MigrationsManager.js @@ -53,7 +53,7 @@ var MigrationsManager = function(options) { * @memberOf module:management.MigrationsManager.prototype * * @example - * management.tmigrations.updateMigrations(data, function (err) { + * management.migrations.updateMigrations(data, function (err) { * if (err) { * // Handle error. * } From fdf6ec0f8d12fafb5d15fd26faab821cb0d473c3 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Tue, 30 Jun 2020 12:00:09 -0400 Subject: [PATCH 7/9] Update src/management/MigrationsManager.js Co-authored-by: Fady Makram --- src/management/MigrationsManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/management/MigrationsManager.js b/src/management/MigrationsManager.js index ba87215df..786207f0e 100644 --- a/src/management/MigrationsManager.js +++ b/src/management/MigrationsManager.js @@ -78,7 +78,7 @@ MigrationsManager.prototype.updateMigrations = function(data, cb) { * Get the tenant migrations. * * @method getMigrations - * @memberOf module:management.MIgrationsManager.prototype + * @memberOf module:management.MigrationsManager.prototype * * @example * management.migrations.getMigrations(function (err, settings) { From ba68ae95427cfabbb232b9da1e7253f069dbd181 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Tue, 30 Jun 2020 12:00:18 -0400 Subject: [PATCH 8/9] Update src/management/MigrationsManager.js Co-authored-by: Fady Makram --- src/management/MigrationsManager.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/management/MigrationsManager.js b/src/management/MigrationsManager.js index 786207f0e..d9adbfb7c 100644 --- a/src/management/MigrationsManager.js +++ b/src/management/MigrationsManager.js @@ -33,8 +33,7 @@ var MigrationsManager = function(options) { }; /** - * Provides an abstraction layer for consuming the - * {@link https://auth0.com/docs/api/v2#!/Stats Stats endpoint}. + * Provides an abstraction layer for consuming the migrations endpoint * * @type {external:RestClient} */ From 9ef24355a76c9c7fd3fe13534e07744c86b15423 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Tue, 30 Jun 2020 12:00:30 -0400 Subject: [PATCH 9/9] Update src/management/MigrationsManager.js Co-authored-by: Fady Makram --- src/management/MigrationsManager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/management/MigrationsManager.js b/src/management/MigrationsManager.js index d9adbfb7c..b051deecb 100644 --- a/src/management/MigrationsManager.js +++ b/src/management/MigrationsManager.js @@ -80,12 +80,12 @@ MigrationsManager.prototype.updateMigrations = function(data, cb) { * @memberOf module:management.MigrationsManager.prototype * * @example - * management.migrations.getMigrations(function (err, settings) { + * management.migrations.getMigrations(function (err, migrations) { * if (err) { * // Handle error. * } * - * console.log(settings); + * console.log(migrations.flags); * }); * * @param {Function} [cb] Callback function.