From 67a5e2a21eb7e2f66ec13109b24659447a3c28d3 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Wed, 9 Jan 2019 11:43:52 +0200 Subject: [PATCH 01/13] Added route to reset password with token --- src/Routers/UsersRouter.js | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index b7c02fa2f5..c400ac0aac 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -369,6 +369,45 @@ export class UsersRouter extends ClassesRouter { ); } + handleResetPasswordSetNew(req) { + const config = req.config; + if (!config) { + this.invalidRequest(); + } + if (!config.publicServerURL) { + return this.missingPublicServerURL(); + } + + const { + username, + token, + new_password + } = req.body; + + if (!username || !token || !new_password) { + return this.invalidLink(req); + } + + return config.userController.checkResetTokenValidity(username, token) + .then(() => { + return config.userController.updatePassword(username, token, new_password); + }, + () => { + throw new Parse.Error( + Parse.Error.OPERATION_FORBIDDEN, + 'invalid token' + ); + } + ) + .then(() => { + return Promise.resolve({ + response: {} + }); + }, err => { + throw err; + }); + } + handleVerificationEmailRequest(req) { this._throwOnBadEmailConfig(req); @@ -444,6 +483,9 @@ export class UsersRouter extends ClassesRouter { this.route('POST', '/requestPasswordReset', req => { return this.handleResetRequest(req); }); + this.route('POST', '/resetPasswordSetNew', req => { + return this.handleResetPasswordSetNew(req) + }); this.route('POST', '/verificationEmailRequest', req => { return this.handleVerificationEmailRequest(req); }); From 671be5df82e0995cf8917f000ec3b28676d3a066 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 12:51:10 +0200 Subject: [PATCH 02/13] Fixed indents --- src/Routers/UsersRouter.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index c400ac0aac..e6eaaedbe0 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -389,23 +389,23 @@ export class UsersRouter extends ClassesRouter { } return config.userController.checkResetTokenValidity(username, token) - .then(() => { - return config.userController.updatePassword(username, token, new_password); - }, - () => { - throw new Parse.Error( - Parse.Error.OPERATION_FORBIDDEN, - 'invalid token' - ); - } - ) - .then(() => { - return Promise.resolve({ - response: {} - }); - }, err => { - throw err; + .then(() => { + return config.userController.updatePassword(username, token, new_password); + }, + () => { + throw new Parse.Error( + Parse.Error.OPERATION_FORBIDDEN, + 'invalid token' + ); + } + ) + .then(() => { + return Promise.resolve({ + response: {} }); + }, err => { + throw err; + }); } handleVerificationEmailRequest(req) { From 85736f570856142e08a3b9bea7539c5599d5e774 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 13:04:05 +0200 Subject: [PATCH 03/13] And another indent fix --- src/Routers/UsersRouter.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index e6eaaedbe0..c37a13dc9b 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -390,22 +390,22 @@ export class UsersRouter extends ClassesRouter { return config.userController.checkResetTokenValidity(username, token) .then(() => { - return config.userController.updatePassword(username, token, new_password); - }, - () => { - throw new Parse.Error( - Parse.Error.OPERATION_FORBIDDEN, - 'invalid token' - ); - } - ) - .then(() => { - return Promise.resolve({ - response: {} - }); - }, err => { - throw err; + return config.userController.updatePassword(username, token, new_password); + }, + () => { + throw new Parse.Error( + Parse.Error.OPERATION_FORBIDDEN, + 'invalid token' + ); + } + ) + .then(() => { + return Promise.resolve({ + response: {} }); + }, err => { + throw err; + }); } handleVerificationEmailRequest(req) { From 9fb60d65cc62f3554517d7ac041d2dffd63b0a77 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 13:40:41 +0200 Subject: [PATCH 04/13] And another indent fix#2 --- src/Routers/UsersRouter.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index c37a13dc9b..1c24741c7c 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -398,14 +398,14 @@ export class UsersRouter extends ClassesRouter { 'invalid token' ); } - ) - .then(() => { - return Promise.resolve({ - response: {} + ) + .then(() => { + return Promise.resolve({ + response: {} + }); + }, err => { + throw err; }); - }, err => { - throw err; - }); } handleVerificationEmailRequest(req) { From c663b0678c87b60f3b2854535fe81cea6eb6fe72 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 16:58:25 +0200 Subject: [PATCH 05/13] Changed password reset errors to default --- src/Routers/UsersRouter.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index 1c24741c7c..49a8228259 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -385,7 +385,7 @@ export class UsersRouter extends ClassesRouter { } = req.body; if (!username || !token || !new_password) { - return this.invalidLink(req); + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'invalid token'); } return config.userController.checkResetTokenValidity(username, token) @@ -393,10 +393,7 @@ export class UsersRouter extends ClassesRouter { return config.userController.updatePassword(username, token, new_password); }, () => { - throw new Parse.Error( - Parse.Error.OPERATION_FORBIDDEN, - 'invalid token' - ); + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'invalid token'); } ) .then(() => { From 21b07c6a9167ef9efaa05e92620b3b53e96c8c64 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 17:08:35 +0200 Subject: [PATCH 06/13] Changed password reset errors to default --- src/Routers/UsersRouter.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index 49a8228259..29902bf7a4 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -385,7 +385,7 @@ export class UsersRouter extends ClassesRouter { } = req.body; if (!username || !token || !new_password) { - throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'invalid token'); + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Missing field); } return config.userController.checkResetTokenValidity(username, token) @@ -393,7 +393,7 @@ export class UsersRouter extends ClassesRouter { return config.userController.updatePassword(username, token, new_password); }, () => { - throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'invalid token'); + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Invalid token'); } ) .then(() => { @@ -401,7 +401,8 @@ export class UsersRouter extends ClassesRouter { response: {} }); }, err => { - throw err; + throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Password does not meet' + + ' Password Policy requirements'); }); } From 0a9096b9945560386ca5581eb0b875bd41e8e727 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 17:44:55 +0200 Subject: [PATCH 07/13] Changed errors to Parse.Error --- src/Routers/UsersRouter.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index 29902bf7a4..a51ae37156 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -385,7 +385,10 @@ export class UsersRouter extends ClassesRouter { } = req.body; if (!username || !token || !new_password) { - throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Missing field); + throw new Parse.Error( + Parse.Error.PASSWORD_MISSING, + 'Empty password, token or username' + ); } return config.userController.checkResetTokenValidity(username, token) @@ -393,16 +396,21 @@ export class UsersRouter extends ClassesRouter { return config.userController.updatePassword(username, token, new_password); }, () => { - throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Invalid token'); + throw new Parse.Error( + Parse.Error.OPERATION_FORBIDDEN, + 'Invalid token' + ); } ) .then(() => { return Promise.resolve({ response: {} }); - }, err => { - throw new _node.default.Error(_node.default.Error.OPERATION_FORBIDDEN, 'Password does not meet' + - ' Password Policy requirements'); + }, () => { + throw new Parse.Error( + Parse.Error.OPERATION_FORBIDDEN, + 'Password does not meet Password Policy requirements' + ); }); } From 5f4a82d303b19c0cb5d0f7878a0301eecc55ec85 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Thu, 10 Jan 2019 18:03:07 +0200 Subject: [PATCH 08/13] Split missing fields errors, removed public server check --- src/Routers/UsersRouter.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index a51ae37156..ae989037da 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -374,9 +374,6 @@ export class UsersRouter extends ClassesRouter { if (!config) { this.invalidRequest(); } - if (!config.publicServerURL) { - return this.missingPublicServerURL(); - } const { username, @@ -384,10 +381,24 @@ export class UsersRouter extends ClassesRouter { new_password } = req.body; - if (!username || !token || !new_password) { + if (!username) { + throw new Parse.Error( + Parse.Error.USERNAME_MISSING, + 'Missing username' + ); + } + + if (!token) { + throw new Parse.Error( + Parse.Error.OPERATION_FORBIDDEN, + 'Missing token' + ); + } + + if (!new_password) { throw new Parse.Error( Parse.Error.PASSWORD_MISSING, - 'Empty password, token or username' + 'Missing password' ); } From 3f1cb34e82ead35f409fe03d5a468d83bdea1556 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Tue, 29 Jan 2019 12:34:09 +0200 Subject: [PATCH 09/13] Draft changes for server --- src/Routers/PublicAPIRouter.js | 66 ++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js index 15d636c5e2..676d7023ea 100644 --- a/src/Routers/PublicAPIRouter.js +++ b/src/Routers/PublicAPIRouter.js @@ -159,21 +159,56 @@ export class PublicAPIRouter extends PromiseRouter { const { username, token, new_password } = req.body; - if (!username || !token || !new_password) { + if ((!username || !token || !new_password) && req.xhr == false) { return this.invalidLink(req); } + if (!username) { + // throw new Parse.Error( + // Parse.Error.USERNAME_MISSING, + // 'Missing username' + // ); + + return Promise.reject( + new Parse.Error( + Parse.Error.USERNAME_MISSING, + 'Missing username' + ) + ); + } + + if (!token) { + throw new Parse.Error( + Parse.Error.OTHER_CAUSE, + 'Missing token' + ); + } + + if (!new_password) { + throw new Parse.Error( + Parse.Error.PASSWORD_MISSING, + 'Missing password' + ); + } + return config.userController .updatePassword(username, token, new_password) .then( () => { const params = qs.stringify({ username: username }); - return Promise.resolve({ - status: 302, - location: `${config.passwordResetSuccessURL}?${params}`, - }); - }, - err => { + + if (req.xhr) { + return Promise.resolve({ + status: 200, + response: 'Password successfully reset' + }); + } else { + return Promise.resolve({ + status: 302, + location: `${config.passwordResetSuccessURL}?${params}` + }); + } + }, err => { const params = qs.stringify({ username: username, token: token, @@ -181,9 +216,20 @@ export class PublicAPIRouter extends PromiseRouter { error: err, app: config.appName, }); - return Promise.resolve({ - status: 302, - location: `${config.choosePasswordURL}?${params}`, + + if (req.xhr) { + return Promise.reject( + new Parse.Error( + Parse.Error.OTHER_CAUSE, + 'Server failed to reset password with provided data' + ) + ); + } else { + return Promise.resolve({ + status: 302, + location: `${config.choosePasswordURL}?${params}` + }); + } }); } ); From 32542565b74a8f5d35b2749f2f2e067b567803b2 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Wed, 30 Jan 2019 17:31:28 +0200 Subject: [PATCH 10/13] Adapted password reset route for ajax --- src/Routers/PublicAPIRouter.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js index 676d7023ea..125a9d9e7f 100644 --- a/src/Routers/PublicAPIRouter.js +++ b/src/Routers/PublicAPIRouter.js @@ -164,16 +164,9 @@ export class PublicAPIRouter extends PromiseRouter { } if (!username) { - // throw new Parse.Error( - // Parse.Error.USERNAME_MISSING, - // 'Missing username' - // ); - - return Promise.reject( - new Parse.Error( - Parse.Error.USERNAME_MISSING, - 'Missing username' - ) + throw new Parse.Error( + Parse.Error.USERNAME_MISSING, + 'Missing username' ); } @@ -218,12 +211,10 @@ export class PublicAPIRouter extends PromiseRouter { }); if (req.xhr) { - return Promise.reject( - new Parse.Error( - Parse.Error.OTHER_CAUSE, - 'Server failed to reset password with provided data' - ) - ); + throw new Parse.Error( + Parse.Error.OTHER_CAUSE, + 'Server failed to reset password with provided data' + ) } else { return Promise.resolve({ status: 302, From 86de6f7117180719719cb4e25216068944f233e3 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Wed, 30 Jan 2019 17:53:50 +0200 Subject: [PATCH 11/13] Removed old code --- src/Routers/UsersRouter.js | 59 -------------------------------------- 1 file changed, 59 deletions(-) diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js index ae989037da..b7c02fa2f5 100644 --- a/src/Routers/UsersRouter.js +++ b/src/Routers/UsersRouter.js @@ -369,62 +369,6 @@ export class UsersRouter extends ClassesRouter { ); } - handleResetPasswordSetNew(req) { - const config = req.config; - if (!config) { - this.invalidRequest(); - } - - const { - username, - token, - new_password - } = req.body; - - if (!username) { - throw new Parse.Error( - Parse.Error.USERNAME_MISSING, - 'Missing username' - ); - } - - if (!token) { - throw new Parse.Error( - Parse.Error.OPERATION_FORBIDDEN, - 'Missing token' - ); - } - - if (!new_password) { - throw new Parse.Error( - Parse.Error.PASSWORD_MISSING, - 'Missing password' - ); - } - - return config.userController.checkResetTokenValidity(username, token) - .then(() => { - return config.userController.updatePassword(username, token, new_password); - }, - () => { - throw new Parse.Error( - Parse.Error.OPERATION_FORBIDDEN, - 'Invalid token' - ); - } - ) - .then(() => { - return Promise.resolve({ - response: {} - }); - }, () => { - throw new Parse.Error( - Parse.Error.OPERATION_FORBIDDEN, - 'Password does not meet Password Policy requirements' - ); - }); - } - handleVerificationEmailRequest(req) { this._throwOnBadEmailConfig(req); @@ -500,9 +444,6 @@ export class UsersRouter extends ClassesRouter { this.route('POST', '/requestPasswordReset', req => { return this.handleResetRequest(req); }); - this.route('POST', '/resetPasswordSetNew', req => { - return this.handleResetPasswordSetNew(req) - }); this.route('POST', '/verificationEmailRequest', req => { return this.handleVerificationEmailRequest(req); }); From 1f99f7378e513bf90968435bcbdc1251f13d6a29 Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Wed, 30 Jan 2019 18:00:57 +0200 Subject: [PATCH 12/13] Removed unnecesary 'else' --- src/Routers/PublicAPIRouter.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js index 125a9d9e7f..7561b5d0ac 100644 --- a/src/Routers/PublicAPIRouter.js +++ b/src/Routers/PublicAPIRouter.js @@ -188,19 +188,19 @@ export class PublicAPIRouter extends PromiseRouter { .updatePassword(username, token, new_password) .then( () => { - const params = qs.stringify({ username: username }); + const params = qs.stringify({username: username}); if (req.xhr) { return Promise.resolve({ status: 200, response: 'Password successfully reset' }); - } else { - return Promise.resolve({ - status: 302, - location: `${config.passwordResetSuccessURL}?${params}` - }); } + + return Promise.resolve({ + status: 302, + location: `${config.passwordResetSuccessURL}?${params}` + }); }, err => { const params = qs.stringify({ username: username, From b30e2e45670c219ae463454fed95025202b370ee Mon Sep 17 00:00:00 2001 From: Vladyslav Chygrinov Date: Tue, 5 Feb 2019 12:12:47 +0200 Subject: [PATCH 13/13] Public API error flow and test --- spec/PublicAPI.spec.js | 21 +++++++++++ src/Routers/PublicAPIRouter.js | 67 ++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/spec/PublicAPI.spec.js b/spec/PublicAPI.spec.js index 1c04294880..374a9a8fc3 100644 --- a/spec/PublicAPI.spec.js +++ b/spec/PublicAPI.spec.js @@ -7,6 +7,27 @@ const request = function(url, callback) { }; describe('public API', () => { + it('should return ajax response on ajax request', done => { + reconfigureServer({ + publicServerURL: 'http://localhost:8378/1', + }).then(() => { + return req({ + method: 'POST', + url: 'http://localhost:8378/1/apps/test/request_password_reset', + body: `new_password=user1&token=43634643&username=`, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'X-Requested-With': 'XMLHttpRequest' + }, + followRedirects: false, + }) + }).catch(error => { + expect(error.status).not.toBe(302); + expect(error.text).toEqual('{"code":200,"error":"Missing username"}'); + done() + }) + }); + it('should get invalid_link.html', done => { request( 'http://localhost:8378/1/apps/invalid_link.html', diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js index 7561b5d0ac..a13441e64a 100644 --- a/src/Routers/PublicAPIRouter.js +++ b/src/Routers/PublicAPIRouter.js @@ -152,14 +152,17 @@ export class PublicAPIRouter extends PromiseRouter { if (!config) { this.invalidRequest(); } - if (!config.publicServerURL) { return this.missingPublicServerURL(); } - const { username, token, new_password } = req.body; + const { + username, + token, + new_password + } = req.body; - if ((!username || !token || !new_password) && req.xhr == false) { + if ((!username || !token || !new_password) && req.xhr === false) { return this.invalidLink(req); } @@ -188,42 +191,44 @@ export class PublicAPIRouter extends PromiseRouter { .updatePassword(username, token, new_password) .then( () => { - const params = qs.stringify({username: username}); - - if (req.xhr) { - return Promise.resolve({ - status: 200, - response: 'Password successfully reset' - }); - } - return Promise.resolve({ - status: 302, - location: `${config.passwordResetSuccessURL}?${params}` + success: true }); + }, err => { - const params = qs.stringify({ - username: username, - token: token, - id: config.applicationId, - error: err, - app: config.appName, + return Promise.resolve({ + success: false, + err }); + }) + .then(result => { + const params = _querystring.default.stringify({ + username: username, + token: token, + id: config.applicationId, + error: result.err, + app: config.appName + }); - if (req.xhr) { - throw new Parse.Error( - Parse.Error.OTHER_CAUSE, - 'Server failed to reset password with provided data' - ) - } else { + if (req.xhr) { + if (result.success) { return Promise.resolve({ - status: 302, - location: `${config.choosePasswordURL}?${params}` - }); + status: 200, + response: 'Password successfully reset' + }) } - }); + + throw new Parse.Error( + Parse.Error.OTHER_CAUSE, + result.err + ) } - ); + + return Promise.resolve({ + status: 302, + location: `${result.success ? config.passwordResetSuccessURL : config.choosePasswordURL}?${params}`, + }); + }); } invalidLink(req) {