Repository: auth0/node-auth0
Pull request #82 (2016-02-27 19:53:29)

Request change password email
Would like to add capability to request for a change password link email using the Auth client.


Patch:
diff --git a/package.json b/package.json
index b313073c4..da95889c3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "auth0",
-  "version": "2.0.0",
+  "version": "2.1.0",
   "description": "SDK for Auth0 API v2",
   "main": "src/index.js",
   "scripts": {
diff --git a/src/auth/DatabaseAuthenticator.js b/src/auth/DatabaseAuthenticator.js
index 303285c6b..fa7085b2c 100644
--- a/src/auth/DatabaseAuthenticator.js
+++ b/src/auth/DatabaseAuthenticator.js
@@ -163,7 +163,7 @@ DatabaseAuthenticator.prototype.signUp = function (userData, cb) {
 
 
 /**
- * Change passwor using a database or active directory service.
+ * Change password using a database or active directory service.
  *
  * @method    changePassword
  * @memberOf  module:auth.DatabaseAuthenticator.prototype
@@ -235,4 +235,69 @@ DatabaseAuthenticator.prototype.changePassword = function (userData, cb) {
 };
 
 
+/**
+ * Request a change password email using a database or active directory service.
+ *
+ * @method    requestChangePasswordEmail
+ * @memberOf  module:auth.DatabaseAuthenticator.prototype
+ *
+ * @example <caption>
+ *   Given the user email, the connection specified, Auth0 will send a change
+ *   password email. once the user clicks on the confirm password change link,
+ *   the new password specified in this POST will be set to this user. Find more
+ *   information in the <a href="https://auth0.com/docs/auth-api#!#post--dbconnections-change_password>
+ *   API Docs</a>.
+ * </caption>
+ *
+ * var data = {
+ *   email: '{EMAIL}',
+ *   connection: 'Username-Password-Authentication'
+ * };
+ *
+ * auth0.database.requestChangePasswordEmail(data, function (err, message) {
+ *   if (err) {
+ *     // Handle error.
+ *   }
+ *
+ *   console.log(message);
+ * });
+ *
+ * @param   {Object}    data              User credentials object.
+ * @param   {String}    data.email        User email address.
+ * @param   {String}    data.connection   Identity provider in use.
+ * @param   {Function}  [cb]              Method callback.
+ *
+ * @return  {Promise|undefined}
+ */
+DatabaseAuthenticator.prototype.requestChangePasswordEmail = function (userData, cb) {
+  var params = {
+    type: 'change_password'
+  };
+  var defaultFields = {
+    client_id: this.clientId
+  };
+  var data = extend(defaultFields, userData);
+
+  if (!userData || typeof userData !== 'object') {
+    throw new ArgumentError('Missing user data object');
+  }
+
+  if (typeof data.email !== 'string'
+      || data.email.trim().length === 0) {
+    throw new ArgumentError('email field is required');
+  }
+
+  if (typeof data.connection !== 'string'
+      || data.connection.trim().length === 0) {
+    throw new ArgumentError('connection field is required');
+  }
+
+  if (cb && cb instanceof Function) {
+    return this.dbConnections.create(params, data, cb);
+  }
+
+  return this.dbConnections.create(params, data);
+};
+
+
 module.exports = DatabaseAuthenticator;
diff --git a/src/auth/index.js b/src/auth/index.js
index 147596085..002f07b50 100644
--- a/src/auth/index.js
+++ b/src/auth/index.js
@@ -360,7 +360,7 @@ AuthenticationClient.prototype.getDelegationToken = function (data, cb) {
 
 
 /**
- * Change passwor using a database or active directory service.
+ * Change password using a database or active directory service.
  *
  * @method    changePassword
  * @memberOf  module:auth.AuthenticationClient.prototype
@@ -406,6 +406,49 @@ AuthenticationClient.prototype.changePassword = function (data, cb) {
 };
 
 
+/**
+ * Request a change password email using a database or active directory service.
+ *
+ * @method    requestChangePasswordEmail
+ * @memberOf  module:auth.AuthenticationClient.prototype
+ *
+ * @example <caption>
+ *   Given the user email, the connection specified, Auth0 will send a change
+ *   password email. once the user clicks on the confirm password change link,
+ *   the new password specified in this POST will be set to this user. Find more
+ *   information in the <a href="https://auth0.com/docs/auth-api#!#post--dbconnections-change_password>
+ *   API Docs</a>.
+ * </caption>
+ *
+ * var data = {
+ *   email: '{EMAIL}',
+ *   connection: 'Username-Password-Authentication'
+ * };
+ *
+ * auth0.requestChangePasswordEmail(data, function (err, message) {
+ *   if (err) {
+ *     // Handle error.
+ *   }
+ *
+ *   console.log(message);
+ * });
+ *
+ * @param   {Object}    data            User data object.
+ * @param   {String}    data.email      User email.
+ * @param   {String}    data.connection Identity provider for the user.
+ *
+ * @return  {Promise|undefined}
+ */
+AuthenticationClient.prototype.requestChangePasswordEmail = function (data, cb) {
+  var translatedData = {
+    connection: data.connection,
+    email: data.email || data.username
+  };
+
+  return this.database.requestChangePasswordEmail(data, cb);
+};
+
+
 /**
  * Given an access token get the user profile linked to it.
  *


Test patch:
diff --git a/test/auth/database-auth.tests.js b/test/auth/database-auth.tests.js
index a6c496769..57114a640 100644
--- a/test/auth/database-auth.tests.js
+++ b/test/auth/database-auth.tests.js
@@ -40,7 +40,7 @@ describe('DatabaseAuthenticator', function () {
 
 
   describe('instance', function () {
-    var methods = ['signIn', 'signUp', 'changePassword'];
+    var methods = ['signIn', 'signUp', 'changePassword', 'requestChangePasswordEmail'];
     var oauth = new OAuth(validOptions);
     var authenticator = new Authenticator(validOptions, oauth);
 
@@ -560,4 +560,128 @@ describe('DatabaseAuthenticator', function () {
     });
   });
 
+
+  describe('#requestChangePasswordEmail', function () {
+    var path = '/dbconnections/change_password';
+    var userData = {
+      email: 'test@domain.com',
+      connection: 'TEST_CONNECTION'
+    };
+
+    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.requestChangePasswordEmail)
+        .to.throw(ArgumentError, 'Missing user data object');
+    });
+
+
+    it('should require an email', function () {
+      var auth = this.authenticator;
+      var userData = {};
+      var requestChangePasswordEmail = auth.requestChangePasswordEmail.bind(auth, userData);
+
+      expect(requestChangePasswordEmail)
+        .to.throw(ArgumentError, 'email field is required');
+    });
+
+
+    it('should require a connection', function () {
+      var auth = this.authenticator;
+      var userData = { email: 'email@domain.com' };
+      var requestChangePasswordEmail = auth.requestChangePasswordEmail.bind(auth, userData);
+
+      expect(requestChangePasswordEmail)
+        .to.throw(ArgumentError, 'connection field is required');
+    });
+
+
+    it('should accept a callback', function (done) {
+      this
+        .authenticator
+        .requestChangePasswordEmail(userData, done.bind(null, null));
+    });
+
+
+    it('should return a promise when no callback is provided', function (done) {
+      this
+        .authenticator
+        .requestChangePasswordEmail(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
+        .requestChangePasswordEmail(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
+        .requestChangePasswordEmail(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
+        .requestChangePasswordEmail(userData)
+        .then(function () {
+          expect(request.isDone())
+            .to.be.true;
+
+          done();
+        })
+        .catch(done);
+    });
+  });
+
 });