Commit 2ffa20d1 authored by Greg Messner's avatar Greg Messner
Browse files

Added support for processing the secret token in X-GitLab-Token.

parent 4e42d84e
package org.gitlab4j.api;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
......@@ -229,13 +230,17 @@ public abstract class AbstractApi {
* @param response response
* @param expected expected respone status
* @return original response if the response status is expected
* @throws GitLabApiException if HTTP status is not as expected
* @throws GitLabApiException if HTTP status is not as expected, or the secret token doesn't match
*/
protected Response validate(Response response, Response.Status expected) throws GitLabApiException {
if (response.getStatus() != expected.getStatusCode()) {
throw new GitLabApiException(response);
}
if (!getApiClient().validateSecretToken(response)) {
throw new GitLabApiException(new NotAuthorizedException("Invalid secret token in response."));
}
return (response);
}
......
......@@ -26,7 +26,7 @@ public class GitLabApi {
* @return new {@code GitLabApi} instance configured for a user-specific token
* @throws GitLabApiException GitLabApiException if any exception occurs during execution
*/
static public GitLabApi create(String url, String username, String password) throws GitLabApiException {
public static GitLabApi create(String url, String username, String password) throws GitLabApiException {
String token = new SessionApi(new GitLabApi(url, null)).login(username, null, password).getPrivateToken();
return new GitLabApi(url, token);
}
......@@ -39,7 +39,19 @@ public class GitLabApi {
* @param privateToken to private token to use for access to the API
*/
public GitLabApi(String hostUrl, String privateToken) {
apiClient = new GitLabApiClient(hostUrl, privateToken);
this(hostUrl, privateToken, null);
}
/**
* Constructs a GitLabApi instance set up to interact with the GitLab server
* specified by hostUrl.
*
* @param hostUrl the URL of the GitLab server
* @param privateToken to private token to use for access to the API
* @param secretToken use this token to validate received payloads
*/
public GitLabApi(String hostUrl, String privateToken, String secretToken) {
apiClient = new GitLabApiClient(hostUrl, privateToken, secretToken);
commitsApi = new CommitsApi(this);
groupApi = new GroupApi(this);
mergeRequestApi = new MergeRequestApi(this);
......
......@@ -35,28 +35,49 @@ import java.util.Map;
public class GitLabApiClient {
protected static final String PRIVATE_TOKEN_HEADER = "PRIVATE-TOKEN";
protected static final String X_GITLAB_TOKEN_HEADER = "X-Gitlab-Token";
protected static final String API_NAMESPACE = "/api/v3";
private ClientConfig clientConfig;
private Client apiClient;
private String hostUrl;
private String privateToken;
private String secretToken;
private static boolean ignoreCertificateErrors;
private static SSLSocketFactory defaultSocketFactory;
/**
* Construct an instance to communicate with a GitLab API server using the specified
* server URL and private token.
* server URL, private token, and secret token.
*
* @param hostUrl the URL to the GitLab API server
* @param privateToken the private token to authenticate with
*/
public GitLabApiClient(String hostUrl, String privateToken) {
this(hostUrl, privateToken, null);
}
/**
* Construct an instance to communicate with a GitLab API server using the specified
* server URL, private token, and secret token.
*
* @param hostUrl the URL to the GitLab API server
* @param privateToken the private token to authenticate with
* @param secretToken use this token to validate received payloads
*/
public GitLabApiClient(String hostUrl, String privateToken, String secretToken) {
// Remove the trailing "/" from the hostUrl if present
this.hostUrl = (hostUrl.endsWith("/") ? hostUrl.replaceAll("/$", "") : hostUrl) + API_NAMESPACE;
this.privateToken = privateToken;
if (secretToken != null) {
secretToken = secretToken.trim();
secretToken = (secretToken.length() > 0 ? secretToken : null);
}
this.secretToken = secretToken;
clientConfig = new ClientConfig();
clientConfig.register(JacksonJson.class);
}
......@@ -159,6 +180,25 @@ public class GitLabApiClient {
return (new URL(url.toString()));
}
/**
* Validates the secret token (X-GitLab-Token) header against the expected secret token, returns true if valid,
* otherwise returns false.
*
* @param response the Response instance sent from the GitLab server
* @return true if the response's secret token is valid, otherwise returns false
*/
protected boolean validateSecretToken(Response response) {
if (this.secretToken == null)
return (true);
String secretToken = response.getHeaderString(X_GITLAB_TOKEN_HEADER);
if (secretToken == null)
return (false);
return (this.secretToken.equals(secretToken));
}
/**
* Perform an HTTP GET call with the specified query parameters and path objects, returning
* a ClientResponse instance with the data returned from the endpoint.
......@@ -288,13 +328,6 @@ public class GitLabApiClient {
return (invocation(url, queryParams).delete());
}
protected class AcceptAllHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
return (true);
}
}
protected Invocation.Builder invocation(URL url, MultivaluedMap<String, String> queryParams) {
if (apiClient == null) {
......@@ -311,6 +344,13 @@ public class GitLabApiClient {
return (target.request().header(PRIVATE_TOKEN_HEADER, privateToken).accept(MediaType.APPLICATION_JSON));
}
protected class AcceptAllHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
return (true);
}
}
private SSLContext getSslContext() {
try {
return SSLContext.getDefault();
......@@ -318,5 +358,4 @@ public class GitLabApiClient {
throw new UnsupportedOperationException(e);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment