diff --git a/common/models/user.js b/common/models/user.js index 7aa7e04c..b19fd396 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -408,14 +408,18 @@ module.exports = function(User) { (options.protocol === 'https' && options.port == '443') ) ? '' : ':' + options.port; + var urlPath = joinUrlPath( + options.restApiRoot, + userModel.http.path, + userModel.sharedClass.findMethodByName('confirm').http.path + ); + options.verifyHref = options.verifyHref || options.protocol + '://' + options.host + displayPort + - options.restApiRoot + - userModel.http.path + - userModel.sharedClass.findMethodByName('confirm').http.path + + urlPath + '?uid=' + options.user.id + '&redirect=' + @@ -783,3 +787,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 8e6055e1..4009366a 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -1547,6 +1547,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() {