diff --git a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubPersonalAccessTokenFetcher.java b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubPersonalAccessTokenFetcher.java index 76ce31d4c7..efb7646435 100644 --- a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubPersonalAccessTokenFetcher.java +++ b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubPersonalAccessTokenFetcher.java @@ -205,13 +205,21 @@ public Optional isValid(PersonalAccessToken personalAccessToken) { @Override public Optional> isValid(PersonalAccessTokenParams params) { - if (!githubApiClient.isConnected(params.getScmProviderUrl())) { - LOG.debug("not a valid url {} for current fetcher ", params.getScmProviderUrl()); - return Optional.empty(); + GithubApiClient apiClient; + if (githubApiClient.isConnected(params.getScmProviderUrl())) { + // The url from the token has the same url as the api client, no need to create a new one. + apiClient = githubApiClient; + } else { + if ("github".equals(params.getScmTokenName())) { + apiClient = new GithubApiClient(params.getScmProviderUrl()); + } else { + LOG.debug("not a valid url {} for current fetcher ", params.getScmProviderUrl()); + return Optional.empty(); + } } try { if (params.getScmTokenName() != null && params.getScmTokenName().startsWith(OAUTH_2_PREFIX)) { - Pair pair = githubApiClient.getTokenScopes(params.getToken()); + Pair pair = apiClient.getTokenScopes(params.getToken()); return Optional.of( Pair.of( containsScopes(pair.second, DEFAULT_TOKEN_SCOPES) ? Boolean.TRUE : Boolean.FALSE, @@ -219,7 +227,7 @@ public Optional> isValid(PersonalAccessTokenParams params) } else { // TODO: add PAT scope validation // No REST API for PAT-s in Github found yet. Just try to do some action. - GithubUser user = githubApiClient.getUser(params.getToken()); + GithubUser user = apiClient.getUser(params.getToken()); return Optional.of(Pair.of(Boolean.TRUE, user.getLogin())); } } catch (ScmItemNotFoundException | ScmCommunicationException | ScmBadRequestException e) { diff --git a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubURLParser.java b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubURLParser.java index 94e55d4391..008df378a7 100644 --- a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubURLParser.java +++ b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubURLParser.java @@ -14,6 +14,7 @@ import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Strings.isNullOrEmpty; import static java.lang.String.format; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; import static java.util.regex.Pattern.compile; import static org.eclipse.che.api.factory.server.ApiExceptionMapper.toApiException; import static org.eclipse.che.api.factory.server.github.GithubApiClient.GITHUB_SAAS_ENDPOINT; @@ -46,15 +47,19 @@ public abstract class AbstractGithubURLParser { private final PersonalAccessTokenManager tokenManager; private final DevfileFilenamesProvider devfileFilenamesProvider; private final GithubApiClient apiClient; - private final String oauthEndpoint; /** * Regexp to find repository details (repository name, project name and branch and subfolder) * Examples of valid URLs are in the test class. */ private final Pattern githubPattern; + private final String githubPatternTemplate = + "^%s/(?[^/]+)/(?[^/]++)((/)|(?:/tree/(?.++))|(/pull/(?\\d++)))?$"; + private final Pattern githubSSHPattern; + private final String githubSSHPatternTemplate = "^git@%s:(?.*)/(?.*)$"; + private final boolean disableSubdomainIsolation; private final String providerName; @@ -70,26 +75,80 @@ public abstract class AbstractGithubURLParser { this.tokenManager = tokenManager; this.devfileFilenamesProvider = devfileFilenamesProvider; this.apiClient = githubApiClient; - this.oauthEndpoint = oauthEndpoint; this.disableSubdomainIsolation = disableSubdomainIsolation; this.providerName = providerName; String endpoint = isNullOrEmpty(oauthEndpoint) ? GITHUB_SAAS_ENDPOINT : trimEnd(oauthEndpoint, '/'); - this.githubPattern = - compile( - format( - "^%s/(?[^/]+)/(?[^/]++)((/)|(?:/tree/(?.++))|(/pull/(?\\d++)))?$", - endpoint)); + this.githubPattern = compile(format(githubPatternTemplate, endpoint)); this.githubSSHPattern = - compile(format("^git@%s:(?.*)/(?.*)$", URI.create(endpoint).getHost())); + compile(format(githubSSHPatternTemplate, URI.create(endpoint).getHost())); } public boolean isValid(@NotNull String url) { String trimmedUrl = trimEnd(url, '/'); return githubPattern.matcher(trimmedUrl).matches() - || githubSSHPattern.matcher(trimmedUrl).matches(); + || githubSSHPattern.matcher(trimmedUrl).matches() + // If the GitHub URL is not configured, try to find it in a manually added user namespace + // token. + || isUserTokenPresent(trimmedUrl) + // Try to call an API request to see if the URL matches GitHub. + || isApiRequestRelevant(trimmedUrl); + } + + private boolean isUserTokenPresent(String repositoryUrl) { + Optional serverUrlOptional = getServerUrl(repositoryUrl); + if (serverUrlOptional.isPresent()) { + String serverUrl = serverUrlOptional.get(); + try { + Optional token = + tokenManager.get(EnvironmentContext.getCurrent().getSubject(), serverUrl); + if (token.isPresent()) { + PersonalAccessToken accessToken = token.get(); + return accessToken.getScmTokenName().equals(providerName); + } + } catch (ScmConfigurationPersistenceException + | ScmUnauthorizedException + | ScmCommunicationException exception) { + return false; + } + } + return false; + } + + private boolean isApiRequestRelevant(String repositoryUrl) { + Optional serverUrlOptional = getServerUrl(repositoryUrl); + if (serverUrlOptional.isPresent()) { + GithubApiClient GithubApiClient = new GithubApiClient(serverUrlOptional.get()); + try { + // If the user request catches the unauthorised error, it means that the provided url + // belongs to GitHub. + GithubApiClient.getUser(""); + } catch (ScmCommunicationException e) { + return e.getStatusCode() == HTTP_UNAUTHORIZED; + } catch (ScmItemNotFoundException | ScmBadRequestException | IllegalArgumentException e) { + return false; + } + } + return false; + } + + private Optional getServerUrl(String repositoryUrl) { + // If the given repository url is an SSH url, generate the base url from the pattern: + // https://. + if (repositoryUrl.startsWith("git@")) { + String substring = repositoryUrl.substring(4); + return Optional.of("https://" + substring.substring(0, substring.indexOf(":"))); + } + // Otherwise, extract the base url from the given repository url by cutting the url after the + // first slash. + Matcher serverUrlMatcher = compile("[^/|:]/").matcher(repositoryUrl); + if (serverUrlMatcher.find()) { + return Optional.of( + repositoryUrl.substring(0, repositoryUrl.indexOf(serverUrlMatcher.group()) + 1)); + } + return Optional.empty(); } public GithubUrl parseWithoutAuthentication(String url) throws ApiException { @@ -100,18 +159,27 @@ public GithubUrl parse(String url) throws ApiException { return parse(trimEnd(url, '/'), true); } + private IllegalArgumentException buildIllegalArgumentException(String url) { + return new IllegalArgumentException( + format("The given url %s is not a valid github URL. ", url)); + } + private GithubUrl parse(String url, boolean authenticationRequired) throws ApiException { + Matcher matcher; boolean isHTTPSUrl = githubPattern.matcher(url).matches(); - Matcher matcher = isHTTPSUrl ? githubPattern.matcher(url) : githubSSHPattern.matcher(url); + if (isHTTPSUrl) { + matcher = githubPattern.matcher(url); + } else if (githubSSHPattern.matcher(url).matches()) { + matcher = githubSSHPattern.matcher(url); + } else { + matcher = getPatternMatcherByUrl(url).orElseThrow(() -> buildIllegalArgumentException(url)); + isHTTPSUrl = url.startsWith("http"); + } if (!matcher.matches()) { - throw new IllegalArgumentException( - format("The given url %s is not a valid github URL. ", url)); + throw buildIllegalArgumentException(url); } - String serverUrl = - isNullOrEmpty(oauthEndpoint) || trimEnd(oauthEndpoint, '/').equals(GITHUB_SAAS_ENDPOINT) - ? null - : trimEnd(oauthEndpoint, '/'); + String serverUrl = getServerUrl(url).orElseThrow(() -> buildIllegalArgumentException(url)); String repoUser = matcher.group("repoUser"); String repoName = matcher.group("repoName"); if (repoName.matches("^[\\w-][\\w.-]*?\\.git$")) { @@ -127,7 +195,7 @@ private GithubUrl parse(String url, boolean authenticationRequired) throws ApiEx if (pullRequestId != null) { GithubPullRequest pullRequest = - this.getPullRequest(pullRequestId, repoUser, repoName, authenticationRequired); + this.getPullRequest(serverUrl, pullRequestId, repoUser, repoName, authenticationRequired); if (pullRequest != null) { String state = pullRequest.getState(); if (!"open".equalsIgnoreCase(state)) { @@ -146,8 +214,12 @@ private GithubUrl parse(String url, boolean authenticationRequired) throws ApiEx String latestCommit = null; GithubCommit commit = - this.getLatestCommit( - repoUser, repoName, firstNonNull(branchName, "HEAD"), authenticationRequired); + getLatestCommit( + serverUrl, + repoUser, + repoName, + firstNonNull(branchName, "HEAD"), + authenticationRequired); if (commit != null) { latestCommit = commit.getSha(); } @@ -165,12 +237,14 @@ private GithubUrl parse(String url, boolean authenticationRequired) throws ApiEx } private GithubPullRequest getPullRequest( - String pullRequestId, String repoUser, String repoName, boolean authenticationRequired) + String githubEndpoint, + String pullRequestId, + String repoUser, + String repoName, + boolean authenticationRequired) throws ApiException { try { // prepare token - String githubEndpoint = - isNullOrEmpty(oauthEndpoint) ? GITHUB_SAAS_ENDPOINT : trimEnd(oauthEndpoint, '/'); Subject subject = EnvironmentContext.getCurrent().getSubject(); PersonalAccessToken personalAccessToken = null; Optional token = tokenManager.get(subject, githubEndpoint); @@ -180,8 +254,13 @@ private GithubPullRequest getPullRequest( personalAccessToken = tokenManager.fetchAndSave(subject, githubEndpoint); } + GithubApiClient apiClient = + this.apiClient.isConnected(githubEndpoint) + ? this.apiClient + : new GithubApiClient(githubEndpoint); + // get pull request - return this.apiClient.getPullRequest( + return apiClient.getPullRequest( pullRequestId, repoUser, repoName, @@ -190,7 +269,7 @@ private GithubPullRequest getPullRequest( // get pull request without authentication try { - return this.apiClient.getPullRequest(pullRequestId, repoUser, repoName, null); + return apiClient.getPullRequest(pullRequestId, repoUser, repoName, null); } catch (ScmItemNotFoundException | ScmCommunicationException | ScmBadRequestException exception) { @@ -211,12 +290,17 @@ private GithubPullRequest getPullRequest( } private GithubCommit getLatestCommit( - String repoUser, String repoName, String branchName, boolean authenticationRequired) - throws ApiException { + String githubEndpoint, + String repoUser, + String repoName, + String branchName, + boolean authenticationRequired) { + GithubApiClient apiClient = + this.apiClient.isConnected(githubEndpoint) + ? this.apiClient + : new GithubApiClient(githubEndpoint); try { // prepare token - String githubEndpoint = - isNullOrEmpty(oauthEndpoint) ? GITHUB_SAAS_ENDPOINT : trimEnd(oauthEndpoint, '/'); Subject subject = EnvironmentContext.getCurrent().getSubject(); PersonalAccessToken personalAccessToken = null; Optional token = tokenManager.get(subject, githubEndpoint); @@ -227,7 +311,7 @@ private GithubCommit getLatestCommit( } // get latest commit - return this.apiClient.getLatestCommit( + return apiClient.getLatestCommit( repoUser, repoName, branchName, @@ -235,7 +319,7 @@ private GithubCommit getLatestCommit( } catch (UnknownScmProviderException | ScmUnauthorizedException e) { // get latest commit without authentication try { - return this.apiClient.getLatestCommit(repoUser, repoName, branchName, null); + return apiClient.getLatestCommit(repoUser, repoName, branchName, null); } catch (ScmItemNotFoundException | ScmCommunicationException | ScmBadRequestException @@ -253,4 +337,21 @@ private GithubCommit getLatestCommit( return null; } + + private Optional getPatternMatcherByUrl(String url) { + URI uri = + URI.create( + url.matches(format(githubSSHPatternTemplate, ".*")) + ? "ssh://" + url.replace(":", "/") + : url); + String scheme = uri.getScheme(); + String host = uri.getHost(); + Matcher matcher = compile(format(githubPatternTemplate, scheme + "://" + host)).matcher(url); + if (matcher.matches()) { + return Optional.of(matcher); + } else { + matcher = compile(format(githubSSHPatternTemplate, host)).matcher(url); + return matcher.matches() ? Optional.of(matcher) : Optional.empty(); + } + } } diff --git a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubUserDataFetcher.java b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubUserDataFetcher.java index 7ab4c7f2cc..522f309e2f 100644 --- a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubUserDataFetcher.java +++ b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/AbstractGithubUserDataFetcher.java @@ -11,6 +11,8 @@ */ package org.eclipse.che.api.factory.server.github; +import static com.google.common.base.Strings.isNullOrEmpty; + import com.google.common.base.Joiner; import com.google.common.collect.ImmutableSet; import java.util.Set; @@ -36,6 +38,9 @@ public abstract class AbstractGithubUserDataFetcher extends AbstractGitUserDataF public static final Set DEFAULT_TOKEN_SCOPES = ImmutableSet.of("repo", "user:email", "read:user"); + private static final String NO_USERNAME_AND_EMAIL_ERROR_MESSAGE = + "User name and/or email is not found in the GitHub profile."; + /** Constructor used for testing only. */ public AbstractGithubUserDataFetcher( String apiEndpoint, @@ -53,15 +58,27 @@ public AbstractGithubUserDataFetcher( protected GitUserData fetchGitUserDataWithOAuthToken(OAuthToken oAuthToken) throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException { GithubUser user = githubApiClient.getUser(oAuthToken.getToken()); - return new GitUserData(user.getName(), user.getEmail()); + if (isNullOrEmpty(user.getName()) || isNullOrEmpty(user.getEmail())) { + throw new ScmItemNotFoundException(NO_USERNAME_AND_EMAIL_ERROR_MESSAGE); + } else { + return new GitUserData(user.getName(), user.getEmail()); + } } @Override protected GitUserData fetchGitUserDataWithPersonalAccessToken( PersonalAccessToken personalAccessToken) throws ScmItemNotFoundException, ScmCommunicationException, ScmBadRequestException { - GithubUser user = githubApiClient.getUser(personalAccessToken.getToken()); - return new GitUserData(user.getName(), user.getEmail()); + GithubApiClient apiClient = + githubApiClient.isConnected(personalAccessToken.getScmProviderUrl()) + ? githubApiClient + : new GithubApiClient(personalAccessToken.getScmProviderUrl()); + GithubUser user = apiClient.getUser(personalAccessToken.getToken()); + if (isNullOrEmpty(user.getName()) || isNullOrEmpty(user.getEmail())) { + throw new ScmItemNotFoundException(NO_USERNAME_AND_EMAIL_ERROR_MESSAGE); + } else { + return new GitUserData(user.getName(), user.getEmail()); + } } protected String getLocalAuthenticateUrl() { diff --git a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/GithubUrl.java b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/GithubUrl.java index fcd106ef0f..8dd1c2f738 100644 --- a/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/GithubUrl.java +++ b/wsmaster/che-core-api-factory-github-common/src/main/java/org/eclipse/che/api/factory/server/github/GithubUrl.java @@ -192,7 +192,7 @@ public String rawFileLocation(String fileName) { return new StringJoiner("/") .add( - isNullOrEmpty(serverUrl) + HOSTNAME.equals(serverUrl) ? "https://raw.githubusercontent.com" : disableSubdomainIsolation ? serverUrl + "/raw" @@ -208,7 +208,8 @@ public String rawFileLocation(String fileName) { @Override public String getHostName() { - return isNullOrEmpty(serverUrl) ? HOSTNAME : serverUrl; + // TODO: rework this method to return hostname in format https:///user/repo + return serverUrl; } /** @@ -218,12 +219,7 @@ public String getHostName() { */ protected String repositoryLocation() { if (isHTTPSUrl) { - return (isNullOrEmpty(serverUrl) ? HOSTNAME : serverUrl) - + "/" - + this.username - + "/" - + this.repository - + ".git"; + return serverUrl + "/" + this.username + "/" + this.repository + ".git"; } return "git@" + getHostName().substring(getHostName().indexOf("://") + 3) diff --git a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubAuthorizingFileContentProviderTest.java b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubAuthorizingFileContentProviderTest.java index 9fd553183b..a530b220ae 100644 --- a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubAuthorizingFileContentProviderTest.java +++ b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubAuthorizingFileContentProviderTest.java @@ -49,6 +49,7 @@ public void shouldExpandRelativePaths() throws Exception { .withUsername("eclipse") .withRepository("che") .withBranch("main") + .withServerUrl("https://github.com") .withLatestCommit("d74923ebf968454cf13251f17df69dcd87d3b932"); FileContentProvider fileContentProvider = @@ -74,6 +75,7 @@ public void shouldPreserveAbsolutePaths() throws Exception { new GithubUrl("github") .withUsername("eclipse") .withRepository("che") + .withServerUrl("https://github.com") .withBranch("main") .withLatestCommit("9ac2f42ed62944d164f189afd57f14a2793a7e4b"); @@ -92,7 +94,11 @@ public void shouldPreserveAbsolutePaths() throws Exception { public void shouldThrowNotFoundForPublicRepos() throws Exception { String url = "https://raw.githubusercontent.com/foo/bar/branch-name/devfile.yaml"; - GithubUrl githubUrl = new GithubUrl("github").withUsername("eclipse").withRepository("che"); + GithubUrl githubUrl = + new GithubUrl("github") + .withUsername("eclipse") + .withRepository("che") + .withServerUrl("https://github.com"); URLFetcher urlFetcher = Mockito.mock(URLFetcher.class); FileContentProvider fileContentProvider = @@ -109,7 +115,11 @@ public void shouldThrowNotFoundForPublicRepos() throws Exception { @Test(expectedExceptions = DevfileException.class) public void shouldThrowDevfileException() throws Exception { String url = "https://raw.githubusercontent.com/foo/bar/branch-name/devfile.yaml"; - GithubUrl githubUrl = new GithubUrl("github").withUsername("eclipse").withRepository("che"); + GithubUrl githubUrl = + new GithubUrl("github") + .withUsername("eclipse") + .withRepository("che") + .withServerUrl("https://github.com"); URLFetcher urlFetcher = Mockito.mock(URLFetcher.class); FileContentProvider fileContentProvider = @@ -128,7 +138,11 @@ public void shouldNotAskGitHubAPIForDifferentDomain() throws Exception { String raw_url = "https://ghserver.com/foo/bar/branch-name/devfile.yaml"; URLFetcher urlFetcher = Mockito.mock(URLFetcher.class); - GithubUrl githubUrl = new GithubUrl("github").withUsername("eclipse").withRepository("che"); + GithubUrl githubUrl = + new GithubUrl("github") + .withUsername("eclipse") + .withRepository("che") + .withServerUrl("https://github.com"); FileContentProvider fileContentProvider = new GithubAuthorizingFileContentProvider(githubUrl, urlFetcher, personalAccessTokenManager); var personalAccessToken = new PersonalAccessToken(raw_url, "che", "my-token"); diff --git a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java index 387acb6cfb..439881e530 100644 --- a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java +++ b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubFactoryParametersResolverTest.java @@ -163,6 +163,7 @@ public void shouldGenerateDevfileForFactoryWithNoDevfile() throws Exception { any(RemoteFactoryUrl.class), any(), anyMap(), anyBoolean())) .thenReturn(Optional.empty()); + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("test-sha")); @@ -182,7 +183,7 @@ public void shouldSkipAuthenticationWhenAccessDenied() throws Exception { // given when(urlFactoryBuilder.buildDefaultDevfile(any())) .thenReturn(generateDevfileFactory().getDevfile()); - + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("test-sha")); @@ -205,7 +206,7 @@ public void shouldNotSkipAuthenticationWhenNoErrorParameterPassed() throws Excep // given when(urlFactoryBuilder.buildDefaultDevfile(any())) .thenReturn(generateDevfileFactory().getDevfile()); - + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("test-sha")); @@ -231,7 +232,7 @@ public void shouldReturnFactoryFromRepositoryWithDevfile() throws Exception { when(urlFactoryBuilder.createFactoryFromDevfile( any(RemoteFactoryUrl.class), any(), anyMap(), anyBoolean())) .thenReturn(Optional.of(computedFactory)); - + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("13bbd0d4605a6ed3350f7b15eb02c4d4e6f8df6e")); @@ -262,7 +263,7 @@ public void shouldSetDefaultProjectIntoDevfileIfNotSpecified() throws Exception when(urlFactoryBuilder.createFactoryFromDevfile( any(RemoteFactoryUrl.class), any(), anyMap(), anyBoolean())) .thenReturn(Optional.of(computedFactory)); - + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("test-sha")); @@ -293,7 +294,7 @@ public void shouldSetBranchIntoDevfileIfNotMatchesCurrent() throws Exception { when(urlFactoryBuilder.createFactoryFromDevfile( any(RemoteFactoryUrl.class), any(), anyMap(), anyBoolean())) .thenReturn(Optional.of(computedFactory)); - + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("test-sha")); @@ -316,7 +317,7 @@ public void shouldSetScmInfoIntoDevfileV2() throws Exception { when(urlFactoryBuilder.createFactoryFromDevfile( any(RemoteFactoryUrl.class), any(), anyMap(), anyBoolean())) .thenReturn(Optional.of(computedFactory)); - + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn(new GithubCommit().withSha("test-sha")); diff --git a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubScmFileResolverTest.java b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubScmFileResolverTest.java index 641fcd44f6..1108148160 100644 --- a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubScmFileResolverTest.java +++ b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubScmFileResolverTest.java @@ -90,6 +90,7 @@ public void shouldReturnContentFromUrlFetcher() throws Exception { .when(personalAccessTokenManager.getAndStore(anyString())) .thenReturn(new PersonalAccessToken("foo", "che", "my-token")); + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getLatestCommit(anyString(), anyString(), anyString(), any())) .thenReturn( new GithubCommit() diff --git a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubURLParserTest.java b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubURLParserTest.java index 3183546cac..50cb3623f3 100644 --- a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubURLParserTest.java +++ b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubURLParserTest.java @@ -13,8 +13,10 @@ 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.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; @@ -89,7 +91,13 @@ public void checkParsing(String url, String username, String repository, String @Test(dataProvider = "parsingBadRepository") public void checkParsingBadRepositoryDoNotModifiesInitialInput(String url, String repository) throws ApiException { + // given + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); + + // when GithubUrl githubUrl = githubUrlParser.parse(url); + + // then assertEquals(githubUrl.getRepository(), repository); } @@ -189,6 +197,7 @@ public void checkPullRequestFromRepository() throws Exception { .withRef("pr-main-to-7.46.0") .withUser(new GithubUser().withId(0).withName("eclipse").withLogin("eclipse")) .withRepo(new GithubRepo().withName("che"))); + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getPullRequest(any(), any(), any(), any())).thenReturn(pr); GithubUrl githubUrl = githubUrlParser.parse(url); @@ -215,6 +224,7 @@ public void checkPullRequestFromForkedRepository() throws Exception { when(personalAccessTokenManager.get(any(Subject.class), anyString())) .thenReturn(Optional.of(personalAccessToken)); + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getPullRequest(anyString(), anyString(), anyString(), anyString())) .thenReturn(pr); @@ -239,6 +249,7 @@ public void checkPullRequestFromForkedRepositoryWithoutAuthentication() throws E .withUser(new GithubUser().withId(0).withName("eclipse").withLogin("eclipse")) .withRepo(new GithubRepo().withName("che"))); + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getPullRequest(any(), any(), any(), any())).thenReturn(pr); GithubUrl githubUrl = githubUrlParser.parseWithoutAuthentication(url); @@ -261,10 +272,47 @@ public void checkPullRequestMergedState() throws Exception { when(personalAccessToken.getToken()).thenReturn("token"); when(personalAccessTokenManager.get(any(Subject.class), anyString())) .thenReturn(Optional.of(personalAccessToken)); + when(githubApiClient.isConnected(eq("https://github.com"))).thenReturn(true); when(githubApiClient.getPullRequest(anyString(), anyString(), anyString(), anyString())) .thenReturn(githubPullRequest); String url = "https://github.com/eclipse/che/pull/11103"; githubUrlParser.parse(url); } + + @Test + public void shouldParseServerUr() throws Exception { + // given + String url = "https://github-server.com/user/repo"; + + // when + GithubUrl githubUrl = githubUrlParser.parse(url); + + // then + assertEquals(githubUrl.getUsername(), "user"); + assertEquals(githubUrl.getRepository(), "repo"); + assertEquals(githubUrl.getHostName(), "https://github-server.com"); + } + + @Test + public void shouldParseServerUrWithPullRequestId() throws Exception { + // given + String url = "https://github-server.com/user/repo/pull/11103"; + GithubPullRequest pr = + new GithubPullRequest() + .withState("open") + .withHead( + new GithubHead() + .withUser(new GithubUser().withId(0).withName("eclipse").withLogin("eclipse")) + .withRepo(new GithubRepo().withName("che"))); + when(githubApiClient.isConnected(eq("https://github-server.com"))).thenReturn(true); + when(githubApiClient.getPullRequest(any(), any(), any(), any())).thenReturn(pr); + + // when + githubUrlParser.parse(url); + + // then + verify(personalAccessTokenManager, times(2)) + .get(any(Subject.class), eq("https://github-server.com")); + } } diff --git a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubUrlTest.java b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubUrlTest.java index c63b5181fe..2cacf8796c 100644 --- a/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubUrlTest.java +++ b/wsmaster/che-core-api-factory-github/src/test/java/org/eclipse/che/api/factory/server/github/GithubUrlTest.java @@ -39,6 +39,7 @@ public class GithubUrlTest { @Test public void checkDevfileLocation() throws Exception { DevfileFilenamesProvider devfileFilenamesProvider = mock(DevfileFilenamesProvider.class); + when(githubApiClient.isConnected("https://github.com")).thenReturn(true); /** Parser used to create the url. */ GithubURLParser githubUrlParser = @@ -67,6 +68,7 @@ public void checkDevfileLocation() throws Exception { @Test public void shouldReturnDevfileLocationFromSSHUrl() throws Exception { DevfileFilenamesProvider devfileFilenamesProvider = mock(DevfileFilenamesProvider.class); + when(githubApiClient.isConnected("https://github.com")).thenReturn(true); /** Parser used to create the url. */ GithubURLParser githubUrlParser = @@ -139,7 +141,11 @@ public void shouldReturnRepositoryLocationFromSSHUrl() throws Exception { public void testRawFileLocationWithDefaultBranchName() { String file = ".che/che-theia-plugins.yaml"; - GithubUrl url = new GithubUrl("github").withUsername("eclipse").withRepository("che"); + GithubUrl url = + new GithubUrl("github") + .withUsername("eclipse") + .withRepository("che") + .withServerUrl("https://github.com"); assertEquals( url.rawFileLocation(file), @@ -151,7 +157,11 @@ public void testRawFileLocationWithCustomBranchName() { String file = ".che/che-theia-plugins.yaml"; GithubUrl url = - new GithubUrl("github").withUsername("eclipse").withRepository("che").withBranch("main"); + new GithubUrl("github") + .withUsername("eclipse") + .withRepository("che") + .withBranch("main") + .withServerUrl("https://github.com"); assertEquals( url.rawFileLocation(file), @@ -166,6 +176,7 @@ public void testRawFileLocationForCommit() { new GithubUrl("github") .withUsername("eclipse") .withRepository("che") + .withServerUrl("https://github.com") .withBranch("main") .withLatestCommit("c24fd44e0f7296be2e49a380fb8abe2fe4db9100");