From 20165d234037cb62640e4d9a3fe285260a6a2444 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Wed, 20 Jul 2011 16:01:58 -0400 Subject: [PATCH] Change password feature (issue 1) --- src/com/gitblit/wicket/pages/ChangePasswordPage.html | 40 ++++++++++ src/com/gitblit/wicket/GitBlitWebApp.properties | 8 + src/com/gitblit/wicket/pages/BasePage.java | 44 +++++++++-- src/com/gitblit/wicket/pages/ChangePasswordPage.java | 133 +++++++++++++++++++++++++++++++++ src/com/gitblit/wicket/pages/BasePage.html | 9 ++ resources/gitblit.css | 4 + 6 files changed, 227 insertions(+), 11 deletions(-) diff --git a/resources/gitblit.css b/resources/gitblit.css index e4d291a..061fef5 100644 --- a/resources/gitblit.css +++ b/resources/gitblit.css @@ -174,6 +174,10 @@ font-style: italic; } +span.userPanel a, span.userPanel a span { + font-size: 11px; +} + div.page_nav { color: #ddd; background-color: #000070; diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties index 2ed61fa..dab5fa0 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -40,8 +40,8 @@ gb.pageNext = next gb.head = HEAD gb.blame = blame -gb.login = Login -gb.logout = Logout +gb.login = login +gb.logout = logout gb.username = username gb.password = password gb.tagger = tagger @@ -99,4 +99,6 @@ gb.commitActivityTrend = commit activity trend gb.commitActivityDOW = commit activity by day of week gb.commitActivityAuthors = primary authors by commit activity -gb.feed = feed \ No newline at end of file +gb.feed = feed +gb.cancel = cancel +gb.changePassword = change password \ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/BasePage.html b/src/com/gitblit/wicket/pages/BasePage.html index cc19fbc..aaf3a35 100644 --- a/src/com/gitblit/wicket/pages/BasePage.html +++ b/src/com/gitblit/wicket/pages/BasePage.html @@ -33,4 +33,13 @@ <div wicket:id="userPanel">[user panel]</div> </div> </body> + + <!-- user fragment --> + <wicket:fragment wicket:id="userFragment"> + <span class="userPanel" wicket:id="username"></span> + <span class="userPanel" wicket:id="loginLink"></span> + <span class="userPanel" wicket:id="separator"></span> + <span class="userPanel"><a wicket:id="changePasswordLink"><wicket:message key="gb.changePassword"></wicket:message></a></span> + </wicket:fragment> + </html> \ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/BasePage.java b/src/com/gitblit/wicket/pages/BasePage.java index 06d5483..e95aee3 100644 --- a/src/com/gitblit/wicket/pages/BasePage.java +++ b/src/com/gitblit/wicket/pages/BasePage.java @@ -22,12 +22,15 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import org.apache.wicket.MarkupContainer; import org.apache.wicket.PageParameters; import org.apache.wicket.RestartResponseAtInterceptPageException; import org.apache.wicket.RestartResponseException; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.panel.FeedbackPanel; +import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.protocol.http.WebRequest; import org.apache.wicket.protocol.http.WebResponse; import org.apache.wicket.protocol.http.servlet.ServletWebRequest; @@ -105,17 +108,12 @@ // footer if (GitBlit.getBoolean(Keys.web.authenticateViewPages, true) || GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) { - if (GitBlitWebSession.get().isLoggedIn()) { - // logout - add(new LinkPanel("userPanel", null, getString("gb.logout") + " " - + GitBlitWebSession.get().getUser().toString(), LogoutPage.class)); - } else { - // login - add(new LinkPanel("userPanel", null, getString("gb.login"), LoginPage.class)); - } + UserFragment userFragment = new UserFragment("userPanel", "userFragment", BasePage.this); + add(userFragment); } else { add(new Label("userPanel", "")); } + add(new Label("gbVersion", "v" + Constants.VERSION)); if (GitBlit.getBoolean(Keys.web.aggressiveHeapManagement, false)) { System.gc(); @@ -186,4 +184,34 @@ throw new RestartResponseAtInterceptPageException(LoginPage.class); } } + + /** + * Panel fragment for displaying login or logout/change_password links. + * + */ + class UserFragment extends Fragment { + + private static final long serialVersionUID = 1L; + + public UserFragment(String id, String markupId, MarkupContainer markupProvider) { + super(id, markupId, markupProvider); + + if (GitBlitWebSession.get().isLoggedIn()) { + // username, logout, and change password + add(new Label("username", GitBlitWebSession.get().getUser().toString() + ":")); + add(new LinkPanel("loginLink", null, markupProvider.getString("gb.logout"), + LogoutPage.class)); + // quick and dirty hack for showing a separator + add(new Label("separator", "|")); + add(new BookmarkablePageLink<Void>("changePasswordLink", ChangePasswordPage.class)); + } else { + // login + add(new Label("username").setVisible(false)); + add(new LinkPanel("loginLink", null, markupProvider.getString("gb.login"), + LoginPage.class)); + add(new Label("separator").setVisible(false)); + add(new Label("changePasswordLink").setVisible(false)); + } + } + } } diff --git a/src/com/gitblit/wicket/pages/ChangePasswordPage.html b/src/com/gitblit/wicket/pages/ChangePasswordPage.html new file mode 100644 index 0000000..031352e --- /dev/null +++ b/src/com/gitblit/wicket/pages/ChangePasswordPage.html @@ -0,0 +1,40 @@ +<!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"> + + <!-- Head with Wicket-controlled resources in this package --> + <wicket:head> + <title wicket:id="title">[page title]</title> + <link rel="stylesheet" type="text/css" href="gitblit.css"/> + <link rel="shortcut icon" href="gitblt-favicon.png" type="image/png" /> + </wicket:head> + + <body onload="document.getElementById('password').focus();"> + <div> + <div style="padding-top: 10px;text-align:center;"> + <img src="gitblt_25.png" alt="Gitblit"/><br/> + <div style="padding-top:30px;font-weight:bold;" wicket:id="name"></div> + </div> + <p/> + <form style="text-align:center;" wicket:id="passwordForm"> + <center> + <table class="plain"> + <tr> + <th><wicket:message key="gb.password"></wicket:message> </th> + <td class="edit"><input type="password" wicket:id="password" id="password" size="30" tabindex="1" /></td> + </tr> + <tr> + <th><wicket:message key="gb.confirmPassword"></wicket:message> </th> + <td class="edit"><input type="password" wicket:id="confirmPassword" size="30" tabindex="2" /></td> + </tr> + </table> + <input type="submit" wicket:message="value:gb.save" wicket:id="save" tabindex="3" /> + <input type="submit" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="4" /> + <div style="padding-top:10px;" wicket:id="feedback"></div> + </center> + </form> + </div> + </body> +</html> \ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/ChangePasswordPage.java b/src/com/gitblit/wicket/pages/ChangePasswordPage.java new file mode 100644 index 0000000..42cd2b7 --- /dev/null +++ b/src/com/gitblit/wicket/pages/ChangePasswordPage.java @@ -0,0 +1,133 @@ +/* + * Copyright 2011 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.pages; + +import java.text.MessageFormat; + +import org.apache.wicket.RestartResponseException; +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Button; +import org.apache.wicket.markup.html.form.PasswordTextField; +import org.apache.wicket.markup.html.form.StatelessForm; +import org.apache.wicket.markup.html.panel.FeedbackPanel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.protocol.http.WebResponse; + +import com.gitblit.Constants; +import com.gitblit.GitBlit; +import com.gitblit.GitBlitException; +import com.gitblit.Keys; +import com.gitblit.models.UserModel; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.GitBlitWebSession; + +public class ChangePasswordPage extends WebPage { + + IModel<String> password = new Model<String>(""); + IModel<String> confirmPassword = new Model<String>(""); + + public ChangePasswordPage() { + super(); + + if (!GitBlitWebSession.get().isLoggedIn()) { + // Change password requires a login + throw new RestartResponseException(getApplication().getHomePage()); + } + + if (!GitBlit.getBoolean(Keys.web.authenticateAdminPages, true) && !GitBlit.getBoolean(Keys.web.authenticateViewPages, false)) { + // no authentication enabled + throw new RestartResponseException(getApplication().getHomePage()); + } + + add(new Label("title", GitBlit.getString(Keys.web.siteName, Constants.NAME))); + add(new Label("name", getString("gb.changePassword") + ": " + + GitBlitWebSession.get().getUser().username)); + + StatelessForm<Void> form = new StatelessForm<Void>("passwordForm") { + + private static final long serialVersionUID = 1L; + + @Override + public void onSubmit() { + String password = ChangePasswordPage.this.password.getObject(); + String confirmPassword = ChangePasswordPage.this.confirmPassword.getObject(); + // ensure passwords match + if (!password.equals(confirmPassword)) { + error("Passwords do not match!"); + return; + } + + // ensure password satisfies minimum length requirement + int minLength = GitBlit.getInteger(Keys.realm.minPasswordLength, 5); + if (minLength < 4) { + minLength = 4; + } + if (password.length() < minLength) { + error(MessageFormat.format( + "Password is too short. Minimum length is {0} characters.", minLength)); + return; + } + + // convert to MD5 digest, if appropriate + String type = GitBlit.getString(Keys.realm.passwordStorage, "md5"); + if (type.equalsIgnoreCase("md5")) { + // store MD5 digest of password + password = StringUtils.MD5_TYPE + StringUtils.getMD5(password); + } + + UserModel user = GitBlitWebSession.get().getUser(); + user.password = password; + try { + GitBlit.self().updateUserModel(user.username, user, false); + if (GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) { + WebResponse response = (WebResponse) getRequestCycle().getResponse(); + GitBlit.self().setCookie(response, user); + } + } catch (GitBlitException e) { + error(e.getMessage()); + return; + } + setRedirect(false); + info("Password successfully changed."); + setResponsePage(RepositoriesPage.class); + } + }; + PasswordTextField passwordField = new PasswordTextField("password", password); + passwordField.setResetPassword(false); + form.add(passwordField); + PasswordTextField confirmPasswordField = new PasswordTextField("confirmPassword", + confirmPassword); + confirmPasswordField.setResetPassword(false); + form.add(confirmPasswordField); + form.add(new FeedbackPanel("feedback")); + + form.add(new Button("save")); + Button cancel = new Button("cancel"){ + private static final long serialVersionUID = 1L; + + @Override + public void onSubmit() { + setResponsePage(RepositoriesPage.class); + } + }; + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + add(form); + } +} -- Gitblit v1.9.1