vertical-align: middle;\r
}\r
\r
+div.odd {\r
+ \r
+}\r
+\r
+div.even {\r
+ background-color: whiteSmoke;\r
+ vertical-align: middle;\r
+}\r
+\r
div.page_footer {\r
clear: both;\r
height: 17px;\r
public static enum AccessPermission {\r
NONE("N"), VIEW("V"), CLONE("R"), PUSH("RW"), CREATE("RWC"), DELETE("RWD"), REWIND("RW+");\r
\r
+ public static final AccessPermission [] NEWPERMISSIONS = { VIEW, CLONE, PUSH, CREATE, DELETE, REWIND };\r
+ \r
public static AccessPermission LEGACY = REWIND;\r
\r
public final String code;\r
--- /dev/null
+/*
+ * Copyright 2012 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.models;
+
+import java.io.Serializable;
+
+import com.gitblit.Constants.AccessPermission;
+import com.gitblit.utils.StringUtils;
+
+/**
+ * Represents a Repository-AccessPermission tuple.
+ *
+ * @author James Moger
+ */
+public class RepositoryAccessPermission implements Serializable, Comparable<RepositoryAccessPermission> {
+
+ private static final long serialVersionUID = 1L;
+
+ public String repository;
+ public AccessPermission permission;
+
+ public RepositoryAccessPermission() {
+ }
+
+ public RepositoryAccessPermission(String repository, AccessPermission permission) {
+ this.repository = repository;
+ this.permission = permission;
+ }
+
+ @Override
+ public int compareTo(RepositoryAccessPermission p) {
+ return StringUtils.compareRepositoryNames(repository, p.repository);
+ }
+
+ @Override
+ public String toString() {
+ return permission.asRole(repository);
+ }
+}
\ No newline at end of file
import java.io.Serializable;\r
import java.util.ArrayList;\r
import java.util.Collection;\r
+import java.util.Collections;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.List;\r
public void removeRepository(String name) {\r
removeRepositoryPermission(name);\r
}\r
+\r
+ \r
+ /**\r
+ * Returns a list of repository permissions for this team.\r
+ * \r
+ * @return the team's list of permissions\r
+ */\r
+ public List<RepositoryAccessPermission> getRepositoryPermissions() {\r
+ List<RepositoryAccessPermission> list = new ArrayList<RepositoryAccessPermission>();\r
+ for (Map.Entry<String, AccessPermission> entry : permissions.entrySet()) {\r
+ list.add(new RepositoryAccessPermission(entry.getKey(), entry.getValue()));\r
+ }\r
+ Collections.sort(list);\r
+ return list;\r
+ }\r
\r
/**\r
* Returns true if the team has any type of specified access permission for\r
\r
import java.io.Serializable;\r
import java.security.Principal;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
+import java.util.List;\r
import java.util.Map;\r
import java.util.Set;\r
\r
removeRepositoryPermission(name);\r
}\r
\r
+ /**\r
+ * Returns a list of repository permissions for this user exclusive of\r
+ * permissions inherited from team memberships.\r
+ * \r
+ * @return the user's list of permissions\r
+ */\r
+ public List<RepositoryAccessPermission> getRepositoryPermissions() {\r
+ List<RepositoryAccessPermission> list = new ArrayList<RepositoryAccessPermission>();\r
+ for (Map.Entry<String, AccessPermission> entry : permissions.entrySet()) {\r
+ list.add(new RepositoryAccessPermission(entry.getKey(), entry.getValue()));\r
+ }\r
+ Collections.sort(list);\r
+ return list;\r
+ }\r
+ \r
/**\r
* Returns true if the user has any type of specified access permission for\r
* this repository.\r
gb.verifyCommitterDescription = require committer identity to match pushing Gitblt user account (all merges require "--no-ff" to enforce committer identity)\r
gb.repositoryPermissions = repository permissions\r
gb.userPermissions = user permissions\r
-gb.teamPermissions = team permissions
\ No newline at end of file
+gb.teamPermissions = team permissions\r
+gb.add = add\r
+gb.noPermission = NO ACCESS\r
+gb.viewPermission = {0} (view)\r
+gb.clonePermission = {0} (clone)\r
+gb.pushPermission = {0} (push)\r
+gb.createPermission = {0} (push, ref creation)\r
+gb.deletePermission = {0} (push, ref creation+deletion)\r
+gb.rewindPermission = {0} (push, ref creation+deletion+rewind)
\ No newline at end of file
*/\r
package com.gitblit.wicket.pages;\r
\r
+import java.text.MessageFormat;\r
import java.util.ArrayList;\r
import java.util.Calendar;\r
import java.util.Collections;\r
import org.slf4j.LoggerFactory;\r
\r
import com.gitblit.Constants;\r
+import com.gitblit.Constants.AccessPermission;\r
import com.gitblit.Constants.AccessRestrictionType;\r
import com.gitblit.Constants.FederationStrategy;\r
import com.gitblit.GitBlit;\r
return map;\r
}\r
\r
+ protected Map<AccessPermission, String> getAccessPermissions() {\r
+ Map<AccessPermission, String> map = new LinkedHashMap<AccessPermission, String>();\r
+ for (AccessPermission type : AccessPermission.values()) {\r
+ switch (type) {\r
+ case NONE:\r
+ map.put(type, MessageFormat.format(getString("gb.noPermission"), type.code));\r
+ break;\r
+ case VIEW:\r
+ map.put(type, MessageFormat.format(getString("gb.viewPermission"), type.code));\r
+ break;\r
+ case CLONE:\r
+ map.put(type, MessageFormat.format(getString("gb.clonePermission"), type.code));\r
+ break;\r
+ case PUSH:\r
+ map.put(type, MessageFormat.format(getString("gb.pushPermission"), type.code));\r
+ break;\r
+ case CREATE:\r
+ map.put(type, MessageFormat.format(getString("gb.createPermission"), type.code));\r
+ break;\r
+ case DELETE:\r
+ map.put(type, MessageFormat.format(getString("gb.deletePermission"), type.code));\r
+ break;\r
+ case REWIND:\r
+ map.put(type, MessageFormat.format(getString("gb.rewindPermission"), type.code));\r
+ break;\r
+ }\r
+ }\r
+ return map;\r
+ }\r
+ \r
protected Map<FederationStrategy, String> getFederationTypes() {\r
Map<FederationStrategy, String> map = new LinkedHashMap<FederationStrategy, String>();\r
for (FederationStrategy type : FederationStrategy.values()) {\r
<tr><td colspan="2" style="padding-top:15px;"><h3><wicket:message key="gb.accessPermissions"></wicket:message> <small><wicket:message key="gb.accessPermissionsForTeamDescription"></wicket:message></small></h3></td></tr> \r
<tr><th style="vertical-align: top;"><wicket:message key="gb.teamMembers"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr>\r
<tr><td colspan="2"><hr></hr></td></tr>\r
- <tr><th style="vertical-align: top;"><wicket:message key="gb.restrictedRepositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr>\r
+ <tr><th style="vertical-align: top;"><wicket:message key="gb.repositoryPermissions"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr>\r
<tr><td colspan="2" style="padding-top:10px;"><h3><wicket:message key="gb.hookScripts"></wicket:message> <small><wicket:message key="gb.hookScriptsDescription"></wicket:message></small></h3></td></tr> \r
<tr><th style="vertical-align: top;"><wicket:message key="gb.preReceiveScripts"></wicket:message><p></p><span wicket:id="inheritedPreReceive"></span></th><td style="padding:2px;"><span wicket:id="preReceiveScripts"></span></td></tr>\r
<tr><th style="vertical-align: top;"><wicket:message key="gb.postReceiveScripts"></wicket:message><p></p><span wicket:id="inheritedPostReceive"></span></th><td style="padding:2px;"><span wicket:id="postReceiveScripts"></span></td></tr>\r
import com.gitblit.GitBlit;\r
import com.gitblit.GitBlitException;\r
import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.RepositoryAccessPermission;\r
import com.gitblit.models.TeamModel;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.wicket.RequiresAdminRole;\r
import com.gitblit.wicket.StringChoiceRenderer;\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.panels.BulletListPanel;\r
+import com.gitblit.wicket.panels.RepositoryPermissionsPanel;\r
\r
@RequiresAdminRole\r
public class EditTeamPage extends RootSubPage {\r
super();\r
isCreate = true;\r
setupPage(new TeamModel(""));\r
+ setStatelessHint(false);\r
}\r
\r
public EditTeamPage(PageParameters params) {\r
String name = WicketUtils.getTeamname(params);\r
TeamModel model = GitBlit.self().getTeamModel(name);\r
setupPage(model);\r
+ setStatelessHint(false);\r
}\r
\r
protected void setupPage(final TeamModel teamModel) {\r
List<String> postReceiveScripts = new ArrayList<String>();\r
\r
final String oldName = teamModel.name;\r
-\r
- // repositories palette\r
- final Palette<String> repositories = new Palette<String>("repositories",\r
- new ListModel<String>(new ArrayList<String>(teamModel.repositories)),\r
- new CollectionModel<String>(repos), new StringChoiceRenderer(), 10, false);\r
+ final List<RepositoryAccessPermission> permissions = teamModel.getRepositoryPermissions();\r
\r
// users palette\r
final Palette<String> users = new Palette<String>("users", new ListModel<String>(\r
return;\r
}\r
}\r
- Iterator<String> selectedRepositories = repositories.getSelectedChoices();\r
- List<String> repos = new ArrayList<String>();\r
- while (selectedRepositories.hasNext()) {\r
- repos.add(selectedRepositories.next().toLowerCase());\r
- }\r
- if (repos.size() == 0) {\r
- error(getString("gb.teamMustSpecifyRepository"));\r
- return;\r
+ // update team permissions\r
+ for (RepositoryAccessPermission repositoryPermission : permissions) {\r
+ teamModel.setRepositoryPermission(repositoryPermission.repository, repositoryPermission.permission);\r
}\r
- teamModel.repositories.clear();\r
- teamModel.repositories.addAll(repos);\r
\r
Iterator<String> selectedUsers = users.getSelectedChoices();\r
List<String> members = new ArrayList<String>();\r
: StringUtils.flattenStrings(teamModel.mailingLists, " "));\r
form.add(new TextField<String>("mailingLists", mailingLists));\r
\r
- form.add(repositories);\r
+ form.add(new RepositoryPermissionsPanel("repositories", permissions, getAccessPermissions()));\r
form.add(preReceivePalette);\r
form.add(new BulletListPanel("inheritedPreReceive", "inherited", GitBlit.self()\r
.getPreReceiveScriptsInherited(null)));\r
<tr><td colspan="2" style="padding-top:15px;"><h3><wicket:message key="gb.accessPermissions"></wicket:message> <small><wicket:message key="gb.accessPermissionsForUserDescription"></wicket:message></small></h3></td></tr> \r
<tr><th style="vertical-align: top;"><wicket:message key="gb.teamMemberships"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr>\r
<tr><td colspan="2"><hr></hr></td></tr>\r
- <tr><th style="vertical-align: top;"><wicket:message key="gb.restrictedRepositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr>\r
+ <tr><th style="vertical-align: top;"><wicket:message key="gb.repositoryPermissions"></wicket:message></th>\r
+ <td style="padding:2px;">\r
+ <div wicket:id="repositories"></div>\r
+ </td>\r
+ </tr>\r
<tr><td colspan='2'><div class="form-actions"><input class="btn btn-primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="9" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="10" /></div></td></tr>\r
</tbody>\r
</table>\r
- </form> \r
+ </form>\r
</body>\r
+\r
</wicket:extend>\r
</html>
\ No newline at end of file
import com.gitblit.GitBlitException;\r
import com.gitblit.Keys;\r
import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.RepositoryAccessPermission;\r
import com.gitblit.models.TeamModel;\r
import com.gitblit.models.UserModel;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.wicket.RequiresAdminRole;\r
import com.gitblit.wicket.StringChoiceRenderer;\r
import com.gitblit.wicket.WicketUtils;\r
+import com.gitblit.wicket.panels.RepositoryPermissionsPanel;\r
\r
@RequiresAdminRole\r
public class EditUserPage extends RootSubPage {\r
\r
private final boolean isCreate;\r
-\r
+ \r
public EditUserPage() {\r
// create constructor\r
super();\r
}\r
isCreate = true;\r
setupPage(new UserModel(""));\r
+ setStatelessHint(false);\r
}\r
\r
public EditUserPage(PageParameters params) {\r
String name = WicketUtils.getUsername(params);\r
UserModel model = GitBlit.self().getUserModel(name);\r
setupPage(model);\r
+ setStatelessHint(false);\r
}\r
\r
protected void setupPage(final UserModel userModel) {\r
Collections.sort(userTeams);\r
\r
final String oldName = userModel.username;\r
- final Palette<String> repositories = new Palette<String>("repositories",\r
- new ListModel<String>(new ArrayList<String>(userModel.repositories)),\r
- new CollectionModel<String>(repos), new StringChoiceRenderer(), 10, false);\r
+ final List<RepositoryAccessPermission> permissions = userModel.getRepositoryPermissions();\r
+\r
final Palette<String> teams = new Palette<String>("teams", new ListModel<String>(\r
new ArrayList<String>(userTeams)), new CollectionModel<String>(GitBlit.self()\r
.getAllTeamnames()), new StringChoiceRenderer(), 10, false);\r
Form<UserModel> form = new Form<UserModel>("editForm", model) {\r
\r
private static final long serialVersionUID = 1L;\r
-\r
+ \r
/*\r
* (non-Javadoc)\r
* \r
}\r
}\r
\r
- Iterator<String> selectedRepositories = repositories.getSelectedChoices();\r
- List<String> repos = new ArrayList<String>();\r
- while (selectedRepositories.hasNext()) {\r
- repos.add(selectedRepositories.next().toLowerCase());\r
+ // update user permissions\r
+ for (RepositoryAccessPermission repositoryPermission : permissions) {\r
+ userModel.setRepositoryPermission(repositoryPermission.repository, repositoryPermission.permission);\r
}\r
- userModel.repositories.clear();\r
- userModel.repositories.addAll(repos);\r
\r
Iterator<String> selectedTeams = teams.getSelectedChoices();\r
userModel.teams.clear();\r
form.add(new CheckBox("canFork"));\r
form.add(new CheckBox("canCreate"));\r
form.add(new CheckBox("excludeFromFederation"));\r
- form.add(repositories);\r
+ form.add(new RepositoryPermissionsPanel("repositories", permissions, getAccessPermissions()));\r
form.add(teams.setEnabled(editTeams));\r
\r
form.add(new Button("save"));\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" \r
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" \r
+ xml:lang="en" \r
+ lang="en"> \r
+\r
+<body>\r
+<wicket:panel>\r
+\r
+ <div wicket:id="permissionRow">\r
+ <div style="padding-top:10px" class="row-fluid">\r
+ <span class="span8" wicket:id="repository"></span> <select class="input-medium" wicket:id="permission"></select>\r
+ </div>\r
+ </div>\r
+\r
+ <div style="padding-top:15px;" class="row-fluid">\r
+ <form class="well form-inline" wicket:id="addPermissionForm">\r
+ <select class="input-large" wicket:id="repository"></select> <select class="input-medium" wicket:id="permission"></select> <input class="btn btn-success" type="submit" value="Add" wicket:message="value:gb.add" wicket:id="addPermissionButton"/>\r
+ </form>\r
+ </div> \r
+ \r
+</wicket:panel>\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2012 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.panels;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.OddEvenItem;
+import org.apache.wicket.markup.repeater.RefreshingView;
+import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+
+import com.gitblit.Constants.AccessPermission;
+import com.gitblit.GitBlit;
+import com.gitblit.models.RepositoryAccessPermission;
+import com.gitblit.utils.DeepCopier;
+
+/**
+ * Allows user to manipulate repository access permissions.
+ *
+ * @author James Moger
+ *
+ */
+public class RepositoryPermissionsPanel extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ public RepositoryPermissionsPanel(String wicketId, final List<RepositoryAccessPermission> permissions, final Map<AccessPermission, String> translations) {
+ super(wicketId);
+
+ // update existing permissions repeater
+ RefreshingView<RepositoryAccessPermission> dataView = new RefreshingView<RepositoryAccessPermission>("permissionRow") {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected Iterator<IModel<RepositoryAccessPermission>> getItemModels() {
+ // the iterator returns RepositoryPermission objects, but we need it to
+ // return models
+ return new ModelIteratorAdapter<RepositoryAccessPermission>(permissions.iterator()) {
+ @Override
+ protected IModel<RepositoryAccessPermission> model(RepositoryAccessPermission permission) {
+ return new CompoundPropertyModel<RepositoryAccessPermission>(permission);
+ }
+ };
+ }
+
+ @Override
+ protected Item<RepositoryAccessPermission> newItem(String id, int index, IModel<RepositoryAccessPermission> model) {
+ // this item sets markup class attribute to either 'odd' or
+ // 'even' for decoration
+ return new OddEvenItem<RepositoryAccessPermission>(id, index, model);
+ }
+
+ public void populateItem(final Item<RepositoryAccessPermission> item) {
+ final RepositoryAccessPermission entry = item.getModelObject();
+ item.add(new Label("repository", entry.repository));
+
+ // use ajax to get immediate update of permission level change
+ // otherwise we can lose it if they change levels and then add
+ // a new repository permission
+ final DropDownChoice<AccessPermission> permissionChoice = new DropDownChoice<AccessPermission>(
+ "permission", Arrays.asList(AccessPermission.values()), new AccessPermissionRenderer(translations));
+ permissionChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
+
+ private static final long serialVersionUID = 1L;
+
+ protected void onUpdate(AjaxRequestTarget target) {
+ target.addComponent(permissionChoice);
+ }
+ });
+
+ item.add(permissionChoice);
+ }
+ };
+ add(dataView);
+ setOutputMarkupId(true);
+
+ // filter out repositories we already have permissions for
+ final List<String> repositories = GitBlit.self().getRepositoryList();
+ for (RepositoryAccessPermission rp : permissions) {
+ repositories.remove(rp.repository);
+ }
+
+ // add new permission form
+ IModel<RepositoryAccessPermission> addPermissionModel = new CompoundPropertyModel<RepositoryAccessPermission>(new RepositoryAccessPermission());
+ Form<RepositoryAccessPermission> addPermissionForm = new Form<RepositoryAccessPermission>("addPermissionForm", addPermissionModel);
+ addPermissionForm.add(new DropDownChoice<String>("repository", repositories));
+ addPermissionForm.add(new DropDownChoice<AccessPermission>("permission", Arrays
+ .asList(AccessPermission.NEWPERMISSIONS), new AccessPermissionRenderer(translations)));
+ AjaxButton button = new AjaxButton("addPermissionButton", addPermissionForm) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
+ // add permission to our list
+ RepositoryAccessPermission rp = (RepositoryAccessPermission) form.getModel().getObject();
+ permissions.add(DeepCopier.copy(rp));
+
+ // remove repository from available choices
+ repositories.remove(rp.repository);
+
+ // force the panel to refresh
+ target.addComponent(RepositoryPermissionsPanel.this);
+ }
+ };
+ addPermissionForm.add(button);
+
+ // only show add permission form if we have a repository choice
+ add(addPermissionForm.setVisible(repositories.size() > 0));
+ }
+
+ private class AccessPermissionRenderer implements IChoiceRenderer<AccessPermission> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Map<AccessPermission, String> map;
+
+ public AccessPermissionRenderer(Map<AccessPermission, String> map) {
+ this.map = map;
+ }
+
+ @Override
+ public String getDisplayValue(AccessPermission type) {
+ return map.get(type);
+ }
+
+ @Override
+ public String getIdValue(AccessPermission type, int index) {
+ return Integer.toString(index);
+ }
+ }
+}