src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -686,16 +686,18 @@ gb.plugins = plugins gb.extensions = extensions gb.pleaseSelectProject = Please select the project! gb.anonymousPush = Anonymous Pushes gb.anonymousPushDescription = Anyone can see, clone, and push to this repository. gb.pushRestrictedAuthenticated = Restrict Pushes (Authenticated) gb.pushRestrictedAuthenticatedDescription = Anyone can see and clone this repository. All authenticated users can push. gb.pushRestrictedNamed = Restrict Pushes (Named) gb.pushRestrictedNamedDescription = Anyone can see and clone this repository. You choose who can push. gb.cloneRestricted = Restrict Clones & Pushes gb.cloneRestrictedDescription = Anyone can see this repository. You choose who can clone and push. gb.private = Private gb.privateRepoDescription = You choose who can see, clone, and push to this repository. gb.accessPolicy = Access Policy gb.accessPolicyDescription = Choose an access policy to control visibility, cloning, and pushing to this repository. gb.anonymousPolicy = Anonymous View, Clone, & Push gb.anonymousPolicyDescription = Anyone can see, clone, and push to this repository. gb.authenticatedPushPolicy = Restrict Push (Authenticated) gb.authenticatedPushPolicyDescription = Anyone can see and clone this repository. All authenticated users have RW+ push permission. gb.namedPushPolicy = Restrict Push (Named) gb.namedPushPolicyDescription = Anyone can see and clone this repository. You choose who can push. gb.clonePolicy = Restrict Clone & Push gb.clonePolicyDescription = Anyone can see this repository. You choose who can clone and push. gb.viewPolicy = Restrict View, Clone, & Push gb.viewPolicyDescription = You choose who can see, clone, and push to this repository. gb.initialCommit = Initial Commit gb.initialCommitDescription = This will allow you to <code>git clone</code> this repository immediately. Skip this step if you have already run <code>git init</code> locally. gb.initWithReadme = Include a README src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.html
@@ -24,10 +24,10 @@ <!-- general tab --> <div class="tab-pane active" id="general"> <div wicket:id="namePanel"></div> <table class="plain"> <tbody class="settings"> <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input class="span4" type="text" wicket:id="name" id="name" size="40" tabindex="1" /> <span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td></tr> <tr><th><wicket:message key="gb.description"></wicket:message></th><td class="edit"><input class="span4" type="text" wicket:id="description" size="40" tabindex="2" /></td></tr> <tr><th colspan="2"><hr/></th></tr> <tr><th><wicket:message key="gb.origin"></wicket:message></th><td class="edit"><input class="span5" type="text" wicket:id="origin" size="80" tabindex="3" /></td></tr> <tr><th><wicket:message key="gb.headRef"></wicket:message></th><td class="edit"><select class="span3" wicket:id="HEAD" tabindex="4" /> <span class="help-inline"><wicket:message key="gb.headRefDescription"></wicket:message></span></td></tr> src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java
@@ -72,10 +72,13 @@ import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; import com.gitblit.wicket.panels.BulletListPanel; import com.gitblit.wicket.panels.RegistrantPermissionsPanel; import com.gitblit.wicket.panels.RepositoryNamePanel; public class EditRepositoryPage extends RootSubPage { private final boolean isCreate; RepositoryNamePanel namePanel; private boolean isAdmin; @@ -263,59 +266,8 @@ @Override protected void onSubmit() { try { // confirm a repository name was entered if (repositoryModel.name == null && StringUtils.isEmpty(repositoryModel.name)) { error(getString("gb.pleaseSetRepositoryName")); if (!namePanel.updateModel(repositoryModel)) { return; } // ensure name is trimmed repositoryModel.name = repositoryModel.name.trim(); // automatically convert backslashes to forward slashes repositoryModel.name = repositoryModel.name.replace('\\', '/'); // Automatically replace // with / repositoryModel.name = repositoryModel.name.replace("//", "/"); // prohibit folder paths if (repositoryModel.name.startsWith("/")) { error(getString("gb.illegalLeadingSlash")); return; } if (repositoryModel.name.startsWith("../")) { error(getString("gb.illegalRelativeSlash")); return; } if (repositoryModel.name.contains("/../")) { error(getString("gb.illegalRelativeSlash")); return; } if (repositoryModel.name.endsWith("/")) { repositoryModel.name = repositoryModel.name.substring(0, repositoryModel.name.length() - 1); } // confirm valid characters in repository name Character c = StringUtils.findInvalidCharacter(repositoryModel.name); if (c != null) { error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"), c)); return; } if (user.canCreate() && !user.canAdmin() && allowEditName) { // ensure repository name begins with the user's path if (!repositoryModel.name.startsWith(user.getPersonalPath())) { error(MessageFormat.format(getString("gb.illegalPersonalRepositoryLocation"), user.getPersonalPath())); return; } if (repositoryModel.name.equals(user.getPersonalPath())) { // reset path prefix and show error repositoryModel.name = user.getPersonalPath() + "/"; error(getString("gb.pleaseSetRepositoryName")); return; } } // confirm access restriction selection @@ -426,6 +378,7 @@ } } catch (GitBlitException e) { error(e.getMessage()); namePanel.resetModel(repositoryModel); return; } setRedirect(false); @@ -437,8 +390,10 @@ form.add(new SimpleAttributeModifier("autocomplete", "off")); // field names reflective match RepositoryModel fields form.add(new TextField<String>("name").setEnabled(allowEditName)); form.add(new TextField<String>("description")); namePanel = new RepositoryNamePanel("namePanel", repositoryModel); namePanel.setEditable(allowEditName); form.add(namePanel); form.add(ownersPalette); form.add(new CheckBox("allowForks").setEnabled(app().settings().getBoolean(Keys.web.allowForking, true))); DropDownChoice<AccessRestrictionType> accessRestriction = new DropDownChoice<AccessRestrictionType>("accessRestriction", src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html
@@ -12,11 +12,6 @@ <div wicket:id="namePanel"></div> <div> <b><wicket:message key="gb.description"></wicket:message></b><br/> <input class="span6" type="text" wicket:id="description" /> </div> <hr/> <div wicket:id="permissionPanel"></div> src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java
@@ -29,7 +29,6 @@ import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice; 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.IModel; import org.apache.wicket.model.Model; @@ -61,7 +60,7 @@ import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.RepositoryNamePanel; import com.gitblit.wicket.panels.RepositoryPermissionPanel; import com.gitblit.wicket.panels.AccessPolicyPanel; public class NewRepositoryPage extends RootSubPage { @@ -70,7 +69,7 @@ private Model<String> gitignoreModel; private IModel<Boolean> addGitflowModel; private IModel<Boolean> addGitignoreModel; private RepositoryPermissionPanel permissionPanel; private AccessPolicyPanel permissionPanel; private RepositoryNamePanel namePanel; public NewRepositoryPage() { @@ -159,8 +158,6 @@ namePanel = new RepositoryNamePanel("namePanel", repositoryModel); form.add(namePanel); form.add(new TextField<String>("description")); // prepare the default access controls AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName( app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name())); @@ -177,7 +174,7 @@ repositoryModel.authorizationControl = defaultControl; repositoryModel.accessRestriction = defaultRestriction; permissionPanel = new RepositoryPermissionPanel("permissionPanel", repositoryModel); permissionPanel = new AccessPolicyPanel("permissionPanel", repositoryModel); form.add(permissionPanel); // src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html
File was renamed from src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.html @@ -7,8 +7,11 @@ <body> <wicket:panel> <span wicket:id="permissionsGroup"> <div wicket:id="permissions"> <h4><wicket:message key="gb.accessPolicy"></wicket:message></h4> <p><wicket:message key="gb.accessPolicyDescription"></wicket:message></p> <span wicket:id="policiesGroup"> <div wicket:id="policies"> <div style="display: inline-block;vertical-align: top;"> <input type="radio" wicket:id="radio" /> <img wicket:id="image"></img> src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.java
File was renamed from src/main/java/com/gitblit/wicket/panels/RepositoryPermissionPanel.java @@ -38,15 +38,15 @@ * @author James Moger * */ public class RepositoryPermissionPanel extends BasePanel { public class AccessPolicyPanel extends BasePanel { private static final long serialVersionUID = 1L; private final RepositoryModel repository; private RadioGroup<Permission> permissionGroup; private RadioGroup<AccessPolicy> policiesGroup; public RepositoryPermissionPanel(String wicketId, RepositoryModel repository) { public AccessPolicyPanel(String wicketId, RepositoryModel repository) { super(wicketId); this.repository = repository; } @@ -55,44 +55,44 @@ protected void onInitialize() { super.onInitialize(); Permission anonymousPermission = new Permission(getString("gb.anonymousPush"), getString("gb.anonymousPushDescription"), AccessPolicy anonymousPolicy = new AccessPolicy(getString("gb.anonymousPolicy"), getString("gb.anonymousPolicyDescription"), "blank.png", AuthorizationControl.AUTHENTICATED, AccessRestrictionType.NONE); Permission authenticatedPermission = new Permission(getString("gb.pushRestrictedAuthenticated"), getString("gb.pushRestrictedAuthenticatedDescription"), AccessPolicy authenticatedPushPolicy = new AccessPolicy(getString("gb.authenticatedPushPolicy"), getString("gb.authenticatedPushPolicyDescription"), "lock_go_16x16.png", AuthorizationControl.AUTHENTICATED, AccessRestrictionType.PUSH); Permission publicPermission = new Permission(getString("gb.pushRestrictedNamed"), getString("gb.pushRestrictedNamedDescription"), AccessPolicy namedPushPolicy = new AccessPolicy(getString("gb.namedPushPolicy"), getString("gb.namedPushPolicyDescription"), "lock_go_16x16.png", AuthorizationControl.NAMED, AccessRestrictionType.PUSH); Permission protectedPermission = new Permission(getString("gb.cloneRestricted"), getString("gb.cloneRestrictedDescription"), AccessPolicy clonePolicy = new AccessPolicy(getString("gb.clonePolicy"), getString("gb.clonePolicyDescription"), "lock_pull_16x16.png", AuthorizationControl.NAMED, AccessRestrictionType.CLONE); Permission privatePermission = new Permission(getString("gb.private"), getString("gb.privateRepoDescription"), AccessPolicy viewPolicy = new AccessPolicy(getString("gb.viewPolicy"), getString("gb.viewPolicyDescription"), "shield_16x16.png", AuthorizationControl.NAMED, AccessRestrictionType.VIEW); List<Permission> permissions = new ArrayList<Permission>(); List<AccessPolicy> policies = new ArrayList<AccessPolicy>(); if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) { permissions.add(anonymousPermission); policies.add(anonymousPolicy); } permissions.add(authenticatedPermission); permissions.add(publicPermission); permissions.add(protectedPermission); permissions.add(privatePermission); policies.add(authenticatedPushPolicy); policies.add(namedPushPolicy); policies.add(clonePolicy); policies.add(viewPolicy); AccessRestrictionType defaultRestriction = repository.accessRestriction; if (defaultRestriction == null) { @@ -106,38 +106,38 @@ AuthorizationControl.NAMED.name())); } Permission defaultPermission = publicPermission; for (Permission permission : permissions) { if (permission.type == defaultRestriction && permission.control == defaultControl) { defaultPermission = permission; AccessPolicy defaultPolicy = namedPushPolicy; for (AccessPolicy policy : policies) { if (policy.type == defaultRestriction && policy.control == defaultControl) { defaultPolicy = policy; } } permissionGroup = new RadioGroup<>("permissionsGroup", new Model<Permission>(defaultPermission)); ListView<Permission> permissionsList = new ListView<Permission>("permissions", permissions) { policiesGroup = new RadioGroup<>("policiesGroup", new Model<AccessPolicy>(defaultPolicy)); ListView<AccessPolicy> policiesList = new ListView<AccessPolicy>("policies", policies) { private static final long serialVersionUID = 1L; @Override protected void populateItem(ListItem<Permission> item) { Permission p = item.getModelObject(); item.add(new Radio<Permission>("radio", item.getModel())); protected void populateItem(ListItem<AccessPolicy> item) { AccessPolicy p = item.getModelObject(); item.add(new Radio<AccessPolicy>("radio", item.getModel())); item.add(WicketUtils.newImage("image", p.image)); item.add(new Label("name", p.name)); item.add(new Label("description", p.description)); } }; permissionGroup.add(permissionsList); policiesGroup.add(policiesList); setOutputMarkupId(true); add(permissionGroup); add(policiesGroup); } public void updateModel(RepositoryModel repository) { Permission permission = permissionGroup.getModelObject(); repository.authorizationControl = permission.control; repository.accessRestriction = permission.type; AccessPolicy policy = policiesGroup.getModelObject(); repository.authorizationControl = policy.control; repository.accessRestriction = policy.type; } @Override @@ -145,7 +145,7 @@ return false; } private static class Permission implements Serializable { private static class AccessPolicy implements Serializable { private static final long serialVersionUID = 1L; @@ -155,7 +155,7 @@ final AuthorizationControl control; final AccessRestrictionType type; Permission(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { AccessPolicy(String name, String description, String img, AuthorizationControl control, AccessRestrictionType type) { this.name = name; this.description = description; this.image = img; src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.html
@@ -11,17 +11,20 @@ <tbody class="settings"> <tr> <th><wicket:message key="gb.project"></wicket:message></th> <td></td> <th><wicket:message key="gb.name"></wicket:message></th> </tr> <tr> <td><select class="span2" wicket:id="projectPath" /></td> <td style="font-size:24px;color:#ccc;">/</td> <td class="edit"><input class="span3" type="text" wicket:id="name" id="name" /> <span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td> </tr> </tbody> </table> <div> <b><wicket:message key="gb.description"></wicket:message></b><br/> <input class="span5" type="text" wicket:id="description" /> </div> </wicket:panel> </body> </html> src/main/java/com/gitblit/wicket/panels/RepositoryNamePanel.java
@@ -17,18 +17,20 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.TextField; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; /** * A radio group panel of the 5 available authorization/access restriction combinations. * A panel for naming a repository, specifying it's project, and entering a description. * * @author James Moger * @@ -37,44 +39,79 @@ private static final long serialVersionUID = 1L; private final RepositoryModel repository; private String fullName; private DropDownChoice<String> projectChoice; private TextField<String> nameField; public RepositoryNamePanel(String wicketId, RepositoryModel repository) { super(wicketId); this.repository = repository; } @Override protected void onInitialize() { super.onInitialize(); GitBlitWebSession session = GitBlitWebSession.get(); UserModel user = session.getUser(); // build project list for repository destination // build project set for repository destination String defaultProject = null; List<String> projects = new ArrayList<String>(); Set<String> projectNames = new TreeSet<String>(); // add the registered/known projects for (ProjectModel project : app().projects().getProjectModels(user, false)) { // TODO issue-351: user.canAdmin(project) if (user.canAdmin()) { projects.add("/"); if (project.isRoot) { projectNames.add("/"); } else { projectNames.add(project.name + "/"); } } } // add the user's personal project namespace if (user.canAdmin() || user.canCreate()) { projectNames.add(user.getPersonalPath() + "/"); } if (!StringUtils.isEmpty(repository.name)) { // editing a repository name // set the defaultProject to the current repository project defaultProject = repository.projectPath; if (StringUtils.isEmpty(defaultProject)) { defaultProject = "/"; } else { defaultProject += "/"; } if (user.canCreate()) { String p = user.getPersonalPath() + "/"; projects.add(p); projectNames.add(defaultProject); } // if default project is not already set, set preference based on the user permissions if (defaultProject == null) { // only prefer personal namespace if default is not already set defaultProject = p; if (user.canAdmin()) { defaultProject = "/"; } else if (user.canCreate()) { defaultProject = user.getPersonalPath() + "/"; } } // update the model which is reflectively mapped to the Wicket fields by name repository.projectPath = defaultProject; if (repository.projectPath.length() > 1 && !StringUtils.isEmpty(repository.name)) { repository.name = repository.name.substring(repository.projectPath.length()); } projectChoice = new DropDownChoice<String>("projectPath", new ArrayList<String>(projectNames)); nameField = new TextField<String>("name"); add(new DropDownChoice<String>("projectPath", projects)); add(new TextField<String>("name")); // only enable project selection if we actually have multiple choices add(projectChoice.setEnabled(projectNames.size() > 1)); add(nameField); add(new TextField<String>("description")); } public void setEditable(boolean editable) { // only enable project selection if we actually have multiple choices projectChoice.setEnabled(projectChoice.getChoices().size() > 1 && editable); nameField.setEnabled(editable); } public boolean updateModel(RepositoryModel repositoryModel) {