Skip to content

Commit 9cb5680

Browse files
committed
Some more refactoring
1 parent 532792c commit 9cb5680

File tree

2 files changed

+116
-86
lines changed

2 files changed

+116
-86
lines changed

src/main/java/org/jenkinsci/plugins/gogs/GogsUtils.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
import hudson.model.Item;
44
import jenkins.model.Jenkins;
5+
import org.apache.commons.codec.binary.Hex;
6+
7+
import javax.annotation.Nonnull;
8+
import javax.crypto.Mac;
9+
import javax.crypto.spec.SecretKeySpec;
10+
import java.nio.charset.Charset;
11+
import java.util.Map;
12+
import java.util.regex.Pattern;
13+
import java.util.stream.Collectors;
514

615
class GogsUtils {
716

@@ -26,4 +35,32 @@ static <T extends Item> T find(String jobName, Class<T> type) {
2635
return item;
2736
}
2837

38+
/**
39+
* Converts Querystring into Map<String,String>
40+
*
41+
* @param qs Querystring
42+
* @return returns map from querystring
43+
*/
44+
static Map<String, String> splitQuery(String qs) {
45+
return Pattern.compile("&").splitAsStream(qs)
46+
.map(p -> p.split("="))
47+
.collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));
48+
}
49+
50+
/**
51+
* encode sha256 hmac
52+
*
53+
* @param data data to hex
54+
* @param key key of HmacSHA256
55+
* @return a String with the encoded sha256 hmac
56+
* @throws Exception Something went wrong getting the sha256 hmac
57+
*/
58+
static @Nonnull
59+
String encode(String data, String key) throws Exception {
60+
final Charset asciiCs = Charset.forName("UTF-8");
61+
final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
62+
final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(asciiCs.encode(key).array(), "HmacSHA256");
63+
sha256_HMAC.init(secret_key);
64+
return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
65+
}
2966
}

src/main/java/org/jenkinsci/plugins/gogs/GogsWebHook.java

Lines changed: 79 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,21 @@ associated documentation files (the "Software"), to deal in the Software without
3030
import net.sf.json.JSONObject;
3131
import org.acegisecurity.context.SecurityContext;
3232
import org.acegisecurity.context.SecurityContextHolder;
33-
import org.apache.commons.codec.binary.Hex;
3433
import org.apache.commons.io.IOUtils;
3534
import org.kohsuke.stapler.StaplerRequest;
3635
import org.kohsuke.stapler.StaplerResponse;
3736

38-
import javax.annotation.Nonnull;
39-
import javax.crypto.Mac;
40-
import javax.crypto.spec.SecretKeySpec;
4137
import java.io.IOException;
4238
import java.io.PrintWriter;
4339
import java.net.URLDecoder;
44-
import java.nio.charset.Charset;
45-
import java.util.Arrays;
4640
import java.util.Map;
41+
import java.util.Objects;
4742
import java.util.StringJoiner;
4843
import java.util.concurrent.atomic.AtomicBoolean;
4944
import java.util.concurrent.atomic.AtomicReference;
5045
import java.util.logging.Logger;
5146
import java.util.regex.Pattern;
52-
import java.util.stream.Collectors;
47+
import java.util.stream.Stream;
5348

5449
import static com.google.common.base.Preconditions.checkNotNull;
5550
import static com.google.common.base.Strings.isNullOrEmpty;
@@ -60,8 +55,12 @@ associated documentation files (the "Software"), to deal in the Software without
6055
@Extension
6156
public class GogsWebHook implements UnprotectedRootAction {
6257
private final static Logger LOGGER = Logger.getLogger(GogsWebHook.class.getName());
63-
static final String URLNAME = "gogs-webhook";
6458
private static final String DEFAULT_CHARSET = "UTF-8";
59+
private GogsResults result = new GogsResults();
60+
private String gogsDelivery = null;
61+
private String gogsSignature = null;
62+
private String jobName = null;
63+
static final String URLNAME = "gogs-webhook";
6564

6665
public String getDisplayName() {
6766
return null;
@@ -75,21 +74,26 @@ public String getUrlName() {
7574
return URLNAME;
7675
}
7776

78-
/**
79-
* encode sha256 hmac
80-
*
81-
* @param data data to hex
82-
* @param key key of HmacSHA256
83-
* @return a String with the encoded sha256 hmac
84-
* @throws Exception Something went wrong getting the sha256 hmac
85-
*/
86-
private static @Nonnull
87-
String encode(String data, String key) throws Exception {
88-
final Charset asciiCs = Charset.forName("UTF-8");
89-
final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
90-
final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(asciiCs.encode(key).array(), "HmacSHA256");
91-
sha256_HMAC.init(secret_key);
92-
return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
77+
private String getGogsDelivery() {
78+
if (isNullOrEmpty(gogsDelivery)) {
79+
return "Triggered by Jenkins-Gogs-Plugin. Delivery ID unknown.";
80+
}
81+
return "Gogs-ID: " + gogsDelivery;
82+
}
83+
84+
private void setGogsDelivery(String gogsDelivery) {
85+
this.gogsDelivery = gogsDelivery;
86+
}
87+
88+
private String getGogsSignature() {
89+
if (isNullOrEmpty(gogsSignature)) {
90+
gogsSignature = null;
91+
}
92+
return gogsSignature;
93+
}
94+
95+
private void setGogsSignature(String gogsSignature) {
96+
this.gogsSignature = gogsSignature;
9397
}
9498

9599
/**
@@ -100,52 +104,17 @@ String encode(String data, String key) throws Exception {
100104
* @throws IOException problem while parsing
101105
*/
102106
public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException {
103-
GogsResults result = new GogsResults();
104107
GogsPayloadProcessor payloadProcessor = new GogsPayloadProcessor();
105108

106-
//Check that we have something to process
107-
checkNotNull(req, "Null request submitted to doIndex method");
108-
checkNotNull(rsp, "Null reply submitted to doIndex method");
109-
110-
// Get X-Gogs-Event
111-
String event = req.getHeader("X-Gogs-Event");
112-
if (!"push".equals(event)) {
113-
result.setStatus(403, "Only push event can be accepted.");
114-
exitWebHook(result, rsp);
109+
if (!sanityChecks(req, rsp)) {
115110
return;
116111
}
117112

118113
// Get X-Gogs-Delivery header with deliveryID
119-
String gogsDelivery = req.getHeader("X-Gogs-Delivery");
120-
if (isNullOrEmpty(gogsDelivery)) {
121-
gogsDelivery = "Triggered by Jenkins-Gogs-Plugin. Delivery ID unknown.";
122-
} else {
123-
gogsDelivery = "Gogs-ID: " + gogsDelivery;
124-
}
114+
setGogsDelivery(req.getHeader("X-Gogs-Delivery"));
125115

126116
// Get X-Gogs-Signature
127-
String gogsSignature = req.getHeader("X-Gogs-Signature");
128-
if (isNullOrEmpty(gogsSignature)) {
129-
gogsSignature = null;
130-
}
131-
132-
133-
// Get queryStringMap from the URI
134-
String queryString = checkNotNull(req.getQueryString(), "The queryString in the request is null");
135-
Map queryStringMap = checkNotNull(splitQuery(queryString), "Null queryStringMap");
136-
137-
//Do we have the job name parameter ?
138-
if (!queryStringMap.containsKey("job")) {
139-
result.setStatus(404, "Parameter 'job' is missing.");
140-
exitWebHook(result, rsp);
141-
return;
142-
}
143-
String jobName = queryStringMap.get("job").toString();
144-
if (isNullOrEmpty(jobName)) {
145-
result.setStatus(404, "No value assigned to parameter 'job'");
146-
exitWebHook(result, rsp);
147-
return;
148-
}
117+
setGogsSignature(req.getHeader("X-Gogs-Signature"));
149118

150119
// Get the POST stream
151120
String body = IOUtils.toString(req.getInputStream(), DEFAULT_CHARSET);
@@ -182,27 +151,24 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException
182151
.forEach(stringJoiner::add);
183152
String ref = stringJoiner.toString();
184153

185-
Arrays.asList(jobName, jobName + "/" + ref).forEach(j -> {
186-
Job job = GogsUtils.find(j, Job.class);
187-
if (job != null) {
188-
foundJob.set(true);
189-
/* secret is stored in the properties of Job */
190-
final GogsProjectProperty property = (GogsProjectProperty) job.getProperty(GogsProjectProperty.class);
191-
if (property != null) { /* only if Gogs secret is defined on the job */
192-
jSecret.set(property.getGogsSecret()); /* Secret provided by Jenkins */
193-
}
154+
/* secret is stored in the properties of Job */
155+
Stream.of(jobName, jobName + "/" + ref).map(j -> GogsUtils.find(j, Job.class)).filter(Objects::nonNull).forEach(job -> {
156+
foundJob.set(true);
157+
final GogsProjectProperty property = (GogsProjectProperty) job.getProperty(GogsProjectProperty.class);
158+
if (property != null) { /* only if Gogs secret is defined on the job */
159+
jSecret.set(property.getGogsSecret()); /* Secret provided by Jenkins */
194160
}
195161
});
196162
} finally {
197163
SecurityContextHolder.setContext(saveCtx);
198164
}
199165

200166
String gSecret = null;
201-
if (gogsSignature == null) {
167+
if (getGogsSignature() == null) {
202168
gSecret = jsonObject.optString("secret", null); /* Secret provided by Gogs < 0.10.x */
203169
} else {
204170
try {
205-
if (gogsSignature.equals(encode(body, jSecret.get()))) {
171+
if (getGogsSignature().equals(GogsUtils.encode(body, jSecret.get()))) {
206172
gSecret = jSecret.get();
207173
// now hex is right, continue to old logic
208174
}
@@ -217,10 +183,10 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException
217183
LOGGER.warning(msg);
218184
} else if (isNullOrEmpty(jSecret.get()) && isNullOrEmpty(gSecret)) {
219185
/* No password is set in Jenkins and Gogs, run without secrets */
220-
result = payloadProcessor.triggerJobs(jobName, gogsDelivery);
186+
result = payloadProcessor.triggerJobs(jobName, getGogsDelivery());
221187
} else if (!isNullOrEmpty(jSecret.get()) && jSecret.get().equals(gSecret)) {
222188
/* Password is set in Jenkins and Gogs, and is correct */
223-
result = payloadProcessor.triggerJobs(jobName, gogsDelivery);
189+
result = payloadProcessor.triggerJobs(jobName, getGogsDelivery());
224190
} else {
225191
/* Gogs and Jenkins secrets differs */
226192
result.setStatus(403, "Incorrect secret");
@@ -232,6 +198,45 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException
232198
exitWebHook(result, rsp);
233199
}
234200

201+
/***
202+
* Do sanity checks
203+
*
204+
* @param req Request
205+
* @param rsp Response
206+
* @throws IOException
207+
*/
208+
private boolean sanityChecks(StaplerRequest req, StaplerResponse rsp) throws IOException {
209+
//Check that we have something to process
210+
checkNotNull(req, "Null request submitted to doIndex method");
211+
checkNotNull(rsp, "Null reply submitted to doIndex method");
212+
213+
// Get X-Gogs-Event
214+
if (!"push".equals(req.getHeader("X-Gogs-Event"))) {
215+
result.setStatus(403, "Only push event can be accepted.");
216+
exitWebHook(result, rsp);
217+
return false;
218+
}
219+
220+
// Get queryStringMap from the URI
221+
String queryString = checkNotNull(req.getQueryString(), "The queryString in the request is null");
222+
Map queryStringMap = checkNotNull(GogsUtils.splitQuery(queryString), "Null queryStringMap");
223+
224+
//Do we have the job name parameter ?
225+
if (!queryStringMap.containsKey("job")) {
226+
result.setStatus(404, "Parameter 'job' is missing.");
227+
exitWebHook(result, rsp);
228+
return false;
229+
}
230+
231+
jobName = queryStringMap.get("job").toString();
232+
if (isNullOrEmpty(jobName)) {
233+
result.setStatus(404, "No value assigned to parameter 'job'");
234+
exitWebHook(result, rsp);
235+
return false;
236+
}
237+
return true;
238+
}
239+
235240
/**
236241
* Exit the WebHook
237242
*
@@ -250,18 +255,6 @@ private void exitWebHook(GogsResults result, StaplerResponse resp) throws IOExce
250255
PrintWriter printer = resp.getWriter();
251256
printer.print(json.toString());
252257
}
253-
254-
/**
255-
* Converts Querystring into Map<String,String>
256-
*
257-
* @param qs Querystring
258-
* @return returns map from querystring
259-
*/
260-
private static Map<String, String> splitQuery(String qs) {
261-
return Pattern.compile("&").splitAsStream(qs)
262-
.map(p -> p.split("="))
263-
.collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));
264-
}
265258
}
266259

267260
// vim: set ts=4 sw=4 tw=0 ft=java et :

0 commit comments

Comments
 (0)