James Moger
2014-06-16 5881c4f334a5842f3c5fe63e3e499fd13aa41277
commit | author | age
1e1b85 1 /*
JM 2  * Copyright 2012 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit.wicket.pages;
17
c9921b 18 import java.io.Serializable;
1e1b85 19 import java.util.ArrayList;
c9921b 20 import java.util.Arrays;
1e1b85 21 import java.util.Collections;
JM 22 import java.util.Comparator;
23 import java.util.List;
c9921b 24 import java.util.Locale;
1e1b85 25
JM 26 import org.apache.wicket.PageParameters;
c9921b 27 import org.apache.wicket.ajax.AjaxRequestTarget;
JM 28 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
1e1b85 29 import org.apache.wicket.markup.html.basic.Label;
c9921b 30 import org.apache.wicket.markup.html.form.Form;
JM 31 import org.apache.wicket.markup.html.panel.Fragment;
1e1b85 32 import org.apache.wicket.markup.repeater.Item;
JM 33 import org.apache.wicket.markup.repeater.data.DataView;
34 import org.apache.wicket.markup.repeater.data.ListDataProvider;
c9921b 35 import org.apache.wicket.model.IModel;
JM 36 import org.apache.wicket.model.Model;
1e1b85 37
1b04d7 38 import com.gitblit.Constants.Transport;
c9921b 39 import com.gitblit.GitBlitException;
1e1b85 40 import com.gitblit.Keys;
856f3f 41 import com.gitblit.models.Menu.ParameterMenuItem;
7a401a 42 import com.gitblit.models.NavLink;
0047fb 43 import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
1e1b85 44 import com.gitblit.models.ProjectModel;
JM 45 import com.gitblit.models.RepositoryModel;
46 import com.gitblit.models.UserModel;
47 import com.gitblit.utils.StringUtils;
48 import com.gitblit.wicket.GitBlitWebApp;
49 import com.gitblit.wicket.GitBlitWebSession;
9bdf88 50 import com.gitblit.wicket.GitblitRedirectException;
1e1b85 51 import com.gitblit.wicket.WicketUtils;
afbaeb 52 import com.gitblit.wicket.panels.BooleanOption;
c9921b 53 import com.gitblit.wicket.panels.ChoiceOption;
1e1b85 54 import com.gitblit.wicket.panels.ProjectRepositoryPanel;
05f229 55 import com.gitblit.wicket.panels.SshKeysPanel;
c9921b 56 import com.gitblit.wicket.panels.TextOption;
JM 57 import com.gitblit.wicket.panels.UserTitlePanel;
1e1b85 58
JM 59 public class UserPage extends RootPage {
699e71 60
1e1b85 61     List<ProjectModel> projectModels = new ArrayList<ProjectModel>();
JM 62
63     public UserPage() {
64         super();
9bdf88 65         throw new GitblitRedirectException(GitBlitWebApp.get().getHomePage());
1e1b85 66     }
JM 67
68     public UserPage(PageParameters params) {
69         super(params);
70         setup(params);
71     }
72
73     @Override
74     protected boolean reusePageParameters() {
75         return true;
76     }
77
78     private void setup(PageParameters params) {
79         setupPage("", "");
80         // check to see if we should display a login message
99d0d4 81         boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, true);
1e1b85 82         if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
JM 83             authenticationError("Please login");
84             return;
85         }
86
87         String userName = WicketUtils.getUsername(params);
88         if (StringUtils.isEmpty(userName)) {
9bdf88 89             throw new GitblitRedirectException(GitBlitWebApp.get().getHomePage());
1e1b85 90         }
JM 91
99d0d4 92         UserModel user = app().users().getUserModel(userName);
1e1b85 93         if (user == null) {
JM 94             // construct a temporary user model
95             user = new UserModel(userName);
96         }
699e71 97
JM 98
c9921b 99         add(new UserTitlePanel("userTitlePanel", user, user.username));
699e71 100
6662e3 101         UserModel sessionUser = GitBlitWebSession.get().getUser();
c9921b 102         boolean isMyProfile = sessionUser != null && sessionUser.equals(user);
JM 103
104         if (isMyProfile) {
105             addPreferences(user);
05f229 106
JM 107             if (app().gitblit().isServingSSH()) {
108                 // show the SSH key management tab
109                 addSshKeys(user);
110             } else {
111                 // SSH daemon is disabled, hide keys tab
112                 add(new Label("sshKeysLink").setVisible(false));
113                 add(new Label("sshKeysTab").setVisible(false));
114             }
6662e3 115         } else {
c9921b 116             // visiting user
JM 117             add(new Label("preferencesLink").setVisible(false));
118             add(new Label("preferencesTab").setVisible(false));
05f229 119
JM 120             add(new Label("sshKeysLink").setVisible(false));
121             add(new Label("sshKeysTab").setVisible(false));
6662e3 122         }
699e71 123
1e1b85 124         List<RepositoryModel> repositories = getRepositories(params);
699e71 125
1e1b85 126         Collections.sort(repositories, new Comparator<RepositoryModel>() {
JM 127             @Override
128             public int compare(RepositoryModel o1, RepositoryModel o2) {
129                 // reverse-chronological sort
130                 return o2.lastChange.compareTo(o1.lastChange);
131             }
132         });
133
134         final ListDataProvider<RepositoryModel> dp = new ListDataProvider<RepositoryModel>(repositories);
135         DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repositoryList", dp) {
136             private static final long serialVersionUID = 1L;
137
699e71 138             @Override
1e1b85 139             public void populateItem(final Item<RepositoryModel> item) {
JM 140                 final RepositoryModel entry = item.getModelObject();
699e71 141
JM 142                 ProjectRepositoryPanel row = new ProjectRepositoryPanel("repository",
1e1b85 143                         getLocalizer(), this, showAdmin, entry, getAccessRestrictions());
JM 144                 item.add(row);
145             }
146         };
147         add(dataView);
148     }
149
150     @Override
7a401a 151     protected void addDropDownMenus(List<NavLink> navLinks) {
1e1b85 152         PageParameters params = getPageParameters();
JM 153
7a401a 154         DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
1e1b85 155                 UserPage.class);
JM 156         // preserve time filter option on repository choices
157         menu.menuItems.addAll(getRepositoryFilterItems(params));
158
159         // preserve repository filter option on time choices
160         menu.menuItems.addAll(getTimeFilterItems(params));
161
162         if (menu.menuItems.size() > 0) {
163             // Reset Filter
856f3f 164             menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
1e1b85 165         }
JM 166
7a401a 167         navLinks.add(menu);
1e1b85 168     }
c9921b 169
JM 170     private void addPreferences(UserModel user) {
171         // add preferences
172         Form<Void> prefs = new Form<Void>("prefsForm");
173
174         List<Language> languages = Arrays.asList(
13dd75 175                 new Language("Deutsch","de"),
c9921b 176                 new Language("English","en"),
JM 177                 new Language("Español", "es"),
178                 new Language("Français", "fr"),
5881c4 179                 new Language("Italiano", "it"),
c9921b 180                 new Language("日本語", "ja"),
JM 181                 new Language("한국말", "ko"),
182                 new Language("Nederlands", "nl"),
183                 new Language("Norsk", "no"),
184                 new Language("Język Polski", "pl"),
185                 new Language("Português", "pt_BR"),
186                 new Language("中文", "zh_CN"));
187
6537de 188         Locale locale = user.getPreferences().getLocale();
JM 189         if (locale == null) {
c9921b 190             // user has not specified language preference
JM 191             // try server default preference
6537de 192             String lc = app().settings().getString(Keys.web.forceDefaultLocale, null);
c9921b 193             if (StringUtils.isEmpty(lc)) {
JM 194                 // server default language is not configured
195                 // try browser preference
196                 Locale sessionLocale = GitBlitWebSession.get().getLocale();
197                 if (sessionLocale != null) {
6537de 198                     locale = sessionLocale;
c9921b 199                 }
6537de 200             } else {
JM 201
c9921b 202             }
JM 203         }
6537de 204
c9921b 205         Language preferredLanguage = null;
6537de 206         if (locale != null) {
JM 207             String localeCode = locale.getLanguage();
208             if (!StringUtils.isEmpty(locale.getCountry())) {
209                 localeCode += "_" + locale.getCountry();
210             }
211
c9921b 212             for (Language language : languages) {
6537de 213                 if (language.code.equals(localeCode)) {
c9921b 214                     // language_COUNTRY match
JM 215                     preferredLanguage = language;
6537de 216                 } else if (preferredLanguage != null && language.code.startsWith(locale.getLanguage())) {
JM 217                     // language match
c9921b 218                     preferredLanguage = language;
JM 219                 }
220             }
221         }
222
223         final IModel<String> displayName = Model.of(user.getDisplayName());
224         final IModel<String> emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress);
225         final IModel<Language> language = Model.of(preferredLanguage);
afbaeb 226         final IModel<Boolean> emailMeOnMyTicketChanges = Model.of(user.getPreferences().isEmailMeOnMyTicketChanges());
1b04d7 227         final IModel<Transport> transport = Model.of(user.getPreferences().getTransport());
c9921b 228
JM 229         prefs.add(new TextOption("displayName",
230                 getString("gb.displayName"),
231                 getString("gb.displayNameDescription"),
232                 displayName).setVisible(app().authentication().supportsDisplayNameChanges(user)));
233
234         prefs.add(new TextOption("emailAddress",
235                 getString("gb.emailAddress"),
236                 getString("gb.emailAddressDescription"),
237                 emailAddress).setVisible(app().authentication().supportsEmailAddressChanges(user)));
238
239         prefs.add(new ChoiceOption<Language>("language",
240                 getString("gb.languagePreference"),
241                 getString("gb.languagePreferenceDescription"),
242                 language,
243                 languages));
244
afbaeb 245         prefs.add(new BooleanOption("emailMeOnMyTicketChanges",
JM 246                 getString("gb.emailMeOnMyTicketChanges"),
247                 getString("gb.emailMeOnMyTicketChangesDescription"),
248                 emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail()));
249
1b04d7 250         List<Transport> availableTransports = new ArrayList<>();
JM 251         if (app().gitblit().isServingSSH()) {
252             availableTransports.add(Transport.SSH);
253         }
254         if (app().gitblit().isServingHTTP()) {
255             availableTransports.add(Transport.HTTPS);
256             availableTransports.add(Transport.HTTP);
257         }
258         if (app().gitblit().isServingGIT()) {
259             availableTransports.add(Transport.GIT);
260         }
261
262         prefs.add(new ChoiceOption<Transport>("transport",
263                 getString("gb.transportPreference"),
264                 getString("gb.transportPreferenceDescription"),
265                 transport,
266                 availableTransports));
267
c9921b 268         prefs.add(new AjaxButton("save") {
JM 269
270             private static final long serialVersionUID = 1L;
271
272             @Override
273             protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
274
275                 UserModel user = GitBlitWebSession.get().getUser();
276
277                 user.displayName = displayName.getObject();
278                 user.emailAddress = emailAddress.getObject();
279
280                 Language lang = language.getObject();
281                 if (lang != null) {
6537de 282                     user.getPreferences().setLocale(lang.code);
c9921b 283                 }
JM 284
afbaeb 285                 user.getPreferences().setEmailMeOnMyTicketChanges(emailMeOnMyTicketChanges.getObject());
1b04d7 286                 user.getPreferences().setTransport(transport.getObject());
afbaeb 287
c9921b 288                 try {
JM 289                     app().gitblit().reviseUser(user.username, user);
290
291                     setRedirect(true);
292                     setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(user.username));
293                 } catch (GitBlitException e) {
294                     // logger.error("Failed to update user " + user.username, e);
295                     // error(getString("gb.failedToUpdateUser"), false);
296                 }
297             }
298         });
299
300         // add the preferences tab
301         add(new Fragment("preferencesLink", "preferencesLinkFragment", this).setRenderBodyOnly(true));
302         Fragment fragment = new Fragment("preferencesTab", "preferencesTabFragment", this);
303         fragment.add(prefs);
304         add(fragment.setRenderBodyOnly(true));
305     }
306
05f229 307     private void addSshKeys(final UserModel user) {
JM 308         Fragment keysTab = new Fragment("sshKeysTab", "sshKeysTabFragment", this);
b0658e 309         keysTab.add(new SshKeysPanel("sshKeysPanel", user));
05f229 310
JM 311         // add the SSH keys tab
312         add(new Fragment("sshKeysLink", "sshKeysLinkFragment", this).setRenderBodyOnly(true));
313         add(keysTab.setRenderBodyOnly(true));
314     }
315
c9921b 316     private class Language implements Serializable {
JM 317
318         private static final long serialVersionUID = 1L;
319
320         final String name;
321         final String code;
322
323         public Language(String name, String code) {
324             this.name = name;
325             this.code = code;
326         }
327
328         @Override
329         public String toString() {
330             return name + " (" + code +")";
331         }
332     }
1e1b85 333 }