diff --git a/docs/management_JobsManager.js.html b/docs/management_JobsManager.js.html index f7e52792c..7bb900673 100644 --- a/docs/management_JobsManager.js.html +++ b/docs/management_JobsManager.js.html @@ -235,7 +235,8 @@

management/JobsManager.js

* * @example * var params = { - * user_id: '{USER_ID}' + * user_id: '{USER_ID}', + * client_id: '{CLIENT_ID}' * }; * * management.jobs.verifyEmail(function (err) { @@ -246,6 +247,7 @@

management/JobsManager.js

* * @param {Object} data User data object. * @param {String} data.user_id ID of the user to be verified. + * @param {String} data.client_id ID of the client for which the verification email will be sent. * @param {Function} [cb] Callback function. * * @return {Promise|undefined} diff --git a/src/auth/OAuthAuthenticator.js b/src/auth/OAuthAuthenticator.js index 0d2b33d81..d8df93582 100644 --- a/src/auth/OAuthAuthenticator.js +++ b/src/auth/OAuthAuthenticator.js @@ -179,6 +179,60 @@ OAuthAuthenticator.prototype.passwordGrant = function(userData, cb) { return this.oauthWithIDTokenValidation.create(params, data); }; +/** + * Sign in using a refresh token + * + * @method refreshToken + * @memberOf module:auth.OAuthAuthenticator.prototype + * + * @example + * Given a refresh token from a previous authentication request + * it will return a JSON with the access_token and id_token. + * More information in the + * + * API Docs + * . + * + * + * var data = { + * client_id: '{CLIENT_ID}', // Optional field. + * refresh_token: '{REFRESH_TOKEN}', + * }; + * + * auth0.oauth.refreshToken(data, function (err, userData) { + * if (err) { + * // Handle error. + * } + * + * console.log(userData); + * }); + * + * @param {Object} userData User credentials object. + * @param {String} userData.refresh_token Refresh token. + * + * @return {Promise|undefined} + */ +OAuthAuthenticator.prototype.refreshToken = function(userData, cb) { + var params = { + type: 'token' + }; + var defaultFields = { + client_id: this.clientId, + grant_type: 'refresh_token' + }; + var data = extend(defaultFields, userData); + if (!userData || typeof userData !== 'object') { + throw new ArgumentError('Missing user data object'); + } + if (typeof data.refresh_token !== 'string' || data.refresh_token.split().length === 0) { + throw new ArgumentError('refresh_token is required'); + } + if (cb && cb instanceof Function) { + return this.oauthWithIDTokenValidation.create(params, data, cb); + } + return this.oauthWithIDTokenValidation.create(params, data); +}; + /** * Sign in using a social provider access token. * diff --git a/src/auth/index.js b/src/auth/index.js index fa410aa9c..acb70f253 100644 --- a/src/auth/index.js +++ b/src/auth/index.js @@ -543,4 +543,39 @@ utils.wrapPropertyMethod( */ utils.wrapPropertyMethod(AuthenticationClient, 'passwordGrant', 'oauth.passwordGrant'); +/** + * Sign in using a refresh token + * + * @method refreshToken + * @memberOf module:auth.AuthenticationClient.prototype + * + * @example + * Given a refresh token from a previous authentication request, + * it will return a JSON with the access_token and id_token. + * More information in the + * + * API Docs + * . + * + * + * var data = { + * client_id: '{CLIENT_ID}', // Optional field. + * refresh_token: '{REFRESH_TOKEN}', + * }; + * + * auth0.refreshToken(data, function (err, userData) { + * if (err) { + * // Handle error. + * } + * + * console.log(userData); + * }); + * + * @param {Object} userData User credentials object. + * @param {String} userData.refresh_token Refresh token. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(AuthenticationClient, 'refreshToken', 'oauth.refreshToken'); + module.exports = AuthenticationClient; diff --git a/src/management/GuardianManager.js b/src/management/GuardianManager.js index eede511d2..c1f516ca1 100644 --- a/src/management/GuardianManager.js +++ b/src/management/GuardianManager.js @@ -1,4 +1,5 @@ var ArgumentError = require('rest-facade').ArgumentError; +var utils = require('../utils'); var Auth0RestClient = require('../Auth0RestClient'); var RetryRestClient = require('../RetryRestClient'); @@ -49,6 +50,60 @@ var GuardianManager = function(options) { options.tokenProvider ); this.enrollments = new RetryRestClient(guardianEnrollmentsAuth0RestClient, options.retry); + + /** + * Provides an abstraction layer for retrieving Guardian tickets. + * + * @type {external:RestClient} + */ + var guardianTicketsAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/enrollments/ticket', + clientOptions, + options.tokenProvider + ); + this.tickets = new RetryRestClient(guardianTicketsAuth0RestClient, options.retry); + + /** + * Provides an abstraction layer for retrieving Guardian factors. + * + * @type {external:RestClient} + */ + var guardianFactorsAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/:name', + clientOptions, + options.tokenProvider + ); + this.factors = new RetryRestClient(guardianFactorsAuth0RestClient, options.retry); + + /** + * Provides an abstraction layer for retrieving Guardian factors. + * + * @type {external:RestClient} + */ + var guardianFactorsTemplatesAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/:name/templates', + clientOptions, + options.tokenProvider + ); + this.factorsTemplates = new RetryRestClient( + guardianFactorsTemplatesAuth0RestClient, + options.retry + ); + + /** + * Provides an abstraction layer for retrieving Guardian factor providers. + * + * @type {external:RestClient} + */ + var guardianFactorsProvidersAuth0RestClient = new Auth0RestClient( + options.baseUrl + '/guardian/factors/:name/providers/:provider', + clientOptions, + options.tokenProvider + ); + this.factorsProviders = new RetryRestClient( + guardianFactorsProvidersAuth0RestClient, + options.retry + ); }; /** @@ -58,7 +113,7 @@ var GuardianManager = function(options) { * @memberOf module:management.GuardianManager.prototype * * @example - * management.users.getGuardianEnrollment({ id: ENROLLMENT_ID }, function (err, enrollment) { + * management.guardian.getGuardianEnrollment({ id: ENROLLMENT_ID }, function (err, enrollment) { * console.log(enrollment); * }); * @@ -68,9 +123,7 @@ var GuardianManager = function(options) { * * @return {Promise|undefined} */ -GuardianManager.prototype.getGuardianEnrollment = function(params, cb) { - return this.enrollments.get(params, cb); -}; +utils.wrapPropertyMethod(GuardianManager, 'getGuardianEnrollment', 'enrollments.get'); /** * Delete a Guardian enrollment. @@ -79,7 +132,7 @@ GuardianManager.prototype.getGuardianEnrollment = function(params, cb) { * @memberOf module:management.GuardianManager.prototype * * @example - * management.users.deleteGuardianEnrollment({ id: ENROLLMENT_ID }, function (err, enrollments) { + * management.guardian.deleteGuardianEnrollment({ id: ENROLLMENT_ID }, function (err, enrollments) { * console.log(enrollments); * }); * @@ -89,8 +142,136 @@ GuardianManager.prototype.getGuardianEnrollment = function(params, cb) { * * @return {Promise|undefined} */ -GuardianManager.prototype.deleteGuardianEnrollment = function(params, cb) { - return this.enrollments.delete(params, cb); -}; +utils.wrapPropertyMethod(GuardianManager, 'deleteGuardianEnrollment', 'enrollments.delete'); + +/** + * Create a Guardian enrollment ticket. + * + * @method createEnrollmentTicket + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.guardian.createEnrollmentTicket(function (err, ticket) { + * console.log(ticket); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'createEnrollmentTicket', 'tickets.create'); + +/** + * Get a list of factors and statuses. + * + * @method getFactors + * @memberOf module:management.GuardianManager.prototype + * + * management.guardian.getFactors(function (err, factors) { + * console.log(factors.length); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'getFactors', 'factors.getAll'); + +/** + * Get Guardian factor provider configuration + * + * @method getFactorProvider + * @memberOf module:management.GuardianManager.prototype + * + * management.guardian.getFactorProvider({ name: 'sms', provider: 'twilio'}, function (err, provider) { + * console.log(provider); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'getFactorProvider', 'factorsProviders.get'); + +/** + * Update Guardian's factor provider + * + * @method updateFactorProvider + * @memberOf module:management.GuardianManager.prototype + * + * management.guardian.updateFactorProvider({ name: 'sms', provider: 'twilio' }, { + * messaging_service_sid: 'XXXXXXXXXXXXXX', + * auth_token: 'XXXXXXXXXXXXXX', + * sid: 'XXXXXXXXXXXXXX' + * }, function(err, provider) { + * console.log(provider); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {Object} data Updated Factor provider data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'updateFactorProvider', 'factorsProviders.update'); + +/** + * Get Guardian enrollment and verification factor templates + * + * @method getFactorTemplates + * @memberOf module:management.GuardianManager.prototype + * + * management.guardian.getFactorTemplates({ name: 'sms' }, function (err, templates) { + * console.log(templates); + * }); + * + * @param {Object} params Factor parameters. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'getFactorTemplates', 'factorsTemplates.get'); + +/** + * Update Guardian enrollment and verification factor templates + * + * @method updateFactorTemplates + * @memberOf module:management.GuardianManager.prototype + * + * management.guardian.updateFactorProvider({ name: 'sms' }, { + * enrollment_message: "{{code}} is your verification code for {{tenant.friendly_name}}. Please enter this code to verify your enrollment.", + * verification_message: "{{code}} is your verification code for {{tenant.friendly_name}}" + * }, function(err, templates) { + * console.log(templates); + * }); + * + * @param {Object} params Factor parameters. + * @param {Object} data Updated factor templates data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'updateFactorTemplates', 'factorsTemplates.update'); + +/** + * Update Guardian Factor + * + * @method updateFactor + * @memberOf module:management.GuardianManager.prototype + * + * management.guardian.updateFactor({ name: 'sms' }, { + * enabled: true + * }, function(err, factor) { + * console.log(factor); + * }); + * + * @param {Object} params Factor parameters. + * @param {Object} data Updated factor data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(GuardianManager, 'updateFactor', 'factors.update'); module.exports = GuardianManager; diff --git a/src/management/index.js b/src/management/index.js index 842b953c4..b9bce9cf0 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -2044,4 +2044,154 @@ utils.wrapPropertyMethod(ManagementClient, 'verifyCustomDomain', 'customDomains. */ utils.wrapPropertyMethod(ManagementClient, 'deleteCustomDomain', 'customDomains.delete'); +/** + * Create a Guardian enrollment ticket. + * + * @method createGuardianEnrollmentTicket + * @memberOf module:management.GuardianManager.prototype + * + * @example + * management.createGuardianEnrollmentTicket(function (err, ticket) { + * console.log(ticket); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'createGuardianEnrollmentTicket', + 'guardian.tickets.create' +); + +/** + * Get a list of Guardian factors and statuses. + * + * @method getGuardianFactors + * @memberOf module:management.GuardianManager.prototype + * + * management.getGuardianFactors(function (err, factors) { + * console.log(factors.length); + * }); + * + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'getGuardianFactors', 'guardian.factors.getAll'); + +/** + * Get Guardian factor provider configuration + * + * @method getGuardianFactorProvider + * @memberOf module:management.GuardianManager.prototype + * + * management.getFactorProvider({ name: 'sms', provider: 'twilio'}, function (err, provider) { + * console.log(provider); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'getGuardianFactorProvider', + 'guardian.factorsProviders.get' +); + +/** + * Update Guardian's factor provider + * + * @method updateFactorProvider + * @memberOf module:management.GuardianManager.prototype + * + * management.updateGuardianFactorProvider({ name: 'sms', provider: 'twilio' }, { + * messaging_service_sid: 'XXXXXXXXXXXXXX', + * auth_token: 'XXXXXXXXXXXXXX', + * sid: 'XXXXXXXXXXXXXX' + * }, function(err, provider) { + * console.log(provider); + * }); + * + * @param {Object} params Factor provider parameters. + * @param {Object} data Updated Factor provider data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'updateGuardianFactorProvider', + 'guardian.factorsProviders.update' +); + +/** + * Get Guardian enrollment and verification factor templates + * + * @method getGuardianFactorTemplates + * @memberOf module:management.GuardianManager.prototype + * + * management.getGuardianFactorTemplates({ name: 'sms' }, function (err, templates) { + * console.log(templates); + * }); + * + * @param {Object} params Factor parameters. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'getGuardianFactorTemplates', + 'guardian.factorsTemplates.get' +); + +/** + * Update Guardian enrollment and verification factor templates + * + * @method updateGuardianFactorTemplates + * @memberOf module:management.GuardianManager.prototype + * + * management.updateGuardianFactorTemplates({ name: 'sms' }, { + * enrollment_message: "{{code}} is your verification code for {{tenant.friendly_name}}. Please enter this code to verify your enrollment.", + * verification_message: "{{code}} is your verification code for {{tenant.friendly_name}}" + * }, function(err, templates) { + * console.log(templates); + * }); + * + * @param {Object} params Factor parameters. + * @param {Object} data Updated factor templates data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod( + ManagementClient, + 'updateGuardianFactorTemplates', + 'guardian.factorsTemplates.update' +); + +/** + * Update Guardian Factor + * + * @method updateGuardianFactor + * @memberOf module.GuardianManager.prototype + * + * management.updateGuardianFactor({ name: 'sms' }, { + * enabled: true + * }, function(err, factor) { + * console.log(factor); + * }); + * + * @param {Object} params Factor parameters. + * @param {Object} data Updated factor data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ManagementClient, 'updateGuardianFactor', 'guardian.factors.update'); + module.exports = ManagementClient; diff --git a/test/auth/oauth.tests.js b/test/auth/oauth.tests.js index 3dcb436a2..f91d4104e 100644 --- a/test/auth/oauth.tests.js +++ b/test/auth/oauth.tests.js @@ -44,7 +44,13 @@ describe('OAuthAuthenticator', function() { }); describe('instance', function() { - var methods = ['signIn', 'socialSignIn', 'passwordGrant', 'authorizationCodeGrant']; + var methods = [ + 'signIn', + 'socialSignIn', + 'passwordGrant', + 'authorizationCodeGrant', + 'refreshToken' + ]; var authenticator = new Authenticator(validOptions); methods.forEach(function(method) { @@ -405,6 +411,96 @@ describe('OAuthAuthenticator', function() { }); }); + describe('#refreshToken', function() { + var path = '/oauth/token'; + var userData = { + refresh_token: 'refresh_token' + }; + beforeEach(function() { + this.authenticator = new Authenticator(validOptions); + this.request = nock(API_URL) + .post(path) + .reply(200); + }); + it('should require an object as first argument', function() { + expect(this.authenticator.refreshToken).to.throw(ArgumentError, 'Missing user data object'); + }); + it('should require a refreshToken', function() { + var auth = this.authenticator; + var refresh = auth.refreshToken.bind(auth, {}); + expect(refresh).to.throw(ArgumentError, 'refresh_token is required'); + }); + it('should accept a callback', function(done) { + this.authenticator.refreshToken(userData, done.bind(null, null)); + }); + it('should return a promise when no callback is provided', function(done) { + this.authenticator + .refreshToken(userData) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + it('should perform a POST request to ' + path, function(done) { + var request = this.request; + this.authenticator + .refreshToken(userData) + .then(function() { + expect(request.isDone()).to.be.true; + done(); + }) + .catch(done); + }); + it('should include the user data in the request', function(done) { + nock.cleanAll(); + var request = nock(API_URL) + .post(path, function(body) { + for (var property in userData) { + if (userData[property] !== body[property]) { + return false; + } + } + return true; + }) + .reply(200); + this.authenticator + .refreshToken(userData) + .then(function() { + expect(request.isDone()).to.be.true; + done(); + }) + .catch(done); + }); + it('should include the Auth0 client ID in the request', function(done) { + nock.cleanAll(); + var request = nock(API_URL) + .post(path, function(body) { + return body.client_id === CLIENT_ID; + }) + .reply(200); + this.authenticator + .refreshToken(userData) + .then(function() { + expect(request.isDone()).to.be.true; + done(); + }) + .catch(done); + }); + it('should use refresh_token as default grant type', function(done) { + nock.cleanAll(); + var request = nock(API_URL) + .post(path, function(body) { + return body.grant_type === 'refresh_token'; + }) + .reply(200); + this.authenticator + .refreshToken(userData) + .then(function() { + expect(request.isDone()).to.be.true; + done(); + }) + .catch(done); + }); + }); + describe('#socialSignIn', function() { var path = '/oauth/access_token'; var userData = { diff --git a/test/management/guardian.tests.js b/test/management/guardian.tests.js index 75f7e2bac..b3fd95731 100644 --- a/test/management/guardian.tests.js +++ b/test/management/guardian.tests.js @@ -17,7 +17,16 @@ describe('GuardianManager', function() { }); describe('instance', function() { - var methods = ['getGuardianEnrollment', 'deleteGuardianEnrollment']; + var methods = [ + 'getGuardianEnrollment', + 'deleteGuardianEnrollment', + 'getFactors', + 'getFactorProvider', + 'updateFactorProvider', + 'getFactorTemplates', + 'updateFactorTemplates', + 'updateFactor' + ]; methods.forEach(function(method) { it('should have a ' + method + ' method', function() { @@ -186,4 +195,512 @@ describe('GuardianManager', function() { }); }); }); + + describe('#createEnrollmentTicket', function() { + var data = { + user_id: '', + email: '', + send_mail: false + }; + + beforeEach(function() { + this.request = nock(API_URL) + .post('/guardian/enrollments/ticket') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.guardian.createEnrollmentTicket(data, function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .createEnrollmentTicket(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) + .post('/guardian/enrollments/ticket') + .reply(500); + + this.guardian.createEnrollmentTicket(data).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should perform a POST request to /api/v2/guardian/enrollments/ticket', function(done) { + var request = this.request; + + this.guardian.createEnrollmentTicket(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) + .post('/guardian/enrollments/ticket', data) + .reply(200); + + this.guardian.createEnrollmentTicket(data).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) + .post('/guardian/enrollments/ticket') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.createEnrollmentTicket(data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#getFactors', function() { + beforeEach(function() { + this.data = [ + { name: 'sms', enabled: true, trial_expired: false }, + { name: 'push-notification', enabled: false, trial_expired: false }, + { name: 'otp', enabled: false, trial_expired: false }, + { name: 'email', enabled: false, trial_expired: false }, + { name: 'duo', enabled: false, trial_expired: false } + ]; + + this.request = nock(API_URL) + .get('/guardian/factors') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.guardian.getFactors(done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .getFactors() + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a POST request to /api/v2/guardian/factors', function(done) { + var request = this.request; + + this.guardian.getFactors().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') + .reply(500); + + this.guardian.getFactors().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') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.getFactors().then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#getFactorProvider', function() { + beforeEach(function() { + this.params = { name: 'sms', provider: 'twilio' }; + this.data = { + from: '+1223323', + messaging_service_sid: '5dEkAiHLPCuQ1uJj4qNXcAnERFAL6cpq', + auth_token: 'zw5Ku6z2sxhd0ZVXto5SDHX6KPDByJPU', + sid: 'wywA2BH4VqTpfywiDuyDAYZL3xQjoO40' + }; + + this.request = nock(API_URL) + .get('/guardian/factors/' + this.params.name + '/providers/' + this.params.provider) + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.guardian.getFactorProvider(this.params, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .getFactorProvider(this.params) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a POST request to /api/v2/guardian/factors/sms/twilio', function(done) { + var request = this.request; + + this.guardian.getFactorProvider(this.params).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/' + this.params.name + '/providers/' + this.params.provider) + .reply(500); + + this.guardian.getFactorProvider(this.params).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/' + this.params.name + '/providers/' + this.params.provider) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.getFactorProvider(this.params).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updateFactorProvider', function() { + beforeEach(function() { + this.params = { name: 'sms', provider: 'twilio' }; + this.data = { + from: '+1223323', + messaging_service_sid: '5dEkAiHLPCuQ1uJj4qNXcAnERFAL6cpq', + auth_token: 'zw5Ku6z2sxhd0ZVXto5SDHX6KPDByJPU', + sid: 'wywA2BH4VqTpfywiDuyDAYZL3xQjoO40' + }; + }); + + it('should accept a callback', function(done) { + this.guardian.updateFactorProvider({ id: 5 }, {}, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .updateFactorProvider(this.params, {}) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a PUT request to /api/v2/guardian/factors/sms/providers/twilio', function(done) { + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/providers/' + this.params.provider) + .reply(200, this.data); + + this.guardian.updateFactorProvider(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 + '/providers/' + this.params.provider) + .reply(200); + + this.guardian.updateFactorProvider(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 + '/providers/' + this.params.provider) + .reply(500); + + this.guardian.updateFactorProvider(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 + '/providers/' + this.params.provider) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.updateFactorProvider(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#getFactorTemplates', function() { + beforeEach(function() { + this.params = { name: 'sms' }; + + this.data = { + enrollment_message: + '{{code}} is your verification code for {{tenant.friendly_name}}. Please enter this code to verify your enrollment.', + verification_message: '{{code}} is your verification code for {{tenant.friendly_name}}' + }; + + this.request = nock(API_URL) + .get('/guardian/factors/sms/templates') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.guardian.getFactorTemplates(this.params, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .getFactorTemplates(this.params) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a POST request to /api/v2/guardian/factors/sms/templates', function(done) { + var request = this.request; + + this.guardian.getFactorTemplates(this.params).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/sms/templates') + .reply(500); + + this.guardian.getFactorTemplates(this.params).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/sms/templates') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.getFactorTemplates(this.params).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updateFactorTemplates', function() { + beforeEach(function() { + this.params = { name: 'sms' }; + this.data = { + enrollment_message: + '{{code}} is your verification code for {{tenant.friendly_name}}. Please enter this code to verify your enrollment.', + verification_message: '{{code}} is your verification code for {{tenant.friendly_name}}' + }; + }); + + it('should accept a callback', function(done) { + this.guardian.updateFactorTemplates(this.params, {}, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .updateFactorTemplates(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/sms/templates', function(done) { + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name + '/templates') + .reply(200, this.data); + + this.guardian.updateFactorTemplates(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 + '/templates') + .reply(200); + + this.guardian.updateFactorTemplates(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 + '/templates') + .reply(500); + + this.guardian.updateFactorTemplates(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 + '/templates') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.updateFactorTemplates(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updateFactor', function() { + beforeEach(function() { + this.params = { name: 'sms' }; + this.data = { + enabled: true + }; + }); + + it('should accept a callback', function(done) { + this.guardian.updateFactor(this.params, {}, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.guardian + .updateFactor(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/sms', function(done) { + var request = nock(API_URL) + .put('/guardian/factors/' + this.params.name) + .reply(200, this.data); + + this.guardian.updateFactor(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) + .reply(200); + + this.guardian.updateFactor(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) + .reply(500); + + this.guardian.updateFactor(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) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.guardian.updateFactor(this.params, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); });