| /* | |
| * Copyright 2011 gitblit.com. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package com.gitblit.wicket.pages; | |
| import java.text.MessageFormat; | |
| import java.util.ArrayList; | |
| import java.util.Collections; | |
| import java.util.Iterator; | |
| import java.util.List; | |
| import org.apache.wicket.PageParameters; | |
| import org.apache.wicket.behavior.SimpleAttributeModifier; | |
| import org.apache.wicket.extensions.markup.html.form.palette.Palette; | |
| import org.apache.wicket.markup.html.form.Button; | |
| import org.apache.wicket.markup.html.form.CheckBox; | |
| import org.apache.wicket.markup.html.form.Form; | |
| import org.apache.wicket.markup.html.form.TextField; | |
| import org.apache.wicket.model.CompoundPropertyModel; | |
| import org.apache.wicket.model.Model; | |
| import org.apache.wicket.model.util.CollectionModel; | |
| import org.apache.wicket.model.util.ListModel; | |
| import com.gitblit.Constants.RegistrantType; | |
| import com.gitblit.Constants.Role; | |
| import com.gitblit.GitBlitException; | |
| import com.gitblit.Keys; | |
| import com.gitblit.models.RegistrantAccessPermission; | |
| import com.gitblit.models.TeamModel; | |
| import com.gitblit.models.UserModel; | |
| import com.gitblit.utils.StringUtils; | |
| import com.gitblit.wicket.NonTrimmedPasswordTextField; | |
| import com.gitblit.wicket.RequiresAdminRole; | |
| import com.gitblit.wicket.StringChoiceRenderer; | |
| import com.gitblit.wicket.WicketUtils; | |
| import com.gitblit.wicket.panels.RegistrantPermissionsPanel; | |
| @RequiresAdminRole | |
| public class EditUserPage extends RootSubPage { | |
| private final boolean isCreate; | |
| public EditUserPage() { | |
| // create constructor | |
| super(); | |
| isCreate = true; | |
| setupPage(new UserModel("")); | |
| setStatelessHint(false); | |
| setOutputMarkupId(true); | |
| } | |
| public EditUserPage(PageParameters params) { | |
| // edit constructor | |
| super(params); | |
| isCreate = false; | |
| String name = WicketUtils.getUsername(params); | |
| UserModel model = app().users().getUserModel(name); | |
| setupPage(model); | |
| setStatelessHint(false); | |
| setOutputMarkupId(true); | |
| } | |
| @Override | |
| protected boolean requiresPageMap() { | |
| return true; | |
| } | |
| @Override | |
| protected Class<? extends BasePage> getRootNavPageClass() { | |
| return UsersPage.class; | |
| } | |
| protected void setupPage(final UserModel userModel) { | |
| if (isCreate) { | |
| super.setupPage(getString("gb.newUser"), ""); | |
| } else { | |
| super.setupPage(getString("gb.edit"), userModel.username); | |
| } | |
| final Model<String> confirmPassword = new Model<String>( | |
| StringUtils.isEmpty(userModel.password) ? "" : userModel.password); | |
| CompoundPropertyModel<UserModel> model = new CompoundPropertyModel<UserModel>(userModel); | |
| // build list of projects including all repositories wildcards | |
| List<String> repos = getAccessRestrictedRepositoryList(true, userModel); | |
| List<String> userTeams = new ArrayList<String>(); | |
| for (TeamModel team : userModel.teams) { | |
| userTeams.add(team.name); | |
| } | |
| Collections.sort(userTeams); | |
| final String oldName = userModel.username; | |
| final List<RegistrantAccessPermission> permissions = app().repositories().getUserAccessPermissions(userModel); | |
| final Palette<String> teams = new Palette<String>("teams", new ListModel<String>( | |
| new ArrayList<String>(userTeams)), new CollectionModel<String>(app().users() | |
| .getAllTeamNames()), new StringChoiceRenderer(), 10, false); | |
| Form<UserModel> form = new Form<UserModel>("editForm", model) { | |
| private static final long serialVersionUID = 1L; | |
| /* | |
| * (non-Javadoc) | |
| * | |
| * @see org.apache.wicket.markup.html.form.Form#onSubmit() | |
| */ | |
| @Override | |
| protected void onSubmit() { | |
| if (StringUtils.isEmpty(userModel.username)) { | |
| error(getString("gb.pleaseSetUsername")); | |
| return; | |
| } | |
| // force username to lower-case | |
| userModel.username = userModel.username.toLowerCase(); | |
| String username = userModel.username; | |
| if (isCreate) { | |
| UserModel model = app().users().getUserModel(username); | |
| if (model != null) { | |
| error(MessageFormat.format(getString("gb.usernameUnavailable"), username)); | |
| return; | |
| } | |
| } | |
| boolean rename = !StringUtils.isEmpty(oldName) | |
| && !oldName.equalsIgnoreCase(username); | |
| if (app().authentication().supportsCredentialChanges(userModel)) { | |
| if (!userModel.password.equals(confirmPassword.getObject())) { | |
| error(getString("gb.passwordsDoNotMatch")); | |
| return; | |
| } | |
| String password = userModel.password; | |
| if (!password.toUpperCase().startsWith(StringUtils.MD5_TYPE) | |
| && !password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) { | |
| // This is a plain text password. | |
| // Check length. | |
| int minLength = app().settings().getInteger(Keys.realm.minPasswordLength, 5); | |
| if (minLength < 4) { | |
| minLength = 4; | |
| } | |
| if (password.trim().length() < minLength) { | |
| error(MessageFormat.format(getString("gb.passwordTooShort"), | |
| minLength)); | |
| return; | |
| } | |
| // change the cookie | |
| userModel.cookie = userModel.createCookie(); | |
| // Optionally store the password MD5 digest. | |
| String type = app().settings().getString(Keys.realm.passwordStorage, "md5"); | |
| if (type.equalsIgnoreCase("md5")) { | |
| // store MD5 digest of password | |
| userModel.password = StringUtils.MD5_TYPE | |
| + StringUtils.getMD5(userModel.password); | |
| } else if (type.equalsIgnoreCase("combined-md5")) { | |
| // store MD5 digest of username+password | |
| userModel.password = StringUtils.COMBINED_MD5_TYPE | |
| + StringUtils.getMD5(username + userModel.password); | |
| } | |
| } else if (rename | |
| && password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) { | |
| error(getString("gb.combinedMd5Rename")); | |
| return; | |
| } | |
| } | |
| // update user permissions | |
| for (RegistrantAccessPermission repositoryPermission : permissions) { | |
| if (repositoryPermission.mutable) { | |
| userModel.setRepositoryPermission(repositoryPermission.registrant, repositoryPermission.permission); | |
| } | |
| } | |
| Iterator<String> selectedTeams = teams.getSelectedChoices(); | |
| userModel.teams.clear(); | |
| while (selectedTeams.hasNext()) { | |
| TeamModel team = app().users().getTeamModel(selectedTeams.next()); | |
| if (team == null) { | |
| continue; | |
| } | |
| userModel.teams.add(team); | |
| } | |
| try { | |
| if (isCreate) { | |
| app().gitblit().addUser(userModel); | |
| } else { | |
| app().gitblit().reviseUser(oldName, userModel); | |
| } | |
| } catch (GitBlitException e) { | |
| error(e.getMessage()); | |
| return; | |
| } | |
| setRedirect(false); | |
| if (isCreate) { | |
| // create another user | |
| info(MessageFormat.format(getString("gb.userCreated"), | |
| userModel.username)); | |
| setResponsePage(EditUserPage.class); | |
| } else { | |
| // back to users page | |
| setResponsePage(UsersPage.class); | |
| } | |
| } | |
| }; | |
| // do not let the browser pre-populate these fields | |
| form.add(new SimpleAttributeModifier("autocomplete", "off")); | |
| // not all user providers support manipulating username and password | |
| boolean editCredentials = app().authentication().supportsCredentialChanges(userModel); | |
| // not all user providers support manipulating display name | |
| boolean editDisplayName = app().authentication().supportsDisplayNameChanges(userModel); | |
| // not all user providers support manipulating email address | |
| boolean editEmailAddress = app().authentication().supportsEmailAddressChanges(userModel); | |
| // not all user providers support manipulating team memberships | |
| boolean editTeams = app().authentication().supportsTeamMembershipChanges(userModel); | |
| // not all user providers support manipulating the admin role | |
| boolean changeAdminRole = app().authentication().supportsRoleChanges(userModel, Role.ADMIN); | |
| // not all user providers support manipulating the create role | |
| boolean changeCreateRole = app().authentication().supportsRoleChanges(userModel, Role.CREATE); | |
| // not all user providers support manipulating the fork role | |
| boolean changeForkRole = app().authentication().supportsRoleChanges(userModel, Role.FORK); | |
| // field names reflective match UserModel fields | |
| form.add(new TextField<String>("username").setEnabled(editCredentials)); | |
| NonTrimmedPasswordTextField passwordField = new NonTrimmedPasswordTextField("password"); | |
| passwordField.setResetPassword(false); | |
| form.add(passwordField.setEnabled(editCredentials)); | |
| NonTrimmedPasswordTextField confirmPasswordField = new NonTrimmedPasswordTextField("confirmPassword", | |
| confirmPassword); | |
| confirmPasswordField.setResetPassword(false); | |
| form.add(confirmPasswordField.setEnabled(editCredentials)); | |
| form.add(new TextField<String>("displayName").setEnabled(editDisplayName)); | |
| form.add(new TextField<String>("emailAddress").setEnabled(editEmailAddress)); | |
| if (userModel.canAdmin() && !userModel.canAdmin) { | |
| // user inherits Admin permission | |
| // display a disabled-yet-checked checkbox | |
| form.add(new CheckBox("canAdmin", Model.of(true)).setEnabled(false)); | |
| } else { | |
| form.add(new CheckBox("canAdmin").setEnabled(changeAdminRole)); | |
| } | |
| if (userModel.canFork() && !userModel.canFork) { | |
| // user inherits Fork permission | |
| // display a disabled-yet-checked checkbox | |
| form.add(new CheckBox("canFork", Model.of(true)).setEnabled(false)); | |
| } else { | |
| final boolean forkingAllowed = app().settings().getBoolean(Keys.web.allowForking, true); | |
| form.add(new CheckBox("canFork").setEnabled(forkingAllowed && changeForkRole)); | |
| } | |
| if (userModel.canCreate() && !userModel.canCreate) { | |
| // user inherits Create permission | |
| // display a disabled-yet-checked checkbox | |
| form.add(new CheckBox("canCreate", Model.of(true)).setEnabled(false)); | |
| } else { | |
| form.add(new CheckBox("canCreate").setEnabled(changeCreateRole)); | |
| } | |
| form.add(new CheckBox("excludeFromFederation")); | |
| form.add(new CheckBox("disabled")); | |
| form.add(new RegistrantPermissionsPanel("repositories", RegistrantType.REPOSITORY, repos, permissions, getAccessPermissions())); | |
| form.add(teams.setEnabled(editTeams)); | |
| form.add(new TextField<String>("organizationalUnit").setEnabled(editDisplayName)); | |
| form.add(new TextField<String>("organization").setEnabled(editDisplayName)); | |
| form.add(new TextField<String>("locality").setEnabled(editDisplayName)); | |
| form.add(new TextField<String>("stateProvince").setEnabled(editDisplayName)); | |
| form.add(new TextField<String>("countryCode").setEnabled(editDisplayName)); | |
| form.add(new Button("save")); | |
| Button cancel = new Button("cancel") { | |
| private static final long serialVersionUID = 1L; | |
| @Override | |
| public void onSubmit() { | |
| setResponsePage(UsersPage.class); | |
| } | |
| }; | |
| cancel.setDefaultFormProcessing(false); | |
| form.add(cancel); | |
| add(form); | |
| } | |
| } |