Apply Gitlab server url validation by testing an API request (#421)
Support factory from public Gitlab-server repository without any oAuth configuration in the Che side. Add a new check that detects a Gitlab server url by testing it by a Gitlab Api request.pull/422/head
parent
5a601bb840
commit
756342b0c0
|
|
@ -130,7 +130,8 @@ public class GitlabApiClient {
|
|||
throw new ScmItemNotFoundException(body);
|
||||
default:
|
||||
throw new ScmCommunicationException(
|
||||
"Unexpected status code " + response.statusCode() + " " + response.toString());
|
||||
"Unexpected status code " + response.statusCode() + " " + response,
|
||||
response.statusCode());
|
||||
}
|
||||
}
|
||||
} catch (IOException | InterruptedException | UncheckedIOException e) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
package org.eclipse.che.api.factory.server.gitlab;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
|
@ -27,6 +28,7 @@ import org.eclipse.che.api.factory.server.scm.PersonalAccessToken;
|
|||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmConfigurationPersistenceException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
|
||||
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
|
|
@ -92,10 +94,29 @@ public class GitlabUrlParser {
|
|||
}
|
||||
|
||||
public boolean isValid(@NotNull String url) {
|
||||
// If Gitlab URL is not configured, try to find it in a manually added user namespace
|
||||
// token.
|
||||
return gitlabUrlPatterns.stream().anyMatch(pattern -> pattern.matcher(url).matches())
|
||||
|| isUserTokenPresent(url);
|
||||
// If the Gitlab URL is not configured, try to find it in a manually added user namespace
|
||||
// token.
|
||||
|| isUserTokenPresent(url)
|
||||
// Try to call an API request to see if the URL matches Gitlab.
|
||||
|| isApiRequestRelevant(url);
|
||||
}
|
||||
|
||||
private boolean isApiRequestRelevant(String repositoryUrl) {
|
||||
Optional<String> serverUrlOptional = getServerUrl(repositoryUrl);
|
||||
if (serverUrlOptional.isPresent()) {
|
||||
GitlabApiClient gitlabApiClient = new GitlabApiClient(serverUrlOptional.get());
|
||||
try {
|
||||
// If the token request catches the unauthorised error, it means that the provided url
|
||||
// belongs to Gitlab.
|
||||
gitlabApiClient.getTokenInfo("");
|
||||
} catch (ScmCommunicationException e) {
|
||||
return e.getStatusCode() == HTTP_UNAUTHORIZED;
|
||||
} catch (ScmItemNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Optional<Matcher> getPatternMatcherByUrl(String url) {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ public class GitlabFactoryParametersResolverTest {
|
|||
/** Check url which is not a Gitlab url can't be accepted by this resolver */
|
||||
@Test
|
||||
public void checkInvalidAcceptUrl() {
|
||||
Map<String, String> parameters = singletonMap(URL_PARAMETER_NAME, "http://github.com");
|
||||
Map<String, String> parameters =
|
||||
singletonMap(URL_PARAMETER_NAME, "http://github.com/user/repo");
|
||||
// shouldn't be accepted
|
||||
assertFalse(gitlabFactoryParametersResolver.accept(parameters));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public class GitlabScmFileResolverTest {
|
|||
@Test
|
||||
public void checkInvalidAcceptUrl() {
|
||||
// shouldn't be accepted
|
||||
assertFalse(gitlabScmFileResolver.accept("http://github.com"));
|
||||
assertFalse(gitlabScmFileResolver.accept("http://github.com/user/repo"));
|
||||
}
|
||||
|
||||
/** Check Gitlab url will be be accepted by this resolver */
|
||||
|
|
|
|||
|
|
@ -11,14 +11,24 @@
|
|||
*/
|
||||
package org.eclipse.che.api.factory.server.gitlab;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.common.Slf4jNotifier;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
|
||||
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Listeners;
|
||||
|
|
@ -32,6 +42,18 @@ public class GitlabUrlParserTest {
|
|||
/** Instance of component that will be tested. */
|
||||
private GitlabUrlParser gitlabUrlParser;
|
||||
|
||||
private WireMockServer wireMockServer;
|
||||
private WireMock wireMock;
|
||||
|
||||
@BeforeClass
|
||||
public void prepare() {
|
||||
wireMockServer =
|
||||
new WireMockServer(wireMockConfig().notifier(new Slf4jNotifier(false)).dynamicPort());
|
||||
wireMockServer.start();
|
||||
WireMock.configureFor("localhost", wireMockServer.port());
|
||||
wireMock = new WireMock("localhost", wireMockServer.port());
|
||||
}
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
gitlabUrlParser =
|
||||
|
|
@ -60,6 +82,32 @@ public class GitlabUrlParserTest {
|
|||
assertEquals(gitlabUrl.getSubfolder(), subfolder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldValidateUrlByApiRequest() {
|
||||
// given
|
||||
String url = wireMockServer.url("/user/repo");
|
||||
stubFor(get(urlEqualTo("/oauth/token/info")).willReturn(aResponse().withStatus(401)));
|
||||
|
||||
// when
|
||||
boolean result = gitlabUrlParser.isValid(url);
|
||||
|
||||
// then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotValidateUrlByApiRequest() {
|
||||
// given
|
||||
String url = wireMockServer.url("/user/repo");
|
||||
stubFor(get(urlEqualTo("/oauth/token/info")).willReturn(aResponse().withStatus(500)));
|
||||
|
||||
// when
|
||||
boolean result = gitlabUrlParser.isValid(url);
|
||||
|
||||
// then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@DataProvider(name = "UrlsProvider")
|
||||
public Object[][] urls() {
|
||||
return new Object[][] {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2021 Red Hat, Inc.
|
||||
* Copyright (c) 2012-2023 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
|
|
@ -13,11 +13,22 @@ package org.eclipse.che.api.factory.server.scm.exception;
|
|||
|
||||
/** Thrown when problem occurred during communication with scm provider */
|
||||
public class ScmCommunicationException extends Exception {
|
||||
private int statusCode;
|
||||
|
||||
public ScmCommunicationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ScmCommunicationException(String message, int statusCode) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public ScmCommunicationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue