Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

RegistrantPermissionsPanel.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. * Copyright 2012 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. */
  16. package com.gitblit.wicket.panels;
  17. import java.text.MessageFormat;
  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.Collections;
  21. import java.util.Iterator;
  22. import java.util.List;
  23. import java.util.Map;
  24. import org.apache.wicket.Component;
  25. import org.apache.wicket.ajax.AjaxRequestTarget;
  26. import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
  27. import org.apache.wicket.ajax.markup.html.form.AjaxButton;
  28. import org.apache.wicket.markup.html.basic.Label;
  29. import org.apache.wicket.markup.html.form.DropDownChoice;
  30. import org.apache.wicket.markup.html.form.Form;
  31. import org.apache.wicket.markup.html.form.IChoiceRenderer;
  32. import org.apache.wicket.markup.html.panel.Fragment;
  33. import org.apache.wicket.markup.repeater.Item;
  34. import org.apache.wicket.markup.repeater.OddEvenItem;
  35. import org.apache.wicket.markup.repeater.RefreshingView;
  36. import org.apache.wicket.markup.repeater.util.ModelIteratorAdapter;
  37. import org.apache.wicket.model.CompoundPropertyModel;
  38. import org.apache.wicket.model.IModel;
  39. import org.eclipse.jgit.lib.PersonIdent;
  40. import com.gitblit.Constants.AccessPermission;
  41. import com.gitblit.Constants.PermissionType;
  42. import com.gitblit.Constants.RegistrantType;
  43. import com.gitblit.models.RegistrantAccessPermission;
  44. import com.gitblit.models.UserModel;
  45. import com.gitblit.utils.DeepCopier;
  46. import com.gitblit.utils.StringUtils;
  47. import com.gitblit.wicket.WicketUtils;
  48. /**
  49. * Allows user to manipulate registrant access permissions.
  50. *
  51. * @author James Moger
  52. *
  53. */
  54. public class RegistrantPermissionsPanel extends BasePanel {
  55. private static final long serialVersionUID = 1L;
  56. public enum Show {
  57. specified, mutable, effective;
  58. public boolean show(RegistrantAccessPermission ap) {
  59. switch (this) {
  60. case specified:
  61. return ap.mutable || ap.isOwner();
  62. case mutable:
  63. return ap.mutable;
  64. case effective:
  65. return true;
  66. default:
  67. return true;
  68. }
  69. }
  70. }
  71. private Show activeState = Show.mutable;
  72. public RegistrantPermissionsPanel(String wicketId, RegistrantType registrantType, List<String> allRegistrants, final List<RegistrantAccessPermission> permissions, final Map<AccessPermission, String> translations) {
  73. super(wicketId);
  74. setOutputMarkupId(true);
  75. /*
  76. * Permission view toggle buttons
  77. */
  78. Form<Void> permissionToggleForm = new Form<Void>("permissionToggleForm");
  79. permissionToggleForm.add(new ShowStateButton("showSpecified", Show.specified));
  80. permissionToggleForm.add(new ShowStateButton("showMutable", Show.mutable));
  81. permissionToggleForm.add(new ShowStateButton("showEffective", Show.effective));
  82. add(permissionToggleForm);
  83. /*
  84. * Permission repeating display
  85. */
  86. RefreshingView<RegistrantAccessPermission> dataView = new RefreshingView<RegistrantAccessPermission>("permissionRow") {
  87. private static final long serialVersionUID = 1L;
  88. @Override
  89. protected Iterator<IModel<RegistrantAccessPermission>> getItemModels() {
  90. // the iterator returns RepositoryPermission objects, but we need it to
  91. // return models
  92. return new ModelIteratorAdapter<RegistrantAccessPermission>(permissions.iterator()) {
  93. @Override
  94. protected IModel<RegistrantAccessPermission> model(RegistrantAccessPermission permission) {
  95. return new CompoundPropertyModel<RegistrantAccessPermission>(permission);
  96. }
  97. };
  98. }
  99. @Override
  100. protected Item<RegistrantAccessPermission> newItem(String id, int index, IModel<RegistrantAccessPermission> model) {
  101. // this item sets markup class attribute to either 'odd' or
  102. // 'even' for decoration
  103. return new OddEvenItem<RegistrantAccessPermission>(id, index, model);
  104. }
  105. @Override
  106. public void populateItem(final Item<RegistrantAccessPermission> item) {
  107. final RegistrantAccessPermission entry = item.getModelObject();
  108. if (RegistrantType.REPOSITORY.equals(entry.registrantType)) {
  109. String repoName = StringUtils.stripDotGit(entry.registrant);
  110. if (!entry.isMissing() && StringUtils.findInvalidCharacter(repoName) == null) {
  111. // repository, strip .git and show swatch
  112. Fragment repositoryFragment = new Fragment("registrant", "repositoryRegistrant", RegistrantPermissionsPanel.this);
  113. Component swatch = new Label("repositorySwatch", "&nbsp;").setEscapeModelStrings(false);
  114. WicketUtils.setCssBackground(swatch, entry.toString());
  115. repositoryFragment.add(swatch);
  116. Label registrant = new Label("repositoryName", repoName);
  117. repositoryFragment.add(registrant);
  118. item.add(repositoryFragment);
  119. } else {
  120. // regex or missing
  121. Label label = new Label("registrant", entry.registrant);
  122. WicketUtils.setCssStyle(label, "font-weight: bold;");
  123. item.add(label);
  124. }
  125. } else if (RegistrantType.USER.equals(entry.registrantType)) {
  126. // user
  127. PersonIdent ident = new PersonIdent(entry.registrant, "");
  128. UserModel user = app().users().getUserModel(entry.registrant);
  129. if (user != null) {
  130. ident = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress);
  131. }
  132. Fragment userFragment = new Fragment("registrant", "userRegistrant", RegistrantPermissionsPanel.this);
  133. userFragment.add(new GravatarImage("userAvatar", ident, 20));
  134. userFragment.add(new Label("userName", entry.registrant));
  135. item.add(userFragment);
  136. } else {
  137. // team
  138. Fragment teamFragment = new Fragment("registrant", "teamRegistrant", RegistrantPermissionsPanel.this);
  139. teamFragment.add(new Label("teamName", entry.registrant));
  140. item.add(teamFragment);
  141. }
  142. switch (entry.permissionType) {
  143. case ADMINISTRATOR:
  144. Label administrator = new Label("pType", entry.source == null ? getString("gb.administrator") : entry.source);
  145. WicketUtils.setHtmlTooltip(administrator, getString("gb.administratorPermission"));
  146. WicketUtils.setCssClass(administrator, "label label-inverse");
  147. item.add(administrator);
  148. break;
  149. case OWNER:
  150. Label owner = new Label("pType", getString("gb.owner"));
  151. WicketUtils.setHtmlTooltip(owner, getString("gb.ownerPermission"));
  152. WicketUtils.setCssClass(owner, "label label-info");
  153. item.add(owner);
  154. break;
  155. case TEAM:
  156. Label team = new Label("pType", entry.source == null ? getString("gb.team") : entry.source);
  157. WicketUtils.setHtmlTooltip(team, MessageFormat.format(getString("gb.teamPermission"), entry.source));
  158. WicketUtils.setCssClass(team, "label label-success");
  159. item.add(team);
  160. break;
  161. case REGEX:
  162. Label regex = new Label("pType", "regex");
  163. if (!StringUtils.isEmpty(entry.source)) {
  164. WicketUtils.setHtmlTooltip(regex, MessageFormat.format(getString("gb.regexPermission"), entry.source));
  165. }
  166. WicketUtils.setCssClass(regex, "label");
  167. item.add(regex);
  168. break;
  169. default:
  170. if (entry.isMissing()) {
  171. // repository is missing, this permission will be removed on save
  172. Label missing = new Label("pType", getString("gb.missing"));
  173. WicketUtils.setCssClass(missing, "label label-important");
  174. WicketUtils.setHtmlTooltip(missing, getString("gb.missingPermission"));
  175. item.add(missing);
  176. } else {
  177. // standard permission
  178. item.add(new Label("pType", "").setVisible(false));
  179. }
  180. break;
  181. }
  182. item.setVisible(activeState.show(entry));
  183. // use ajax to get immediate update of permission level change
  184. // otherwise we can lose it if they change levels and then add
  185. // a new repository permission
  186. final DropDownChoice<AccessPermission> permissionChoice = new DropDownChoice<AccessPermission>(
  187. "permission", Arrays.asList(AccessPermission.values()), new AccessPermissionRenderer(translations));
  188. // only allow changing an explicitly defined permission
  189. // this is designed to prevent changing a regex permission in
  190. // a repository
  191. permissionChoice.setEnabled(entry.mutable);
  192. permissionChoice.setOutputMarkupId(true);
  193. if (entry.mutable) {
  194. permissionChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
  195. private static final long serialVersionUID = 1L;
  196. @Override
  197. protected void onUpdate(AjaxRequestTarget target) {
  198. target.addComponent(permissionChoice);
  199. }
  200. });
  201. }
  202. item.add(permissionChoice);
  203. }
  204. };
  205. add(dataView);
  206. setOutputMarkupId(true);
  207. // filter out registrants we already have permissions for
  208. final List<String> registrants = new ArrayList<String>(allRegistrants);
  209. for (RegistrantAccessPermission rp : permissions) {
  210. if (rp.mutable) {
  211. // remove editable duplicates
  212. // this allows for specifying an explicit permission
  213. registrants.remove(rp.registrant);
  214. } else if (rp.isAdmin()) {
  215. // administrators can not have their permission changed
  216. registrants.remove(rp.registrant);
  217. } else if (rp.isOwner()) {
  218. // owners can not have their permission changed
  219. registrants.remove(rp.registrant);
  220. }
  221. }
  222. /*
  223. * Add permission form
  224. */
  225. IModel<RegistrantAccessPermission> addPermissionModel = new CompoundPropertyModel<RegistrantAccessPermission>(new RegistrantAccessPermission(registrantType));
  226. Form<RegistrantAccessPermission> addPermissionForm = new Form<RegistrantAccessPermission>("addPermissionForm", addPermissionModel);
  227. addPermissionForm.add(new DropDownChoice<String>("registrant", registrants));
  228. addPermissionForm.add(new DropDownChoice<AccessPermission>("permission", Arrays
  229. .asList(AccessPermission.NEWPERMISSIONS), new AccessPermissionRenderer(translations)));
  230. AjaxButton button = new AjaxButton("addPermissionButton", addPermissionForm) {
  231. private static final long serialVersionUID = 1L;
  232. @Override
  233. protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
  234. // add permission to our list
  235. RegistrantAccessPermission rp = (RegistrantAccessPermission) form.getModel().getObject();
  236. if (rp.permission == null) {
  237. return;
  238. }
  239. if (rp.registrant == null) {
  240. return;
  241. }
  242. RegistrantAccessPermission copy = DeepCopier.copy(rp);
  243. if (StringUtils.findInvalidCharacter(copy.registrant) != null) {
  244. copy.permissionType = PermissionType.REGEX;
  245. copy.source = copy.registrant;
  246. }
  247. permissions.add(copy);
  248. // resort permissions after insert to convey idea of eval order
  249. Collections.sort(permissions);
  250. // remove registrant from available choices
  251. registrants.remove(rp.registrant);
  252. // force the panel to refresh
  253. target.addComponent(RegistrantPermissionsPanel.this);
  254. }
  255. };
  256. addPermissionForm.add(button);
  257. // only show add permission form if we have a registrant choice
  258. add(addPermissionForm.setVisible(registrants.size() > 0));
  259. }
  260. @Override
  261. protected boolean getStatelessHint()
  262. {
  263. return false;
  264. }
  265. private class AccessPermissionRenderer implements IChoiceRenderer<AccessPermission> {
  266. private static final long serialVersionUID = 1L;
  267. private final Map<AccessPermission, String> map;
  268. public AccessPermissionRenderer(Map<AccessPermission, String> map) {
  269. this.map = map;
  270. }
  271. @Override
  272. public String getDisplayValue(AccessPermission type) {
  273. return map.get(type);
  274. }
  275. @Override
  276. public String getIdValue(AccessPermission type, int index) {
  277. return Integer.toString(index);
  278. }
  279. }
  280. private class ShowStateButton extends AjaxButton {
  281. private static final long serialVersionUID = 1L;
  282. Show buttonState;
  283. public ShowStateButton(String wicketId, Show state) {
  284. super(wicketId);
  285. this.buttonState = state;
  286. setOutputMarkupId(true);
  287. }
  288. @Override
  289. protected void onBeforeRender()
  290. {
  291. String cssClass = "btn";
  292. if (buttonState.equals(RegistrantPermissionsPanel.this.activeState)) {
  293. cssClass = "btn btn-info active";
  294. }
  295. WicketUtils.setCssClass(this, cssClass);
  296. super.onBeforeRender();
  297. }
  298. @Override
  299. protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
  300. RegistrantPermissionsPanel.this.activeState = buttonState;
  301. target.addComponent(RegistrantPermissionsPanel.this);
  302. }
  303. };
  304. }