diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index ccaa8127c50..dc99cec694a 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -55,11 +55,11 @@ Package.onUse(function(api) { // SERVER FUNCTIONS api.addFiles('server/functions/checkUsernameAvailability.coffee', 'server'); - api.addFiles('server/functions/checkEmailAvailability.coffee', 'server'); + api.addFiles('server/functions/checkEmailAvailability.js', 'server'); api.addFiles('server/functions/sendMessage.coffee', 'server'); api.addFiles('server/functions/settings.coffee', 'server'); api.addFiles('server/functions/setUsername.coffee', 'server'); - api.addFiles('server/functions/setEmail.coffee', 'server'); + api.addFiles('server/functions/setEmail.js', 'server'); api.addFiles('server/functions/Notifications.coffee', 'server'); // SERVER METHODS @@ -75,7 +75,7 @@ Package.onUse(function(api) { api.addFiles('server/methods/setAdminStatus.coffee', 'server'); api.addFiles('server/methods/setRealName.coffee', 'server'); api.addFiles('server/methods/setUsername.coffee', 'server'); - api.addFiles('server/methods/setEmail.coffee', 'server'); + api.addFiles('server/methods/setEmail.js', 'server'); api.addFiles('server/methods/updateUser.coffee', 'server'); api.addFiles('server/methods/restartServer.coffee', 'server'); diff --git a/packages/rocketchat-lib/server/functions/checkEmailAvailability.coffee b/packages/rocketchat-lib/server/functions/checkEmailAvailability.coffee deleted file mode 100644 index e6c95d7702a..00000000000 --- a/packages/rocketchat-lib/server/functions/checkEmailAvailability.coffee +++ /dev/null @@ -1,2 +0,0 @@ -RocketChat.checkEmailAvailability = (email) -> - return not Meteor.users.findOne({ "emails.address": { $regex : new RegExp("^" + s.trim(s.escapeRegExp(email)) + "$", "i") } }) diff --git a/packages/rocketchat-lib/server/functions/checkEmailAvailability.js b/packages/rocketchat-lib/server/functions/checkEmailAvailability.js new file mode 100644 index 00000000000..1176500aaf0 --- /dev/null +++ b/packages/rocketchat-lib/server/functions/checkEmailAvailability.js @@ -0,0 +1,3 @@ +RocketChat.checkEmailAvailability = function(email) { + return !Meteor.users.findOne({ "emails.address": { $regex : new RegExp("^" + s.trim(s.escapeRegExp(email)) + "$", "i") } }) +} diff --git a/packages/rocketchat-lib/server/functions/setEmail.coffee b/packages/rocketchat-lib/server/functions/setEmail.coffee deleted file mode 100644 index a947436d7a0..00000000000 --- a/packages/rocketchat-lib/server/functions/setEmail.coffee +++ /dev/null @@ -1,26 +0,0 @@ -RocketChat._setEmail = (userId, email) -> - email = s.trim email - if not userId or not email - return false - - emailValidation = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ - if not emailValidation.test email - return false - - user = RocketChat.models.Users.findOneById userId - - # User already has desired username, return - if user.emails?[0]?.address is email - return user - - # Check e-mail availability - unless RocketChat.checkEmailAvailability email - return false - - # Set new email - RocketChat.models.Users.setEmail user._id, email - user.email = email - return user - -RocketChat.setEmail = RocketChat.RateLimiter.limitFunction RocketChat._setEmail, 1, 60000, - 0: (userId) -> return not RocketChat.authz.hasPermission(userId, 'edit-other-user-info') # Administrators have permission to change others emails, so don't limit those diff --git a/packages/rocketchat-lib/server/functions/setEmail.js b/packages/rocketchat-lib/server/functions/setEmail.js new file mode 100644 index 00000000000..e5af486d5f8 --- /dev/null +++ b/packages/rocketchat-lib/server/functions/setEmail.js @@ -0,0 +1,36 @@ +RocketChat._setEmail = function(userId, email) { + email = s.trim(email) + if (!userId) { + throw new Meteor.Error('invalid-user', "[methods] setEmail -> Invalid user"); + } + + if (!email) { + throw new Meteor.Error('invalid-email', "[methods] setEmail -> Invalid email"); + } + + emailValidation = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; + if (!emailValidation.test(email)) { + throw new Meteor.Error('email-invalid', "#{email} is not a valid e-mail"); + } + + user = RocketChat.models.Users.findOneById(userId); + + // User already has desired username, return + if (user.emails && user.emails[0] && user.emails[0].address === email) { + return user; + } + + // Check e-mail availability + if (!RocketChat.checkEmailAvailability(email)) { + throw new Meteor.Error('email-unavailable', "#{email} is already in use :("); + } + + // Set new email + RocketChat.models.Users.setEmail(user._id, email); + user.email = email; + return user; +} + +RocketChat.setEmail = RocketChat.RateLimiter.limitFunction(RocketChat._setEmail, 1, 60000, { + 0: function(userId) { return !RocketChat.authz.hasPermission(userId, 'edit-other-user-info') } // Administrators have permission to change others emails, so don't limit those +}); diff --git a/packages/rocketchat-lib/server/methods/setEmail.coffee b/packages/rocketchat-lib/server/methods/setEmail.coffee deleted file mode 100644 index c4030c517cb..00000000000 --- a/packages/rocketchat-lib/server/methods/setEmail.coffee +++ /dev/null @@ -1,27 +0,0 @@ -Meteor.methods - setEmail: (email) -> - if not Meteor.userId() - throw new Meteor.Error('invalid-user', "[methods] setEmail -> Invalid user") - - user = Meteor.user() - - if not RocketChat.settings.get("Accounts_AllowEmailChange") - throw new Meteor.Error(403, "[methods] setEmail -> E-mail change not allowed") - - if user.emails?[0]?.address is email - return email - - emailValidation = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ - if not emailValidation.test email - throw new Meteor.Error 'email-invalid', "#{email} is not a valid e-mail" - - if not RocketChat.checkEmailAvailability email - throw new Meteor.Error 'email-unavailable', "#{email} is already in use :(" - - unless RocketChat.setEmail user._id, email - throw new Meteor.Error 'could-not-change-email', "Could not change email" - - return email - -RocketChat.RateLimiter.limitMethod 'setEmail', 1, 1000, - userId: (userId) -> return true diff --git a/packages/rocketchat-lib/server/methods/setEmail.js b/packages/rocketchat-lib/server/methods/setEmail.js new file mode 100644 index 00000000000..18a04155b46 --- /dev/null +++ b/packages/rocketchat-lib/server/methods/setEmail.js @@ -0,0 +1,36 @@ +Meteor.methods({ + setEmail: function(email) { + if (!Meteor.userId()) { + throw new Meteor.Error('invalid-user', "[methods] setEmail -> Invalid user"); + } + + user = Meteor.user(); + + if (!RocketChat.settings.get("Accounts_AllowEmailChange")) { + throw new Meteor.Error(403, "[methods] setEmail -> E-mail change not allowed"); + } + + if (user.emails && user.emails[0] && user.emails[0].address === email) { + return email; + } + + emailValidation = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; + if (!emailValidation.test(email)) { + throw new Meteor.Error('email-invalid', "#{email} is not a valid e-mail"); + } + + if (!RocketChat.checkEmailAvailability(email)) { + throw new Meteor.Error('email-unavailable', "#{email} is already in use :("); + } + + if (!RocketChat.setEmail(user._id, email)) { + throw new Meteor.Error('could-not-change-email', "Could not change email"); + } + + return email; + } +}); + +RocketChat.RateLimiter.limitMethod('setEmail', 1, 1000, { + userId: function(userId) { return true } +});