mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Make BasePage.onInitialize() final.
Add security check for GitFilter
This commit is contained in:
parent
0aab6f6089
commit
ff4dd0b7cf
@ -14,6 +14,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.UnauthorizedException;
|
||||
import org.eclipse.jgit.http.server.ServletUtils;
|
||||
import org.eclipse.jgit.transport.PacketLineOut;
|
||||
import org.slf4j.Logger;
|
||||
@ -22,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.pmease.commons.git.Git;
|
||||
import com.pmease.gitop.core.manager.ProjectManager;
|
||||
import com.pmease.gitop.core.model.Project;
|
||||
import com.pmease.gitop.core.permission.ObjectPermission;
|
||||
|
||||
@Singleton
|
||||
public class GitFilter implements Filter {
|
||||
@ -37,7 +40,7 @@ public class GitFilter implements Filter {
|
||||
this.projectManager = projectManager;
|
||||
}
|
||||
|
||||
private Project getProject(HttpServletRequest request, HttpServletResponse response, String repoInfo)
|
||||
private Project getProject(HttpServletRequest request, HttpServletResponse response, String pathInfo, String repoInfo)
|
||||
throws IOException {
|
||||
|
||||
repoInfo = StringUtils.stripStart(StringUtils.stripEnd(repoInfo, "/"), "/");
|
||||
@ -47,8 +50,8 @@ public class GitFilter implements Filter {
|
||||
|
||||
if (StringUtils.isBlank(ownerName) || StringUtils.isBlank(projectName)) {
|
||||
String url = request.getRequestURL().toString();
|
||||
String urlRoot = url.substring(0, url.length()-request.getPathInfo().length());
|
||||
String message = "Expecting url of format " + urlRoot + "/<owner name>/<project name>";
|
||||
String urlRoot = url.substring(0, url.length()-pathInfo.length());
|
||||
String message = "Expecting url of format " + urlRoot + "<owner name>/<project name>";
|
||||
logger.error("Error serving git request: " + message);
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
|
||||
return null;
|
||||
@ -61,7 +64,7 @@ public class GitFilter implements Filter {
|
||||
if (project == null) {
|
||||
String message = "Unable to find project '" + projectName + "' owned by '" + ownerName + "'.";
|
||||
logger.error("Error serving git request: " + message);
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -78,7 +81,7 @@ public class GitFilter implements Filter {
|
||||
String service = StringUtils.substringAfterLast(pathInfo, "/");
|
||||
|
||||
String repoInfo = StringUtils.substringBeforeLast(pathInfo, "/");
|
||||
Project project = getProject(req, resp, repoInfo);
|
||||
Project project = getProject(req, resp, pathInfo, repoInfo);
|
||||
|
||||
if (project != null) {
|
||||
doNotCache(resp);
|
||||
@ -86,23 +89,34 @@ public class GitFilter implements Filter {
|
||||
|
||||
Git git = new Git(projectManager.locateStorage(project).ofCode());
|
||||
|
||||
try {
|
||||
if (service.contains("upload")) {
|
||||
git.upload().input(ServletUtils.getInputStream(req)).output(resp.getOutputStream()).call();
|
||||
} else if (service.contains("receive")) {
|
||||
git.receive().input(ServletUtils.getInputStream(req)).output(resp.getOutputStream()).call();
|
||||
} else {
|
||||
String message = "Invalid service name '" + service + "'.";
|
||||
logger.error("Error serving git request: " + message);
|
||||
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
|
||||
if (service.contains("upload")) {
|
||||
if (!SecurityUtils.getSubject().isPermitted(ObjectPermission.ofProjectRead(project))) {
|
||||
throw new UnauthorizedException("You do not have permission to pull from this project.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error serving git request.", e);
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
|
||||
git.upload().input(ServletUtils.getInputStream(req)).output(resp.getOutputStream()).call();
|
||||
} else if (service.contains("receive")) {
|
||||
if (!SecurityUtils.getSubject().isPermitted(ObjectPermission.ofProjectWrite(project))) {
|
||||
throw new UnauthorizedException("You do not have permission to push to this project.");
|
||||
}
|
||||
git.receive().input(ServletUtils.getInputStream(req)).output(resp.getOutputStream()).call();
|
||||
} else {
|
||||
String message = "Invalid service name '" + service + "'.";
|
||||
logger.error("Error serving git request: " + message);
|
||||
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void writeInitial(HttpServletResponse resp, String service) throws IOException {
|
||||
doNotCache(resp);
|
||||
resp.setHeader("Content-Type", "application/x-" + service + "-advertisement");
|
||||
|
||||
PacketLineOut pack = new PacketLineOut(resp.getOutputStream());
|
||||
pack.setFlushOnEnd(false);
|
||||
pack.writeString("# service=" + service + "\n");
|
||||
pack.end();
|
||||
}
|
||||
|
||||
protected void processRefs(HttpServletRequest req, HttpServletResponse resp, String pathInfo) throws ServletException, IOException {
|
||||
if (!pathInfo.endsWith(INFO_REFS)) {
|
||||
String message = "Invalid refs request url: " + req.getRequestURL();
|
||||
@ -112,32 +126,27 @@ public class GitFilter implements Filter {
|
||||
}
|
||||
|
||||
String repoInfo = pathInfo.substring(0, pathInfo.length() - INFO_REFS.length());
|
||||
Project project = getProject(req, resp, repoInfo);
|
||||
Project project = getProject(req, resp, pathInfo, repoInfo);
|
||||
if (project != null) {
|
||||
doNotCache(resp);
|
||||
String service = req.getParameter("service");
|
||||
resp.setHeader("Content-Type", "application/x-" + service + "-advertisement");
|
||||
|
||||
PacketLineOut pack = new PacketLineOut(resp.getOutputStream());
|
||||
pack.setFlushOnEnd(false);
|
||||
pack.writeString("# service=" + service + "\n");
|
||||
pack.end();
|
||||
|
||||
Git git = new Git(projectManager.locateStorage(project).ofCode());
|
||||
|
||||
try {
|
||||
if (service.contains("upload")) {
|
||||
git.advertiseUploadRefs().output(resp.getOutputStream()).call();
|
||||
} else if (service.contains("receive")) {
|
||||
git.advertiseReceiveRefs().output(resp.getOutputStream()).call();
|
||||
} else {
|
||||
String message = "Invalid service name '" + service + "'.";
|
||||
logger.error("Error serving git request: " + message);
|
||||
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
|
||||
if (service.contains("upload")) {
|
||||
if (!SecurityUtils.getSubject().isPermitted(ObjectPermission.ofProjectRead(project))) {
|
||||
throw new UnauthorizedException("You do not have permission to pull from this project.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error serving git request.", e);
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
|
||||
writeInitial(resp, service);
|
||||
git.advertiseUploadRefs().output(resp.getOutputStream()).call();
|
||||
} else if (service.contains("receive")) {
|
||||
if (!SecurityUtils.getSubject().isPermitted(ObjectPermission.ofProjectWrite(project))) {
|
||||
throw new UnauthorizedException("You do not have permission to push to this project.");
|
||||
}
|
||||
writeInitial(resp, service);
|
||||
git.advertiseReceiveRefs().output(resp.getOutputStream()).call();
|
||||
} else {
|
||||
String message = "Invalid service name '" + service + "'.";
|
||||
logger.error("Error serving git request: " + message);
|
||||
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,7 +160,6 @@ public class GitFilter implements Filter {
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
|
||||
String pathInfo = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());
|
||||
pathInfo = StringUtils.stripStart(pathInfo, "/");
|
||||
|
||||
|
||||
@ -14,10 +14,7 @@ import com.pmease.gitop.web.page.BasePage;
|
||||
@SuppressWarnings("serial")
|
||||
public class TestPage extends BasePage {
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
public TestPage() {
|
||||
final EditContext editContext = EditableUtils.getContext(new Project());
|
||||
|
||||
Form<?> form = new Form<Void>("form") {
|
||||
@ -39,7 +36,7 @@ public class TestPage extends BasePage {
|
||||
|
||||
add(form);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getPageTitle() {
|
||||
return "Test page used by Robin";
|
||||
|
||||
@ -42,6 +42,7 @@ public class WebUserNameReservation implements UserNameReservation {
|
||||
}
|
||||
|
||||
reserved.add("wicket");
|
||||
reserved.add("rest");
|
||||
|
||||
for (IRequestMapper mapper: webApp.getRequestMappers()) {
|
||||
if (mapper instanceof MountedMapper || mapper instanceof ResourceMapper) {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.pmease.gitop.web.page;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.pmease.gitop.core.model.User;
|
||||
@ -8,9 +10,21 @@ import com.pmease.gitop.core.model.User;
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractLayoutPage extends BasePage {
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
public AbstractLayoutPage() {
|
||||
commonInit();
|
||||
}
|
||||
|
||||
public AbstractLayoutPage(PageParameters params) {
|
||||
super(params);
|
||||
commonInit();
|
||||
}
|
||||
|
||||
public AbstractLayoutPage(IModel<?> model) {
|
||||
super(model);
|
||||
commonInit();
|
||||
}
|
||||
|
||||
private void commonInit() {
|
||||
add(new GlobalHeaderPanel("header"));
|
||||
}
|
||||
|
||||
|
||||
@ -48,24 +48,10 @@ public abstract class BasePage extends WebPage {
|
||||
return Strings.isNullOrEmpty(css) ? "" : css;
|
||||
}
|
||||
}));
|
||||
|
||||
if (!Gitop.getInstance().isReady() && getClass() != ServerInitPage.class) {
|
||||
|
||||
if (!isServerReady() && getClass() != ServerInitPage.class) {
|
||||
throw new RestartResponseAtInterceptPageException(ServerInitPage.class);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPageCssClass() {
|
||||
String name = getClass().getSimpleName();
|
||||
return StringUtils.camelCaseToLowerCaseWithHyphen(name);
|
||||
}
|
||||
|
||||
protected boolean isPermitted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
if (!isPermitted()) {
|
||||
throw new AccessDeniedException();
|
||||
@ -100,6 +86,31 @@ public abstract class BasePage extends WebPage {
|
||||
add(new WebMarkupContainer("globalResourceBinder").add(new BaseResourceBehavior()));
|
||||
}
|
||||
|
||||
protected String getPageCssClass() {
|
||||
String name = getClass().getSimpleName();
|
||||
return StringUtils.camelCaseToLowerCaseWithHyphen(name);
|
||||
}
|
||||
|
||||
protected boolean isPermitted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isServerReady() {
|
||||
return Gitop.getInstance().isReady();
|
||||
}
|
||||
|
||||
/*
|
||||
* For pages, we make this final to prevent sub classes from putting page initialization
|
||||
* logics here. Instead, one should put all page initialization logic in page
|
||||
* constructor to avoid the situation that if page constructor throws an exception
|
||||
* intentionally (such as RestartResponseException) to by pass initialization logic
|
||||
* but onInitialize will still be called to cause undesired behavior.
|
||||
*/
|
||||
@Override
|
||||
protected final void onInitialize() {
|
||||
super.onInitialize();
|
||||
}
|
||||
|
||||
protected abstract String getPageTitle();
|
||||
|
||||
protected int getPageRefreshInterval() {
|
||||
|
||||
@ -36,12 +36,7 @@ public class AccountHomePage extends AbstractLayoutPage {
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
|
||||
add(new Label("accountName", getAccount().getName()));
|
||||
|
||||
add(new Link<Void>("link") {
|
||||
@ -53,7 +48,7 @@ public class AccountHomePage extends AbstractLayoutPage {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getPageTitle() {
|
||||
return "Gitop";
|
||||
|
||||
@ -40,11 +40,8 @@ public class RegisterPage extends AbstractLayoutPage {
|
||||
protected String getPageTitle() {
|
||||
return "Gitop - Sign Up";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
|
||||
public RegisterPage() {
|
||||
final IModel<User> model = Model.<User>of(new User());
|
||||
Form<User> form = new Form<User>("form", model);
|
||||
add(form);
|
||||
|
||||
@ -10,6 +10,8 @@ import org.apache.wicket.markup.html.link.Link;
|
||||
import org.apache.wicket.markup.html.list.ListItem;
|
||||
import org.apache.wicket.markup.html.list.ListView;
|
||||
import org.apache.wicket.model.AbstractReadOnlyModel;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.pmease.gitop.core.model.User;
|
||||
@ -48,10 +50,21 @@ public abstract class AccountSettingPage extends AbstractLayoutPage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
public AccountSettingPage() {
|
||||
commonInit();
|
||||
}
|
||||
|
||||
public AccountSettingPage(PageParameters params) {
|
||||
super(params);
|
||||
commonInit();
|
||||
}
|
||||
|
||||
public AccountSettingPage(IModel<?> model) {
|
||||
super(model);
|
||||
commonInit();
|
||||
}
|
||||
|
||||
private void commonInit() {
|
||||
add(new UserAvatarLink("userlink", new UserModel(getAccount())));
|
||||
|
||||
add(new ListView<Category>("setting", ImmutableList.<Category>copyOf(Category.values())) {
|
||||
|
||||
@ -34,10 +34,7 @@ public class AccountPasswordPage extends AccountSettingPage {
|
||||
return Category.PASSWORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
public AccountPasswordPage() {
|
||||
Form<User> form = new Form<User>("form", new UserModel(getAccount()));
|
||||
add(form);
|
||||
form.add(new PasswordFieldElement("oldPass", "Current Password",
|
||||
|
||||
@ -27,14 +27,11 @@ public class AccountProfilePage extends AccountSettingPage {
|
||||
protected Category getSettingCategory() {
|
||||
return Category.PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
|
||||
public AccountProfilePage() {
|
||||
add(new ProfileForm("form", new UserModel(getAccount())));
|
||||
}
|
||||
|
||||
|
||||
private class ProfileForm extends Form<User> {
|
||||
|
||||
public ProfileForm(String id, IModel<User> model) {
|
||||
|
||||
@ -6,6 +6,5 @@
|
||||
<div wicket:id="upload"></div>
|
||||
</div>
|
||||
<a wicket:id="accountLink">account</a>
|
||||
<a wicket:id="projectLink">project</a>
|
||||
</wicket:extend>
|
||||
</html>
|
||||
@ -3,29 +3,24 @@ package com.pmease.gitop.web.page.home;
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
|
||||
import com.pmease.gitop.core.Gitop;
|
||||
import com.pmease.gitop.core.manager.ProjectManager;
|
||||
import com.pmease.gitop.core.manager.UserManager;
|
||||
import com.pmease.gitop.web.common.component.fileupload.FileUploadBar;
|
||||
import com.pmease.gitop.web.page.AbstractLayoutPage;
|
||||
import com.pmease.gitop.web.page.account.AccountHomePage;
|
||||
import com.pmease.gitop.web.page.project.ProjectHomePage;
|
||||
|
||||
public class HomePage extends AbstractLayoutPage {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public HomePage() {
|
||||
add(new FileUploadBar("upload"));
|
||||
|
||||
add(new BookmarkablePageLink<>("accountLink", AccountHomePage.class, AccountHomePage.paramsOf(Gitop.getInstance(UserManager.class).getRootUser())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPageTitle() {
|
||||
return "Gitop - Home";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
add(new FileUploadBar("upload"));
|
||||
|
||||
add(new BookmarkablePageLink<>("accountLink", AccountHomePage.class, AccountHomePage.paramsOf(Gitop.getInstance(UserManager.class).getRootUser())));
|
||||
add(new BookmarkablePageLink<>("projectLink", ProjectHomePage.class, ProjectHomePage.paramsOf(Gitop.getInstance(ProjectManager.class).load(1L))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,33 +25,26 @@ public class ServerInitPage extends BasePage {
|
||||
continueToOriginalDestination();
|
||||
throw new RestartResponseException(getApplication().getHomePage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
if (initStage != null) {
|
||||
add(new Label("message", initStage.getMessage()));
|
||||
|
||||
if (!initStage.getManualConfigs().isEmpty()) {
|
||||
List<ManualConfigStep> configSteps = new ArrayList<ManualConfigStep>();
|
||||
for (ManualConfig each: initStage.getManualConfigs())
|
||||
configSteps.add(new ManualConfigStep(each));
|
||||
add(new Wizard("wizard", configSteps) {
|
||||
|
||||
@Override
|
||||
protected void finished() {
|
||||
setResponsePage(ServerInitPage.class);
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
add(new WebMarkupContainer("wizard").setVisible(false));
|
||||
}
|
||||
add(new Label("message", initStage.getMessage()));
|
||||
|
||||
if (!initStage.getManualConfigs().isEmpty()) {
|
||||
List<ManualConfigStep> configSteps = new ArrayList<ManualConfigStep>();
|
||||
for (ManualConfig each: initStage.getManualConfigs())
|
||||
configSteps.add(new ManualConfigStep(each));
|
||||
add(new Wizard("wizard", configSteps) {
|
||||
|
||||
@Override
|
||||
protected void finished() {
|
||||
setResponsePage(ServerInitPage.class);
|
||||
}
|
||||
|
||||
});
|
||||
} else {
|
||||
add(new WebMarkupContainer("wizard").setVisible(false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getPageTitle() {
|
||||
return "Server Initialization";
|
||||
|
||||
@ -3,7 +3,5 @@
|
||||
<h1>Welcome, Project Home</h1>
|
||||
<div wicket:id="accountName"></div>
|
||||
<div wicket:id="projectName"></div>
|
||||
|
||||
<a wicket:id="link">link</a>
|
||||
</wicket:extend>
|
||||
</html>
|
||||
@ -1,7 +1,6 @@
|
||||
package com.pmease.gitop.web.page.project;
|
||||
|
||||
import org.apache.wicket.markup.html.basic.Label;
|
||||
import org.apache.wicket.markup.html.link.Link;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.model.LoadableDetachableModel;
|
||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||
@ -45,24 +44,10 @@ public class ProjectHomePage extends AbstractLayoutPage {
|
||||
|
||||
};
|
||||
|
||||
add(new Link<Void>("link") {
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
|
||||
add(new Label("accountName", getProject().getOwner().getName()));
|
||||
add(new Label("projectName", getProject().getName()));
|
||||
}
|
||||
|
||||
|
||||
public Project getProject() {
|
||||
return projectModel.getObject();
|
||||
}
|
||||
|
||||
@ -26,17 +26,11 @@ public class LoginPage extends AbstractLayoutPage {
|
||||
if (isSignedIn()) {
|
||||
throw new RestartResponseException(getApplication().getHomePage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitialize() {
|
||||
super.onInitialize();
|
||||
add(new LoginForm("login"));
|
||||
FeedbackPanel feedback = new FeedbackPanel("feedback");
|
||||
add(feedback);
|
||||
}
|
||||
|
||||
|
||||
private class LoginForm extends StatelessForm<Void> {
|
||||
|
||||
public LoginForm(String id) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user