diff --git a/src/auth.js b/src/auth.js index 23800ca48..bab2ab1e6 100644 --- a/src/auth.js +++ b/src/auth.js @@ -25,22 +25,22 @@ var assert = require('assert'), function initialize(callback) { assert.strictEqual(typeof callback, 'function'); - + passport.serializeUser(function (user, callback) { callback(null, user.id); }); - + passport.deserializeUser(function(userId, callback) { user.get(userId, function (error, result) { if (error) return callback(error); - - var md5 = crypto.createHash('md5').update(result.alternateEmail || result.email).digest('hex'); + + var md5 = crypto.createHash('md5').update(result.fallbackEmail || result.email).digest('hex'); result.gravatar = 'https://www.gravatar.com/avatar/' + md5 + '.jpg?s=24&d=mm'; - + callback(null, result); }); }); - + passport.use(new LocalStrategy(function (username, password, callback) { if (username.indexOf('@') === -1) { user.verifyWithUsername(username, password, function (error, result) { @@ -60,7 +60,7 @@ function initialize(callback) { }); } })); - + passport.use(new BasicStrategy(function (username, password, callback) { if (username.indexOf('cid-') === 0) { debug('BasicStrategy: detected client id %s instead of username:password', username); @@ -82,7 +82,7 @@ function initialize(callback) { }); } })); - + passport.use(new ClientPasswordStrategy(function (clientId, clientSecret, callback) { clients.get(clientId, function(error, client) { if (error && error.reason === ClientsError.NOT_FOUND) return callback(null, false); @@ -91,15 +91,15 @@ function initialize(callback) { return callback(null, client); }); })); - + passport.use(new BearerStrategy(accessTokenAuth)); - + callback(null); } function uninitialize(callback) { assert.strictEqual(typeof callback, 'function'); - + callback(null); } @@ -110,15 +110,15 @@ function accessTokenAuth(accessToken, callback) { tokendb.get(accessToken, function (error, token) { if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, false); if (error) return callback(error); - + // scopes here can define what capabilities that token carries // passport put the 'info' object into req.authInfo, where we can further validate the scopes var info = { scope: token.scope }; - + user.get(token.identifier, function (error, user) { if (error && error.reason === UserError.NOT_FOUND) return callback(null, false); if (error) return callback(error); - + callback(null, user, info); }); }); diff --git a/src/certificates.js b/src/certificates.js index ec5eb2d49..eecbec3e5 100644 --- a/src/certificates.js +++ b/src/certificates.js @@ -107,7 +107,7 @@ function getApi(app, callback) { // we simply update the account with the latest email we have each time when getting letsencrypt certs // https://github.com/ietf-wg-acme/acme/issues/30 user.getOwner(function (error, owner) { - options.email = error ? 'support@cloudron.io' : (owner.alternateEmail || owner.email); // can error if not activated yet + options.email = error ? 'support@cloudron.io' : (owner.fallbackEmail || owner.email); // can error if not activated yet callback(null, api, options); }); diff --git a/src/ldap.js b/src/ldap.js index 13aaa9871..76001e51f 100644 --- a/src/ldap.js +++ b/src/ldap.js @@ -152,7 +152,7 @@ function userSearch(req, res, next) { cn: entry.id, uid: entry.id, mail: entry.email, - mailAlternateAddress: entry.alternateEmail, + mailAlternateAddress: entry.fallbackEmail, displayname: displayName, givenName: firstName, username: entry.username, diff --git a/src/mail_templates/password_reset.ejs b/src/mail_templates/password_reset.ejs index 2e20766ff..ba1d349c2 100644 --- a/src/mail_templates/password_reset.ejs +++ b/src/mail_templates/password_reset.ejs @@ -1,6 +1,6 @@ <%if (format === 'text') { %> -Hi <%= user.displayName || user.username || user.alternateEmail || user.email %>, +Hi <%= user.displayName || user.username || user.email %>, Someone, hopefully you, has requested your account's password be reset. If you did not request this reset, please ignore this message. @@ -18,7 +18,7 @@ Powered by https://cloudron.io -

Hi <%= user.displayName || user.username || user.alternateEmail || user.email %>,

+

Hi <%= user.displayName || user.username || user.email %>,

Someone, hopefully you, has requested your account's password be reset.
diff --git a/src/mail_templates/user_added.ejs b/src/mail_templates/user_added.ejs index f049c0939..12d5f04d0 100644 --- a/src/mail_templates/user_added.ejs +++ b/src/mail_templates/user_added.ejs @@ -2,7 +2,7 @@ Dear <%= cloudronName %> Admin, -A new user with email <%= user.alternateEmail || user.email %> was added to <%= cloudronName %>. +A new user with email <%= user.email %> was added to <%= cloudronName %>. <% if (inviteLink) { %> As requested, this user has not been sent an invitation email. @@ -24,7 +24,7 @@ Powered by https://cloudron.io

Dear <%= cloudronName %> Admin,

- A new user with email <%= user.alternateEmail || user.email %> was added to <%= cloudronName %>. + A new user with email <%= user.email %> was added to <%= cloudronName %>.

<% if (inviteLink) { %> diff --git a/src/mail_templates/user_event.ejs b/src/mail_templates/user_event.ejs index 16bc01a63..d23ddfe0b 100644 --- a/src/mail_templates/user_event.ejs +++ b/src/mail_templates/user_event.ejs @@ -2,7 +2,7 @@ Dear Cloudron Admin, -User <%= user.username || user.alternateEmail || user.email %> <%= event %>. +User <%= user.username || user.email %> <%= event %>. Powered by https://cloudron.io diff --git a/src/mail_templates/welcome_user.ejs b/src/mail_templates/welcome_user.ejs index 997678248..157afc9ed 100644 --- a/src/mail_templates/welcome_user.ejs +++ b/src/mail_templates/welcome_user.ejs @@ -1,6 +1,6 @@ <%if (format === 'text') { %> -Dear <%= user.displayName || user.username || user.alternateEmail || user.email %>, +Dear <%= user.displayName || user.username || user.email %>, Welcome to <%= cloudronName %>! @@ -20,7 +20,7 @@ Powered by https://cloudron.io -

Hi <%= user.displayName || user.username || user.alternateEmail || user.email %>,

+

Hi <%= user.displayName || user.username || user.email %>,

Welcome to <%= cloudronName %>!

diff --git a/src/mailer.js b/src/mailer.js index c33822490..b22f1a4e1 100644 --- a/src/mailer.js +++ b/src/mailer.js @@ -162,7 +162,7 @@ function getAdminEmails(callback) { if (admins.length === 0) return callback(new Error('No admins on this cloudron')); // box not activated yet var adminEmails = [ ]; - if (admins[0].alternateEmail) adminEmails.push(admins[0].alternateEmail); + adminEmails.push(admins[0].fallbackEmail); admins.forEach(function (admin) { adminEmails.push(admin.email); }); callback(null, adminEmails); @@ -181,7 +181,7 @@ function mailUserEventToAdmins(user, event) { var mailOptions = { from: mailConfig.notificationFrom, to: adminEmails.join(', '), - subject: util.format('[%s] %s %s', mailConfig.cloudronName, user.username || user.alternateEmail || user.email, event), + subject: util.format('[%s] %s %s', mailConfig.cloudronName, user.username || user.fallbackEmail || user.email, event), text: render('user_event.ejs', { user: user, event: event, format: 'text' }), }; @@ -215,7 +215,7 @@ function sendInvite(user, invitor) { var mailOptions = { from: mailConfig.notificationFrom, - to: user.alternateEmail || user.email, + to: user.fallbackEmail, subject: util.format('Welcome to %s', mailConfig.cloudronName), text: render('welcome_user.ejs', templateDataText), html: render('welcome_user.ejs', templateDataHTML) @@ -252,7 +252,7 @@ function userAdded(user, inviteSent) { var mailOptions = { from: mailConfig.notificationFrom, to: adminEmails.join(', '), - subject: util.format('[%s] User %s added', mailConfig.cloudronName, user.alternateEmail || user.email), + subject: util.format('[%s] User %s added', mailConfig.cloudronName, user.fallbackEmail), text: render('user_added.ejs', templateDataText), html: render('user_added.ejs', templateDataHTML) }; @@ -301,7 +301,7 @@ function passwordReset(user) { var mailOptions = { from: mailConfig.notificationFrom, - to: user.alternateEmail || user.email, + to: user.fallbackEmail, subject: util.format('[%s] Password Reset', mailConfig.cloudronName), text: render('password_reset.ejs', templateDataText), html: render('password_reset.ejs', templateDataHTML) diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 7d9441b05..56127cc42 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -228,7 +228,7 @@ function feedback(req, res, next) { if (typeof req.body.subject !== 'string' || !req.body.subject) return next(new HttpError(400, 'subject must be string')); if (typeof req.body.description !== 'string' || !req.body.description) return next(new HttpError(400, 'description must be string')); - appstore.sendFeedback(_.extend(req.body, { email: req.user.alternateEmail || req.user.email, displayName: req.user.displayName }), function (error) { + appstore.sendFeedback(_.extend(req.body, { email: req.user.email, displayName: req.user.displayName }), function (error) { if (error && error.reason === AppstoreError.BILLING_REQUIRED) return next(new HttpError(402, 'Login to App Store to create support tickets. You can also email support@cloudron.io')); if (error) return next(new HttpError(503, 'Error contacting cloudron.io. Please email support@cloudron.io')); diff --git a/src/routes/profile.js b/src/routes/profile.js index 0c703f810..870abae3b 100644 --- a/src/routes/profile.js +++ b/src/routes/profile.js @@ -25,7 +25,7 @@ function get(req, res, next) { id: req.user.id, username: req.user.username, email: req.user.email, - alternateEmail: req.user.alternateEmail, + fallbackEmail: req.user.fallbackEmail, admin: req.user.admin, displayName: req.user.displayName })); diff --git a/src/routes/user.js b/src/routes/user.js index d608fbfed..6a346f9e8 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -56,7 +56,6 @@ function create(req, res, next) { displayName: user.displayName, email: user.email, fallbackEmail: user.fallbackEmail, - alternateEmail: user.alternateEmail, admin: user.admin, groupIds: [ ], resetToken: user.resetToken @@ -93,7 +92,7 @@ function list(req, res, next) { if (error) return next(new HttpError(500, error)); var users = results.map(function (result) { - return _.pick(result, 'id', 'username', 'email', 'fallbackEmail', 'alternateEmail', 'displayName', 'groupIds', 'admin'); + return _.pick(result, 'id', 'username', 'email', 'fallbackEmail', 'displayName', 'groupIds', 'admin'); }); next(new HttpSuccess(200, { users: users })); @@ -116,7 +115,6 @@ function get(req, res, next) { displayName: result.displayName, email: result.email, fallbackEmail: result.fallbackEmail, - alternateEmail: result.alternateEmail, admin: result.admin, groupIds: result.groupIds })); diff --git a/src/test/database-test.js b/src/test/database-test.js index f4170166b..fec63665e 100644 --- a/src/test/database-test.js +++ b/src/test/database-test.js @@ -30,6 +30,7 @@ var USER_0 = { username: 'uuid0', password: 'secret', email: 'safe@me.com', + fallbackEmail: 'safer@me.com', salt: 'morton', createdAt: 'sometime back', modifiedAt: 'now', @@ -42,6 +43,7 @@ var USER_1 = { username: 'uuid1', password: 'secret', email: 'safe2@me.com', + fallbackEmail: 'safer2@me.com', salt: 'tata', createdAt: 'sometime back', modifiedAt: 'now', @@ -54,6 +56,7 @@ var USER_2 = { username: 'uuid2', password: 'secret', email: 'safe3@me.com', + fallbackEmail: 'safer3@me.com', salt: 'tata', createdAt: 'sometime back', modifiedAt: 'now', @@ -65,8 +68,7 @@ const TEST_DOMAIN = { domain: 'example.com', zoneName: 'example.com', provider: 'manual', - config: { - } + config: {} }; describe('database', function () { diff --git a/src/test/user-test.js b/src/test/user-test.js index 6ce9512d7..7aa2daaa3 100644 --- a/src/test/user-test.js +++ b/src/test/user-test.js @@ -210,7 +210,7 @@ describe('User', function () { expect(result).to.be.ok(); expect(result.username).to.equal(USERNAME.toLowerCase()); expect(result.email).to.equal(EMAIL.toLowerCase()); - expect(result.alternateEmail).not.to.be.ok(); + expect(result.fallbackEmail).to.equal(EMAIL.toLowerCase()); // first user is owner, do not send mail to admins checkMails(0, done); @@ -268,7 +268,7 @@ describe('User', function () { }); }); - it('succeeds and attempts to send invite to alternateEmail', function (done) { + it('succeeds and attempts to send invite to fallbackEmail', function (done) { // use maildb to not trigger further events maildb.update(DOMAIN_0.domain, { enabled: true }, function (error) { expect(error).not.to.be.ok(); @@ -277,8 +277,8 @@ describe('User', function () { expect(error).not.to.be.ok(); expect(result).to.be.ok(); expect(result.username).to.equal(USERNAME_1.toLowerCase()); - expect(result.email).to.equal(USERNAME_1.toLowerCase() + '@' + config.fqdn()); - expect(result.alternateEmail).to.equal(EMAIL_1.toLowerCase()); + expect(result.email).to.equal(EMAIL_1.toLowerCase()); + expect(result.fallbackEmail).to.equal(EMAIL_1.toLowerCase()); // first user is owner, do not send mail to admins checkMails(2, { sentTo: EMAIL_1.toLowerCase() }, function (error) { @@ -636,7 +636,7 @@ describe('User', function () { expect(result).to.be.ok(); expect(result.id).to.equal(userObject.id); expect(result.email).to.equal(EMAIL.toLowerCase()); - expect(result.alternateEmail).not.to.be.ok(); + expect(result.fallbackEmail).to.equal(EMAIL.toLowerCase()); expect(result.username).to.equal(USERNAME.toLowerCase()); expect(result.displayName).to.equal(DISPLAY_NAME); @@ -653,8 +653,8 @@ describe('User', function () { expect(error).to.not.be.ok(); expect(result).to.be.ok(); expect(result.id).to.equal(userObject.id); - expect(result.email).to.equal(USERNAME.toLowerCase() + '@' + config.fqdn()); - expect(result.alternateEmail).to.equal(EMAIL.toLowerCase()); + expect(result.email).to.equal(EMAIL.toLowerCase()); + expect(result.fallbackEmail).to.equal(EMAIL.toLowerCase()); expect(result.username).to.equal(USERNAME.toLowerCase()); expect(result.displayName).to.equal(DISPLAY_NAME); diff --git a/src/user.js b/src/user.js index 01448416b..3c1a086a7 100644 --- a/src/user.js +++ b/src/user.js @@ -179,23 +179,12 @@ function createUser(username, password, email, displayName, auditSource, options if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new UserError(UserError.ALREADY_EXISTS, error.message)); if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - mail.get(config.fqdn(), function (error, mailConfig) { - if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); + callback(null, user); - if (mailConfig.enabled) { - user.alternateEmail = user.email; - user.email = user.username ? user.username + '@' + config.fqdn() : null; - } else { - user.alternateEmail = null; - } + eventlog.add(eventlog.ACTION_USER_ADD, auditSource, { userId: user.id, email: user.email }); - callback(null, user); - - eventlog.add(eventlog.ACTION_USER_ADD, auditSource, { userId: user.id, email: user.email }); - - if (!owner) mailer.userAdded(user, sendInvite); - if (sendInvite) mailer.sendInvite(user, invitor); - }); + if (!owner) mailer.userAdded(user, sendInvite); + if (sendInvite) mailer.sendInvite(user, invitor); }); }); }); @@ -303,22 +292,11 @@ function listUsers(callback) { userdb.getAllWithGroupIds(function (error, results) { if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - mail.get(config.fqdn(), function (error, mailConfig) { - if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - - results.forEach(function (result) { - result.admin = result.groupIds.indexOf(constants.ADMIN_GROUP_ID) !== -1; - - if (mailConfig.enabled) { - result.alternateEmail = result.email; - result.email = result.username ? result.username + '@' + config.fqdn() : null; - } else { - result.alternateEmail = null; - } - }); - - return callback(null, results); + results.forEach(function (result) { + result.admin = result.groupIds.indexOf(constants.ADMIN_GROUP_ID) !== -1; }); + + return callback(null, results); }); } @@ -346,18 +324,7 @@ function getUser(userId, callback) { result.groupIds = groupIds; result.admin = groupIds.indexOf(constants.ADMIN_GROUP_ID) !== -1; - mail.get(config.fqdn(), function (error, mailConfig) { - if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - - if (mailConfig.enabled) { - result.alternateEmail = result.email; - result.email = result.username ? result.username + '@' + config.fqdn() : null; - } else { - result.alternateEmail = null; - } - - return callback(null, result); - }); + return callback(null, result); }); }); } @@ -458,20 +425,7 @@ function getAllAdmins(callback) { userdb.getAllAdmins(function (error, admins) { if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - mail.get(config.fqdn(), function (error, mailConfig) { - if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - - admins.forEach(function (admin) { - if (mailConfig.enabled) { - admin.alternateEmail = admin.email; - admin.email = admin.username ? admin.username + '@' + config.fqdn() : null; - } else { - admin.alternateEmail = null; - } - }); - - callback(null, admins); - }); + callback(null, admins); }); } @@ -582,18 +536,7 @@ function getOwner(callback) { if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new UserError(UserError.NOT_FOUND)); if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - mail.get(config.fqdn(), function (error, mailConfig) { - if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); - - if (mailConfig.enabled) { - owner.alternateEmail = owner.email; - owner.email = owner.username ? owner.username + '@' + config.fqdn() : null; - } else { - owner.alternateEmail = null; - } - - return callback(null, owner); - }); + return callback(null, owner); }); } diff --git a/webadmin/src/js/client.js b/webadmin/src/js/client.js index 8f990ffee..01767993f 100644 --- a/webadmin/src/js/client.js +++ b/webadmin/src/js/client.js @@ -217,11 +217,11 @@ angular.module('Application').service('Client', ['$http', '$interval', 'md5', 'N this._userInfo.id = userInfo.id; this._userInfo.username = userInfo.username; this._userInfo.email = userInfo.email; - this._userInfo.alternateEmail = userInfo.alternateEmail; + this._userInfo.fallbackEmail = userInfo.fallbackEmail; this._userInfo.displayName = userInfo.displayName; this._userInfo.admin = !!userInfo.admin; - this._userInfo.gravatar = 'https://www.gravatar.com/avatar/' + md5.createHash(userInfo.alternateEmail || userInfo.email) + '.jpg?s=24&d=mm'; - this._userInfo.gravatarHuge = 'https://www.gravatar.com/avatar/' + md5.createHash(userInfo.alternateEmail || userInfo.email) + '.jpg?s=128&d=mm'; + this._userInfo.gravatar = 'https://www.gravatar.com/avatar/' + md5.createHash(userInfo.fallbackEmail || userInfo.email) + '.jpg?s=24&d=mm'; + this._userInfo.gravatarHuge = 'https://www.gravatar.com/avatar/' + md5.createHash(userInfo.fallbackEmail || userInfo.email) + '.jpg?s=128&d=mm'; }; Client.prototype.setConfig = function (config) { diff --git a/webadmin/src/views/account.html b/webadmin/src/views/account.html index 6c21f5672..df3a02778 100644 --- a/webadmin/src/views/account.html +++ b/webadmin/src/views/account.html @@ -124,12 +124,12 @@ {{ user.displayName }} - Email - {{ user.email }} + Default email + {{ user.email }} - + Password recovery email - {{ user.alternateEmail }} + {{ user.fallbackEmail }} diff --git a/webadmin/src/views/users.html b/webadmin/src/views/users.html index a8880ce0f..04aabf923 100644 --- a/webadmin/src/views/users.html +++ b/webadmin/src/views/users.html @@ -275,7 +275,7 @@ {{ user.username }}   {{ user.email }} - {{ user.alternateEmail || user.email }} + {{ user.fallbackEmail }} diff --git a/webadmin/src/views/users.js b/webadmin/src/views/users.js index 47b49a7a6..0b3a8ccd5 100644 --- a/webadmin/src/views/users.js +++ b/webadmin/src/views/users.js @@ -144,12 +144,14 @@ angular.module('Application').controller('UsersController', ['$scope', '$locatio error: {}, userInfo: {}, email: '', + fallbackEmail: '', aliases: '', superuser: false, show: function (userInfo) { $scope.useredit.error = {}; - $scope.useredit.email = userInfo.alternateEmail || userInfo.email; + $scope.useredit.email = userInfo.email; + $scope.useredit.fallbackEmail = userInfo.fallbackEmail; $scope.useredit.userInfo = userInfo; $scope.useredit.groupIds = angular.copy(userInfo.groupIds); $scope.useredit.superuser = userInfo.groupIds.indexOf('admin') !== -1; @@ -369,7 +371,7 @@ angular.module('Application').controller('UsersController', ['$scope', '$locatio }; $scope.sendInvite = function (user) { - $scope.inviteSent.email = user.alternateEmail || user.email; + $scope.inviteSent.email = user.fallbackEmail; $scope.inviteSent.setupLink = ''; Client.sendInvite(user, function (error, resetToken) {