From cebdc365b2512aff657d9feca5419c00e2241d14 Mon Sep 17 00:00:00 2001 From: Cristofer Gonzales Date: Fri, 26 Jun 2020 14:30:43 -0400 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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.