| | |
| | | /*
|
| | | * 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 java.util.ArrayList;
|
| | | import java.util.Arrays;
|
| | | import java.util.Calendar;
|
| | | import java.util.Collections;
|
| | | import java.util.Date;
|
| | | import java.util.HashMap;
|
| | | import java.util.HashSet;
|
| | | import java.util.LinkedHashSet;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Set;
|
| | | import java.util.concurrent.atomic.AtomicInteger;
|
| | | import java.util.regex.Pattern;
|
| | |
|
| | | import org.apache.wicket.MarkupContainer;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.PasswordTextField;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | 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.Keys;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.TeamModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.PageRegistration;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.SessionlessForm;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.GravatarImage;
|
| | | import com.gitblit.wicket.panels.NavigationPanel;
|
| | |
|
| | | /**
|
| | | * Root page is a topbar, navigable page like Repositories, Users, or
|
| | | * Federation.
|
| | | * |
| | | * @author James Moger
|
| | | * |
| | | */
|
| | | public abstract class RootPage extends BasePage {
|
| | |
|
| | | boolean showAdmin;
|
| | |
|
| | | IModel<String> username = new Model<String>("");
|
| | | IModel<String> password = new Model<String>("");
|
| | | List<RepositoryModel> repositoryModels = new ArrayList<RepositoryModel>();
|
| | |
|
| | | public RootPage() {
|
| | | super();
|
| | | }
|
| | |
|
| | | public RootPage(PageParameters params) {
|
| | | super(params);
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void setupPage(String repositoryName, String pageName) {
|
| | | boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, false);
|
| | | boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
|
| | | boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, true);
|
| | |
|
| | | if (authenticateAdmin) {
|
| | | showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
|
| | | // authentication requires state and session
|
| | | setStatelessHint(false);
|
| | | } else {
|
| | | showAdmin = allowAdmin;
|
| | | if (authenticateView) {
|
| | | // authentication requires state and session
|
| | | setStatelessHint(false);
|
| | | } else {
|
| | | // no authentication required, no state and no session required
|
| | | setStatelessHint(true);
|
| | | }
|
| | | }
|
| | | |
| | | if (authenticateView || authenticateAdmin) {
|
| | | if (GitBlitWebSession.get().isLoggedIn()) {
|
| | | UserMenu userFragment = new UserMenu("userPanel", "userMenuFragment", RootPage.this);
|
| | | add(userFragment);
|
| | | } else {
|
| | | LoginForm loginForm = new LoginForm("userPanel", "loginFormFragment", RootPage.this);
|
| | | add(loginForm);
|
| | | }
|
| | | } else {
|
| | | add(new Label("userPanel").setVisible(false));
|
| | | }
|
| | | |
| | | boolean showRegistrations = GitBlit.canFederate()
|
| | | && GitBlit.getBoolean(Keys.web.showFederationRegistrations, false);
|
| | |
|
| | | // navigation links
|
| | | List<PageRegistration> pages = new ArrayList<PageRegistration>();
|
| | | if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) {
|
| | | // pages.add(new PageRegistration("gb.home", HomePage.class,
|
| | | // getRootPageParameters()));
|
| | | pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class,
|
| | | getRootPageParameters()));
|
| | | pages.add(new PageRegistration("gb.activity", ActivityPage.class, getRootPageParameters()));
|
| | | if (GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true)) {
|
| | | pages.add(new PageRegistration("gb.search", LuceneSearchPage.class));
|
| | | }
|
| | | if (showAdmin) {
|
| | | pages.add(new PageRegistration("gb.users", UsersPage.class));
|
| | | }
|
| | | if (showAdmin || showRegistrations) {
|
| | | pages.add(new PageRegistration("gb.federation", FederationPage.class));
|
| | | }
|
| | |
|
| | | if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) {
|
| | | addDropDownMenus(pages);
|
| | | }
|
| | | }
|
| | | |
| | | NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), pages);
|
| | | add(navPanel);
|
| | |
|
| | | // display an error message cached from a redirect
|
| | | String cachedMessage = GitBlitWebSession.get().clearErrorMessage();
|
| | | if (!StringUtils.isEmpty(cachedMessage)) {
|
| | | error(cachedMessage);
|
| | | } else if (showAdmin) {
|
| | | int pendingProposals = GitBlit.self().getPendingFederationProposals().size();
|
| | | if (pendingProposals == 1) {
|
| | | info(getString("gb.OneProposalToReview"));
|
| | | } else if (pendingProposals > 1) {
|
| | | info(MessageFormat.format(getString("gb.nFederationProposalsToReview"),
|
| | | pendingProposals));
|
| | | }
|
| | | }
|
| | |
|
| | | super.setupPage(repositoryName, pageName);
|
| | | }
|
| | | |
| | | protected Class<? extends BasePage> getRootNavPageClass() {
|
| | | return getClass();
|
| | | }
|
| | |
|
| | | private PageParameters getRootPageParameters() {
|
| | | if (reusePageParameters()) {
|
| | | PageParameters pp = getPageParameters();
|
| | | if (pp != null) {
|
| | | PageParameters params = new PageParameters(pp);
|
| | | // remove named project parameter
|
| | | params.remove("p");
|
| | |
|
| | | // remove named repository parameter
|
| | | params.remove("r");
|
| | |
|
| | | // remove named user parameter
|
| | | params.remove("user");
|
| | |
|
| | | // remove days back parameter if it is the default value
|
| | | if (params.containsKey("db")
|
| | | && params.getInt("db") == GitBlit.getInteger(Keys.web.activityDuration, 14)) {
|
| | | params.remove("db");
|
| | | }
|
| | | return params;
|
| | | } |
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | protected boolean reusePageParameters() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | private void loginUser(UserModel user) {
|
| | | if (user != null) {
|
| | | // Set the user into the session
|
| | | GitBlitWebSession session = GitBlitWebSession.get();
|
| | | // issue 62: fix session fixation vulnerability
|
| | | session.replaceSession();
|
| | | session.setUser(user);
|
| | |
|
| | | // Set Cookie
|
| | | if (GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) {
|
| | | WebResponse response = (WebResponse) getRequestCycle().getResponse();
|
| | | GitBlit.self().setCookie(response, user);
|
| | | }
|
| | |
|
| | | if (!session.continueRequest()) {
|
| | | PageParameters params = getPageParameters();
|
| | | if (params == null) {
|
| | | // redirect to this page
|
| | | setResponsePage(getClass());
|
| | | } else {
|
| | | // Strip username and password and redirect to this page
|
| | | params.remove("username");
|
| | | params.remove("password");
|
| | | setResponsePage(getClass(), params);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | |
| | | protected List<RepositoryModel> getRepositoryModels() {
|
| | | if (repositoryModels.isEmpty()) {
|
| | | final UserModel user = GitBlitWebSession.get().getUser();
|
| | | List<RepositoryModel> repositories = GitBlit.self().getRepositoryModels(user);
|
| | | repositoryModels.addAll(repositories);
|
| | | Collections.sort(repositoryModels);
|
| | | }
|
| | | return repositoryModels;
|
| | | }
|
| | |
|
| | | protected void addDropDownMenus(List<PageRegistration> pages) {
|
| | |
|
| | | }
|
| | |
|
| | | protected List<DropDownMenuItem> getRepositoryFilterItems(PageParameters params) {
|
| | | final UserModel user = GitBlitWebSession.get().getUser();
|
| | | Set<DropDownMenuItem> filters = new LinkedHashSet<DropDownMenuItem>();
|
| | | List<RepositoryModel> repositories = getRepositoryModels();
|
| | |
|
| | | // accessible repositories by federation set
|
| | | Map<String, AtomicInteger> setMap = new HashMap<String, AtomicInteger>();
|
| | | for (RepositoryModel repository : repositories) {
|
| | | for (String set : repository.federationSets) {
|
| | | String key = set.toLowerCase();
|
| | | if (setMap.containsKey(key)) {
|
| | | setMap.get(key).incrementAndGet();
|
| | | } else {
|
| | | setMap.put(key, new AtomicInteger(1));
|
| | | }
|
| | | }
|
| | | }
|
| | | if (setMap.size() > 0) {
|
| | | List<String> sets = new ArrayList<String>(setMap.keySet());
|
| | | Collections.sort(sets);
|
| | | for (String set : sets) {
|
| | | filters.add(new DropDownMenuItem(MessageFormat.format("{0} ({1})", set,
|
| | | setMap.get(set).get()), "set", set, params));
|
| | | }
|
| | | // divider
|
| | | filters.add(new DropDownMenuItem());
|
| | | }
|
| | |
|
| | | // user's team memberships
|
| | | if (user != null && user.teams.size() > 0) {
|
| | | List<TeamModel> teams = new ArrayList<TeamModel>(user.teams);
|
| | | Collections.sort(teams);
|
| | | for (TeamModel team : teams) {
|
| | | filters.add(new DropDownMenuItem(MessageFormat.format("{0} ({1})", team.name,
|
| | | team.repositories.size()), "team", team.name, params));
|
| | | }
|
| | | // divider
|
| | | filters.add(new DropDownMenuItem());
|
| | | }
|
| | |
|
| | | // custom filters
|
| | | String customFilters = GitBlit.getString(Keys.web.customFilters, null);
|
| | | if (!StringUtils.isEmpty(customFilters)) {
|
| | | boolean addedExpression = false;
|
| | | List<String> expressions = StringUtils.getStringsFromValue(customFilters, "!!!");
|
| | | for (String expression : expressions) {
|
| | | if (!StringUtils.isEmpty(expression)) {
|
| | | addedExpression = true;
|
| | | filters.add(new DropDownMenuItem(null, "x", expression, params));
|
| | | }
|
| | | }
|
| | | // if we added any custom expressions, add a divider
|
| | | if (addedExpression) {
|
| | | filters.add(new DropDownMenuItem());
|
| | | }
|
| | | }
|
| | | return new ArrayList<DropDownMenuItem>(filters);
|
| | | }
|
| | |
|
| | | protected List<DropDownMenuItem> getTimeFilterItems(PageParameters params) {
|
| | | // days back choices - additive parameters
|
| | | int daysBack = GitBlit.getInteger(Keys.web.activityDuration, 14);
|
| | | if (daysBack < 1) {
|
| | | daysBack = 14;
|
| | | }
|
| | | List<DropDownMenuItem> items = new ArrayList<DropDownMenuItem>();
|
| | | Set<Integer> choicesSet = new HashSet<Integer>(Arrays.asList(daysBack, 14, 28, 60, 90, 180));
|
| | | List<Integer> choices = new ArrayList<Integer>(choicesSet);
|
| | | Collections.sort(choices);
|
| | | String lastDaysPattern = getString("gb.lastNDays");
|
| | | for (Integer db : choices) {
|
| | | String txt = MessageFormat.format(lastDaysPattern, db);
|
| | | items.add(new DropDownMenuItem(txt, "db", db.toString(), params));
|
| | | }
|
| | | items.add(new DropDownMenuItem());
|
| | | return items;
|
| | | }
|
| | |
|
| | | protected List<RepositoryModel> getRepositories(PageParameters params) {
|
| | | if (params == null) {
|
| | | return getRepositoryModels();
|
| | | }
|
| | |
|
| | | boolean hasParameter = false;
|
| | | String projectName = WicketUtils.getProjectName(params);
|
| | | String userName = WicketUtils.getUsername(params);
|
| | | if (StringUtils.isEmpty(projectName)) {
|
| | | if (!StringUtils.isEmpty(userName)) {
|
| | | projectName = "~" + userName;
|
| | | }
|
| | | }
|
| | | String repositoryName = WicketUtils.getRepositoryName(params);
|
| | | String set = WicketUtils.getSet(params);
|
| | | String regex = WicketUtils.getRegEx(params);
|
| | | String team = WicketUtils.getTeam(params);
|
| | | int daysBack = params.getInt("db", 0);
|
| | |
|
| | | List<RepositoryModel> availableModels = getRepositoryModels();
|
| | | Set<RepositoryModel> models = new HashSet<RepositoryModel>();
|
| | |
|
| | | if (!StringUtils.isEmpty(repositoryName)) {
|
| | | // try named repository
|
| | | hasParameter = true;
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (model.name.equalsIgnoreCase(repositoryName)) {
|
| | | models.add(model);
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(projectName)) {
|
| | | // try named project
|
| | | hasParameter = true; |
| | | if (projectName.equalsIgnoreCase(GitBlit.getString(Keys.web.repositoryRootGroupName, "main"))) {
|
| | | // root project/group
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (model.name.indexOf('/') == -1) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | } else {
|
| | | // named project/group
|
| | | String group = projectName.toLowerCase() + "/";
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (model.name.toLowerCase().startsWith(group)) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(regex)) {
|
| | | // filter the repositories by the regex
|
| | | hasParameter = true;
|
| | | Pattern pattern = Pattern.compile(regex);
|
| | | for (RepositoryModel model : availableModels) {
|
| | | if (pattern.matcher(model.name).find()) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(set)) {
|
| | | // filter the repositories by the specified sets
|
| | | hasParameter = true;
|
| | | List<String> sets = StringUtils.getStringsFromValue(set, ",");
|
| | | for (RepositoryModel model : availableModels) {
|
| | | for (String curr : sets) {
|
| | | if (model.federationSets.contains(curr)) {
|
| | | models.add(model);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!StringUtils.isEmpty(team)) {
|
| | | // filter the repositories by the specified teams
|
| | | hasParameter = true;
|
| | | List<String> teams = StringUtils.getStringsFromValue(team, ",");
|
| | |
|
| | | // need TeamModels first
|
| | | List<TeamModel> teamModels = new ArrayList<TeamModel>();
|
| | | for (String name : teams) {
|
| | | TeamModel teamModel = GitBlit.self().getTeamModel(name);
|
| | | if (teamModel != null) {
|
| | | teamModels.add(teamModel);
|
| | | }
|
| | | }
|
| | |
|
| | | // brute-force our way through finding the matching models
|
| | | for (RepositoryModel repositoryModel : availableModels) {
|
| | | for (TeamModel teamModel : teamModels) {
|
| | | if (teamModel.hasRepositoryPermission(repositoryModel.name)) {
|
| | | models.add(repositoryModel);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (!hasParameter) {
|
| | | models.addAll(availableModels);
|
| | | }
|
| | |
|
| | | // time-filter the list
|
| | | if (daysBack > 0) {
|
| | | Calendar cal = Calendar.getInstance();
|
| | | cal.set(Calendar.HOUR_OF_DAY, 0);
|
| | | cal.set(Calendar.MINUTE, 0);
|
| | | cal.set(Calendar.SECOND, 0);
|
| | | cal.set(Calendar.MILLISECOND, 0);
|
| | | cal.add(Calendar.DATE, -1 * daysBack);
|
| | | Date threshold = cal.getTime();
|
| | | Set<RepositoryModel> timeFiltered = new HashSet<RepositoryModel>();
|
| | | for (RepositoryModel model : models) {
|
| | | if (model.lastChange.after(threshold)) {
|
| | | timeFiltered.add(model);
|
| | | }
|
| | | }
|
| | | models = timeFiltered;
|
| | | }
|
| | | |
| | | List<RepositoryModel> list = new ArrayList<RepositoryModel>(models);
|
| | | Collections.sort(list);
|
| | | return list;
|
| | | }
|
| | | |
| | | /**
|
| | | * Inline login form. |
| | | */
|
| | | private class LoginForm extends Fragment {
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public LoginForm(String id, String markupId, MarkupContainer markupProvider) {
|
| | | super(id, markupId, markupProvider);
|
| | | setRenderBodyOnly(true);
|
| | |
|
| | | SessionlessForm<Void> loginForm = new SessionlessForm<Void>("loginForm", RootPage.this.getClass(), getPageParameters()) {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onSubmit() {
|
| | | String username = RootPage.this.username.getObject();
|
| | | char[] password = RootPage.this.password.getObject().toCharArray();
|
| | |
|
| | | UserModel user = GitBlit.self().authenticate(username, password);
|
| | | if (user == null) {
|
| | | error(getString("gb.invalidUsernameOrPassword"));
|
| | | } else if (user.username.equals(Constants.FEDERATION_USER)) {
|
| | | // disallow the federation user from logging in via the
|
| | | // web ui
|
| | | error(getString("gb.invalidUsernameOrPassword"));
|
| | | user = null;
|
| | | } else {
|
| | | loginUser(user);
|
| | | }
|
| | | }
|
| | | };
|
| | | TextField<String> unameField = new TextField<String>("username", username);
|
| | | WicketUtils.setInputPlaceholder(unameField, markupProvider.getString("gb.username"));
|
| | | loginForm.add(unameField);
|
| | | PasswordTextField pwField = new PasswordTextField("password", password);
|
| | | WicketUtils.setInputPlaceholder(pwField, markupProvider.getString("gb.password"));
|
| | | loginForm.add(pwField);
|
| | | add(loginForm);
|
| | | }
|
| | | }
|
| | | |
| | | /**
|
| | | * Menu for the authenticated user.
|
| | | */
|
| | | static class UserMenu extends Fragment {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public UserMenu(String id, String markupId, MarkupContainer markupProvider) {
|
| | | super(id, markupId, markupProvider);
|
| | | setRenderBodyOnly(true);
|
| | |
|
| | | GitBlitWebSession session = GitBlitWebSession.get();
|
| | | UserModel user = session.getUser();
|
| | | boolean editCredentials = GitBlit.self().supportsCredentialChanges(user);
|
| | | boolean standardLogin = session.authenticationType.isStandard();
|
| | |
|
| | | if (GitBlit.getBoolean(Keys.web.allowGravatar, true)) {
|
| | | add(new GravatarImage("username", user.getDisplayName(),
|
| | | user.emailAddress, "navbarGravatar", 20, false, false));
|
| | | } else {
|
| | | add(new Label("username", user.getDisplayName()));
|
| | | }
|
| | |
|
| | | add(new Label("displayName", user.getDisplayName()));
|
| | | |
| | | add(new BookmarkablePageLink<Void>("myProfile", |
| | | UserPage.class, WicketUtils.newUsernameParameter(user.username)));
|
| | |
|
| | | add(new BookmarkablePageLink<Void>("changePassword", |
| | | ChangePasswordPage.class).setVisible(editCredentials));
|
| | | |
| | | add(new BookmarkablePageLink<Void>("logout",
|
| | | LogoutPage.class).setVisible(standardLogin));
|
| | | }
|
| | | }
|
| | | }
|
| | | /* |
| | | * 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 java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Calendar; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.regex.Pattern; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | |
| | | import org.apache.wicket.MarkupContainer; |
| | | import org.apache.wicket.PageParameters; |
| | | import org.apache.wicket.RequestCycle; |
| | | import org.apache.wicket.behavior.HeaderContributor; |
| | | import org.apache.wicket.markup.html.IHeaderContributor; |
| | | import org.apache.wicket.markup.html.IHeaderResponse; |
| | | import org.apache.wicket.markup.html.basic.Label; |
| | | import org.apache.wicket.markup.html.form.TextField; |
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink; |
| | | 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.apache.wicket.model.IModel; |
| | | import org.apache.wicket.model.Model; |
| | | import org.apache.wicket.protocol.http.WebRequest; |
| | | import org.apache.wicket.protocol.http.WebResponse; |
| | | |
| | | import com.gitblit.Constants; |
| | | import com.gitblit.Constants.AuthenticationType; |
| | | import com.gitblit.Keys; |
| | | import com.gitblit.extensions.NavLinkExtension; |
| | | import com.gitblit.extensions.UserMenuExtension; |
| | | import com.gitblit.models.Menu.ExternalLinkMenuItem; |
| | | import com.gitblit.models.Menu.MenuDivider; |
| | | import com.gitblit.models.Menu.MenuItem; |
| | | import com.gitblit.models.Menu.PageLinkMenuItem; |
| | | import com.gitblit.models.Menu.ParameterMenuItem; |
| | | import com.gitblit.models.Menu.ToggleMenuItem; |
| | | import com.gitblit.models.NavLink; |
| | | import com.gitblit.models.NavLink.PageNavLink; |
| | | import com.gitblit.models.RepositoryModel; |
| | | import com.gitblit.models.TeamModel; |
| | | import com.gitblit.models.UserModel; |
| | | import com.gitblit.utils.ModelUtils; |
| | | import com.gitblit.utils.StringUtils; |
| | | import com.gitblit.wicket.GitBlitWebSession; |
| | | import com.gitblit.wicket.NonTrimmedPasswordTextField; |
| | | import com.gitblit.wicket.SessionlessForm; |
| | | import com.gitblit.wicket.WicketUtils; |
| | | import com.gitblit.wicket.panels.AvatarImage; |
| | | import com.gitblit.wicket.panels.LinkPanel; |
| | | import com.gitblit.wicket.panels.NavigationPanel; |
| | | |
| | | /** |
| | | * Root page is a topbar, navigable page like Repositories, Users, or |
| | | * Federation. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public abstract class RootPage extends BasePage { |
| | | |
| | | boolean showAdmin; |
| | | |
| | | IModel<String> username = new Model<String>(""); |
| | | IModel<String> password = new Model<String>(""); |
| | | List<RepositoryModel> repositoryModels = new ArrayList<RepositoryModel>(); |
| | | |
| | | public RootPage() { |
| | | super(); |
| | | } |
| | | |
| | | public RootPage(PageParameters params) { |
| | | super(params); |
| | | } |
| | | |
| | | @Override |
| | | protected void setupPage(String repositoryName, String pageName) { |
| | | |
| | | // CSS header overrides |
| | | add(new HeaderContributor(new IHeaderContributor() { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void renderHead(IHeaderResponse response) { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | buffer.append("<style type=\"text/css\">\n"); |
| | | buffer.append(".navbar-inner {\n"); |
| | | final String headerBackground = app().settings().getString(Keys.web.headerBackgroundColor, null); |
| | | if (!StringUtils.isEmpty(headerBackground)) { |
| | | buffer.append(MessageFormat.format("background-color: {0};\n", headerBackground)); |
| | | } |
| | | final String headerBorder = app().settings().getString(Keys.web.headerBorderColor, null); |
| | | if (!StringUtils.isEmpty(headerBorder)) { |
| | | buffer.append(MessageFormat.format("border-bottom: 1px solid {0} !important;\n", headerBorder)); |
| | | } |
| | | buffer.append("}\n"); |
| | | final String headerBorderFocus = app().settings().getString(Keys.web.headerBorderFocusColor, null); |
| | | if (!StringUtils.isEmpty(headerBorderFocus)) { |
| | | buffer.append(".navbar ul li:focus, .navbar .active {\n"); |
| | | buffer.append(MessageFormat.format("border-bottom: 4px solid {0};\n", headerBorderFocus)); |
| | | buffer.append("}\n"); |
| | | } |
| | | final String headerForeground = app().settings().getString(Keys.web.headerForegroundColor, null); |
| | | if (!StringUtils.isEmpty(headerForeground)) { |
| | | buffer.append(".navbar ul.nav li a {\n"); |
| | | buffer.append(MessageFormat.format("color: {0};\n", headerForeground)); |
| | | buffer.append("}\n"); |
| | | buffer.append(".navbar ul.nav .active a {\n"); |
| | | buffer.append(MessageFormat.format("color: {0};\n", headerForeground)); |
| | | buffer.append("}\n"); |
| | | } |
| | | final String headerHover = app().settings().getString(Keys.web.headerHoverColor, null); |
| | | if (!StringUtils.isEmpty(headerHover)) { |
| | | buffer.append(".navbar ul.nav li a:hover {\n"); |
| | | buffer.append(MessageFormat.format("color: {0} !important;\n", headerHover)); |
| | | buffer.append("}\n"); |
| | | } |
| | | buffer.append("</style>\n"); |
| | | response.renderString(buffer.toString()); |
| | | } |
| | | })); |
| | | |
| | | boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, false); |
| | | boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true); |
| | | boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true); |
| | | boolean allowLucene = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true); |
| | | boolean displayUserPanel = app().settings().getBoolean(Keys.web.displayUserPanel, true); |
| | | boolean isLoggedIn = GitBlitWebSession.get().isLoggedIn(); |
| | | |
| | | if (authenticateAdmin) { |
| | | showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin(); |
| | | // authentication requires state and session |
| | | setStatelessHint(false); |
| | | } else { |
| | | showAdmin = allowAdmin; |
| | | if (authenticateView) { |
| | | // authentication requires state and session |
| | | setStatelessHint(false); |
| | | } else { |
| | | // no authentication required, no state and no session required |
| | | setStatelessHint(true); |
| | | } |
| | | } |
| | | |
| | | if (displayUserPanel && (authenticateView || authenticateAdmin)) { |
| | | if (isLoggedIn) { |
| | | UserMenu userFragment = new UserMenu("userPanel", "userMenuFragment", RootPage.this); |
| | | add(userFragment); |
| | | } else { |
| | | LoginForm loginForm = new LoginForm("userPanel", "loginFormFragment", RootPage.this); |
| | | add(loginForm); |
| | | } |
| | | } else { |
| | | add(new Label("userPanel").setVisible(false)); |
| | | } |
| | | |
| | | // navigation links |
| | | List<NavLink> navLinks = new ArrayList<NavLink>(); |
| | | if (!authenticateView || (authenticateView && isLoggedIn)) { |
| | | UserModel user = UserModel.ANONYMOUS; |
| | | if (isLoggedIn) { |
| | | user = GitBlitWebSession.get().getUser(); |
| | | } |
| | | |
| | | navLinks.add(new PageNavLink(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class, |
| | | getRootPageParameters())); |
| | | if (isLoggedIn && app().tickets().isReady()) { |
| | | navLinks.add(new PageNavLink("gb.myTickets", MyTicketsPage.class)); |
| | | } |
| | | navLinks.add(new PageNavLink("gb.repositories", RepositoriesPage.class, |
| | | getRootPageParameters())); |
| | | |
| | | navLinks.add(new PageNavLink("gb.filestore", FilestorePage.class, getRootPageParameters())); |
| | | |
| | | navLinks.add(new PageNavLink("gb.activity", ActivityPage.class, getRootPageParameters())); |
| | | if (allowLucene) { |
| | | navLinks.add(new PageNavLink("gb.search", LuceneSearchPage.class)); |
| | | } |
| | | |
| | | if (!authenticateView || (authenticateView && isLoggedIn)) { |
| | | addDropDownMenus(navLinks); |
| | | } |
| | | |
| | | // add nav link extensions |
| | | List<NavLinkExtension> extensions = app().plugins().getExtensions(NavLinkExtension.class); |
| | | for (NavLinkExtension ext : extensions) { |
| | | navLinks.addAll(ext.getNavLinks(user)); |
| | | } |
| | | } |
| | | |
| | | NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), navLinks); |
| | | add(navPanel); |
| | | |
| | | // display an error message cached from a redirect |
| | | String cachedMessage = GitBlitWebSession.get().clearErrorMessage(); |
| | | if (!StringUtils.isEmpty(cachedMessage)) { |
| | | error(cachedMessage); |
| | | } else if (showAdmin) { |
| | | int pendingProposals = app().federation().getPendingFederationProposals().size(); |
| | | if (pendingProposals == 1) { |
| | | info(getString("gb.OneProposalToReview")); |
| | | } else if (pendingProposals > 1) { |
| | | info(MessageFormat.format(getString("gb.nFederationProposalsToReview"), |
| | | pendingProposals)); |
| | | } |
| | | } |
| | | |
| | | super.setupPage(repositoryName, pageName); |
| | | } |
| | | |
| | | protected Class<? extends BasePage> getRootNavPageClass() { |
| | | return getClass(); |
| | | } |
| | | |
| | | private PageParameters getRootPageParameters() { |
| | | if (reusePageParameters()) { |
| | | PageParameters pp = getPageParameters(); |
| | | if (pp != null) { |
| | | PageParameters params = new PageParameters(pp); |
| | | // remove named project parameter |
| | | params.remove("p"); |
| | | |
| | | // remove named repository parameter |
| | | params.remove("r"); |
| | | |
| | | // remove named user parameter |
| | | params.remove("user"); |
| | | |
| | | // remove days back parameter if it is the default value |
| | | if (params.containsKey("db") |
| | | && params.getInt("db") == app().settings().getInteger(Keys.web.activityDuration, 7)) { |
| | | params.remove("db"); |
| | | } |
| | | return params; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | protected boolean reusePageParameters() { |
| | | return false; |
| | | } |
| | | |
| | | private void loginUser(UserModel user) { |
| | | if (user != null) { |
| | | HttpServletRequest request = ((WebRequest) getRequest()).getHttpServletRequest(); |
| | | HttpServletResponse response = ((WebResponse) getResponse()).getHttpServletResponse(); |
| | | |
| | | // Set the user into the session |
| | | GitBlitWebSession session = GitBlitWebSession.get(); |
| | | |
| | | // issue 62: fix session fixation vulnerability |
| | | session.replaceSession(); |
| | | session.setUser(user); |
| | | |
| | | request = ((WebRequest) getRequest()).getHttpServletRequest(); |
| | | response = ((WebResponse) getResponse()).getHttpServletResponse(); |
| | | request.getSession().setAttribute(Constants.ATTRIB_AUTHTYPE, AuthenticationType.CREDENTIALS); |
| | | |
| | | // Set Cookie |
| | | app().authentication().setCookie(request, response, user); |
| | | |
| | | if (!session.continueRequest()) { |
| | | PageParameters params = getPageParameters(); |
| | | if (params == null) { |
| | | // redirect to this page |
| | | redirectTo(getClass()); |
| | | } else { |
| | | // Strip username and password and redirect to this page |
| | | params.remove("username"); |
| | | params.remove("password"); |
| | | redirectTo(getClass(), params); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected List<RepositoryModel> getRepositoryModels() { |
| | | if (repositoryModels.isEmpty()) { |
| | | final UserModel user = GitBlitWebSession.get().getUser(); |
| | | List<RepositoryModel> repositories = app().repositories().getRepositoryModels(user); |
| | | repositoryModels.addAll(repositories); |
| | | Collections.sort(repositoryModels); |
| | | } |
| | | return repositoryModels; |
| | | } |
| | | |
| | | protected void addDropDownMenus(List<NavLink> navLinks) { |
| | | |
| | | } |
| | | |
| | | protected List<com.gitblit.models.Menu.MenuItem> getRepositoryFilterItems(PageParameters params) { |
| | | final UserModel user = GitBlitWebSession.get().getUser(); |
| | | Set<MenuItem> filters = new LinkedHashSet<MenuItem>(); |
| | | List<RepositoryModel> repositories = getRepositoryModels(); |
| | | |
| | | // accessible repositories by federation set |
| | | Map<String, AtomicInteger> setMap = new HashMap<String, AtomicInteger>(); |
| | | for (RepositoryModel repository : repositories) { |
| | | for (String set : repository.federationSets) { |
| | | String key = set.toLowerCase(); |
| | | if (setMap.containsKey(key)) { |
| | | setMap.get(key).incrementAndGet(); |
| | | } else { |
| | | setMap.put(key, new AtomicInteger(1)); |
| | | } |
| | | } |
| | | } |
| | | if (setMap.size() > 0) { |
| | | List<String> sets = new ArrayList<String>(setMap.keySet()); |
| | | Collections.sort(sets); |
| | | for (String set : sets) { |
| | | filters.add(new ToggleMenuItem(MessageFormat.format("{0} ({1})", set, |
| | | setMap.get(set).get()), "set", set, params)); |
| | | } |
| | | // divider |
| | | filters.add(new MenuDivider()); |
| | | } |
| | | |
| | | // user's team memberships |
| | | if (user != null && user.teams.size() > 0) { |
| | | List<TeamModel> teams = new ArrayList<TeamModel>(user.teams); |
| | | Collections.sort(teams); |
| | | for (TeamModel team : teams) { |
| | | filters.add(new ToggleMenuItem(MessageFormat.format("{0} ({1})", team.name, |
| | | team.repositories.size()), "team", team.name, params)); |
| | | } |
| | | // divider |
| | | filters.add(new MenuDivider()); |
| | | } |
| | | |
| | | // custom filters |
| | | String customFilters = app().settings().getString(Keys.web.customFilters, null); |
| | | if (!StringUtils.isEmpty(customFilters)) { |
| | | boolean addedExpression = false; |
| | | List<String> expressions = StringUtils.getStringsFromValue(customFilters, "!!!"); |
| | | for (String expression : expressions) { |
| | | if (!StringUtils.isEmpty(expression)) { |
| | | addedExpression = true; |
| | | filters.add(new ToggleMenuItem(null, "x", expression, params)); |
| | | } |
| | | } |
| | | // if we added any custom expressions, add a divider |
| | | if (addedExpression) { |
| | | filters.add(new MenuDivider()); |
| | | } |
| | | } |
| | | return new ArrayList<MenuItem>(filters); |
| | | } |
| | | |
| | | protected List<MenuItem> getTimeFilterItems(PageParameters params) { |
| | | // days back choices - additive parameters |
| | | int daysBack = app().settings().getInteger(Keys.web.activityDuration, 7); |
| | | int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30); |
| | | if (daysBack < 1) { |
| | | daysBack = 7; |
| | | } |
| | | if (daysBack > maxDaysBack) { |
| | | daysBack = maxDaysBack; |
| | | } |
| | | PageParameters clonedParams; |
| | | if (params == null) { |
| | | clonedParams = new PageParameters(); |
| | | } else { |
| | | clonedParams = new PageParameters(params); |
| | | } |
| | | |
| | | if (!clonedParams.containsKey("db")) { |
| | | clonedParams.put("db", daysBack); |
| | | } |
| | | |
| | | List<MenuItem> items = new ArrayList<MenuItem>(); |
| | | Set<Integer> choicesSet = new TreeSet<Integer>(app().settings().getIntegers(Keys.web.activityDurationChoices)); |
| | | if (choicesSet.isEmpty()) { |
| | | choicesSet.addAll(Arrays.asList(1, 3, 7, 14, 21, 28)); |
| | | } |
| | | List<Integer> choices = new ArrayList<Integer>(choicesSet); |
| | | Collections.sort(choices); |
| | | String lastDaysPattern = getString("gb.lastNDays"); |
| | | for (Integer db : choices) { |
| | | if (db == 1) { |
| | | items.add(new ParameterMenuItem(getString("gb.time.today"), "db", db.toString(), clonedParams)); |
| | | } else { |
| | | String txt = MessageFormat.format(lastDaysPattern, db); |
| | | items.add(new ParameterMenuItem(txt, "db", db.toString(), clonedParams)); |
| | | } |
| | | } |
| | | items.add(new MenuDivider()); |
| | | return items; |
| | | } |
| | | |
| | | protected List<RepositoryModel> getRepositories(PageParameters params) { |
| | | if (params == null) { |
| | | return getRepositoryModels(); |
| | | } |
| | | |
| | | boolean hasParameter = false; |
| | | String projectName = WicketUtils.getProjectName(params); |
| | | String userName = WicketUtils.getUsername(params); |
| | | if (StringUtils.isEmpty(projectName)) { |
| | | if (!StringUtils.isEmpty(userName)) { |
| | | projectName = ModelUtils.getPersonalPath(userName); |
| | | } |
| | | } |
| | | String repositoryName = WicketUtils.getRepositoryName(params); |
| | | String set = WicketUtils.getSet(params); |
| | | String regex = WicketUtils.getRegEx(params); |
| | | String team = WicketUtils.getTeam(params); |
| | | int daysBack = params.getInt("db", 0); |
| | | int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30); |
| | | |
| | | List<RepositoryModel> availableModels = getRepositoryModels(); |
| | | Set<RepositoryModel> models = new HashSet<RepositoryModel>(); |
| | | |
| | | if (!StringUtils.isEmpty(repositoryName)) { |
| | | // try named repository |
| | | hasParameter = true; |
| | | for (RepositoryModel model : availableModels) { |
| | | if (model.name.equalsIgnoreCase(repositoryName)) { |
| | | models.add(model); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(projectName)) { |
| | | // try named project |
| | | hasParameter = true; |
| | | if (projectName.equalsIgnoreCase(app().settings().getString(Keys.web.repositoryRootGroupName, "main"))) { |
| | | // root project/group |
| | | for (RepositoryModel model : availableModels) { |
| | | if (model.name.indexOf('/') == -1) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } else { |
| | | // named project/group |
| | | String group = projectName.toLowerCase() + "/"; |
| | | for (RepositoryModel model : availableModels) { |
| | | if (model.name.toLowerCase().startsWith(group)) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(regex)) { |
| | | // filter the repositories by the regex |
| | | hasParameter = true; |
| | | Pattern pattern = Pattern.compile(regex); |
| | | for (RepositoryModel model : availableModels) { |
| | | if (pattern.matcher(model.name).find()) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(set)) { |
| | | // filter the repositories by the specified sets |
| | | hasParameter = true; |
| | | List<String> sets = StringUtils.getStringsFromValue(set, ","); |
| | | for (RepositoryModel model : availableModels) { |
| | | for (String curr : sets) { |
| | | if (model.federationSets.contains(curr)) { |
| | | models.add(model); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!StringUtils.isEmpty(team)) { |
| | | // filter the repositories by the specified teams |
| | | hasParameter = true; |
| | | List<String> teams = StringUtils.getStringsFromValue(team, ","); |
| | | |
| | | // need TeamModels first |
| | | List<TeamModel> teamModels = new ArrayList<TeamModel>(); |
| | | for (String name : teams) { |
| | | TeamModel teamModel = app().users().getTeamModel(name); |
| | | if (teamModel != null) { |
| | | teamModels.add(teamModel); |
| | | } |
| | | } |
| | | |
| | | // brute-force our way through finding the matching models |
| | | for (RepositoryModel repositoryModel : availableModels) { |
| | | for (TeamModel teamModel : teamModels) { |
| | | if (teamModel.hasRepositoryPermission(repositoryModel.name)) { |
| | | models.add(repositoryModel); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!hasParameter) { |
| | | models.addAll(availableModels); |
| | | } |
| | | |
| | | // time-filter the list |
| | | if (daysBack > 0) { |
| | | if (maxDaysBack > 0 && daysBack > maxDaysBack) { |
| | | daysBack = maxDaysBack; |
| | | } |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.set(Calendar.HOUR_OF_DAY, 0); |
| | | cal.set(Calendar.MINUTE, 0); |
| | | cal.set(Calendar.SECOND, 0); |
| | | cal.set(Calendar.MILLISECOND, 0); |
| | | cal.add(Calendar.DATE, -1 * daysBack); |
| | | Date threshold = cal.getTime(); |
| | | Set<RepositoryModel> timeFiltered = new HashSet<RepositoryModel>(); |
| | | for (RepositoryModel model : models) { |
| | | if (model.lastChange.after(threshold)) { |
| | | timeFiltered.add(model); |
| | | } |
| | | } |
| | | models = timeFiltered; |
| | | } |
| | | |
| | | List<RepositoryModel> list = new ArrayList<RepositoryModel>(models); |
| | | Collections.sort(list); |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * Inline login form. |
| | | */ |
| | | private class LoginForm extends Fragment { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public LoginForm(String id, String markupId, MarkupContainer markupProvider) { |
| | | super(id, markupId, markupProvider); |
| | | setRenderBodyOnly(true); |
| | | |
| | | SessionlessForm<Void> loginForm = new SessionlessForm<Void>("loginForm", RootPage.this.getClass(), getPageParameters()) { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void onSubmit() { |
| | | String username = RootPage.this.username.getObject(); |
| | | char[] password = RootPage.this.password.getObject().toCharArray(); |
| | | |
| | | HttpServletRequest request = ((WebRequest)RequestCycle.get().getRequest()).getHttpServletRequest(); |
| | | |
| | | UserModel user = app().authentication().authenticate(username, password, request.getRemoteAddr()); |
| | | if (user == null) { |
| | | error(getString("gb.invalidUsernameOrPassword")); |
| | | } else if (user.username.equals(Constants.FEDERATION_USER)) { |
| | | // disallow the federation user from logging in via the |
| | | // web ui |
| | | error(getString("gb.invalidUsernameOrPassword")); |
| | | user = null; |
| | | } else { |
| | | loginUser(user); |
| | | } |
| | | } |
| | | }; |
| | | TextField<String> unameField = new TextField<String>("username", username); |
| | | WicketUtils.setInputPlaceholder(unameField, markupProvider.getString("gb.username")); |
| | | loginForm.add(unameField); |
| | | NonTrimmedPasswordTextField pwField = new NonTrimmedPasswordTextField("password", password); |
| | | WicketUtils.setInputPlaceholder(pwField, markupProvider.getString("gb.password")); |
| | | loginForm.add(pwField); |
| | | add(loginForm); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Menu for the authenticated user. |
| | | */ |
| | | class UserMenu extends Fragment { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public UserMenu(String id, String markupId, MarkupContainer markupProvider) { |
| | | super(id, markupId, markupProvider); |
| | | setRenderBodyOnly(true); |
| | | } |
| | | |
| | | @Override |
| | | protected void onInitialize() { |
| | | super.onInitialize(); |
| | | |
| | | GitBlitWebSession session = GitBlitWebSession.get(); |
| | | UserModel user = session.getUser(); |
| | | boolean editCredentials = app().authentication().supportsCredentialChanges(user); |
| | | HttpServletRequest request = ((WebRequest) getRequest()).getHttpServletRequest(); |
| | | AuthenticationType authenticationType = (AuthenticationType) request.getAttribute(Constants.ATTRIB_AUTHTYPE); |
| | | boolean standardLogin = (null != authenticationType) ? authenticationType.isStandard() : true; |
| | | |
| | | if (app().settings().getBoolean(Keys.web.allowGravatar, true)) { |
| | | add(new AvatarImage("username", user, "navbarGravatar", 20, false)); |
| | | } else { |
| | | add(new Label("username", user.getDisplayName())); |
| | | } |
| | | |
| | | List<MenuItem> standardItems = new ArrayList<MenuItem>(); |
| | | standardItems.add(new MenuDivider()); |
| | | if (user.canAdmin() || user.canCreate()) { |
| | | standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage())); |
| | | } |
| | | standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, |
| | | WicketUtils.newUsernameParameter(user.username))); |
| | | if (editCredentials) { |
| | | standardItems.add(new PageLinkMenuItem("gb.changePassword", ChangePasswordPage.class)); |
| | | } |
| | | standardItems.add(new MenuDivider()); |
| | | add(newSubmenu("standardMenu", user.getDisplayName(), standardItems)); |
| | | |
| | | if (showAdmin) { |
| | | // admin menu |
| | | List<MenuItem> adminItems = new ArrayList<MenuItem>(); |
| | | adminItems.add(new MenuDivider()); |
| | | adminItems.add(new PageLinkMenuItem("gb.users", UsersPage.class)); |
| | | adminItems.add(new PageLinkMenuItem("gb.teams", TeamsPage.class)); |
| | | |
| | | boolean showRegistrations = app().federation().canFederate() |
| | | && app().settings().getBoolean(Keys.web.showFederationRegistrations, false); |
| | | if (showRegistrations) { |
| | | adminItems.add(new PageLinkMenuItem("gb.federation", FederationPage.class)); |
| | | } |
| | | adminItems.add(new MenuDivider()); |
| | | |
| | | add(newSubmenu("adminMenu", getString("gb.administration"), adminItems)); |
| | | } else { |
| | | add(new Label("adminMenu").setVisible(false)); |
| | | } |
| | | |
| | | // plugin extension items |
| | | List<MenuItem> extensionItems = new ArrayList<MenuItem>(); |
| | | List<UserMenuExtension> extensions = app().plugins().getExtensions(UserMenuExtension.class); |
| | | for (UserMenuExtension ext : extensions) { |
| | | List<MenuItem> items = ext.getMenuItems(user); |
| | | extensionItems.addAll(items); |
| | | } |
| | | |
| | | if (extensionItems.isEmpty()) { |
| | | // no extension items |
| | | add(new Label("extensionsMenu").setVisible(false)); |
| | | } else { |
| | | // found extension items |
| | | extensionItems.add(0, new MenuDivider()); |
| | | add(newSubmenu("extensionsMenu", getString("gb.extensions"), extensionItems)); |
| | | extensionItems.add(new MenuDivider()); |
| | | } |
| | | |
| | | add(new BookmarkablePageLink<Void>("logout", |
| | | LogoutPage.class).setVisible(standardLogin)); |
| | | } |
| | | |
| | | /** |
| | | * Creates a submenu. This is not actually submenu because we're using |
| | | * an older Twitter Bootstrap which is pre-submenu. |
| | | * |
| | | * @param wicketId |
| | | * @param submenuTitle |
| | | * @param menuItems |
| | | * @return a submenu fragment |
| | | */ |
| | | private Fragment newSubmenu(String wicketId, String submenuTitle, List<MenuItem> menuItems) { |
| | | Fragment submenu = new Fragment(wicketId, "submenuFragment", this); |
| | | submenu.add(new Label("submenuTitle", submenuTitle).setRenderBodyOnly(true)); |
| | | ListDataProvider<MenuItem> menuItemsDp = new ListDataProvider<MenuItem>(menuItems); |
| | | DataView<MenuItem> submenuItems = new DataView<MenuItem>("submenuItem", menuItemsDp) { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @Override |
| | | public void populateItem(final Item<MenuItem> menuItem) { |
| | | final MenuItem item = menuItem.getModelObject(); |
| | | String name = item.toString(); |
| | | try { |
| | | // try to lookup translation |
| | | name = getString(name); |
| | | } catch (Exception e) { |
| | | } |
| | | if (item instanceof PageLinkMenuItem) { |
| | | // link to another Wicket page |
| | | PageLinkMenuItem pageLink = (PageLinkMenuItem) item; |
| | | menuItem.add(new LinkPanel("submenuLink", null, null, name, pageLink.getPageClass(), |
| | | pageLink.getPageParameters(), false).setRenderBodyOnly(true)); |
| | | } else if (item instanceof ExternalLinkMenuItem) { |
| | | // link to a specified href |
| | | ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) item; |
| | | menuItem.add(new LinkPanel("submenuLink", null, name, extLink.getHref(), |
| | | extLink.openInNewWindow()).setRenderBodyOnly(true)); |
| | | } else if (item instanceof MenuDivider) { |
| | | // divider |
| | | menuItem.add(new Label("submenuLink").setRenderBodyOnly(true)); |
| | | WicketUtils.setCssClass(menuItem, "divider"); |
| | | } |
| | | } |
| | | }; |
| | | submenu.add(submenuItems); |
| | | submenu.setRenderBodyOnly(true); |
| | | return submenu; |
| | | } |
| | | } |
| | | } |