releases.moxie
@@ -34,6 +34,8 @@ - Added CRUD functionality for Ticket Milestones (ticket-17) - Implemented Ticket migration tool to move between backends (ticket-19) - Added extension points for top nav links, root-level pages, repository nav links, user menu links, and http request filters (ticket-23) - Added an editor panel in the user profile page to manipulate preferences (issue-108, issue-424, ticket-64) - Added an editor panel in the user profile page to manipulate public SSH keys (ticket-64) - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) - Add setting to allow STARTTLS without requiring SMTPS (pr-183) src/main/java/com/gitblit/ConfigUserService.java
@@ -96,6 +96,8 @@ private static final String LOCALE = "locale"; private static final String EMAILONMYTICKETCHANGES = "emailMeOnMyTicketChanges"; private static final String ACCOUNTTYPE = "accountType"; private static final String DISABLED = "disabled"; @@ -707,9 +709,11 @@ config.setBoolean(USER, model.username, DISABLED, true); } if (model.getPreferences() != null) { if (!StringUtils.isEmpty(model.getPreferences().locale)) { config.setString(USER, model.username, LOCALE, model.getPreferences().locale); if (model.getPreferences().getLocale() != null) { String val = model.getPreferences().getLocale().getLanguage() + "_" + model.getPreferences().getLocale().getCountry(); config.setString(USER, model.username, LOCALE, val); } config.setBoolean(USER, model.username, EMAILONMYTICKETCHANGES, model.getPreferences().isEmailMeOnMyTicketChanges()); } // user roles @@ -880,11 +884,14 @@ user.stateProvince = config.getString(USER, username, STATEPROVINCE); user.countryCode = config.getString(USER, username, COUNTRYCODE); user.cookie = config.getString(USER, username, COOKIE); user.getPreferences().locale = config.getString(USER, username, LOCALE); if (StringUtils.isEmpty(user.cookie) && !StringUtils.isEmpty(user.password)) { user.cookie = StringUtils.getSHA1(user.username + user.password); } // preferences user.getPreferences().setLocale(config.getString(USER, username, LOCALE)); user.getPreferences().setEmailMeOnMyTicketChanges(config.getBoolean(USER, username, EMAILONMYTICKETCHANGES, true)); // user roles Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList( USER, username, ROLE))); src/main/java/com/gitblit/FederationClient.java
@@ -166,6 +166,11 @@ } @Override public boolean isSendingMail() { return false; } @Override public void sendMailToAdministrators(String subject, String message) { } src/main/java/com/gitblit/GitBlit.java
@@ -117,6 +117,21 @@ 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()}; } src/main/java/com/gitblit/manager/GitblitManager.java
@@ -602,6 +602,21 @@ } @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(); } @@ -646,6 +661,11 @@ */ @Override public boolean isSendingMail() { return notificationManager.isSendingMail(); } @Override public void sendMailToAdministrators(String subject, String message) { notificationManager.sendMailToAdministrators(subject, message); } src/main/java/com/gitblit/manager/INotificationManager.java
@@ -22,6 +22,14 @@ public interface INotificationManager extends IManager { /** * Returns true if the email service is configured and ready to send notifications. * * @return true if the email service is operational * @since 1.6.0 */ boolean isSendingMail(); /** * Notify the administrators by email. * * @param subject src/main/java/com/gitblit/manager/IRuntimeManager.java
@@ -57,6 +57,33 @@ 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 * * @return true if Gitblit is running in debug mode src/main/java/com/gitblit/manager/NotificationManager.java
@@ -71,6 +71,11 @@ return this; } @Override public boolean isSendingMail() { return mailService.isReady(); } /** * Notify the administrators by email. * src/main/java/com/gitblit/manager/RuntimeManager.java
@@ -119,9 +119,42 @@ */ @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; } /** src/main/java/com/gitblit/manager/ServicesManager.java
@@ -112,9 +112,21 @@ } 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() { src/main/java/com/gitblit/models/UserPreferences.java
@@ -37,7 +37,9 @@ public final String username; public String locale; private String locale; private Boolean emailMeOnMyTicketChanges; private final Map<String, UserRepositoryPreferences> repositoryPreferences = new TreeMap<String, UserRepositoryPreferences>(); @@ -56,6 +58,10 @@ return new Locale(lang, cc); } return new Locale(locale); } public void setLocale(String locale) { this.locale = locale; } public UserRepositoryPreferences getRepositoryPreferences(String repositoryName) { @@ -96,4 +102,15 @@ Collections.sort(list); return list; } public boolean isEmailMeOnMyTicketChanges() { if (emailMeOnMyTicketChanges == null) { return true; } return emailMeOnMyTicketChanges; } public void setEmailMeOnMyTicketChanges(boolean value) { this.emailMeOnMyTicketChanges = value; } } src/main/java/com/gitblit/tickets/TicketNotifier.java
@@ -545,7 +545,6 @@ } } } mailing.setRecipients(toAddresses); // // CC recipients @@ -554,7 +553,7 @@ // repository owners if (!ArrayUtils.isEmpty(repository.owners)) { tos.addAll(repository.owners); ccs.addAll(repository.owners); } // cc users mentioned in last comment @@ -595,6 +594,14 @@ } ccAddresses.addAll(settings.getStrings(Keys.mail.mailingLists)); // respect the author's email preference UserModel lastAuthor = userManager.getUserModel(lastChange.author); if (!lastAuthor.getPreferences().isEmailMeOnMyTicketChanges()) { toAddresses.remove(lastAuthor.emailAddress); ccAddresses.remove(lastAuthor.emailAddress); } mailing.setRecipients(toAddresses); mailing.setCCs(ccAddresses); } src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -723,3 +723,20 @@ gb.garbageCollection = Garbage Collection gb.garbageCollectionDescription = The garbage collector will pack loose objects pushed from clients and will remove unreferenced objects from the repository. gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup. gb.preferences = preferences gb.accountPreferences = Account Preferences gb.accountPreferencesDescription = Specify your account preferences gb.languagePreference = Language Preference gb.languagePreferenceDescription = Select your preferred translation for Gitblit gb.emailMeOnMyTicketChanges = Email me on my ticket changes gb.emailMeOnMyTicketChangesDescription = Send me an email notification for changes that I make to a ticket gb.displayNameDescription = The preferred name for display 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 src/main/java/com/gitblit/wicket/pages/UserPage.html
@@ -7,27 +7,20 @@ <body> <wicket:extend> <div class="container"> <div class="row" style="padding-top:10px;"> <div class="span4"> <div wicket:id="gravatar"></div> <div style="text-align: left;"> <h2><span wicket:id="userDisplayName"></span></h2> <div><i class="icon-user"></i> <span wicket:id="userUsername"></span></div> <div><i class="icon-envelope"></i><span wicket:id="userEmail"></span></div> <div class="row" style="padding-top:15px;"> <div class="span3"> <div wicket:id="userTitlePanel"></div> </div> </div> <div class="span8"> <div class="pull-right"> <a class="btn-small" wicket:id="newRepository" style="padding-right:0px;"> <i class="icon icon-plus-sign"></i> <wicket:message key="gb.newRepository"></wicket:message> </a> </div> <div class="tabbable"> <div class="row" style="padding-top:10px;"> <div class="span12"> <div class="tabbable tabs-left"> <!-- tab titles --> <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 --> @@ -41,11 +34,50 @@ </tbody> </table> </div> <!-- preferences tab --> <div wicket:id="preferencesTab"></div> <!-- ssh keys tab --> <div wicket:id="sshKeysTab"></div> </div> </div> </div> </div> </div> <wicket:fragment wicket:id="preferencesLinkFragment"> <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> <p><wicket:message key="gb.accountPreferencesDescription"></wicket:message></p> <hr /> <form wicket:id="prefsForm"> <div wicket:id="displayName"></div> <div wicket:id="emailAddress"></div> <div wicket:id="language"></div> <div wicket:id="emailMeOnMyTicketChanges"></div> <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" /></div> </form> </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> src/main/java/com/gitblit/wicket/pages/UserPage.java
@@ -15,19 +15,27 @@ */ package com.gitblit.wicket.pages; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Locale; 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.basic.Label; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.panel.Fragment; 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.eclipse.jgit.lib.PersonIdent; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import com.gitblit.GitBlitException; import com.gitblit.Keys; import com.gitblit.models.Menu.ParameterMenuItem; import com.gitblit.models.NavLink; @@ -40,9 +48,12 @@ import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.GravatarImage; import com.gitblit.wicket.panels.LinkPanel; import com.gitblit.wicket.panels.BooleanOption; 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; public class UserPage extends RootPage { @@ -83,21 +94,30 @@ user = new UserModel(userName); } add(new Label("userDisplayName", user.getDisplayName())); add(new Label("userUsername", user.username)); LinkPanel email = new LinkPanel("userEmail", null, user.emailAddress, "mailto:#"); email.setRenderBodyOnly(true); add(email.setVisible(app().settings().getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress))); PersonIdent person = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress); add(new GravatarImage("gravatar", person, 210)); add(new UserTitlePanel("userTitlePanel", user, user.username)); UserModel sessionUser = GitBlitWebSession.get().getUser(); if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) { // user can create personal repositories add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage())); boolean isMyProfile = sessionUser != null && sessionUser.equals(user); if (isMyProfile) { addPreferences(user); if (app().gitblit().isServingSSH()) { // show the SSH key management tab addSshKeys(user); } else { add(new Label("newRepository").setVisible(false)); // 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); @@ -145,4 +165,146 @@ navLinks.add(menu); } private void addPreferences(UserModel user) { // add preferences Form<Void> prefs = new Form<Void>("prefsForm"); List<Language> languages = Arrays.asList( new Language("English","en"), new Language("Español", "es"), new Language("Français", "fr"), new Language("日本語", "ja"), new Language("한국말", "ko"), new Language("Nederlands", "nl"), new Language("Norsk", "no"), new Language("Język Polski", "pl"), new Language("Português", "pt_BR"), new Language("中文", "zh_CN")); Locale locale = user.getPreferences().getLocale(); if (locale == null) { // user has not specified language preference // try server default preference String lc = app().settings().getString(Keys.web.forceDefaultLocale, null); if (StringUtils.isEmpty(lc)) { // server default language is not configured // try browser preference Locale sessionLocale = GitBlitWebSession.get().getLocale(); if (sessionLocale != null) { locale = sessionLocale; } } else { } } Language preferredLanguage = null; if (locale != null) { String localeCode = locale.getLanguage(); if (!StringUtils.isEmpty(locale.getCountry())) { localeCode += "_" + locale.getCountry(); } for (Language language : languages) { if (language.code.equals(localeCode)) { // language_COUNTRY match preferredLanguage = language; } else if (preferredLanguage != null && language.code.startsWith(locale.getLanguage())) { // language match preferredLanguage = language; } } } final IModel<String> displayName = Model.of(user.getDisplayName()); final IModel<String> emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress); final IModel<Language> language = Model.of(preferredLanguage); final IModel<Boolean> emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges()); prefs.add(new TextOption("displayName", getString("gb.displayName"), getString("gb.displayNameDescription"), displayName).setVisible(app().authentication().supportsDisplayNameChanges(user))); prefs.add(new TextOption("emailAddress", getString("gb.emailAddress"), getString("gb.emailAddressDescription"), emailAddress).setVisible(app().authentication().supportsEmailAddressChanges(user))); prefs.add(new ChoiceOption<Language>("language", getString("gb.languagePreference"), getString("gb.languagePreferenceDescription"), language, languages)); prefs.add(new BooleanOption("emailMeOnMyTicketChanges", getString("gb.emailMeOnMyTicketChanges"), getString("gb.emailMeOnMyTicketChangesDescription"), emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail())); prefs.add(new AjaxButton("save") { private static final long serialVersionUID = 1L; @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { UserModel user = GitBlitWebSession.get().getUser(); user.displayName = displayName.getObject(); user.emailAddress = emailAddress.getObject(); Language lang = language.getObject(); if (lang != null) { user.getPreferences().setLocale(lang.code); } user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject()); try { app().gitblit().reviseUser(user.username, user); setRedirect(true); setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(user.username)); } catch (GitBlitException e) { // logger.error("Failed to update user " + user.username, e); // error(getString("gb.failedToUpdateUser"), false); } } }); // add the preferences tab add(new Fragment("preferencesLink", "preferencesLinkFragment", this).setRenderBodyOnly(true)); Fragment fragment = new Fragment("preferencesTab", "preferencesTabFragment", this); fragment.add(prefs); add(fragment.setRenderBodyOnly(true)); } private void addSshKeys(final UserModel user) { Fragment keysTab = new Fragment("sshKeysTab", "sshKeysTabFragment", this); keysTab.add(new SshKeysPanel("sshKeysPanel", user)); // 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; final String name; final String code; public Language(String name, String code) { this.name = name; this.code = code; } @Override public String toString() { return name + " (" + code +")"; } } } src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html
@@ -13,7 +13,7 @@ <div wicket:id="policiesGroup"> <div wicket:id="policies" style="padding-top:4px;"> <div> <label style="font-weight:bold;"><input type="radio" wicket:id="radio" /> <img wicket:id="image"></img> <span wicket:id="name"></span></label> <label style="font-weight:bold;margin-bottom:1px;"><input type="radio" wicket:id="radio" /> <img wicket:id="image"></img> <span wicket:id="name"></span></label> </div> <label class="checkbox" style="color:#777;" wicket:id="description"></label> </div> src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html
@@ -8,7 +8,7 @@ <wicket:panel> <div style="padding-top:4px;"> <div> <label style="font-weight:bold;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label> <label style="font-weight:bold;margin-bottom:1px;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label> </div> <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span> <p style="padding-top:5px;"><select class="span3" wicket:id="choice" /></p> src/main/java/com/gitblit/wicket/panels/BooleanOption.html
@@ -8,7 +8,7 @@ <wicket:panel> <div style="padding-top:4px;"> <div> <label style="font-weight:bold;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label> <label style="font-weight:bold;margin-bottom:1px;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label> </div> <label class="checkbox" style="color:#777;" wicket:id="description"></label> </div> src/main/java/com/gitblit/wicket/panels/ChoiceOption.html
@@ -7,7 +7,7 @@ <body> <wicket:panel> <div style="padding-top:4px;"> <div> <div style="margin-bottom:1px;"> <b><span wicket:id="name"></span></b> </div> <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span> src/main/java/com/gitblit/wicket/panels/SshKeysPanel.html
New file @@ -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> src/main/java/com/gitblit/wicket/panels/SshKeysPanel.java
New file @@ -0,0 +1,169 @@ /* * 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.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Form; 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 using AJAX. * * @author James Moger * */ public class SshKeysPanel extends BasePanel { private static final long serialVersionUID = 1L; private final UserModel user; public SshKeysPanel(String wicketId, UserModel user) { super(wicketId); this.user = user; } @Override protected void onInitialize() { super.onInitialize(); setOutputMarkupId(true); final List<SshKey> keys = new ArrayList<SshKey>(app().keys().getKeys(user.username)); final ListDataProvider<SshKey> dp = new ListDataProvider<SshKey>(keys); final 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())); AjaxLink<Void> delete = new AjaxLink<Void>("delete") { private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { if (app().keys().removeKey(user.username, key)) { // reset the keys list keys.clear(); keys.addAll(app().keys().getKeys(user.username)); // update the panel target.addComponent(SshKeysPanel.this); } } }; 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)) { // reset add key fields keyData.setObject(""); keyPermission.setObject(AccessPermission.PUSH); keyComment.setObject(""); // reset the keys list keys.clear(); keys.addAll(app().keys().getKeys(user.username)); // update the panel target.addComponent(SshKeysPanel.this); } } }); add(addKeyForm); } } src/main/java/com/gitblit/wicket/panels/TextAreaOption.html
New file @@ -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> src/main/java/com/gitblit/wicket/panels/TextAreaOption.java
New file @@ -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); } } src/main/java/com/gitblit/wicket/panels/TextOption.html
@@ -7,7 +7,7 @@ <body> <wicket:panel> <div style="padding-top:4px;"> <div> <div style="margin-bottom:1px;"> <b><span wicket:id="name"></span></b> </div> <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span> src/test/java/com/gitblit/tests/mock/MockRuntimeManager.java
@@ -82,6 +82,21 @@ } @Override public boolean isServingHTTP() { return true; } @Override public boolean isServingGIT() { return true; } @Override public boolean isServingSSH() { return true; } @Override public boolean isDebugMode() { return true; }