commit | author | age
|
f13c4c
|
1 |
/*
|
JM |
2 |
* Copyright 2011 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 |
*/
|
1f9dae
|
16 |
package com.gitblit.wicket.pages;
|
5fe7df
|
17 |
|
13a3f5
|
18 |
import java.util.ArrayList;
|
JM |
19 |
import java.util.Calendar;
|
|
20 |
import java.util.Collections;
|
|
21 |
import java.util.Comparator;
|
|
22 |
import java.util.Date;
|
|
23 |
import java.util.HashSet;
|
f98825
|
24 |
import java.util.LinkedHashMap;
|
13a3f5
|
25 |
import java.util.List;
|
f98825
|
26 |
import java.util.Map;
|
9adf62
|
27 |
import java.util.ResourceBundle;
|
13a3f5
|
28 |
import java.util.Set;
|
bc10f9
|
29 |
import java.util.TimeZone;
|
13a3f5
|
30 |
import java.util.regex.Pattern;
|
bc10f9
|
31 |
|
85c2e6
|
32 |
import javax.servlet.http.Cookie;
|
cebf45
|
33 |
import javax.servlet.http.HttpServletRequest;
|
JM |
34 |
|
3cc6e2
|
35 |
import org.apache.wicket.Application;
|
20165d
|
36 |
import org.apache.wicket.MarkupContainer;
|
5fe7df
|
37 |
import org.apache.wicket.PageParameters;
|
d97e52
|
38 |
import org.apache.wicket.RedirectToUrlException;
|
85c2e6
|
39 |
import org.apache.wicket.RestartResponseException;
|
62cec2
|
40 |
import org.apache.wicket.markup.html.CSSPackageResource;
|
5fe7df
|
41 |
import org.apache.wicket.markup.html.WebPage;
|
JM |
42 |
import org.apache.wicket.markup.html.basic.Label;
|
20165d
|
43 |
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
94750e
|
44 |
import org.apache.wicket.markup.html.link.ExternalLink;
|
c1c3c6
|
45 |
import org.apache.wicket.markup.html.panel.FeedbackPanel;
|
20165d
|
46 |
import org.apache.wicket.markup.html.panel.Fragment;
|
d97e52
|
47 |
import org.apache.wicket.protocol.http.RequestUtils;
|
85c2e6
|
48 |
import org.apache.wicket.protocol.http.WebRequest;
|
JM |
49 |
import org.apache.wicket.protocol.http.WebResponse;
|
cebf45
|
50 |
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
|
5fe7df
|
51 |
import org.slf4j.Logger;
|
JM |
52 |
import org.slf4j.LoggerFactory;
|
|
53 |
|
cebf45
|
54 |
import com.gitblit.Constants;
|
f98825
|
55 |
import com.gitblit.Constants.AccessRestrictionType;
|
831469
|
56 |
import com.gitblit.Constants.FederationStrategy;
|
87cc1e
|
57 |
import com.gitblit.GitBlit;
|
155bf7
|
58 |
import com.gitblit.Keys;
|
13a3f5
|
59 |
import com.gitblit.models.ProjectModel;
|
e21181
|
60 |
import com.gitblit.models.RepositoryModel;
|
13a3f5
|
61 |
import com.gitblit.models.TeamModel;
|
85c2e6
|
62 |
import com.gitblit.models.UserModel;
|
13a3f5
|
63 |
import com.gitblit.utils.StringUtils;
|
9adf62
|
64 |
import com.gitblit.utils.TimeUtils;
|
1f9dae
|
65 |
import com.gitblit.wicket.GitBlitWebSession;
|
13a3f5
|
66 |
import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
94750e
|
67 |
import com.gitblit.wicket.WicketUtils;
|
1f9dae
|
68 |
import com.gitblit.wicket.panels.LinkPanel;
|
5fe7df
|
69 |
|
JM |
70 |
public abstract class BasePage extends WebPage {
|
|
71 |
|
87cc1e
|
72 |
private final Logger logger;
|
9adf62
|
73 |
|
JM |
74 |
private transient TimeUtils timeUtils;
|
5fe7df
|
75 |
|
JM |
76 |
public BasePage() {
|
|
77 |
super();
|
87cc1e
|
78 |
logger = LoggerFactory.getLogger(getClass());
|
62cec2
|
79 |
customizeHeader();
|
85c2e6
|
80 |
loginByCookie();
|
5fe7df
|
81 |
}
|
JM |
82 |
|
|
83 |
public BasePage(PageParameters params) {
|
|
84 |
super(params);
|
87cc1e
|
85 |
logger = LoggerFactory.getLogger(getClass());
|
62cec2
|
86 |
customizeHeader();
|
85c2e6
|
87 |
loginByCookie();
|
JM |
88 |
}
|
3cc6e2
|
89 |
|
62cec2
|
90 |
private void customizeHeader() {
|
JM |
91 |
if (GitBlit.getBoolean(Keys.web.useResponsiveLayout, true)) {
|
|
92 |
add(CSSPackageResource.getHeaderContribution("bootstrap/css/bootstrap-responsive.css"));
|
|
93 |
}
|
|
94 |
}
|
|
95 |
|
9adf62
|
96 |
protected String getLanguageCode() {
|
JM |
97 |
return GitBlitWebSession.get().getLocale().getLanguage();
|
|
98 |
}
|
|
99 |
|
|
100 |
protected TimeUtils getTimeUtils() {
|
|
101 |
if (timeUtils == null) {
|
|
102 |
ResourceBundle bundle;
|
|
103 |
try {
|
|
104 |
bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", GitBlitWebSession.get().getLocale());
|
|
105 |
} catch (Throwable t) {
|
|
106 |
bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp");
|
|
107 |
}
|
|
108 |
timeUtils = new TimeUtils(bundle);
|
|
109 |
}
|
|
110 |
return timeUtils;
|
|
111 |
}
|
|
112 |
|
3cc6e2
|
113 |
@Override
|
JM |
114 |
protected void onBeforeRender() {
|
|
115 |
if (GitBlit.isDebugMode()) {
|
|
116 |
// strip Wicket tags in debug mode for jQuery DOM traversal
|
|
117 |
Application.get().getMarkupSettings().setStripWicketTags(true);
|
|
118 |
}
|
|
119 |
super.onBeforeRender();
|
|
120 |
}
|
|
121 |
|
|
122 |
@Override
|
|
123 |
protected void onAfterRender() {
|
|
124 |
if (GitBlit.isDebugMode()) {
|
|
125 |
// restore Wicket debug tags
|
|
126 |
Application.get().getMarkupSettings().setStripWicketTags(false);
|
|
127 |
}
|
|
128 |
super.onAfterRender();
|
|
129 |
}
|
85c2e6
|
130 |
|
JM |
131 |
private void loginByCookie() {
|
|
132 |
if (!GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) {
|
|
133 |
return;
|
|
134 |
}
|
|
135 |
UserModel user = null;
|
|
136 |
|
|
137 |
// Grab cookie from Browser Session
|
|
138 |
Cookie[] cookies = ((WebRequest) getRequestCycle().getRequest()).getCookies();
|
|
139 |
if (cookies != null && cookies.length > 0) {
|
|
140 |
user = GitBlit.self().authenticate(cookies);
|
|
141 |
}
|
|
142 |
|
|
143 |
// Login the user
|
|
144 |
if (user != null) {
|
|
145 |
// Set the user into the session
|
e78838
|
146 |
GitBlitWebSession session = GitBlitWebSession.get();
|
JM |
147 |
// issue 62: fix session fixation vulnerability
|
|
148 |
session.replaceSession();
|
|
149 |
session.setUser(user);
|
85c2e6
|
150 |
|
JM |
151 |
// Set Cookie
|
|
152 |
WebResponse response = (WebResponse) getRequestCycle().getResponse();
|
|
153 |
GitBlit.self().setCookie(response, user);
|
d97e52
|
154 |
|
JM |
155 |
session.continueRequest();
|
85c2e6
|
156 |
}
|
5fe7df
|
157 |
}
|
155bf7
|
158 |
|
cebf45
|
159 |
protected void setupPage(String repositoryName, String pageName) {
|
JM |
160 |
if (repositoryName != null && repositoryName.trim().length() > 0) {
|
|
161 |
add(new Label("title", getServerName() + " - " + repositoryName));
|
|
162 |
} else {
|
|
163 |
add(new Label("title", getServerName()));
|
|
164 |
}
|
155bf7
|
165 |
|
94750e
|
166 |
ExternalLink rootLink = new ExternalLink("rootLink", urlFor(RepositoriesPage.class, null).toString());
|
JM |
167 |
WicketUtils.setHtmlTooltip(rootLink, GitBlit.getString(Keys.web.siteName, Constants.NAME));
|
|
168 |
add(rootLink);
|
|
169 |
|
c1c3c6
|
170 |
// Feedback panel for info, warning, and non-fatal error messages
|
JM |
171 |
add(new FeedbackPanel("feedback"));
|
|
172 |
|
cebf45
|
173 |
// footer
|
2a7306
|
174 |
if (GitBlit.getBoolean(Keys.web.authenticateViewPages, true)
|
JM |
175 |
|| GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) {
|
20165d
|
176 |
UserFragment userFragment = new UserFragment("userPanel", "userFragment", BasePage.this);
|
JM |
177 |
add(userFragment);
|
94b96b
|
178 |
} else {
|
87cc1e
|
179 |
add(new Label("userPanel", ""));
|
94b96b
|
180 |
}
|
20165d
|
181 |
|
cebf45
|
182 |
add(new Label("gbVersion", "v" + Constants.VERSION));
|
2a7306
|
183 |
if (GitBlit.getBoolean(Keys.web.aggressiveHeapManagement, false)) {
|
cebf45
|
184 |
System.gc();
|
JM |
185 |
}
|
|
186 |
}
|
155bf7
|
187 |
|
f98825
|
188 |
protected Map<AccessRestrictionType, String> getAccessRestrictions() {
|
JM |
189 |
Map<AccessRestrictionType, String> map = new LinkedHashMap<AccessRestrictionType, String>();
|
|
190 |
for (AccessRestrictionType type : AccessRestrictionType.values()) {
|
|
191 |
switch (type) {
|
|
192 |
case NONE:
|
|
193 |
map.put(type, getString("gb.notRestricted"));
|
|
194 |
break;
|
|
195 |
case PUSH:
|
|
196 |
map.put(type, getString("gb.pushRestricted"));
|
|
197 |
break;
|
|
198 |
case CLONE:
|
|
199 |
map.put(type, getString("gb.cloneRestricted"));
|
|
200 |
break;
|
|
201 |
case VIEW:
|
|
202 |
map.put(type, getString("gb.viewRestricted"));
|
|
203 |
break;
|
|
204 |
}
|
|
205 |
}
|
|
206 |
return map;
|
|
207 |
}
|
831469
|
208 |
|
JM |
209 |
protected Map<FederationStrategy, String> getFederationTypes() {
|
|
210 |
Map<FederationStrategy, String> map = new LinkedHashMap<FederationStrategy, String>();
|
|
211 |
for (FederationStrategy type : FederationStrategy.values()) {
|
|
212 |
switch (type) {
|
|
213 |
case EXCLUDE:
|
|
214 |
map.put(type, getString("gb.excludeFromFederation"));
|
|
215 |
break;
|
|
216 |
case FEDERATE_THIS:
|
|
217 |
map.put(type, getString("gb.federateThis"));
|
|
218 |
break;
|
|
219 |
case FEDERATE_ORIGIN:
|
|
220 |
map.put(type, getString("gb.federateOrigin"));
|
|
221 |
break;
|
|
222 |
}
|
|
223 |
}
|
|
224 |
return map;
|
|
225 |
}
|
f98825
|
226 |
|
bc10f9
|
227 |
protected TimeZone getTimeZone() {
|
2a7306
|
228 |
return GitBlit.getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
|
6c6e7d
|
229 |
.getTimezone() : GitBlit.getTimezone();
|
bc10f9
|
230 |
}
|
155bf7
|
231 |
|
cebf45
|
232 |
protected String getServerName() {
|
JM |
233 |
ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
|
|
234 |
HttpServletRequest req = servletWebRequest.getHttpServletRequest();
|
|
235 |
return req.getServerName();
|
|
236 |
}
|
e21181
|
237 |
|
JM |
238 |
protected String getRepositoryUrl(RepositoryModel repository) {
|
|
239 |
StringBuilder sb = new StringBuilder();
|
|
240 |
sb.append(WicketUtils.getGitblitURL(getRequestCycle().getRequest()));
|
|
241 |
sb.append(Constants.GIT_PATH);
|
|
242 |
sb.append(repository.name);
|
|
243 |
|
|
244 |
// inject username into repository url if authentication is required
|
|
245 |
if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE)
|
|
246 |
&& GitBlitWebSession.get().isLoggedIn()) {
|
d97e52
|
247 |
String username = GitBlitWebSession.get().getUsername();
|
e21181
|
248 |
sb.insert(sb.indexOf("://") + 3, username + "@");
|
JM |
249 |
}
|
|
250 |
return sb.toString();
|
|
251 |
}
|
13a3f5
|
252 |
|
JM |
253 |
protected List<ProjectModel> getProjectModels() {
|
|
254 |
final UserModel user = GitBlitWebSession.get().getUser();
|
|
255 |
List<ProjectModel> projects = GitBlit.self().getProjectModels(user);
|
|
256 |
return projects;
|
|
257 |
}
|
|
258 |
|
|
259 |
protected List<ProjectModel> getProjects(PageParameters params) {
|
|
260 |
if (params == null) {
|
|
261 |
return getProjectModels();
|
|
262 |
}
|
|
263 |
|
|
264 |
boolean hasParameter = false;
|
|
265 |
String regex = WicketUtils.getRegEx(params);
|
|
266 |
String team = WicketUtils.getTeam(params);
|
|
267 |
int daysBack = params.getInt("db", 0);
|
|
268 |
|
|
269 |
List<ProjectModel> availableModels = getProjectModels();
|
|
270 |
Set<ProjectModel> models = new HashSet<ProjectModel>();
|
|
271 |
|
|
272 |
if (!StringUtils.isEmpty(regex)) {
|
|
273 |
// filter the projects by the regex
|
|
274 |
hasParameter = true;
|
|
275 |
Pattern pattern = Pattern.compile(regex);
|
|
276 |
for (ProjectModel model : availableModels) {
|
|
277 |
if (pattern.matcher(model.name).find()) {
|
|
278 |
models.add(model);
|
|
279 |
}
|
|
280 |
}
|
|
281 |
}
|
|
282 |
|
|
283 |
if (!StringUtils.isEmpty(team)) {
|
|
284 |
// filter the projects by the specified teams
|
|
285 |
hasParameter = true;
|
|
286 |
List<String> teams = StringUtils.getStringsFromValue(team, ",");
|
|
287 |
|
|
288 |
// need TeamModels first
|
|
289 |
List<TeamModel> teamModels = new ArrayList<TeamModel>();
|
|
290 |
for (String name : teams) {
|
|
291 |
TeamModel teamModel = GitBlit.self().getTeamModel(name);
|
|
292 |
if (teamModel != null) {
|
|
293 |
teamModels.add(teamModel);
|
|
294 |
}
|
|
295 |
}
|
|
296 |
|
|
297 |
// brute-force our way through finding the matching models
|
|
298 |
for (ProjectModel projectModel : availableModels) {
|
|
299 |
for (String repositoryName : projectModel.repositories) {
|
|
300 |
for (TeamModel teamModel : teamModels) {
|
|
301 |
if (teamModel.hasRepository(repositoryName)) {
|
|
302 |
models.add(projectModel);
|
|
303 |
}
|
|
304 |
}
|
|
305 |
}
|
|
306 |
}
|
|
307 |
}
|
|
308 |
|
|
309 |
if (!hasParameter) {
|
|
310 |
models.addAll(availableModels);
|
|
311 |
}
|
|
312 |
|
|
313 |
// time-filter the list
|
|
314 |
if (daysBack > 0) {
|
|
315 |
Calendar cal = Calendar.getInstance();
|
|
316 |
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
317 |
cal.set(Calendar.MINUTE, 0);
|
|
318 |
cal.set(Calendar.SECOND, 0);
|
|
319 |
cal.set(Calendar.MILLISECOND, 0);
|
|
320 |
cal.add(Calendar.DATE, -1 * daysBack);
|
|
321 |
Date threshold = cal.getTime();
|
|
322 |
Set<ProjectModel> timeFiltered = new HashSet<ProjectModel>();
|
|
323 |
for (ProjectModel model : models) {
|
|
324 |
if (model.lastChange.after(threshold)) {
|
|
325 |
timeFiltered.add(model);
|
|
326 |
}
|
|
327 |
}
|
|
328 |
models = timeFiltered;
|
|
329 |
}
|
|
330 |
|
|
331 |
List<ProjectModel> list = new ArrayList<ProjectModel>(models);
|
|
332 |
Collections.sort(list);
|
|
333 |
return list;
|
|
334 |
}
|
85c2e6
|
335 |
|
5450d0
|
336 |
public void warn(String message, Throwable t) {
|
JM |
337 |
logger.warn(message, t);
|
|
338 |
}
|
13a3f5
|
339 |
|
bc9d4a
|
340 |
public void error(String message, boolean redirect) {
|
d97e52
|
341 |
logger.error(message + " for " + GitBlitWebSession.get().getUsername());
|
bc9d4a
|
342 |
if (redirect) {
|
JM |
343 |
GitBlitWebSession.get().cacheErrorMessage(message);
|
d97e52
|
344 |
String relativeUrl = urlFor(RepositoriesPage.class, null).toString();
|
JM |
345 |
String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
|
|
346 |
throw new RedirectToUrlException(absoluteUrl);
|
bc9d4a
|
347 |
} else {
|
JM |
348 |
super.error(message);
|
|
349 |
}
|
|
350 |
}
|
|
351 |
|
|
352 |
public void error(String message, Throwable t, boolean redirect) {
|
5fe7df
|
353 |
logger.error(message, t);
|
bc9d4a
|
354 |
if (redirect) {
|
JM |
355 |
GitBlitWebSession.get().cacheErrorMessage(message);
|
85c2e6
|
356 |
throw new RestartResponseException(getApplication().getHomePage());
|
bc9d4a
|
357 |
} else {
|
JM |
358 |
super.error(message);
|
|
359 |
}
|
5fe7df
|
360 |
}
|
85c2e6
|
361 |
|
JM |
362 |
public void authenticationError(String message) {
|
d97e52
|
363 |
logger.error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername());
|
JM |
364 |
if (!GitBlitWebSession.get().isLoggedIn()) {
|
|
365 |
// cache the request if we have not authenticated.
|
|
366 |
// the request will continue after authentication.
|
|
367 |
GitBlitWebSession.get().cacheRequest(getClass());
|
85c2e6
|
368 |
}
|
d97e52
|
369 |
error(message, true);
|
85c2e6
|
370 |
}
|
20165d
|
371 |
|
JM |
372 |
/**
|
|
373 |
* Panel fragment for displaying login or logout/change_password links.
|
|
374 |
*
|
|
375 |
*/
|
88598b
|
376 |
static class UserFragment extends Fragment {
|
20165d
|
377 |
|
JM |
378 |
private static final long serialVersionUID = 1L;
|
|
379 |
|
|
380 |
public UserFragment(String id, String markupId, MarkupContainer markupProvider) {
|
|
381 |
super(id, markupId, markupProvider);
|
|
382 |
|
|
383 |
if (GitBlitWebSession.get().isLoggedIn()) {
|
|
384 |
// username, logout, and change password
|
4682d1
|
385 |
add(new Label("username", GitBlitWebSession.get().getUser().getDisplayName() + ":"));
|
20165d
|
386 |
add(new LinkPanel("loginLink", null, markupProvider.getString("gb.logout"),
|
JM |
387 |
LogoutPage.class));
|
6cca86
|
388 |
boolean editCredentials = GitBlit.self().supportsCredentialChanges();
|
88598b
|
389 |
// quick and dirty hack for showing a separator
|
6cca86
|
390 |
add(new Label("separator", "|").setVisible(editCredentials));
|
JM |
391 |
add(new BookmarkablePageLink<Void>("changePasswordLink",
|
|
392 |
ChangePasswordPage.class).setVisible(editCredentials));
|
20165d
|
393 |
} else {
|
JM |
394 |
// login
|
|
395 |
add(new Label("username").setVisible(false));
|
a7571b
|
396 |
add(new Label("loginLink").setVisible(false));
|
20165d
|
397 |
add(new Label("separator").setVisible(false));
|
JM |
398 |
add(new Label("changePasswordLink").setVisible(false));
|
|
399 |
}
|
|
400 |
}
|
|
401 |
}
|
5fe7df
|
402 |
}
|