RainerW
2015-10-08 979c75ae88f2a1da3c7bc70d58aff38e9028f0c3
commit | author | age
f13c4c 1 /*
JM 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
dfb889 16 package com.gitblit.wicket.pages;
JM 17
a098da 18 import java.text.MessageFormat;
dfb889 19 import java.util.ArrayList;
fe24a0 20 import java.util.Collections;
dfb889 21 import java.util.Iterator;
JM 22 import java.util.List;
23
24 import org.apache.wicket.PageParameters;
d3ca1c 25 import org.apache.wicket.behavior.SimpleAttributeModifier;
dfb889 26 import org.apache.wicket.extensions.markup.html.form.palette.Palette;
331fbc 27 import org.apache.wicket.markup.html.form.Button;
dfb889 28 import org.apache.wicket.markup.html.form.CheckBox;
JM 29 import org.apache.wicket.markup.html.form.Form;
30 import org.apache.wicket.markup.html.form.TextField;
31 import org.apache.wicket.model.CompoundPropertyModel;
32 import org.apache.wicket.model.Model;
33 import org.apache.wicket.model.util.CollectionModel;
34 import org.apache.wicket.model.util.ListModel;
35
a4231d 36 import com.gitblit.Constants.RegistrantType;
6e3481 37 import com.gitblit.Constants.Role;
dfb889 38 import com.gitblit.GitBlitException;
f98825 39 import com.gitblit.Keys;
822dfe 40 import com.gitblit.models.RegistrantAccessPermission;
fe24a0 41 import com.gitblit.models.TeamModel;
1f9dae 42 import com.gitblit.models.UserModel;
f98825 43 import com.gitblit.utils.StringUtils;
979c75 44 import com.gitblit.wicket.NonTrimmedPasswordTextField;
1f9dae 45 import com.gitblit.wicket.RequiresAdminRole;
6fa6ab 46 import com.gitblit.wicket.StringChoiceRenderer;
dfb889 47 import com.gitblit.wicket.WicketUtils;
822dfe 48 import com.gitblit.wicket.panels.RegistrantPermissionsPanel;
dfb889 49
1f9dae 50 @RequiresAdminRole
d376ab 51 public class EditUserPage extends RootSubPage {
dfb889 52
JM 53     private final boolean isCreate;
699e71 54
dfb889 55     public EditUserPage() {
JM 56         // create constructor
57         super();
58         isCreate = true;
511554 59         setupPage(new UserModel(""));
b0e164 60         setStatelessHint(false);
092f0a 61         setOutputMarkupId(true);
dfb889 62     }
JM 63
64     public EditUserPage(PageParameters params) {
65         // edit constructor
66         super(params);
67         isCreate = false;
68         String name = WicketUtils.getUsername(params);
99d0d4 69         UserModel model = app().users().getUserModel(name);
dfb889 70         setupPage(model);
b0e164 71         setStatelessHint(false);
092f0a 72         setOutputMarkupId(true);
dfb889 73     }
699e71 74
dd630f 75     @Override
JM 76     protected boolean requiresPageMap() {
77         return true;
78     }
699e71 79
6ef8d7 80     @Override
JM 81     protected Class<? extends BasePage> getRootNavPageClass() {
82         return UsersPage.class;
83     }
dfb889 84
511554 85     protected void setupPage(final UserModel userModel) {
dfb889 86         if (isCreate) {
a7571b 87             super.setupPage(getString("gb.newUser"), "");
dfb889 88         } else {
a7571b 89             super.setupPage(getString("gb.edit"), userModel.username);
dfb889 90         }
d5623a 91
2a7306 92         final Model<String> confirmPassword = new Model<String>(
JM 93                 StringUtils.isEmpty(userModel.password) ? "" : userModel.password);
511554 94         CompoundPropertyModel<UserModel> model = new CompoundPropertyModel<UserModel>(userModel);
dfb889 95
479cc2 96         // build list of projects including all repositories wildcards
092f0a 97         List<String> repos = getAccessRestrictedRepositoryList(true, userModel);
699e71 98
fe24a0 99         List<String> userTeams = new ArrayList<String>();
JM 100         for (TeamModel team : userModel.teams) {
101             userTeams.add(team.name);
102         }
103         Collections.sort(userTeams);
699e71 104
2a7306 105         final String oldName = userModel.username;
99d0d4 106         final List<RegistrantAccessPermission> permissions = app().repositories().getUserAccessPermissions(userModel);
b0e164 107
fe24a0 108         final Palette<String> teams = new Palette<String>("teams", new ListModel<String>(
99d0d4 109                 new ArrayList<String>(userTeams)), new CollectionModel<String>(app().users()
db4f6b 110                 .getAllTeamNames()), new StringChoiceRenderer(), 10, false);
511554 111         Form<UserModel> form = new Form<UserModel>("editForm", model) {
dfb889 112
JM 113             private static final long serialVersionUID = 1L;
699e71 114
a098da 115             /*
JM 116              * (non-Javadoc)
699e71 117              *
a098da 118              * @see org.apache.wicket.markup.html.form.Form#onSubmit()
JM 119              */
dfb889 120             @Override
JM 121             protected void onSubmit() {
ae0b13 122                 if (StringUtils.isEmpty(userModel.username)) {
6caa93 123                     error(getString("gb.pleaseSetUsername"));
a098da 124                     return;
JM 125                 }
ae0b13 126                 // force username to lower-case
JM 127                 userModel.username = userModel.username.toLowerCase();
128                 String username = userModel.username;
a098da 129                 if (isCreate) {
99d0d4 130                     UserModel model = app().users().getUserModel(username);
a098da 131                     if (model != null) {
6caa93 132                         error(MessageFormat.format(getString("gb.usernameUnavailable"), username));
a098da 133                         return;
JM 134                     }
135                 }
fe24a0 136                 boolean rename = !StringUtils.isEmpty(oldName)
JM 137                         && !oldName.equalsIgnoreCase(username);
04a985 138                 if (app().authentication().supportsCredentialChanges(userModel)) {
f3b625 139                     if (!userModel.password.equals(confirmPassword.getObject())) {
JC 140                         error(getString("gb.passwordsDoNotMatch"));
a098da 141                         return;
JM 142                     }
f3b625 143                     String password = userModel.password;
JC 144                     if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE)
145                             && !password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {
146                         // This is a plain text password.
147                         // Check length.
99d0d4 148                         int minLength = app().settings().getInteger(Keys.realm.minPasswordLength, 5);
f3b625 149                         if (minLength < 4) {
JC 150                             minLength = 4;
151                         }
152                         if (password.trim().length() < minLength) {
153                             error(MessageFormat.format(getString("gb.passwordTooShort"),
154                                     minLength));
155                             return;
156                         }
699e71 157
7ab32b 158                         // change the cookie
JM 159                         userModel.cookie = StringUtils.getSHA1(userModel.username + password);
160
f3b625 161                         // Optionally store the password MD5 digest.
99d0d4 162                         String type = app().settings().getString(Keys.realm.passwordStorage, "md5");
f3b625 163                         if (type.equalsIgnoreCase("md5")) {
JC 164                             // store MD5 digest of password
165                             userModel.password = StringUtils.MD5_TYPE
166                                     + StringUtils.getMD5(userModel.password);
167                         } else if (type.equalsIgnoreCase("combined-md5")) {
168                             // store MD5 digest of username+password
169                             userModel.password = StringUtils.COMBINED_MD5_TYPE
170                                     + StringUtils.getMD5(username + userModel.password);
171                         }
172                     } else if (rename
173                             && password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {
174                         error(getString("gb.combinedMd5Rename"));
175                         return;
f98825 176                     }
JM 177                 }
178
b0e164 179                 // update user permissions
822dfe 180                 for (RegistrantAccessPermission repositoryPermission : permissions) {
f163d0 181                     if (repositoryPermission.mutable) {
JM 182                         userModel.setRepositoryPermission(repositoryPermission.registrant, repositoryPermission.permission);
183                     }
dfb889 184                 }
fe24a0 185
JM 186                 Iterator<String> selectedTeams = teams.getSelectedChoices();
187                 userModel.teams.clear();
188                 while (selectedTeams.hasNext()) {
99d0d4 189                     TeamModel team = app().users().getTeamModel(selectedTeams.next());
fe24a0 190                     if (team == null) {
JM 191                         continue;
192                     }
193                     userModel.teams.add(team);
194                 }
195
699e71 196                 try {
5ae529 197                     if (isCreate) {
JM 198                         app().gitblit().addUser(userModel);
199                     } else {
200                         app().gitblit().reviseUser(oldName, userModel);
201                     }
dfb889 202                 } catch (GitBlitException e) {
JM 203                     error(e.getMessage());
204                     return;
205                 }
a098da 206                 setRedirect(false);
f98825 207                 if (isCreate) {
JM 208                     // create another user
6caa93 209                     info(MessageFormat.format(getString("gb.userCreated"),
2a7306 210                             userModel.username));
f98825 211                     setResponsePage(EditUserPage.class);
JM 212                 } else {
d376ab 213                     // back to users page
JM 214                     setResponsePage(UsersPage.class);
f98825 215                 }
dfb889 216             }
JM 217         };
699e71 218
d3ca1c 219         // do not let the browser pre-populate these fields
JM 220         form.add(new SimpleAttributeModifier("autocomplete", "off"));
699e71 221
6e3481 222         // not all user providers support manipulating username and password
04a985 223         boolean editCredentials = app().authentication().supportsCredentialChanges(userModel);
699e71 224
6e3481 225         // not all user providers support manipulating display name
04a985 226         boolean editDisplayName = app().authentication().supportsDisplayNameChanges(userModel);
0aa8cf 227
6e3481 228         // not all user providers support manipulating email address
04a985 229         boolean editEmailAddress = app().authentication().supportsEmailAddressChanges(userModel);
6cca86 230
6e3481 231         // not all user providers support manipulating team memberships
04a985 232         boolean editTeams = app().authentication().supportsTeamMembershipChanges(userModel);
6e3481 233
JM 234         // not all user providers support manipulating the admin role
235         boolean changeAdminRole = app().authentication().supportsRoleChanges(userModel, Role.ADMIN);
236
237         // not all user providers support manipulating the create role
238         boolean changeCreateRole = app().authentication().supportsRoleChanges(userModel, Role.CREATE);
239
240         // not all user providers support manipulating the fork role
241         boolean changeForkRole = app().authentication().supportsRoleChanges(userModel, Role.FORK);
dfb889 242
JM 243         // field names reflective match UserModel fields
6cca86 244         form.add(new TextField<String>("username").setEnabled(editCredentials));
979c75 245         NonTrimmedPasswordTextField passwordField = new NonTrimmedPasswordTextField("password");
f98825 246         passwordField.setResetPassword(false);
6cca86 247         form.add(passwordField.setEnabled(editCredentials));
979c75 248         NonTrimmedPasswordTextField confirmPasswordField = new NonTrimmedPasswordTextField("confirmPassword",
2a7306 249                 confirmPassword);
f98825 250         confirmPasswordField.setResetPassword(false);
6cca86 251         form.add(confirmPasswordField.setEnabled(editCredentials));
0aa8cf 252         form.add(new TextField<String>("displayName").setEnabled(editDisplayName));
JM 253         form.add(new TextField<String>("emailAddress").setEnabled(editEmailAddress));
48019b 254
JM 255         if (userModel.canAdmin() && !userModel.canAdmin) {
256             // user inherits Admin permission
257             // display a disabled-yet-checked checkbox
258             form.add(new CheckBox("canAdmin", Model.of(true)).setEnabled(false));
259         } else {
6e3481 260             form.add(new CheckBox("canAdmin").setEnabled(changeAdminRole));
48019b 261         }
JM 262
263         if (userModel.canFork() && !userModel.canFork) {
264             // user inherits Fork permission
265             // display a disabled-yet-checked checkbox
266             form.add(new CheckBox("canFork", Model.of(true)).setEnabled(false));
267         } else {
268             final boolean forkingAllowed = app().settings().getBoolean(Keys.web.allowForking, true);
6e3481 269             form.add(new CheckBox("canFork").setEnabled(forkingAllowed && changeForkRole));
48019b 270         }
JM 271
272         if (userModel.canCreate() && !userModel.canCreate) {
273             // user inherits Create permission
274             // display a disabled-yet-checked checkbox
275             form.add(new CheckBox("canCreate", Model.of(true)).setEnabled(false));
276         } else {
6e3481 277             form.add(new CheckBox("canCreate").setEnabled(changeCreateRole));
48019b 278         }
JM 279
831469 280         form.add(new CheckBox("excludeFromFederation"));
9aa119 281         form.add(new CheckBox("disabled"));
JM 282
092f0a 283         form.add(new RegistrantPermissionsPanel("repositories",    RegistrantType.REPOSITORY, repos, permissions, getAccessPermissions()));
6cca86 284         form.add(teams.setEnabled(editTeams));
88598b 285
6929d9 286         form.add(new TextField<String>("organizationalUnit").setEnabled(editDisplayName));
JM 287         form.add(new TextField<String>("organization").setEnabled(editDisplayName));
288         form.add(new TextField<String>("locality").setEnabled(editDisplayName));
289         form.add(new TextField<String>("stateProvince").setEnabled(editDisplayName));
290         form.add(new TextField<String>("countryCode").setEnabled(editDisplayName));
719798 291         form.add(new Button("save"));
JM 292         Button cancel = new Button("cancel") {
331fbc 293             private static final long serialVersionUID = 1L;
JM 294
295             @Override
296             public void onSubmit() {
8c5d72 297                 setResponsePage(UsersPage.class);
88598b 298             }
JM 299         };
300         cancel.setDefaultFormProcessing(false);
301         form.add(cancel);
302
dfb889 303         add(form);
JM 304     }
305 }