Skip to content

Commit a96d8b7

Browse files
authored
[Bug fix] Header bug fix (#140)
* Fixed header issue with strings * Fixed ActionResolverTest
1 parent b39c7f5 commit a96d8b7

File tree

7 files changed

+426
-9
lines changed

7 files changed

+426
-9
lines changed

src/main/java/com/gitee/jenkins/webhook/ActionResolver.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.gitee.jenkins.webhook;
22

33
import com.gitee.jenkins.util.ACLUtil;
4-
import com.gitee.jenkins.webhook.build.PullRequestBuildAction;
4+
import com.gitee.jenkins.webhook.build.LegacyPullRequestBuildAction;
5+
import com.gitee.jenkins.webhook.build.LegacyNoteBuildAction;
6+
import com.gitee.jenkins.webhook.build.LegacyPipelineBuildAction;
7+
import com.gitee.jenkins.webhook.build.LegacyPushBuildAction;
58
import com.gitee.jenkins.webhook.build.NoteBuildAction;
69
import com.gitee.jenkins.webhook.build.PipelineBuildAction;
10+
import com.gitee.jenkins.webhook.build.PullRequestBuildAction;
711
import com.gitee.jenkins.webhook.build.PushBuildAction;
812
import com.gitee.jenkins.webhook.status.BranchBuildPageRedirectAction;
913
import com.gitee.jenkins.webhook.status.BranchStatusPngAction;
@@ -106,10 +110,14 @@ private WebHookAction onPost(Item project, StaplerRequest2 request) {
106110
}
107111
String tokenHeader = request.getHeader("X-Gitee-Token");
108112
return switch (eventHeader) {
109-
case "Merge Request Hook" -> new PullRequestBuildAction(project, getRequestBody(request), tokenHeader);
110-
case "Push Hook", "Tag Push Hook" -> new PushBuildAction(project, getRequestBody(request), tokenHeader);
111-
case "Note Hook" -> new NoteBuildAction(project, getRequestBody(request), tokenHeader);
112-
case "Pipeline Hook" -> new PipelineBuildAction(project, getRequestBody(request), tokenHeader);
113+
case "Merge Request Hook" -> new LegacyPullRequestBuildAction(project, getRequestBody(request), tokenHeader);
114+
case "Push Hook", "Tag Push Hook" -> new LegacyPushBuildAction(project, getRequestBody(request), tokenHeader);
115+
case "Note Hook" -> new LegacyNoteBuildAction(project, getRequestBody(request), tokenHeader);
116+
case "Pipeline Hook" -> new LegacyPipelineBuildAction(project, getRequestBody(request), tokenHeader);
117+
case "merge_request_hooks" -> new PullRequestBuildAction(project, getRequestBody(request), tokenHeader);
118+
case "push_hooks", "tag_push_hooks" -> new PushBuildAction(project, getRequestBody(request), tokenHeader);
119+
case "note_hooks" -> new NoteBuildAction(project, getRequestBody(request), tokenHeader);
120+
case "pipeline_hooks" -> new PipelineBuildAction(project, getRequestBody(request), tokenHeader);
113121
default -> {
114122
LOGGER.log(Level.FINE, "Unsupported X-Gitee-Event header: {0}", eventHeader);
115123
yield new NoopAction();
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.gitee.jenkins.webhook.build;
2+
3+
import java.io.IOException;
4+
import java.util.Objects;
5+
import java.util.logging.Logger;
6+
7+
import com.gitee.jenkins.gitee.hook.model.WebHook;
8+
import hudson.model.Item;
9+
import hudson.model.Job;
10+
import hudson.security.Permission;
11+
import hudson.util.HttpResponses;
12+
import jenkins.model.Jenkins;
13+
import org.apache.commons.lang.StringUtils;
14+
15+
import com.gitee.jenkins.trigger.GiteePushTrigger;
16+
import com.gitee.jenkins.connection.GiteeConnectionConfig;
17+
import com.gitee.jenkins.webhook.WebHookAction;
18+
import org.kohsuke.stapler.StaplerRequest2;
19+
import org.kohsuke.stapler.StaplerResponse2;
20+
21+
import jakarta.servlet.ServletException;
22+
import org.springframework.security.core.Authentication;
23+
24+
/**
25+
* @author Xinran Xiao
26+
* @author Yashin Luo
27+
*/
28+
abstract class LegacyBuildWebHookAction implements WebHookAction {
29+
30+
private static final Logger LOGGER = Logger.getLogger(LegacyBuildWebHookAction.class.getName());
31+
32+
abstract void processForCompatibility();
33+
34+
abstract void execute();
35+
36+
public final void execute(StaplerResponse2 response) {
37+
processForCompatibility();
38+
execute();
39+
}
40+
41+
public static HttpResponses.HttpResponseException responseWithHook(final WebHook webHook) {
42+
return new HttpResponses.HttpResponseException() {
43+
@Override
44+
public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException {
45+
String text = webHook.getWebHookDescription() + " has been accepted.";
46+
rsp.setContentType("text/plain;charset=UTF-8");
47+
rsp.getWriter().println(text);
48+
}
49+
};
50+
}
51+
52+
protected abstract static class TriggerNotifier implements Runnable {
53+
54+
private final Item project;
55+
private final String secretToken;
56+
private final Authentication authentication;
57+
58+
public TriggerNotifier(Item project, String secretToken, Authentication authentication) {
59+
this.project = project;
60+
this.secretToken = secretToken;
61+
this.authentication = authentication;
62+
}
63+
64+
public void run() {
65+
GiteePushTrigger trigger = GiteePushTrigger.getFromJob((Job<?, ?>) project);
66+
if (trigger != null) {
67+
if (StringUtils.isEmpty(trigger.getSecretToken())) {
68+
checkPermission(Item.BUILD, project);
69+
} else if (!StringUtils.equals(trigger.getSecretToken(), secretToken)) {
70+
throw HttpResponses.errorWithoutStack(401, "Invalid token");
71+
}
72+
performOnPost(trigger);
73+
}
74+
}
75+
76+
private void checkPermission(Permission permission, Item project) {
77+
if (((GiteeConnectionConfig) Objects.requireNonNull(Jenkins.get().getDescriptor(GiteeConnectionConfig.class))).isUseAuthenticatedEndpoint()) {
78+
if (!project.getACL().hasPermission2(authentication, permission)) {
79+
String message = authentication.getName() + " is missing the " + permission.group.title+"/"+permission.name+ " permission";
80+
LOGGER.finest("Unauthorized (Did you forget to add API Token to the web hook ?)");
81+
throw HttpResponses.errorWithoutStack(403, message);
82+
}
83+
}
84+
}
85+
86+
protected abstract void performOnPost(GiteePushTrigger trigger);
87+
}
88+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.gitee.jenkins.webhook.build;
2+
3+
import com.gitee.jenkins.trigger.GiteePushTrigger;
4+
import com.gitee.jenkins.gitee.hook.model.NoteHook;
5+
import com.gitee.jenkins.util.JsonUtil;
6+
import hudson.model.Item;
7+
import hudson.model.Job;
8+
import hudson.security.ACL;
9+
import hudson.security.ACLContext;
10+
import hudson.util.HttpResponses;
11+
import jenkins.model.Jenkins;
12+
13+
import java.util.logging.Level;
14+
import java.util.logging.Logger;
15+
16+
import org.springframework.security.core.Authentication;
17+
18+
import static com.gitee.jenkins.util.JsonUtil.toPrettyPrint;
19+
20+
/**
21+
* @author Nikolay Ustinov
22+
*/
23+
public class LegacyNoteBuildAction extends LegacyBuildWebHookAction {
24+
25+
private static final Logger LOGGER = Logger.getLogger(LegacyNoteBuildAction.class.getName());
26+
private Item project;
27+
private NoteHook noteHook;
28+
private final String secretToken;
29+
30+
public LegacyNoteBuildAction(Item project, String json, String secretToken) {
31+
LOGGER.log(Level.FINE, "Note: {0}", toPrettyPrint(json));
32+
this.project = project;
33+
this.noteHook = JsonUtil.read(json, NoteHook.class);
34+
this.noteHook.setJsonBody(json);
35+
this.secretToken = secretToken;
36+
}
37+
38+
@Override
39+
void processForCompatibility() {
40+
41+
}
42+
43+
@Override
44+
public void execute() {
45+
if (!(project instanceof Job<?, ?>)) {
46+
throw HttpResponses.errorWithoutStack(409, "Note Hook is not supported for this project");
47+
}
48+
Authentication auth = Jenkins.getAuthentication2();
49+
try (ACLContext ignored = ACL.as2(ACL.SYSTEM2)) {
50+
new LegacyBuildWebHookAction.TriggerNotifier(project, secretToken, auth) {
51+
@Override
52+
protected void performOnPost(GiteePushTrigger trigger) {
53+
trigger.onPost(noteHook);
54+
}
55+
}.run();
56+
}
57+
throw responseWithHook(noteHook);
58+
}
59+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.gitee.jenkins.webhook.build;
2+
3+
import com.gitee.jenkins.trigger.GiteePushTrigger;
4+
import com.gitee.jenkins.gitee.hook.model.*;
5+
import com.gitee.jenkins.util.JsonUtil;
6+
import hudson.model.Item;
7+
import hudson.model.Job;
8+
import hudson.security.ACL;
9+
import hudson.security.ACLContext;
10+
import hudson.util.HttpResponses;
11+
import jenkins.model.Jenkins;
12+
import org.apache.commons.lang.StringUtils;
13+
import org.springframework.security.core.Authentication;
14+
15+
import java.net.MalformedURLException;
16+
import java.net.URL;
17+
import java.util.logging.Level;
18+
import java.util.logging.Logger;
19+
20+
import static com.gitee.jenkins.util.JsonUtil.toPrettyPrint;
21+
22+
/**
23+
* @author Milena Zachow
24+
*/
25+
public class LegacyPipelineBuildAction extends LegacyBuildWebHookAction {
26+
27+
private static final Logger LOGGER = Logger.getLogger(LegacyPipelineBuildAction.class.getName());
28+
private Item project;
29+
private PipelineHook pipelineBuildHook;
30+
private final String secretToken;
31+
32+
public LegacyPipelineBuildAction(Item project, String json, String secretToken) {
33+
LOGGER.log(Level.FINE, "Pipeline event: {0}", toPrettyPrint(json));
34+
this.project = project;
35+
this.pipelineBuildHook = JsonUtil.read(json, PipelineHook.class);
36+
this.pipelineBuildHook.setJsonBody(json);
37+
this.secretToken = secretToken;
38+
}
39+
40+
void processForCompatibility() {
41+
//if no project is defined, set it here
42+
if (this.pipelineBuildHook.getProject() == null && this.pipelineBuildHook.getRepository() != null) {
43+
try {
44+
String path = new URL(this.pipelineBuildHook.getRepository().getGitHttpUrl()).getPath();
45+
if (StringUtils.isNotBlank(path)) {
46+
Project project = new Project();
47+
project.setNamespace(path.replaceFirst("/", "").substring(0, path.lastIndexOf("/")));
48+
this.pipelineBuildHook.setProject(project);
49+
} else {
50+
LOGGER.log(Level.WARNING, "Could not find suitable namespace.");
51+
}
52+
} catch (MalformedURLException ignored) {
53+
LOGGER.log(Level.WARNING, "Invalid repository url found while building namespace.");
54+
}
55+
}
56+
}
57+
58+
void execute() {
59+
if (!(project instanceof Job<?, ?>)) {
60+
throw HttpResponses.errorWithoutStack(409, "Pipeline Hook is not supported for this project");
61+
}
62+
Authentication auth = Jenkins.getAuthentication2();
63+
try (ACLContext ignored = ACL.as2(ACL.SYSTEM2)) {
64+
new TriggerNotifier(project, secretToken, auth) {
65+
@Override
66+
protected void performOnPost(GiteePushTrigger trigger) {
67+
trigger.onPost(pipelineBuildHook);
68+
}
69+
}.run();
70+
}
71+
throw responseWithHook(pipelineBuildHook);
72+
}
73+
74+
}
75+
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.gitee.jenkins.webhook.build;
2+
3+
import com.gitee.jenkins.gitee.hook.model.PullRequestHook;
4+
import com.gitee.jenkins.trigger.GiteePushTrigger;
5+
import com.gitee.jenkins.gitee.hook.model.PullRequestObjectAttributes;
6+
import com.gitee.jenkins.gitee.hook.model.Project;
7+
import com.gitee.jenkins.util.JsonUtil;
8+
import hudson.model.Item;
9+
import hudson.model.Job;
10+
import hudson.security.ACL;
11+
import hudson.security.ACLContext;
12+
import hudson.util.HttpResponses;
13+
import jenkins.model.Jenkins;
14+
15+
import java.util.logging.Level;
16+
import java.util.logging.Logger;
17+
18+
import org.springframework.security.core.Authentication;
19+
20+
import static com.gitee.jenkins.util.JsonUtil.toPrettyPrint;
21+
22+
/**
23+
* @author Robin Müller
24+
*/
25+
public class LegacyPullRequestBuildAction extends LegacyBuildWebHookAction {
26+
27+
private static final Logger LOGGER = Logger.getLogger(LegacyPullRequestBuildAction.class.getName());
28+
private Item project;
29+
private PullRequestHook pullRequestHook;
30+
private final String secretToken;
31+
32+
public LegacyPullRequestBuildAction(Item project, String json, String secretToken) {
33+
LOGGER.log(Level.FINE, "PullRequest: {0}", toPrettyPrint(json));
34+
this.project = project;
35+
this.pullRequestHook = JsonUtil.read(json, PullRequestHook.class);
36+
this.pullRequestHook.setJsonBody(json);
37+
this.secretToken = secretToken;
38+
}
39+
40+
void processForCompatibility() {
41+
final PullRequestObjectAttributes attributes = this.pullRequestHook.getPullRequest();
42+
if (attributes != null) {
43+
final Project source = attributes.getSource();
44+
if (source != null && source.getGitHttpUrl() != null) {
45+
if (source.getUrl() == null) {
46+
source.setUrl(source.getGitHttpUrl());
47+
}
48+
if (source.getHomepage() == null) {
49+
source.setHomepage(source.getGitHttpUrl().substring(0, source.getGitHttpUrl().lastIndexOf(".git")));
50+
}
51+
}
52+
53+
// The PullRequestHookTriggerHandlerImpl is looking for Project
54+
if (pullRequestHook.getRepo() == null && attributes.getTarget() != null) {
55+
pullRequestHook.setRepo(attributes.getTarget());
56+
}
57+
}
58+
}
59+
60+
public void execute() {
61+
if (!(project instanceof Job<?, ?>)) {
62+
throw HttpResponses.errorWithoutStack(409, "Merge Request Hook is not supported for this project");
63+
}
64+
Authentication auth = Jenkins.getAuthentication2();
65+
try (ACLContext ignored = ACL.as2(ACL.SYSTEM2)) {
66+
new TriggerNotifier(project, secretToken, auth) {
67+
@Override
68+
protected void performOnPost(GiteePushTrigger trigger) {
69+
trigger.onPost(pullRequestHook);
70+
}
71+
}.run();
72+
}
73+
throw responseWithHook(pullRequestHook);
74+
}
75+
}

0 commit comments

Comments
 (0)