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