diff --git a/common/models/user.js b/common/models/user.js index 224ce924..dd07a620 100644 --- a/common/models/user.js +++ b/common/models/user.js @@ -366,12 +366,17 @@ module.exports = function(User) { options.host = options.host || (app && app.get('host')) || 'localhost'; options.port = options.port || (app && app.get('port')) || 3000; options.restApiRoot = options.restApiRoot || (app && app.get('restApiRoot')) || '/api'; + + var displayPort = ( + (options.protocol === 'http' && options.port == '80') || + (options.protocol === 'https' && options.port == '443') + ) ? '' : ':' + options.port; + options.verifyHref = options.verifyHref || options.protocol + '://' + options.host + - ':' + - options.port + + displayPort + options.restApiRoot + userModel.http.path + userModel.sharedClass.find('confirm', true).http.path + diff --git a/test/user.test.js b/test/user.test.js index a31b0d1f..063d2378 100644 --- a/test/user.test.js +++ b/test/user.test.js @@ -1109,6 +1109,140 @@ describe('User', function() { }); }); + describe('Verification link port-squashing', function() { + it('Do not squash non-80 ports for HTTP links', function(done) { + 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: '/', + protocol: 'http', + host: 'myapp.org', + port: 3000 + }; + + user.verify(options, function(err, result) { + var msg = result.email.response.toString('utf-8'); + assert(~msg.indexOf('http://myapp.org:3000/')); + done(); + }); + }); + + request(app) + .post('/test-users') + .expect('Content-Type', /json/) + .expect(200) + .send({email: 'bar@bat.com', password: 'bar'}) + .end(function(err, res) { + if (err) { + return done(err); + } + }); + }); + + it('Squash port 80 for HTTP links', function(done) { + 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: '/', + protocol: 'http', + host: 'myapp.org', + port: 80 + }; + + user.verify(options, function(err, result) { + var msg = result.email.response.toString('utf-8'); + assert(~msg.indexOf('http://myapp.org/')); + done(); + }); + }); + + request(app) + .post('/test-users') + .expect('Content-Type', /json/) + .expect(200) + .send({email: 'bar@bat.com', password: 'bar'}) + .end(function(err, res) { + if (err) { + return done(err); + } + }); + }); + + it('Do not squash non-443 ports for HTTPS links', function(done) { + 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: '/', + protocol: 'https', + host: 'myapp.org', + port: 3000 + }; + + user.verify(options, function(err, result) { + var msg = result.email.response.toString('utf-8'); + assert(~msg.indexOf('https://myapp.org:3000/')); + done(); + }); + }); + + request(app) + .post('/test-users') + .expect('Content-Type', /json/) + .expect(200) + .send({email: 'bar@bat.com', password: 'bar'}) + .end(function(err, res) { + if (err) { + return done(err); + } + }); + }); + + it('Squash port 443 for HTTPS links', function(done) { + 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: '/', + protocol: 'https', + host: 'myapp.org', + port: 443 + }; + + user.verify(options, function(err, result) { + var msg = result.email.response.toString('utf-8'); + assert(~msg.indexOf('https://myapp.org/')); + done(); + }); + }); + + request(app) + .post('/test-users') + .expect('Content-Type', /json/) + .expect(200) + .send({email: 'bar@bat.com', password: 'bar'}) + .end(function(err, res) { + if (err) { + return done(err); + } + }); + }); + }); + }); describe('User.confirm(options, fn)', function() {