diff --git a/src/management/UserBlocksManager.js b/src/management/UserBlocksManager.js new file mode 100644 index 000000000..3794d7e69 --- /dev/null +++ b/src/management/UserBlocksManager.js @@ -0,0 +1,176 @@ +var ArgumentError = require('rest-facade').ArgumentError; +var Auth0RestClient = require('../Auth0RestClient'); +var RetryRestClient = require('../RetryRestClient'); + +/** + * Simple facade for consuming a REST API endpoint. + * @external RestClient + * @see https://github.com/ngonzalvez/rest-facade + */ + +/** + * @class + * Abstracts interaction with the user-blocks 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 UserBlocksManager = 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 } + }; + + var userBlocksByIdResource = new Auth0RestClient( + options.baseUrl + '/user-blocks/:id', + clientOptions, + options.tokenProvider + ); + this.userBlocksById = new RetryRestClient(userBlocksByIdResource, options.retry); + + var userBlocksByIdentifierResource = new Auth0RestClient( + options.baseUrl + '/user-blocks', + clientOptions, + options.tokenProvider + ); + this.userBlocksByIdentifier = new RetryRestClient(userBlocksByIdentifierResource, options.retry); +}; + +/** + * Get user blocks by id. + * + * @method get + * @memberOf module:management.UserBlocksManager.prototype + * + * @example + * management.userBlocks.get({ id: USER_ID }, function (err, blocks) { + * if (err) { + * // Handle error. + * } + * + * console.log(blocks); + * }); + * + * + * @param {Object} params The user data object.. + * @param {String} params.id The user id. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ +UserBlocksManager.prototype.get = function(params) { + if (typeof params !== 'object' || typeof params.id !== 'string') { + throw new ArgumentError('You must provide an user id for the get method'); + } + + return this.userBlocksById.get.apply(this.userBlocksById, arguments); +}; + +/** + * Unblock an user by its id. + * + * @method delete + * @memberOf module:management.UserBlocksManager.prototype + * + * @example + * management.userBlocks.delete({ id: USER_ID }, function (err) { + * if (err) { + * // Handle error. + * } + * + * // User unblocked. + * }); + * + * + * @param {Object} params The user data object.. + * @param {String} params.id The user id. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ +UserBlocksManager.prototype.delete = function(params) { + if (typeof params !== 'object' || typeof params.id !== 'string') { + throw new ArgumentError('You must provide an user id for the delete method'); + } + + return this.userBlocksById.delete.apply(this.userBlocksById, arguments); +}; + +/** + * Get user blocks by identifier. + * + * @method getByIdentifier + * @memberOf module:management.UserBlocksManager.prototype + * + * @example + * management.userBlocks.getByIdentifier({ identifier: USER_ID }, function (err, blocks) { + * if (err) { + * // Handle error. + * } + * + * console.log(blocks); + * }); + * + * + * @param {Object} params The user data object.. + * @param {String} params.identifier The user identifier, any of: username, phone_number, email. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ + UserBlocksManager.prototype.getByIdentifier = function(params) { + if (typeof params !== 'object' || typeof params.identifier !== 'string') { + throw new ArgumentError('You must provide an user identifier for the getByIdentifier method'); + } + + return this.userBlocksByIdentifier.get.apply(this.userBlocksByIdentifier, arguments); + }; + +/** + * Unblock an user by identifier. + * + * @method deleteByIdentifier + * @memberOf module:management.UserBlocksManager.prototype + * + * @example + * management.userBlocks.deleteByIdentifier({ identifier: USER_ID }, function (err) { + * if (err) { + * // Handle error. + * } + * + * // User unblocked. + * }); + * + * + * @param {Object} params The user data object.. + * @param {String} params.identifier The user identifier, any of: username, phone_number, email. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ + UserBlocksManager.prototype.deleteByIdentifier = function(params) { + if (typeof params !== 'object' || typeof params.identifier !== 'string') { + throw new ArgumentError('You must provide an user identifier for the deleteByIdentifier method'); + } + + return this.userBlocksByIdentifier.delete.apply(this.userBlocksByIdentifier, arguments); + }; + + module.exports = UserBlocksManager; diff --git a/src/management/index.js b/src/management/index.js index 33a544ccc..b687a7e0b 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -12,6 +12,7 @@ var ClientsManager = require('./ClientsManager'); var ClientGrantsManager = require('./ClientGrantsManager'); var GrantsManager = require('./GrantsManager'); var UsersManager = require('./UsersManager'); +var UserBlocksManager = require('./UserBlocksManager'); var ConnectionsManager = require('./ConnectionsManager'); var BlacklistedTokensManager = require('./BlacklistedTokensManager'); var RulesManager = require('./RulesManager'); @@ -169,6 +170,14 @@ var ManagementClient = function(options) { */ this.users = new UsersManager(managerOptions); + /** + * Simple abstraction for performing CRUD operations on the + * user-blocks endpoint. + * + * @type {UserBlocksManager} + */ + this.userBlocks = new UserBlocksManager(managerOptions); + /** * Simple abstraction for performing CRUD operations on the * guardian endpoint. @@ -1502,6 +1511,98 @@ utils.wrapPropertyMethod( 'users.regenerateRecoveryCode' ); +/** + * Get user blocks by its id. + * + * @method getUserBlocks + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.getUserBlocks({ id: USER_ID }, function (err, blocks) { + * if (err) { + * // Handle error. + * } + * + * console.log(blocks); + * }); + * + * @param {Object} params The user data object.. + * @param {String} params.id The user id. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'getUserBlocks', 'userBlocks.get'); + +/** + * Unblock an user by its id. + * + * @method unblockUser + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.unblockUser({ id: USER_ID }, function (err) { + * if (err) { + * // Handle error. + * } + * + * // User unblocked. + * }); + * + * @param {Object} params The user data object.. + * @param {String} params.id The user id. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'unblockUser', 'userBlocks.delete'); + +/** + * Get user blocks by its identifier. + * + * @method getUserBlocksByIdentifier + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.getUserBlocksByIdentifier({ identifier: USER_ID }, function (err, blocks) { + * if (err) { + * // Handle error. + * } + * + * console.log(blocks); + * }); + * + * @param {Object} params The user data object.. + * @param {String} params.identifier The user identifier, any of: username, phone_number, email. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'getUserBlocksByIdentifier', 'userBlocks.getByIdentifier'); + +/** + * Unblock an user by its id. + * + * @method unblockUser + * @memberOf module:management.ManagementClient.prototype + * + * @example + * management.unblockUserByIdentifier({ identifier: USER_ID }, function (err) { + * if (err) { + * // Handle error. + * } + * + * // User unblocked. + * }); + * + * @param {Object} params The user data object.. + * @param {String} params.identifier The user identifier, any of: username, phone_number, email. + * @param {Function} [cb] Callback function + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'unblockUserByIdentifier', 'userBlocks.deleteByIdentifier'); + /** * Get a single Guardian enrollment. * diff --git a/test/management/management-client.tests.js b/test/management/management-client.tests.js index 4b0f92fdd..64928b492 100644 --- a/test/management/management-client.tests.js +++ b/test/management/management-client.tests.js @@ -7,6 +7,7 @@ var ManagementClient = require('../../src/management'); var ArgumentError = require('rest-facade').ArgumentError; var UsersManager = require('../../src/management/UsersManager'); +var UserBlocksManager = require('../../src/management/UserBlocksManager'); var BlacklistedTokensManager = require('../../src/management/BlacklistedTokensManager'); var ClientsManager = require('../../src/management/ClientsManager'); var ClientGrantsManager = require('../../src/management/ClientGrantsManager'); @@ -101,6 +102,10 @@ describe('ManagementClient', function() { property: 'users', cls: UsersManager }, + UserBlocksManager: { + property: 'userBlocks', + cls: UserBlocksManager + }, BlacklistedTokensManager: { property: 'blacklistedTokens', cls: BlacklistedTokensManager @@ -760,7 +765,11 @@ describe('ManagementClient', function() { 'deleteUserMultifcator', 'setRulesConfig', 'getRulesConfigs', - 'deleteRulesConfig' + 'deleteRulesConfig', + 'getUserBlocks', + 'unblockUser', + 'getUserBlocksByIdentifier', + 'unblockUserByIdentifier' ]; before(function() { diff --git a/test/management/user-blocks.tests.js b/test/management/user-blocks.tests.js new file mode 100644 index 000000000..0db1b37ce --- /dev/null +++ b/test/management/user-blocks.tests.js @@ -0,0 +1,352 @@ +var expect = require('chai').expect; +var nock = require('nock'); + +var SRC_DIR = '../../src'; +var API_URL = 'https://tenants.auth0.com'; + +var UserBlocksManager = require(SRC_DIR + '/management/UserBlocksManager'); +var ArgumentError = require('rest-facade').ArgumentError; + +describe('UserBlocksManager', function() { + before(function() { + this.token = 'TOKEN'; + this.userBlocks = new UserBlocksManager({ + headers: { authorization: 'Bearer ' + this.token }, + baseUrl: API_URL + }); + }); + + describe('instance', function() { + var methods = ['get', 'delete', 'getByIdentifier', 'deleteByIdentifier']; + + methods.forEach(function(method) { + it('should have a ' + method + ' method', function() { + expect(this.userBlocks[method]).to.exist.to.be.an.instanceOf(Function); + }); + }); + }); + + describe('#constructor', function() { + it('should error when no options are provided', function() { + expect(UserBlocksManager).to.throw(ArgumentError, 'Must provide manager options'); + }); + + it('should throw an error when no base URL is provided', function() { + var manager = UserBlocksManager.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 = UserBlocksManager.bind(null, { baseUrl: '' }); + + expect(manager).to.throw(ArgumentError, 'The provided base URL is invalid'); + }); + }); + + describe('#get', function() { + var id = 'USER_5'; + + beforeEach(function() { + this.request = nock(API_URL) + .get('/user-blocks/' + id) + .reply(200); + }); + + afterEach(function() { + nock.cleanAll(); + }) + + it('should throw an error when no id is provided', function() { + var userBlocks = this.userBlocks + + expect(function() { + userBlocks.get({}); + }).to.throw(ArgumentError, 'You must provide an user id for the get method'); + }); + + it('should accept a callback', function(done) { + this.userBlocks.get({ id }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.userBlocks.get({ id }).then(done.bind(null, null)); + }); + + it('should perform a get request to /user-blocks/' + id, function(done) { + var request = this.request; + + this.userBlocks.get({ id }) + .then(function() { + expect(request.isDone()).to.be.true; + done(); + }) + .catch(done); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + nock(API_URL) + .get('/user-blocks/' + id) + .reply(500); + + this.userBlocks.get({ id }) + .catch(function(err) { + expect(err).to.exist; + + done(); + }) + .catch(done); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/user-blocks/' + id) + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.userBlocks.get({ id }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + }); + + describe('#delete', function() { + var id = 'USER_5'; + + beforeEach(function() { + this.request = nock(API_URL) + .delete('/user-blocks/' + id) + .reply(200); + }); + + afterEach(function() { + nock.cleanAll(); + }) + + it('should throw an error when no id is provided', function() { + var userBlocks = this.userBlocks + + expect(function() { + userBlocks.delete({}); + }).to.throw(ArgumentError, 'You must provide an user id for the delete method'); + }); + + it('should accept a callback', function(done) { + this.userBlocks.delete({ id }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.userBlocks.delete({ id }).then(done.bind(null, null)); + }); + + it('should perform a delete request to /user-blocks/' + id, function(done) { + var request = this.request; + + this.userBlocks.delete({ id }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + nock(API_URL) + .delete('/user-blocks/' + id) + .reply(500); + + this.userBlocks.delete({ id }) + .catch(function(err) { + expect(err).to.exist; + + done(); + }) + .catch(done); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .delete('/user-blocks/' + id) + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.userBlocks.delete({ id }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + }); + + describe('#getByIdentifier', function() { + var identifier = 'USER_5'; + + beforeEach(function() { + this.request = nock(API_URL) + .get('/user-blocks') + .query({ identifier }) + .reply(200); + }); + + afterEach(function() { + nock.cleanAll(); + }) + + it('should throw an error when no identifier is provided', function() { + var userBlocks = this.userBlocks + + expect(function() { + userBlocks.getByIdentifier({}); + }).to.throw(ArgumentError, 'You must provide an user identifier for the getByIdentifier method'); + }); + + it('should accept a callback', function(done) { + this.userBlocks.getByIdentifier({ identifier }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.userBlocks.getByIdentifier({ identifier }).then(done.bind(null, null)); + }); + + it('should perform a get request to /user-blocks', function(done) { + var request = this.request; + + this.userBlocks.getByIdentifier({ identifier }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + nock(API_URL) + .get('/user-blocks') + .query({ identifier }) + .reply(500); + + this.userBlocks.getByIdentifier({ identifier }) + .catch(function(err) { + expect(err).to.exist; + + done(); + }) + .catch(done); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/user-blocks') + .query({ identifier }) + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.userBlocks.getByIdentifier({ identifier }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + }); + + describe('#deleteByIdentifier', function() { + var identifier = 'USER_5'; + + beforeEach(function() { + this.request = nock(API_URL) + .delete('/user-blocks') + .query({ identifier }) + .reply(200); + }); + + afterEach(function() { + nock.cleanAll(); + }) + + it('should throw an error when no identifier is provided', function() { + var userBlocks = this.userBlocks + + expect(function() { + userBlocks.deleteByIdentifier({}); + }).to.throw(ArgumentError, 'You must provide an user identifier for the deleteByIdentifier method'); + }); + + it('should accept a callback', function(done) { + this.userBlocks.deleteByIdentifier({ identifier }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.userBlocks.deleteByIdentifier({ identifier }).then(done.bind(null, null)); + }); + + it('should perform a delete request to /user-blocks', function(done) { + var request = this.request; + + this.userBlocks.deleteByIdentifier({ identifier }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + nock(API_URL) + .delete('/user-blocks') + .query({ identifier }) + .reply(500); + + this.userBlocks.deleteByIdentifier({ identifier }) + .catch(function(err) { + expect(err).to.exist; + + done(); + }) + .catch(done); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .delete('/user-blocks') + .query({ identifier }) + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.userBlocks.deleteByIdentifier({ identifier }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(done); + }); + }); + +});