chore: Add an ability to manually configure git provider oAuth token (#313)

Read user namespace oauth token before checking the oAuth configuration in case when user manually added a bitbucket / github / gitlab oAuth secret to the user namespace.
pull/318/head
Igor Vinokur 2022-06-29 11:17:08 +03:00 committed by GitHub
parent 73b48498ff
commit a47f115553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 217 additions and 47 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -15,7 +15,7 @@ import java.net.URL;
/**
* Dummy implementation of @{@link OAuthAuthenticator} used in the case if no Bitbucket Server
* integration is configured.
* integration is configured to register an empty @{@link BitbucketServerApiClient}.
*/
public class NoopOAuthAuthenticator extends OAuthAuthenticator {
public NoopOAuthAuthenticator() {
@ -49,7 +49,6 @@ public class NoopOAuthAuthenticator extends OAuthAuthenticator {
@Override
public String getLocalAuthenticateUrl() {
throw new RuntimeException(
"The fallback noop authenticator cannot be used for authentication. Make sure OAuth is properly configured.");
return "Noop URL";
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -25,6 +25,7 @@ import javax.inject.Named;
import org.eclipse.che.api.factory.server.bitbucket.server.BitbucketPersonalAccessToken;
import org.eclipse.che.api.factory.server.bitbucket.server.BitbucketServerApiClient;
import org.eclipse.che.api.factory.server.bitbucket.server.BitbucketUser;
import org.eclipse.che.api.factory.server.bitbucket.server.HttpBitbucketServerApiClient;
import org.eclipse.che.api.factory.server.scm.PersonalAccessToken;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenFetcher;
import org.eclipse.che.api.factory.server.scm.exception.ScmBadRequestException;
@ -33,6 +34,7 @@ import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.security.oauth1.NoopOAuthAuthenticator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -104,8 +106,20 @@ public class BitbucketServerPersonalAccessTokenFetcher implements PersonalAccess
public Optional<Boolean> isValid(PersonalAccessToken personalAccessToken)
throws ScmCommunicationException, ScmUnauthorizedException {
if (!bitbucketServerApiClient.isConnected(personalAccessToken.getScmProviderUrl())) {
LOG.debug("not a valid url {} for current fetcher ", personalAccessToken.getScmProviderUrl());
return Optional.empty();
// If BitBucket oAuth is not configured check the manually added user namespace token.
HttpBitbucketServerApiClient apiClient =
new HttpBitbucketServerApiClient(
personalAccessToken.getScmProviderUrl(), new NoopOAuthAuthenticator());
try {
apiClient.getUser(personalAccessToken.getScmUserName(), personalAccessToken.getToken());
return Optional.of(Boolean.TRUE);
} catch (ScmItemNotFoundException
| ScmUnauthorizedException
| ScmCommunicationException exception) {
LOG.debug(
"not a valid url {} for current fetcher ", personalAccessToken.getScmProviderUrl());
return Optional.empty();
}
}
try {
BitbucketPersonalAccessToken bitbucketPersonalAccessToken =

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -17,13 +17,20 @@ import com.google.common.base.Splitter;
import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
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.ScmUnauthorizedException;
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.StringUtils;
/**
@ -35,15 +42,19 @@ import org.eclipse.che.commons.lang.StringUtils;
public class BitbucketURLParser {
private final DevfileFilenamesProvider devfileFilenamesProvider;
private final PersonalAccessTokenManager personalAccessTokenManager;
private static final String bitbucketUrlPatternTemplate =
"^(?<host>%s)/scm/(?<project>[^/]++)/(?<repo>[^.]++).git(\\?at=)?(?<branch>[\\w\\d-_]*)";
private final List<Pattern> bitbucketUrlPatterns = new ArrayList<>();
private static final String OAUTH_PROVIDER_NAME = "bitbucket-server";
@Inject
public BitbucketURLParser(
@Nullable @Named("che.integration.bitbucket.server_endpoints") String bitbucketEndpoints,
DevfileFilenamesProvider devfileFilenamesProvider) {
DevfileFilenamesProvider devfileFilenamesProvider,
PersonalAccessTokenManager personalAccessTokenManager) {
this.devfileFilenamesProvider = devfileFilenamesProvider;
this.personalAccessTokenManager = personalAccessTokenManager;
if (bitbucketEndpoints != null) {
for (String bitbucketEndpoint : Splitter.on(",").split(bitbucketEndpoints)) {
String trimmedEndpoint = StringUtils.trimEnd(bitbucketEndpoint, '/');
@ -53,9 +64,42 @@ public class BitbucketURLParser {
}
}
private boolean isUserTokenPresent(String repositoryUrl) {
String serverUrl = getServerUrl(repositoryUrl);
if (Pattern.compile(format(bitbucketUrlPatternTemplate, serverUrl))
.matcher(repositoryUrl)
.matches()) {
try {
Optional<PersonalAccessToken> token =
personalAccessTokenManager.get(EnvironmentContext.getCurrent().getSubject(), serverUrl);
return token.isPresent() && token.get().getScmTokenName().equals(OAUTH_PROVIDER_NAME);
} catch (ScmConfigurationPersistenceException
| ScmUnauthorizedException
| ScmCommunicationException exception) {
return false;
}
}
return false;
}
public boolean isValid(@NotNull String url) {
return !bitbucketUrlPatterns.isEmpty()
&& bitbucketUrlPatterns.stream().anyMatch(pattern -> pattern.matcher(url).matches());
if (!bitbucketUrlPatterns.isEmpty()) {
return bitbucketUrlPatterns.stream().anyMatch(pattern -> pattern.matcher(url).matches());
} else {
// If Bitbucket server URL is not configured try to find it in a manually added user namespace
// token.
return isUserTokenPresent(url);
}
}
private String getServerUrl(String repositoryUrl) {
return repositoryUrl.substring(
0,
repositoryUrl.indexOf("/scm") > 0 ? repositoryUrl.indexOf("/scm") : repositoryUrl.length());
}
private Matcher getPatternMatcherByUrl(String url) {
return Pattern.compile(format(bitbucketUrlPatternTemplate, getServerUrl(url))).matcher(url);
}
/**
@ -66,6 +110,10 @@ public class BitbucketURLParser {
public BitbucketUrl parse(String url) {
if (bitbucketUrlPatterns.isEmpty()) {
Matcher patternMatcher = getPatternMatcherByUrl(url);
if (patternMatcher.matches()) {
return parse(patternMatcher);
}
throw new UnsupportedOperationException(
"The Bitbucket integration is not configured properly and cannot be used at this moment."
+ "Please refer to docs to check the Bitbucket integration instructions");
@ -82,6 +130,10 @@ public class BitbucketURLParser {
format(
"The given url %s is not a valid Bitbucket server URL. Check either URL or server configuration.",
url)));
return parse(matcher);
}
private BitbucketUrl parse(Matcher matcher) {
String host = matcher.group("host");
String project = matcher.group("project");
String repoName = matcher.group("repo");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -17,6 +17,7 @@ import org.eclipse.che.api.factory.server.scm.exception.ScmBadRequestException;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException;
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.subject.Subject;
/** Bitbucket Server API client. */
@ -36,13 +37,14 @@ public interface BitbucketServerApiClient {
throws ScmUnauthorizedException, ScmCommunicationException, ScmItemNotFoundException;
/**
* @param slug
* @param slug scm username.
* @param token token to override. Pass {@code null} to use token from the authentication flow.
* @return - Retrieve the {@link BitbucketUser} matching the supplied userSlug.
* @throws ScmItemNotFoundException
* @throws ScmUnauthorizedException
* @throws ScmCommunicationException
*/
BitbucketUser getUser(String slug)
BitbucketUser getUser(String slug, @Nullable String token)
throws ScmItemNotFoundException, ScmUnauthorizedException, ScmCommunicationException;
/**

View File

@ -46,6 +46,7 @@ import org.eclipse.che.api.factory.server.scm.exception.ScmBadRequestException;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException;
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.concurrent.LoggingUncaughtExceptionHandler;
import org.eclipse.che.commons.subject.Subject;
@ -128,12 +129,16 @@ public class HttpBitbucketServerApiClient implements BitbucketServerApiClient {
}
@Override
public BitbucketUser getUser(String slug)
public BitbucketUser getUser(String slug, @Nullable String token)
throws ScmItemNotFoundException, ScmUnauthorizedException, ScmCommunicationException {
URI uri = serverUri.resolve("/rest/api/1.0/users/" + slug);
HttpRequest request =
HttpRequest.newBuilder(uri)
.headers("Authorization", computeAuthorizationHeader("GET", uri.toString()))
.headers(
"Authorization",
token != null
? "Bearer " + token
: computeAuthorizationHeader("GET", uri.toString()))
.timeout(DEFAULT_HTTP_TIMEOUT)
.build();
@ -308,7 +313,7 @@ public class HttpBitbucketServerApiClient implements BitbucketServerApiClient {
throws ScmCommunicationException, ScmUnauthorizedException, ScmItemNotFoundException {
for (String userSlug : userSlugs) {
BitbucketUser user = getUser(userSlug);
BitbucketUser user = getUser(userSlug, null);
try {
getPersonalAccessTokens(userSlug);
return Optional.of(user);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -17,6 +17,7 @@ import org.eclipse.che.api.factory.server.scm.exception.ScmBadRequestException;
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
import org.eclipse.che.api.factory.server.scm.exception.ScmItemNotFoundException;
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.subject.Subject;
/**
@ -37,7 +38,7 @@ public class NoopBitbucketServerApiClient implements BitbucketServerApiClient {
}
@Override
public BitbucketUser getUser(String slug)
public BitbucketUser getUser(String slug, @Nullable String token)
throws ScmItemNotFoundException, ScmUnauthorizedException, ScmCommunicationException {
throw new RuntimeException(
"The fallback noop api client cannot be used for real operation. Make sure Bitbucket OAuth1 is properly configured.");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -19,6 +19,7 @@ import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
@ -68,7 +69,10 @@ public class BitbucketServerAuthorizingFactoryParametersResolverTest {
@BeforeMethod
protected void init() {
bitbucketURLParser =
new BitbucketURLParser("http://bitbucket.2mcl.com", devfileFilenamesProvider);
new BitbucketURLParser(
"http://bitbucket.2mcl.com",
devfileFilenamesProvider,
mock(PersonalAccessTokenManager.class));
assertNotNull(this.bitbucketURLParser);
bitbucketServerFactoryParametersResolver =
new BitbucketServerAuthorizingFactoryParametersResolver(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -14,6 +14,7 @@ package org.eclipse.che.api.factory.server.bitbucket;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.*;
@ -47,7 +48,9 @@ public class BitbucketServerScmFileResolverTest {
@BeforeMethod
protected void init() {
bitbucketURLParser = new BitbucketURLParser(SCM_URL, devfileFilenamesProvider);
bitbucketURLParser =
new BitbucketURLParser(
SCM_URL, devfileFilenamesProvider, mock(PersonalAccessTokenManager.class));
assertNotNull(this.bitbucketURLParser);
serverScmFileResolver =
new BitbucketServerScmFileResolver(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -11,9 +11,11 @@
*/
package org.eclipse.che.api.factory.server.bitbucket;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
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;
@ -34,7 +36,9 @@ public class BitbucketURLParserTest {
public void setUp() {
bitbucketURLParser =
new BitbucketURLParser(
"https://bitbucket.2mcl.com,https://bbkt.com", devfileFilenamesProvider);
"https://bitbucket.2mcl.com,https://bbkt.com",
devfileFilenamesProvider,
mock(PersonalAccessTokenManager.class));
}
/** Check URLs are valid with regexp */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -95,7 +95,7 @@ public class HttpBitbucketServerApiClientTest {
.withHeader("Content-Type", "application/json; charset=utf-8")
.withBodyFile("bitbucket/rest/api/1.0/users/ksmster/response.json")));
BitbucketUser user = bitbucketServer.getUser("ksmster");
BitbucketUser user = bitbucketServer.getUser("ksmster", null);
assertNotNull(user);
}

View File

@ -149,9 +149,13 @@ public class GitlabOAuthTokenFetcher implements PersonalAccessTokenFetcher {
GitlabApiClient gitlabApiClient = getApiClient(personalAccessToken.getScmProviderUrl());
if (gitlabApiClient == null
|| !gitlabApiClient.isConnected(personalAccessToken.getScmProviderUrl())) {
LOG.debug(
"not a valid url {} for current fetcher ", personalAccessToken.getScmProviderUrl());
return Optional.empty();
if (personalAccessToken.getScmTokenName().equals(OAUTH_PROVIDER_NAME)) {
gitlabApiClient = new GitlabApiClient(personalAccessToken.getScmProviderUrl());
} else {
LOG.debug(
"not a valid url {} for current fetcher ", personalAccessToken.getScmProviderUrl());
return Optional.empty();
}
}
if (personalAccessToken.getScmTokenName() != null
&& personalAccessToken.getScmTokenName().startsWith(OAUTH_2_PREFIX)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -17,12 +17,19 @@ import com.google.common.base.Splitter;
import jakarta.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
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.ScmUnauthorizedException;
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.StringUtils;
/**
@ -33,6 +40,7 @@ import org.eclipse.che.commons.lang.StringUtils;
public class GitlabUrlParser {
private final DevfileFilenamesProvider devfileFilenamesProvider;
private final PersonalAccessTokenManager personalAccessTokenManager;
private static final List<String> gitlabUrlPatternTemplates =
List.of(
"^(?<host>%s)/(?<user>[^/]++)/(?<project>[^./]++).git",
@ -40,12 +48,15 @@ public class GitlabUrlParser {
"^(?<host>%s)/(?<user>[^/]++)/(?<project>[^/]++)(/)?(?<repository>[^/]++)?(/)?",
"^(?<host>%s)/(?<user>[^/]++)/(?<project>[^/]++)(/)?(?<repository>[^/]++)?/-/tree/(?<branch>[^/]++)(/)?(?<subfolder>[^/]++)?");
private final List<Pattern> gitlabUrlPatterns = new ArrayList<>();
private static final String OAUTH_PROVIDER_NAME = "gitlab";
@Inject
public GitlabUrlParser(
@Nullable @Named("che.integration.gitlab.server_endpoints") String bitbucketEndpoints,
DevfileFilenamesProvider devfileFilenamesProvider) {
DevfileFilenamesProvider devfileFilenamesProvider,
PersonalAccessTokenManager personalAccessTokenManager) {
this.devfileFilenamesProvider = devfileFilenamesProvider;
this.personalAccessTokenManager = personalAccessTokenManager;
if (bitbucketEndpoints != null) {
for (String bitbucketEndpoint : Splitter.on(",").split(bitbucketEndpoints)) {
String trimmedEndpoint = StringUtils.trimEnd(bitbucketEndpoint, '/');
@ -57,9 +68,55 @@ public class GitlabUrlParser {
}
}
private boolean isUserTokenPresent(String repositoryUrl) {
Optional<String> serverUrlOptional = getServerUrl(repositoryUrl);
if (serverUrlOptional.isPresent()) {
String serverUrl = serverUrlOptional.get();
try {
Optional<PersonalAccessToken> token =
personalAccessTokenManager.get(EnvironmentContext.getCurrent().getSubject(), serverUrl);
if (token.isPresent()) {
PersonalAccessToken accessToken = token.get();
return accessToken.getScmTokenName().equals(OAUTH_PROVIDER_NAME);
}
} catch (ScmConfigurationPersistenceException
| ScmUnauthorizedException
| ScmCommunicationException exception) {
return false;
}
}
return false;
}
public boolean isValid(@NotNull String url) {
return !gitlabUrlPatterns.isEmpty()
&& gitlabUrlPatterns.stream().anyMatch(pattern -> pattern.matcher(url).matches());
if (!gitlabUrlPatterns.isEmpty()) {
return gitlabUrlPatterns.stream().anyMatch(pattern -> pattern.matcher(url).matches());
} else {
// If Gitlab URL is not configured, try to find it in a manually added user namespace
// token.
return isUserTokenPresent(url);
}
}
private Optional<Matcher> getPatternMatcherByUrl(String url) {
Optional<String> serverUrlOptional = getServerUrl(url);
if (serverUrlOptional.isPresent()) {
String serverUrl = serverUrlOptional.get();
return gitlabUrlPatternTemplates.stream()
.map(t -> Pattern.compile(format(t, serverUrl)).matcher(url))
.filter(Matcher::matches)
.findAny();
}
return Optional.empty();
}
private Optional<String> getServerUrl(String repositoryUrl) {
Matcher serverUrlMatcher = Pattern.compile("[^/|:]/").matcher(repositoryUrl);
if (serverUrlMatcher.find()) {
return Optional.of(
repositoryUrl.substring(0, repositoryUrl.indexOf(serverUrlMatcher.group()) + 1));
}
return Optional.empty();
}
/**
@ -69,6 +126,10 @@ public class GitlabUrlParser {
public GitlabUrl parse(String url) {
if (gitlabUrlPatterns.isEmpty()) {
Optional<Matcher> optionalMatcher = getPatternMatcherByUrl(url);
if (optionalMatcher.isPresent()) {
return parse(optionalMatcher.get());
}
throw new UnsupportedOperationException(
"The gitlab integration is not configured properly and cannot be used at this moment."
+ "Please refer to docs to check the Gitlab integration instructions");
@ -85,6 +146,10 @@ public class GitlabUrlParser {
format(
"The given url %s is not a valid Gitlab server URL. Check either URL or server configuration.",
url)));
return parse(matcher);
}
private GitlabUrl parse(Matcher matcher) {
String host = matcher.group("host");
String userName = matcher.group("user");
String project = matcher.group("project");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -19,6 +19,7 @@ import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
@ -71,7 +72,11 @@ public class GitlabFactoryParametersResolverTest {
@BeforeMethod
protected void init() {
gitlabUrlParser = new GitlabUrlParser("http://gitlab.2mcl.com", devfileFilenamesProvider);
gitlabUrlParser =
new GitlabUrlParser(
"http://gitlab.2mcl.com",
devfileFilenamesProvider,
mock(PersonalAccessTokenManager.class));
assertNotNull(this.gitlabUrlParser);
gitlabFactoryParametersResolver =
new GitlabFactoryParametersResolver(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -14,6 +14,7 @@ package org.eclipse.che.api.factory.server.gitlab;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.*;
@ -47,7 +48,9 @@ public class GitlabScmFileResolverTest {
@BeforeMethod
protected void init() {
gitlabUrlParser = new GitlabUrlParser(SCM_URL, devfileFilenamesProvider);
gitlabUrlParser =
new GitlabUrlParser(
SCM_URL, devfileFilenamesProvider, mock(PersonalAccessTokenManager.class));
assertNotNull(this.gitlabUrlParser);
gitlabScmFileResolver =
new GitlabScmFileResolver(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -11,9 +11,11 @@
*/
package org.eclipse.che.api.factory.server.gitlab;
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
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;
@ -33,7 +35,10 @@ public class GitlabUrlParserTest {
@BeforeMethod
public void setUp() {
gitlabUrlParser =
new GitlabUrlParser("https://gitlab1.com,https://gitlab.foo.xxx", devfileFilenamesProvider);
new GitlabUrlParser(
"https://gitlab1.com,https://gitlab.foo.xxx",
devfileFilenamesProvider,
mock(PersonalAccessTokenManager.class));
}
/** Check URLs are valid with regexp */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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,13 @@ package org.eclipse.che.api.factory.server.gitlab;
import static java.lang.String.format;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import java.util.Arrays;
import java.util.Iterator;
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl.DevfileLocation;
import org.mockito.Mock;
@ -45,7 +47,9 @@ public class GitlabUrlTest {
protected void init() {
when(devfileFilenamesProvider.getConfiguredDevfileFilenames())
.thenReturn(Arrays.asList("devfile.yaml", "foo.bar"));
gitlabUrlParser = new GitlabUrlParser("https://gitlab.net", devfileFilenamesProvider);
gitlabUrlParser =
new GitlabUrlParser(
"https://gitlab.net", devfileFilenamesProvider, mock(PersonalAccessTokenManager.class));
}
/** Check when there is devfile in the repository */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2022 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/
@ -42,8 +42,8 @@ public interface PersonalAccessTokenManager {
/**
* Gets {@link PersonalAccessToken} from permanent storage.
*
* @param cheUser
* @param scmServerUrl
* @param cheUser Che user object
* @param scmServerUrl Git provider endpoint
* @return personal access token
* @throws ScmConfigurationPersistenceException - problem occurred during communication with *
* permanent storage.