From 3df5b2814cd67c00e547a09d6d47aa83ac608311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 6 Sep 2016 13:55:54 +0200 Subject: [PATCH] Fix double-slash in confirmation URL Fix the code building the URL used in the email-verification email to prevent double-slash in the URL when e.g. restApiRoot is '/'. Before: http://example.com//users/confirm?... Now: http://example.com/users/confirm?... --- common/models/user.js | 20 +++++++++++++++++--- test/user.test.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/common/models/user.js b/common/models/user.js index ea35f6b1..e90980cd 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -401,14 +401,18 @@ module.exports = function(User) { (options.protocol === 'https' && options.port == '443') ) ? '' : ':' + options.port; + var urlPath = joinUrlPath( + options.restApiRoot, + userModel.http.path, + userModel.sharedClass.find('confirm', true).http.path + ); + options.verifyHref = options.verifyHref || options.protocol + '://' + options.host + displayPort + - options.restApiRoot + - userModel.http.path + - userModel.sharedClass.find('confirm', true).http.path + + urlPath + '?uid=' + options.user.id + '&redirect=' + @@ -767,3 +771,13 @@ function emailValidator(err, done) { if (!isEmail(value)) return err('email'); } + +function joinUrlPath(args) { + var result = arguments[0]; + for (var ix = 1; ix < arguments.length; ix++) { + var next = arguments[ix]; + result += result[result.length - 1] === '/' && next[0] === '/' ? + next.slice(1) : next; + } + return result; +} diff --git a/test/user.test.js b/test/user.test.js index c22f8039..55d89327 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -1551,6 +1551,41 @@ describe('User', function() { done(); }); + + it('should squash "//" when restApiRoot is "/"', function(done) { + var emailBody; + User.afterRemote('create', function(ctx, user, next) { + assert(user, 'afterRemote should include result'); + + var options = { + type: 'email', + to: user.email, + from: 'noreply@myapp.org', + redirect: '/', + host: 'myapp.org', + port: 3000, + restApiRoot: '/', + }; + + user.verify(options, function(err, result) { + if (err) return next(err); + emailBody = result.email.response.toString('utf-8'); + next(); + }); + }); + + request(app) + .post('/test-users') + .expect('Content-Type', /json/) + .expect(200) + .send({email: 'user@example.com', password: 'pass'}) + .end(function(err, res) { + if (err) return done(err); + expect(emailBody) + .to.contain('http://myapp.org:3000/test-users/confirm'); + done(); + }); + }); }); describe('User.confirm(options, fn)', function() {