Allow changing e-mail; invalidates verification on e-mail change

pull/1962/head
Marcelo Schmidt 9 years ago
parent c6d1814d81
commit 134ed42360
  1. 2
      i18n/en.i18n.json
  2. 3
      packages/rocketchat-lib/package.js
  3. 2
      packages/rocketchat-lib/server/functions/checkEmailAvailability.coffee
  4. 26
      packages/rocketchat-lib/server/functions/setEmail.coffee
  5. 2
      packages/rocketchat-lib/server/functions/setUsername.coffee
  6. 27
      packages/rocketchat-lib/server/methods/setEmail.coffee
  7. 8
      packages/rocketchat-lib/server/models/Users.coffee
  8. 1
      packages/rocketchat-lib/server/startup/settings.coffee
  9. 16
      packages/rocketchat-ui-account/account/accountProfile.coffee
  10. 16
      packages/rocketchat-ui-account/account/accountProfile.html
  11. 3
      server/methods/saveUserProfile.coffee

@ -6,6 +6,7 @@
"Accounts" : "Accounts",
"Accounts_AllowedDomainsList" : "Allowed Domains List",
"Accounts_AllowedDomainsList_Description" : "Comma-separated list of allowed domains",
"Accounts_AllowEmailChange" : "Allow E-mail Change",
"Accounts_AllowPasswordChange" : "Allow Password Change",
"Accounts_AllowUserAvatarChange" : "Allow User Avatar Change",
"Accounts_AllowUsernameChange" : "Allow Username Change",
@ -159,6 +160,7 @@
"E-mail" : "E-mail",
"edited" : "edited",
"Email_already_exists" : "Email already exists",
"Email_Change_Disabled" : "Your Rocket.Chat administrator has disabled the changing of e-mail",
"Email_or_username" : "Email or username",
"Email_verified" : "Email verified",
"Emoji" : "Emoji",

@ -55,9 +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/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/Notifications.coffee', 'server');
// SERVER METHODS
@ -73,6 +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/updateUser.coffee', 'server');
api.addFiles('server/methods/restartServer.coffee', 'server');

@ -0,0 +1,2 @@
RocketChat.checkEmailAvailability = (email) ->
return not Meteor.users.findOne({ "emails.address": { $regex : new RegExp("^" + s.trim(email) + "$", "i") } })

@ -0,0 +1,26 @@
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

@ -60,4 +60,4 @@ RocketChat._setUsername = (userId, username) ->
return user
RocketChat.setUsername = RocketChat.RateLimiter.limitFunction RocketChat._setUsername, 1, 60000,
0: (userId) -> return true; return not RocketChat.authz.hasPermission(userId, 'edit-other-user-info') # Administrators have permission to change others usernames, so don't limit those
0: (userId) -> return not RocketChat.authz.hasPermission(userId, 'edit-other-user-info') # Administrators have permission to change others usernames, so don't limit those

@ -0,0 +1,27 @@
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

@ -154,6 +154,14 @@ RocketChat.models.Users = new class extends RocketChat.models._Base
return @update _id, update
setEmail: (_id, email) ->
update =
$set:
'emails.0.address': email
'emails.0.verified': false
return @update _id, update
setName: (_id, name) ->
update =
$set:

@ -6,6 +6,7 @@ RocketChat.settings.addGroup 'Accounts', ->
@add 'Accounts_AllowUserProfileChange', true, { type: 'boolean', public: true }
@add 'Accounts_AllowUserAvatarChange', true, { type: 'boolean', public: true }
@add 'Accounts_AllowUsernameChange', true, { type: 'boolean', public: true }
@add 'Accounts_AllowEmailChange', true, { type: 'boolean', public: true }
@add 'Accounts_AllowPasswordChange', true, { type: 'boolean', public: true }
@add 'Accounts_RequireNameForSignUp', true, { type: 'boolean', public: true }
@add 'Accounts_LoginExpiration', 90, { type: 'int', public: true }

@ -15,9 +15,15 @@ Template.accountProfile.helpers
username: ->
return Meteor.user().username
email: ->
return Meteor.user().emails?[0]?.address
allowUsernameChange: ->
return RocketChat.settings.get("Accounts_AllowUsernameChange")
allowEmailChange: ->
return RocketChat.settings.get("Accounts_AllowEmailChange")
usernameChangeDisabled: ->
return t('Username_Change_Disabled')
@ -84,6 +90,14 @@ Template.accountProfile.onCreated ->
else
data.username = _.trim $('#username').val()
if _.trim $('#email').val()
if !RocketChat.settings.get("Accounts_AllowEmailChange")
toastr.error t('Email_Change_Disabled')
instance.clearForm()
return
else
data.email = _.trim $('#email').val()
Meteor.call 'saveUserProfile', data, (error, results) ->
if results
toastr.success t('Profile_saved_successfully')
@ -107,7 +121,7 @@ Template.accountProfile.events
'click .submit button': (e, t) ->
t.save()
'click .logoutOthers button': (event, templateInstance) ->
Meteor.logoutOtherClients (error) ->
Meteor.logoutOtherClients (error) ->
if error
toastr.error error.reason
else

@ -19,9 +19,19 @@
<label for="username">{{_ "Username"}}</label>
<div>
{{#if allowUsernameChange}}
<input type="text" name="username" id="username" placeholder="{{username}}" />
<input type="text" name="username" id="username" placeholder="{{username}}" />
{{else}}
<input type="text" name="username" id="username" placeholder="{{username}}" disabled="disabled" title="{{usernameChangeDisabled}}" />
<input type="text" name="username" id="username" placeholder="{{username}}" disabled="disabled" title="{{usernameChangeDisabled}}" />
{{/if}}
</div>
</div>
<div class="input-line">
<label for="email">{{_ "E-mail"}}</label>
<div>
{{#if allowEmailChange}}
<input type="text" name="email" id="email" placeholder="{{email}}" />
{{else}}
<input type="text" name="email" id="email" placeholder="{{email}}" disabled="disabled" title="{{emailChangeDisabled}}" />
{{/if}}
</div>
</div>
@ -60,7 +70,7 @@
<button class="button"><i class="icon-send"></i><span>{{_ "Save_changes"}}</span></button>
</div>
<div class="logoutOthers">
<button class="button">{{_ "Logout_Others"}}</button>
<button class="button">{{_ "Logout_Others"}}</button>
</div>
</div>
</div>

@ -16,6 +16,9 @@ Meteor.methods
if settings.username?
Meteor.call 'setUsername', settings.username
if settings.email?
Meteor.call 'setEmail', settings.email
profile = {}
RocketChat.models.Users.setProfile Meteor.userId(), profile

Loading…
Cancel
Save