Fixing LDAP editing of attributes (#2824)

Этот коммит содержится в:
Christopher Speller
2016-05-02 08:07:58 -04:00
родитель 3346a9a63a
Коммит c63e027aec
6 изменённых файлов: 210 добавлений и 139 удалений

Просмотреть файл

@@ -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=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=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 ./utils || exit 1
$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1 $(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=120s ./web || exit 1
ifeq ($(BUILD_ENTERPRISE_READY),true) ifeq ($(BUILD_ENTERPRISE_READY),true)

Просмотреть файл

@@ -3495,6 +3495,10 @@
"id": "store.sql_user.update.app_error", "id": "store.sql_user.update.app_error",
"translation": "We couldn't update the account" "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", "id": "store.sql_user.update.email_taken.app_error",
"translation": "This email is already taken. Please choose another." "translation": "This email is already taken. Please choose another."

Просмотреть файл

@@ -136,7 +136,17 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha
if user.IsOAuthUser() { if user.IsOAuthUser() {
user.Email = oldUser.Email 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 user.EmailVerified = false
} }

Просмотреть файл

@@ -77,6 +77,12 @@ func TestUserStoreUpdate(t *testing.T) {
Must(store.User().Save(u1)) Must(store.User().Save(u1))
Must(store.Team().SaveMember(&model.TeamMember{TeamId: model.NewId(), UserId: u1.Id})) 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) time.Sleep(100 * time.Millisecond)
if err := (<-store.User().Update(u1, false)).Err; err != nil { 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 { if err := (<-store.User().Update(u1, false)).Err; err == nil {
t.Fatal("Update should have faile because id change") 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) { func TestUserStoreUpdateLastPingAt(t *testing.T) {

Просмотреть файл

@@ -259,6 +259,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["EnableLdap"] = strconv.FormatBool(*c.LdapSettings.Enable) props["EnableLdap"] = strconv.FormatBool(*c.LdapSettings.Enable)
props["LdapLoginFieldName"] = *c.LdapSettings.LoginFieldName props["LdapLoginFieldName"] = *c.LdapSettings.LoginFieldName
props["LdapPasswordFieldName"] = *c.LdapSettings.PasswordFieldName props["LdapPasswordFieldName"] = *c.LdapSettings.PasswordFieldName
props["NicknameAttributeSet"] = strconv.FormatBool(*c.LdapSettings.NicknameAttribute != "")
} }
if *License.Features.MFA { if *License.Features.MFA {

Просмотреть файл

@@ -513,85 +513,100 @@ class UserSettingsGeneralTab extends React.Component {
const inputs = []; const inputs = [];
if (this.props.activeSection === 'name') { if (this.props.activeSection === 'name') {
inputs.push( let extraInfo;
<div let submit = null;
key='firstNameSetting' if (this.props.user.auth_service === '') {
className='form-group' inputs.push(
> <div
<label className='col-sm-5 control-label'> key='firstNameSetting'
<FormattedMessage className='form-group'
id='user.settings.general.firstName' >
defaultMessage='First Name' <label className='col-sm-5 control-label'>
/> <FormattedMessage
</label> id='user.settings.general.firstName'
<div className='col-sm-7'> defaultMessage='First Name'
<input />
className='form-control' </label>
type='text' <div className='col-sm-7'>
onChange={this.updateFirstName} <input
value={this.state.firstName} className='form-control'
/> type='text'
onChange={this.updateFirstName}
value={this.state.firstName}
/>
</div>
</div> </div>
</div> );
);
inputs.push( inputs.push(
<div <div
key='lastNameSetting' key='lastNameSetting'
className='form-group' className='form-group'
> >
<label className='col-sm-5 control-label'> <label className='col-sm-5 control-label'>
<FormattedMessage <FormattedMessage
id='user.settings.general.lastName' id='user.settings.general.lastName'
defaultMessage='Last Name' defaultMessage='Last Name'
/> />
</label> </label>
<div className='col-sm-7'> <div className='col-sm-7'>
<input <input
className='form-control' className='form-control'
type='text' type='text'
onChange={this.updateLastName} onChange={this.updateLastName}
value={this.state.lastName} value={this.state.lastName}
/> />
</div>
</div> </div>
</div> );
);
function notifClick(e) { function notifClick(e) {
e.preventDefault(); e.preventDefault();
this.updateSection(''); this.updateSection('');
this.props.updateTab('notifications'); this.props.updateTab('notifications');
}
const notifLink = (
<a
href='#'
onClick={notifClick.bind(this)}
>
<FormattedMessage
id='user.settings.general.notificationsLink'
defaultMessage='Notifications'
/>
</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)
}}
/>
</span>
);
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 = ( nameSection = (
<SettingItemMax <SettingItemMax
title={formatMessage(holders.fullName)} title={formatMessage(holders.fullName)}
inputs={inputs} inputs={inputs}
submit={this.submitName} submit={submit}
server_error={serverError} server_error={serverError}
client_error={clientError} client_error={clientError}
updateSection={(e) => { updateSection={(e) => {
@@ -632,47 +647,62 @@ class UserSettingsGeneralTab extends React.Component {
let nicknameSection; let nicknameSection;
if (this.props.activeSection === 'nickname') { if (this.props.activeSection === 'nickname') {
let nicknameLabel = ( let extraInfo;
<FormattedMessage let submit = null;
id='user.settings.general.nickname' if (this.props.user.auth_service === 'ldap' && global.window.mm_config.NicknameAttributeSet) {
defaultMessage='Nickname' extraInfo = (
/> <span>
); <FormattedMessage
if (Utils.isMobile()) { id='user.settings.general.field_handled_externally'
nicknameLabel = ''; defaultMessage='This field is handled through your login provider. If you want to change it, you need to do so though your login provider.'
}
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> </span>
</div> );
); } else {
let nicknameLabel = (
const extraInfo = (
<span>
<FormattedMessage <FormattedMessage
id='user.settings.general.nicknameExtra' id='user.settings.general.nickname'
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.' 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 = ( nicknameSection = (
<SettingItemMax <SettingItemMax
title={formatMessage(holders.nickname)} title={formatMessage(holders.nickname)}
inputs={inputs} inputs={inputs}
submit={this.submitNickname} submit={submit}
server_error={serverError} server_error={serverError}
client_error={clientError} client_error={clientError}
updateSection={(e) => { updateSection={(e) => {
@@ -708,48 +738,63 @@ class UserSettingsGeneralTab extends React.Component {
let usernameSection; let usernameSection;
if (this.props.activeSection === 'username') { if (this.props.activeSection === 'username') {
let usernameLabel = ( let extraInfo;
<FormattedMessage let submit = null;
id='user.settings.general.username' if (this.props.user.auth_service === '') {
defaultMessage='Username' let usernameLabel = (
/>
);
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}
/>
</div>
</div>
);
const extraInfo = (
<span>
<FormattedMessage <FormattedMessage
id='user.settings.general.usernameInfo' id='user.settings.general.username'
defaultMessage='Pick something easy for teammates to recognize and recall.' defaultMessage='Username'
/> />
</span> );
); 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}
/>
</div>
</div>
);
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 = ( usernameSection = (
<SettingItemMax <SettingItemMax
title={formatMessage(holders.username)} title={formatMessage(holders.username)}
inputs={inputs} inputs={inputs}
submit={this.submitUsername} submit={submit}
server_error={serverError} server_error={serverError}
client_error={clientError} client_error={clientError}
updateSection={(e) => { updateSection={(e) => {