From 05f229883c4e15e044c5c103acf69265cfb8806e Mon Sep 17 00:00:00 2001 From: James Moger Date: Thu, 5 Jun 2014 08:38:35 -0400 Subject: [PATCH] Add a basic SSH public key management UI --- src/main/java/com/gitblit/GitBlit.java | 15 ++ .../com/gitblit/manager/GitblitManager.java | 15 ++ .../com/gitblit/manager/IRuntimeManager.java | 27 +++ .../com/gitblit/manager/RuntimeManager.java | 39 ++++- .../com/gitblit/manager/ServicesManager.java | 18 +- .../gitblit/wicket/GitBlitWebApp.properties | 10 +- .../com/gitblit/wicket/pages/UserPage.html | 14 ++ .../com/gitblit/wicket/pages/UserPage.java | 22 +++ .../gitblit/wicket/panels/SshKeysPanel.html | 46 +++++ .../gitblit/wicket/panels/SshKeysPanel.java | 161 ++++++++++++++++++ .../gitblit/wicket/panels/TextAreaOption.html | 20 +++ .../gitblit/wicket/panels/TextAreaOption.java | 54 ++++++ .../tests/mock/MockRuntimeManager.java | 15 ++ 13 files changed, 449 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html create mode 100644 src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java create mode 100644 src/main/java/com/gitblit/wicket/panels/TextAreaOption.html create mode 100644 src/main/java/com/gitblit/wicket/panels/TextAreaOption.java diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index 3db5f087..81793850 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -117,6 +117,21 @@ public class GitBlit extends GitblitManager { return servicesManager.isServingRepositories(); } + @Override + public boolean isServingHTTP() { + return servicesManager.isServingHTTP(); + } + + @Override + public boolean isServingGIT() { + return servicesManager.isServingGIT(); + } + + @Override + public boolean isServingSSH() { + return servicesManager.isServingSSH(); + } + protected Object [] getModules() { return new Object [] { new GitBlitModule()}; } diff --git a/src/main/java/com/gitblit/manager/GitblitManager.java b/src/main/java/com/gitblit/manager/GitblitManager.java index 16c71ba6..ef2433dd 100644 --- a/src/main/java/com/gitblit/manager/GitblitManager.java +++ b/src/main/java/com/gitblit/manager/GitblitManager.java @@ -601,6 +601,21 @@ public class GitblitManager implements IGitblit { return runtimeManager.isServingRepositories(); } + @Override + public boolean isServingHTTP() { + return runtimeManager.isServingHTTP(); + } + + @Override + public boolean isServingGIT() { + return runtimeManager.isServingGIT(); + } + + @Override + public boolean isServingSSH() { + return runtimeManager.isServingSSH(); + } + @Override public TimeZone getTimezone() { return runtimeManager.getTimezone(); diff --git a/src/main/java/com/gitblit/manager/IRuntimeManager.java b/src/main/java/com/gitblit/manager/IRuntimeManager.java index 29e7368f..b2d7a2b3 100644 --- a/src/main/java/com/gitblit/manager/IRuntimeManager.java +++ b/src/main/java/com/gitblit/manager/IRuntimeManager.java @@ -56,6 +56,33 @@ public interface IRuntimeManager extends IManager { */ boolean isServingRepositories(); + /** + * Determine if this Gitblit instance is actively serving git repositories + * over HTTP. + * + * @return true if Gitblit is serving repositories over HTTP + * @since 1.6.0 + */ + boolean isServingHTTP(); + + /** + * Determine if this Gitblit instance is actively serving git repositories + * over the GIT Daemon protocol. + * + * @return true if Gitblit is serving repositories over the GIT Daemon protocol + * @since 1.6.0 + */ + boolean isServingGIT(); + + /** + * Determine if this Gitblit instance is actively serving git repositories + * over the SSH protocol. + * + * @return true if Gitblit is serving repositories over the SSH protocol + * @since 1.6.0 + */ + boolean isServingSSH(); + /** * Determine if this Gitblit instance is running in debug mode * diff --git a/src/main/java/com/gitblit/manager/RuntimeManager.java b/src/main/java/com/gitblit/manager/RuntimeManager.java index 52f4d67b..9cdc64eb 100644 --- a/src/main/java/com/gitblit/manager/RuntimeManager.java +++ b/src/main/java/com/gitblit/manager/RuntimeManager.java @@ -119,9 +119,42 @@ public class RuntimeManager implements IRuntimeManager { */ @Override public boolean isServingRepositories() { - return settings.getBoolean(Keys.git.enableGitServlet, true) - || (settings.getInteger(Keys.git.daemonPort, 0) > 0) - || (settings.getInteger(Keys.git.sshPort, 0) > 0); + return isServingHTTP() + || isServingGIT() + || isServingSSH(); + } + + /** + * Determine if this Gitblit instance is actively serving git repositories + * over the HTTP protocol. + * + * @return true if Gitblit is serving repositories over the HTTP protocol + */ + @Override + public boolean isServingHTTP() { + return settings.getBoolean(Keys.git.enableGitServlet, true); + } + + /** + * Determine if this Gitblit instance is actively serving git repositories + * over the Git Daemon protocol. + * + * @return true if Gitblit is serving repositories over the Git Daemon protocol + */ + @Override + public boolean isServingGIT() { + return settings.getInteger(Keys.git.daemonPort, 0) > 0; + } + + /** + * Determine if this Gitblit instance is actively serving git repositories + * over the SSH protocol. + * + * @return true if Gitblit is serving repositories over the SSH protocol + */ + @Override + public boolean isServingSSH() { + return settings.getInteger(Keys.git.sshPort, 0) > 0; } /** diff --git a/src/main/java/com/gitblit/manager/ServicesManager.java b/src/main/java/com/gitblit/manager/ServicesManager.java index 755d8bac..37215786 100644 --- a/src/main/java/com/gitblit/manager/ServicesManager.java +++ b/src/main/java/com/gitblit/manager/ServicesManager.java @@ -112,9 +112,21 @@ public class ServicesManager implements IManager { } public boolean isServingRepositories() { - return settings.getBoolean(Keys.git.enableGitServlet, true) - || (gitDaemon != null && gitDaemon.isRunning()) - || (sshDaemon != null && sshDaemon.isRunning()); + return isServingHTTP() + || isServingGIT() + || isServingSSH(); + } + + public boolean isServingHTTP() { + return settings.getBoolean(Keys.git.enableGitServlet, true); + } + + public boolean isServingGIT() { + return gitDaemon != null && gitDaemon.isRunning(); + } + + public boolean isServingSSH() { + return sshDaemon != null && sshDaemon.isRunning(); } protected void configureFederation() { diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 81171799..7dc0f9b6 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -729,4 +729,12 @@ gb.accountPreferencesDescription = Specify your account preferences gb.languagePreference = Language Preference gb.languagePreferenceDescription = Select your preferred translation for the Gitblit UI gb.displayNameDescription = The preferred name for display -gb.emailAddressDescription = The primary email address for receiving notifications \ No newline at end of file +gb.emailAddressDescription = The primary email address for receiving notifications +gb.sshKeys = SSH Keys +gb.sshKeysDescription = SSH public key authentication is a secure alternative to password authentication +gb.addSshKey = Add SSH Key +gb.key = Key +gb.comment = Comment +gb.sshKeyCommentDescription = Enter an optional comment. If blank, the comment will be extracted from the key data. +gb.permission = Permission +gb.sshKeyPermissionDescription = Specify the access permission for the SSH key \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html index 09267873..d71cb2b5 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.html +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.html @@ -20,6 +20,7 @@ @@ -37,6 +38,9 @@
+ +
+ @@ -47,6 +51,10 @@
  • + +
  • +
    +

    @@ -63,6 +71,12 @@
    + +
    +
    +
    +
    + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index baad4a06..4a955c7c 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -50,6 +50,7 @@ import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.ChoiceOption; import com.gitblit.wicket.panels.ProjectRepositoryPanel; +import com.gitblit.wicket.panels.SshKeysPanel; import com.gitblit.wicket.panels.TextOption; import com.gitblit.wicket.panels.UserTitlePanel; @@ -100,10 +101,22 @@ public class UserPage extends RootPage { if (isMyProfile) { addPreferences(user); + + if (app().gitblit().isServingSSH()) { + // show the SSH key management tab + addSshKeys(user); + } else { + // SSH daemon is disabled, hide keys tab + add(new Label("sshKeysLink").setVisible(false)); + add(new Label("sshKeysTab").setVisible(false)); + } } else { // visiting user add(new Label("preferencesLink").setVisible(false)); add(new Label("preferencesTab").setVisible(false)); + + add(new Label("sshKeysLink").setVisible(false)); + add(new Label("sshKeysTab").setVisible(false)); } List repositories = getRepositories(params); @@ -251,6 +264,15 @@ public class UserPage extends RootPage { add(fragment.setRenderBodyOnly(true)); } + private void addSshKeys(final UserModel user) { + Fragment keysTab = new Fragment("sshKeysTab", "sshKeysTabFragment", this); + keysTab.add(new SshKeysPanel("sshKeysPanel", user, getClass(), getPageParameters())); + + // add the SSH keys tab + add(new Fragment("sshKeysLink", "sshKeysLinkFragment", this).setRenderBodyOnly(true)); + add(keysTab.setRenderBodyOnly(true)); + } + private class Language implements Serializable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html new file mode 100644 index 00000000..d67b704a --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html @@ -0,0 +1,46 @@ + + + + + +

    +

    +
    + +
    +
    + +
    +
    +
    +
    
    +		
    + +
    +
    +
    +
    + +
    + +
    + +
    +
    + +
    +
    +

    +
    +
    +
    + +
    +
    +
    +
    + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java new file mode 100644 index 00000000..03cb93ca --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java @@ -0,0 +1,161 @@ +/* + * Copyright 2014 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.List; + +import org.apache.wicket.PageParameters; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.link.Link; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.markup.repeater.data.DataView; +import org.apache.wicket.markup.repeater.data.ListDataProvider; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.models.UserModel; +import com.gitblit.transport.ssh.SshKey; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.GitBlitWebSession; + + +/** + * A panel that enumerates and manages SSH public keys. + * + * @author James Moger + * + */ +public class SshKeysPanel extends BasePanel { + + private static final long serialVersionUID = 1L; + + private final UserModel user; + + private final Class pageClass; + + private final PageParameters params; + + public SshKeysPanel(String wicketId, UserModel user, Class pageClass, PageParameters params) { + super(wicketId); + + this.user = user; + this.pageClass = pageClass; + this.params = params; + } + + @Override + protected void onInitialize() { + super.onInitialize(); + List keys = app().keys().getKeys(user.username); + + final ListDataProvider dp = new ListDataProvider(keys); + DataView keysView = new DataView("keys", dp) { + private static final long serialVersionUID = 1L; + + @Override + public void populateItem(final Item item) { + final SshKey key = item.getModelObject(); + item.add(new Label("comment", key.getComment())); + item.add(new Label("fingerprint", key.getFingerprint())); + item.add(new Label("permission", key.getPermission().toString())); + item.add(new Label("algorithm", key.getAlgorithm())); + + Link delete = new Link("delete") { + + private static final long serialVersionUID = 1L; + + @Override + public void onClick() { + if (app().keys().removeKey(user.username, key)) { + setRedirect(true); + setResponsePage(pageClass, params); + } + } + }; + item.add(delete); + } + }; + add(keysView); + + Form addKeyForm = new Form("addKeyForm"); + + final IModel keyData = Model.of(""); + addKeyForm.add(new TextAreaOption("addKeyData", + getString("gb.key"), + null, + "span5", + keyData)); + + final IModel keyPermission = Model.of(AccessPermission.PUSH); + addKeyForm.add(new ChoiceOption("addKeyPermission", + getString("gb.permission"), + getString("gb.sshKeyPermissionDescription"), + keyPermission, + Arrays.asList(AccessPermission.SSHPERMISSIONS))); + + final IModel keyComment = Model.of(""); + addKeyForm.add(new TextOption("addKeyComment", + getString("gb.comment"), + getString("gb.sshKeyCommentDescription"), + "span5", + keyComment)); + + addKeyForm.add(new AjaxButton("addKeyButton") { + + private static final long serialVersionUID = 1L; + + @Override + protected void onSubmit(AjaxRequestTarget target, Form form) { + + UserModel user = GitBlitWebSession.get().getUser(); + String data = keyData.getObject(); + if (StringUtils.isEmpty(data)) { + // do not submit empty key + return; + } + + SshKey key = new SshKey(data); + try { + key.getPublicKey(); + } catch (Exception e) { + // failed to parse the key + return; + } + + AccessPermission permission = keyPermission.getObject(); + key.setPermission(permission); + + String comment = keyComment.getObject(); + if (!StringUtils.isEmpty(comment)) { + key.setComment(comment); + } + + if (app().keys().addKey(user.username, key)) { + setRedirect(true); + setResponsePage(pageClass, params); + } + } + }); + + add(addKeyForm); + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/TextAreaOption.html b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.html new file mode 100644 index 00000000..bb7dc7c6 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.html @@ -0,0 +1,20 @@ + + + + + +
    +
    + +
    + + +
    +
    + + \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/TextAreaOption.java b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.java new file mode 100644 index 00000000..d2c74a06 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/TextAreaOption.java @@ -0,0 +1,54 @@ +/* + * Copyright 2014 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 org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.TextArea; +import org.apache.wicket.model.IModel; + +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.WicketUtils; + +/** + * A re-usable textarea option panel. + * + * title + * description + * [text + * area] + * + * @author James Moger + * + */ +public class TextAreaOption extends BasePanel { + + private static final long serialVersionUID = 1L; + + public TextAreaOption(String wicketId, String title, String description, IModel model) { + this(wicketId, title, description, null, model); + } + + public TextAreaOption(String wicketId, String title, String description, String css, IModel model) { + super(wicketId); + add(new Label("name", title)); + add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); + TextArea tf = new TextArea("text", model); + if (!StringUtils.isEmpty(css)) { + WicketUtils.setCssClass(tf, css); + } + add(tf); + } +} diff --git a/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java b/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java index 6e56a873..54be539f 100644 --- a/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java +++ b/src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java @@ -81,6 +81,21 @@ public class MockRuntimeManager implements IRuntimeManager { return true; } + @Override + public boolean isServingHTTP() { + return true; + } + + @Override + public boolean isServingGIT() { + return true; + } + + @Override + public boolean isServingSSH() { + return true; + } + @Override public boolean isDebugMode() { return true; -- 2.39.5