@@ -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()}; | |||
} |
@@ -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(); |
@@ -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 | |||
* |
@@ -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; | |||
} | |||
/** |
@@ -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() { |
@@ -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 | |||
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 |
@@ -20,6 +20,7 @@ | |||
<ul class="nav nav-tabs"> | |||
<li class="active"><a href="#repositories" data-toggle="tab"><wicket:message key="gb.repositories"></wicket:message></a></li> | |||
<div wicket:id="preferencesLink"></div> | |||
<div wicket:id="sshKeysLink"></div> | |||
</ul> | |||
<!-- tab content --> | |||
@@ -37,6 +38,9 @@ | |||
<!-- preferences tab --> | |||
<div wicket:id="preferencesTab"></div> | |||
<!-- ssh keys tab --> | |||
<div wicket:id="sshKeysTab"></div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -47,6 +51,10 @@ | |||
<li><a href="#preferences" data-toggle="tab"><wicket:message key="gb.preferences"></wicket:message></a></li> | |||
</wicket:fragment> | |||
<wicket:fragment wicket:id="sshKeysLinkFragment"> | |||
<li><a href="#ssh" data-toggle="tab"><wicket:message key="gb.sshKeys"></wicket:message></a></li> | |||
</wicket:fragment> | |||
<wicket:fragment wicket:id="preferencesTabFragment"> | |||
<div class="tab-pane" id="preferences"> | |||
<h4><wicket:message key="gb.accountPreferences"></wicket:message></h4> | |||
@@ -63,6 +71,12 @@ | |||
</div> | |||
</wicket:fragment> | |||
<wicket:fragment wicket:id="sshKeysTabFragment"> | |||
<div class="tab-pane" id="ssh"> | |||
<div wicket:id="sshKeysPanel"></div> | |||
</div> | |||
</wicket:fragment> | |||
</wicket:extend> | |||
</body> | |||
</html> |
@@ -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<RepositoryModel> 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; |
@@ -0,0 +1,46 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" | |||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||
xml:lang="en" | |||
lang="en"> | |||
<body> | |||
<wicket:panel> | |||
<h4><wicket:message key="gb.sshKeys"></wicket:message></h4> | |||
<p><wicket:message key="gb.sshKeysDescription"></wicket:message></p> | |||
<hr /> | |||
<div wicket:id="keys"> | |||
<div style="display:inline-block;font-size:2em;padding:10px;"> | |||
<i class="fa fa-key"></i> | |||
</div> | |||
<div style="display:inline-block;"> | |||
<div wicket:id="comment" style="font-weight:bold;"></div> | |||
<pre wicket:id="fingerprint"></pre> | |||
</div> | |||
<div style="display:inline-block;padding: 0px 20px"> | |||
<div wicket:id="permission" style="font-weight:bold;"></div> | |||
<div wicket:id="algorithm"></div> | |||
</div> | |||
<div style="display:inline-block;vertical-align:text-bottom;"> | |||
<button class="btn btn-danger" wicket:id="delete"><wicket:message key="gb.delete"></wicket:message></button> | |||
</div> | |||
<hr /> | |||
</div> | |||
<div class="well"> | |||
<form wicket:id="addKeyForm"> | |||
<h4><wicket:message key="gb.addSshKey"></wicket:message></h4> | |||
<div wicket:id="addKeyData"></div> | |||
<div wicket:id="addKeyPermission"></div> | |||
<div wicket:id="addKeyComment"></div> | |||
<div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Add" wicket:message="value:gb.add" wicket:id="addKeyButton" /></div> | |||
</form> | |||
</div> | |||
</wicket:panel> | |||
</body> | |||
</html> |
@@ -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<? extends WebPage> pageClass; | |||
private final PageParameters params; | |||
public SshKeysPanel(String wicketId, UserModel user, Class<? extends WebPage> pageClass, PageParameters params) { | |||
super(wicketId); | |||
this.user = user; | |||
this.pageClass = pageClass; | |||
this.params = params; | |||
} | |||
@Override | |||
protected void onInitialize() { | |||
super.onInitialize(); | |||
List<SshKey> keys = app().keys().getKeys(user.username); | |||
final ListDataProvider<SshKey> dp = new ListDataProvider<SshKey>(keys); | |||
DataView<SshKey> keysView = new DataView<SshKey>("keys", dp) { | |||
private static final long serialVersionUID = 1L; | |||
@Override | |||
public void populateItem(final Item<SshKey> 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<Void> delete = new Link<Void>("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<Void> addKeyForm = new Form<Void>("addKeyForm"); | |||
final IModel<String> keyData = Model.of(""); | |||
addKeyForm.add(new TextAreaOption("addKeyData", | |||
getString("gb.key"), | |||
null, | |||
"span5", | |||
keyData)); | |||
final IModel<AccessPermission> keyPermission = Model.of(AccessPermission.PUSH); | |||
addKeyForm.add(new ChoiceOption<AccessPermission>("addKeyPermission", | |||
getString("gb.permission"), | |||
getString("gb.sshKeyPermissionDescription"), | |||
keyPermission, | |||
Arrays.asList(AccessPermission.SSHPERMISSIONS))); | |||
final IModel<String> 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); | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" | |||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||
xml:lang="en" | |||
lang="en"> | |||
<body> | |||
<wicket:panel> | |||
<div style="padding-top:4px;"> | |||
<div style="margin-bottom:1px;"> | |||
<b><span wicket:id="name"></span></b> | |||
</div> | |||
<label class="checkbox" style="color:#777;"> <span wicket:id="description"></span> | |||
<p style="padding-top:5px;"><textarea rows="12" class="span5" wicket:id="text"></textarea></p> | |||
</label> | |||
</div> | |||
</wicket:panel> | |||
</body> | |||
</html> |
@@ -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<String> model) { | |||
this(wicketId, title, description, null, model); | |||
} | |||
public TextAreaOption(String wicketId, String title, String description, String css, IModel<String> model) { | |||
super(wicketId); | |||
add(new Label("name", title)); | |||
add(new Label("description", description).setVisible(!StringUtils.isEmpty(description))); | |||
TextArea<String> tf = new TextArea<String>("text", model); | |||
if (!StringUtils.isEmpty(css)) { | |||
WicketUtils.setCssClass(tf, css); | |||
} | |||
add(tf); | |||
} | |||
} |
@@ -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; |