summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--i18n/en.json4
-rw-r--r--store/sql_user_store.go12
-rw-r--r--store/sql_user_store_test.go11
-rw-r--r--utils/config.go1
-rw-r--r--webapp/components/user_settings/user_settings_general.jsx313
6 files changed, 207 insertions, 136 deletions
diff --git a/Makefile b/Makefile
index f1300176b..6934e8545 100644
--- a/Makefile
+++ b/Makefile
@@ -145,7 +145,7 @@ test: start-docker
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=340s ./api || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=12s ./model || exit 1
- $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./store || exit 1
+ $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./store || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./utils || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
ifeq ($(BUILD_ENTERPRISE_READY),true)
diff --git a/i18n/en.json b/i18n/en.json
index 5cc2ec9f6..bfcfe845e 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -3496,6 +3496,10 @@
"translation": "We couldn't update the account"
},
{
+ "id": "store.sql_user.update.can_not_change_ldap.app_error",
+ "translation": "Can not change fields set by LDAP"
+ },
+ {
"id": "store.sql_user.update.email_taken.app_error",
"translation": "This email is already taken. Please choose another."
},
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index 636400ce9..9db378341 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -136,7 +136,17 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha
if user.IsOAuthUser() {
user.Email = oldUser.Email
- } else if !user.IsLDAPUser() && user.Email != oldUser.Email {
+ } else if user.IsLDAPUser() {
+ if user.Username != oldUser.Username ||
+ user.FirstName != oldUser.FirstName ||
+ user.LastName != oldUser.LastName ||
+ user.Email != oldUser.Email {
+ result.Err = model.NewLocAppError("SqlUserStore.Update", "store.sql_user.update.can_not_change_ldap.app_error", nil, "user_id="+user.Id)
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+ } else if user.Email != oldUser.Email {
user.EmailVerified = false
}
diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go
index 2d17c5888..9fed32dc8 100644
--- a/store/sql_user_store_test.go
+++ b/store/sql_user_store_test.go
@@ -77,6 +77,12 @@ func TestUserStoreUpdate(t *testing.T) {
Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id}))
+ u2 := &model.User{}
+ u2.Email = model.NewId()
+ u2.AuthService = "ldap"
+ Must(store.User().Save(u2))
+ Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u2.Id}))
+
time.Sleep(100 * time.Millisecond)
if err := (<-store.User().Update(u1, false)).Err; err != nil {
@@ -92,6 +98,11 @@ func TestUserStoreUpdate(t *testing.T) {
if err := (<-store.User().Update(u1, false)).Err; err == nil {
t.Fatal("Update should have faile because id change")
}
+
+ u2.Email = model.NewId()
+ if err := (<-store.User().Update(u2, false)).Err; err == nil {
+ t.Fatal("Update should have failed because you can't modify LDAP fields")
+ }
}
func TestUserStoreUpdateLastPingAt(t *testing.T) {
diff --git a/utils/config.go b/utils/config.go
index 1ae658b16..9e2776f75 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -259,6 +259,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["EnableLdap"] = strconv.FormatBool(*c.LdapSettings.Enable)
props["LdapLoginFieldName"] = *c.LdapSettings.LoginFieldName
props["LdapPasswordFieldName"] = *c.LdapSettings.PasswordFieldName
+ props["NicknameAttributeSet"] = strconv.FormatBool(*c.LdapSettings.NicknameAttribute != "")
}
if *License.Features.MFA {
diff --git a/webapp/components/user_settings/user_settings_general.jsx b/webapp/components/user_settings/user_settings_general.jsx
index abf5ca7a9..718ad5ed8 100644
--- a/webapp/components/user_settings/user_settings_general.jsx
+++ b/webapp/components/user_settings/user_settings_general.jsx
@@ -513,85 +513,100 @@ class UserSettingsGeneralTab extends React.Component {
const inputs = [];
if (this.props.activeSection === 'name') {
- inputs.push(
- <div
- key='firstNameSetting'
- className='form-group'
- >
- <label className='col-sm-5 control-label'>
- <FormattedMessage
- id='user.settings.general.firstName'
- defaultMessage='First Name'
- />
- </label>
- <div className='col-sm-7'>
- <input
- className='form-control'
- type='text'
- onChange={this.updateFirstName}
- value={this.state.firstName}
- />
+ let extraInfo;
+ let submit = null;
+ if (this.props.user.auth_service === '') {
+ inputs.push(
+ <div
+ key='firstNameSetting'
+ className='form-group'
+ >
+ <label className='col-sm-5 control-label'>
+ <FormattedMessage
+ id='user.settings.general.firstName'
+ defaultMessage='First Name'
+ />
+ </label>
+ <div className='col-sm-7'>
+ <input
+ className='form-control'
+ type='text'
+ onChange={this.updateFirstName}
+ value={this.state.firstName}
+ />
+ </div>
</div>
- </div>
- );
+ );
- inputs.push(
- <div
- key='lastNameSetting'
- className='form-group'
- >
- <label className='col-sm-5 control-label'>
+ inputs.push(
+ <div
+ key='lastNameSetting'
+ className='form-group'
+ >
+ <label className='col-sm-5 control-label'>
+ <FormattedMessage
+ id='user.settings.general.lastName'
+ defaultMessage='Last Name'
+ />
+ </label>
+ <div className='col-sm-7'>
+ <input
+ className='form-control'
+ type='text'
+ onChange={this.updateLastName}
+ value={this.state.lastName}
+ />
+ </div>
+ </div>
+ );
+
+ function notifClick(e) {
+ e.preventDefault();
+ this.updateSection('');
+ this.props.updateTab('notifications');
+ }
+
+ const notifLink = (
+ <a
+ href='#'
+ onClick={notifClick.bind(this)}
+ >
<FormattedMessage
- id='user.settings.general.lastName'
- defaultMessage='Last Name'
+ id='user.settings.general.notificationsLink'
+ defaultMessage='Notifications'
/>
- </label>
- <div className='col-sm-7'>
- <input
- className='form-control'
- type='text'
- onChange={this.updateLastName}
- value={this.state.lastName}
+ </a>
+ );
+
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.notificationsExtra'
+ defaultMessage='By default, you will receive mention notifications when someone types your first name. Go to {notify} settings to change this default.'
+ values={{
+ notify: (notifLink)
+ }}
/>
- </div>
- </div>
- );
+ </span>
+ );
- function notifClick(e) {
- e.preventDefault();
- this.updateSection('');
- this.props.updateTab('notifications');
+ submit = this.submitName;
+ } else {
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.field_handled_externally'
+ defaultMessage='This field is handled through your login provider. If you want to change it, you need to do so though your login provider.'
+ />
+ </span>
+ );
}
- const notifLink = (
- <a
- href='#'
- onClick={notifClick.bind(this)}
- >
- <FormattedMessage
- id='user.settings.general.notificationsLink'
- defaultMessage='Notifications'
- />
- </a>
- );
-
- const extraInfo = (
- <span>
- <FormattedMessage
- id='user.settings.general.notificationsExtra'
- defaultMessage='By default, you will receive mention notifications when someone types your first name. Go to {notify} settings to change this default.'
- values={{
- notify: (notifLink)
- }}
- />
- </span>
- );
-
nameSection = (
<SettingItemMax
title={formatMessage(holders.fullName)}
inputs={inputs}
- submit={this.submitName}
+ submit={submit}
server_error={serverError}
client_error={clientError}
updateSection={(e) => {
@@ -632,47 +647,62 @@ class UserSettingsGeneralTab extends React.Component {
let nicknameSection;
if (this.props.activeSection === 'nickname') {
- let nicknameLabel = (
- <FormattedMessage
- id='user.settings.general.nickname'
- defaultMessage='Nickname'
- />
- );
- if (Utils.isMobile()) {
- nicknameLabel = '';
- }
-
- inputs.push(
- <div
- key='nicknameSetting'
- className='form-group'
- >
- <label className='col-sm-5 control-label'>{nicknameLabel}</label>
- <div className='col-sm-7'>
- <input
- className='form-control'
- type='text'
- onChange={this.updateNickname}
- value={this.state.nickname}
+ let extraInfo;
+ let submit = null;
+ if (this.props.user.auth_service === 'ldap' && global.window.mm_config.NicknameAttributeSet) {
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.field_handled_externally'
+ defaultMessage='This field is handled through your login provider. If you want to change it, you need to do so though your login provider.'
/>
- </div>
- </div>
- );
-
- const extraInfo = (
- <span>
+ </span>
+ );
+ } else {
+ let nicknameLabel = (
<FormattedMessage
- id='user.settings.general.nicknameExtra'
- defaultMessage='Use Nickname for a name you might be called that is different from your first name and username. This is most often used when two or more people have similar sounding names and usernames.'
+ id='user.settings.general.nickname'
+ defaultMessage='Nickname'
/>
- </span>
- );
+ );
+ if (Utils.isMobile()) {
+ nicknameLabel = '';
+ }
+
+ inputs.push(
+ <div
+ key='nicknameSetting'
+ className='form-group'
+ >
+ <label className='col-sm-5 control-label'>{nicknameLabel}</label>
+ <div className='col-sm-7'>
+ <input
+ className='form-control'
+ type='text'
+ onChange={this.updateNickname}
+ value={this.state.nickname}
+ />
+ </div>
+ </div>
+ );
+
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.nicknameExtra'
+ defaultMessage='Use Nickname for a name you might be called that is different from your first name and username. This is most often used when two or more people have similar sounding names and usernames.'
+ />
+ </span>
+ );
+
+ submit = this.submitNickname;
+ }
nicknameSection = (
<SettingItemMax
title={formatMessage(holders.nickname)}
inputs={inputs}
- submit={this.submitNickname}
+ submit={submit}
server_error={serverError}
client_error={clientError}
updateSection={(e) => {
@@ -708,48 +738,63 @@ class UserSettingsGeneralTab extends React.Component {
let usernameSection;
if (this.props.activeSection === 'username') {
- let usernameLabel = (
- <FormattedMessage
- id='user.settings.general.username'
- defaultMessage='Username'
- />
- );
- if (Utils.isMobile()) {
- usernameLabel = '';
- }
+ let extraInfo;
+ let submit = null;
+ if (this.props.user.auth_service === '') {
+ let usernameLabel = (
+ <FormattedMessage
+ id='user.settings.general.username'
+ defaultMessage='Username'
+ />
+ );
+ if (Utils.isMobile()) {
+ usernameLabel = '';
+ }
- inputs.push(
- <div
- key='usernameSetting'
- className='form-group'
- >
- <label className='col-sm-5 control-label'>{usernameLabel}</label>
- <div className='col-sm-7'>
- <input
- maxLength={Constants.MAX_USERNAME_LENGTH}
- className='form-control'
- type='text'
- onChange={this.updateUsername}
- value={this.state.username}
- />
+ inputs.push(
+ <div
+ key='usernameSetting'
+ className='form-group'
+ >
+ <label className='col-sm-5 control-label'>{usernameLabel}</label>
+ <div className='col-sm-7'>
+ <input
+ maxLength={Constants.MAX_USERNAME_LENGTH}
+ className='form-control'
+ type='text'
+ onChange={this.updateUsername}
+ value={this.state.username}
+ />
+ </div>
</div>
- </div>
- );
+ );
- const extraInfo = (
- <span>
- <FormattedMessage
- id='user.settings.general.usernameInfo'
- defaultMessage='Pick something easy for teammates to recognize and recall.'
- />
- </span>
- );
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.usernameInfo'
+ defaultMessage='Pick something easy for teammates to recognize and recall.'
+ />
+ </span>
+ );
+
+ submit = this.submitUsername;
+ } else {
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.field_handled_externally'
+ defaultMessage='This field is handled through your login provider. If you want to change it, you need to do so though your login provider.'
+ />
+ </span>
+ );
+ }
usernameSection = (
<SettingItemMax
title={formatMessage(holders.username)}
inputs={inputs}
- submit={this.submitUsername}
+ submit={submit}
server_error={serverError}
client_error={clientError}
updateSection={(e) => {