chore: Apply git user data configmap to mount to /etc/gitconfig
parent
04098e10e8
commit
1af2cdc32f
|
|
@ -125,6 +125,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-dto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-factory</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
@ -49,6 +49,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.environment.Kubernete
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.RemoveNamespaceOnWorkspaceRemove;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.CredentialsSecretConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.GitconfigUserDataConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.PreferencesConfigMapConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.SshKeysConfigurator;
|
||||
|
|
@ -118,6 +119,7 @@ public class KubernetesInfraModule extends AbstractModule {
|
|||
namespaceConfigurators.addBinding().to(UserProfileConfigurator.class);
|
||||
namespaceConfigurators.addBinding().to(UserPreferencesConfigurator.class);
|
||||
namespaceConfigurators.addBinding().to(SshKeysConfigurator.class);
|
||||
namespaceConfigurators.addBinding().to(GitconfigUserDataConfigurator.class);
|
||||
|
||||
bind(KubernetesNamespaceService.class);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserData;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
|
||||
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
|
||||
import org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
|
||||
|
||||
public class GitconfigUserDataConfigurator implements NamespaceConfigurator {
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final Set<GitUserDataFetcher> gitUserDataFetchers;
|
||||
private static final String CONFIGMAP_NAME = "workspace-userdata-gitconfig";
|
||||
private static final String CONFIGMAP_DATA_KEY = "gitconfig";
|
||||
|
||||
@Inject
|
||||
public GitconfigUserDataConfigurator(
|
||||
KubernetesClientFactory clientFactory, Set<GitUserDataFetcher> gitUserDataFetchers) {
|
||||
this.clientFactory = clientFactory;
|
||||
this.gitUserDataFetchers = gitUserDataFetchers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NamespaceResolutionContext namespaceResolutionContext, String namespaceName)
|
||||
throws InfrastructureException {
|
||||
var client = clientFactory.create();
|
||||
GitUserData gitUserData = null;
|
||||
for (GitUserDataFetcher fetcher : gitUserDataFetchers) {
|
||||
try {
|
||||
gitUserData = fetcher.fetchGitUserData();
|
||||
break;
|
||||
} catch (ScmUnauthorizedException | ScmCommunicationException ignored) {
|
||||
}
|
||||
}
|
||||
Map<String, String> annotations =
|
||||
ImmutableMap.of(
|
||||
"controller.devfile.io/mount-as",
|
||||
"subpath",
|
||||
"controller.devfile.io/mount-path",
|
||||
"/etc/");
|
||||
Map<String, String> labels =
|
||||
ImmutableMap.of(
|
||||
"controller.devfile.io/mount-to-devworkspace",
|
||||
"true",
|
||||
"controller.devfile.io/watch-configmap",
|
||||
"true");
|
||||
if (gitUserData != null
|
||||
&& client.configMaps().inNamespace(namespaceName).withName(CONFIGMAP_NAME).get() == null
|
||||
&& client
|
||||
.configMaps()
|
||||
.inNamespace(namespaceName)
|
||||
.withLabels(labels)
|
||||
.list()
|
||||
.getItems()
|
||||
.stream()
|
||||
.noneMatch(
|
||||
configMap ->
|
||||
configMap
|
||||
.getMetadata()
|
||||
.getAnnotations()
|
||||
.entrySet()
|
||||
.containsAll(annotations.entrySet())
|
||||
&& configMap.getData().containsKey(CONFIGMAP_DATA_KEY))) {
|
||||
ConfigMap configMap =
|
||||
new ConfigMapBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(CONFIGMAP_NAME)
|
||||
.withLabels(labels)
|
||||
.withAnnotations(annotations)
|
||||
.endMetadata()
|
||||
.build();
|
||||
configMap.setData(
|
||||
ImmutableMap.of(
|
||||
CONFIGMAP_DATA_KEY,
|
||||
String.format(
|
||||
"[user]\n\tname = %1$s\n\temail = %2$s",
|
||||
gitUserData.getScmUsername(), gitUserData.getScmUserEmail())));
|
||||
client.configMaps().inNamespace(namespaceName).create(configMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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/
|
||||
|
|
@ -54,6 +54,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.environment.Kubernete
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesNamespaceFactory;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.CredentialsSecretConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.GitconfigUserDataConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.NamespaceConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.PreferencesConfigMapConfigurator;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.configurator.SshKeysConfigurator;
|
||||
|
|
@ -127,6 +128,7 @@ public class OpenShiftInfraModule extends AbstractModule {
|
|||
namespaceConfigurators.addBinding().to(OpenShiftWorkspaceServiceAccountConfigurator.class);
|
||||
namespaceConfigurators.addBinding().to(OpenShiftStopWorkspaceRoleConfigurator.class);
|
||||
namespaceConfigurators.addBinding().to(SshKeysConfigurator.class);
|
||||
namespaceConfigurators.addBinding().to(GitconfigUserDataConfigurator.class);
|
||||
|
||||
bind(KubernetesNamespaceService.class);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import org.eclipse.che.api.factory.server.bitbucket.server.BitbucketServerApiClient;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenFetcher;
|
||||
import org.eclipse.che.security.oauth1.BitbucketServerApiProvider;
|
||||
|
||||
|
|
@ -24,5 +25,8 @@ public class BitbucketServerModule extends AbstractModule {
|
|||
Multibinder.newSetBinder(binder(), PersonalAccessTokenFetcher.class);
|
||||
tokenFetcherMultibinder.addBinding().to(BitbucketServerPersonalAccessTokenFetcher.class);
|
||||
bind(BitbucketServerApiClient.class).toProvider(BitbucketServerApiProvider.class);
|
||||
Multibinder<GitUserDataFetcher> gitUserDataMultibinder =
|
||||
Multibinder.newSetBinder(binder(), GitUserDataFetcher.class);
|
||||
gitUserDataMultibinder.addBinding().to(BitbucketServerUserDataFetcher.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.api.factory.server.bitbucket;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
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.scm.GitUserData;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
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.StringUtils;
|
||||
import org.eclipse.che.commons.subject.Subject;
|
||||
|
||||
/** Bitbucket git user data retriever. */
|
||||
public class BitbucketServerUserDataFetcher implements GitUserDataFetcher {
|
||||
|
||||
/** Bitbucket API client. */
|
||||
private final BitbucketServerApiClient bitbucketServerApiClient;
|
||||
|
||||
private final List<String> registeredBitbucketEndpoints;
|
||||
|
||||
@Inject
|
||||
public BitbucketServerUserDataFetcher(
|
||||
BitbucketServerApiClient bitbucketServerApiClient,
|
||||
@Nullable @Named("che.integration.bitbucket.server_endpoints") String bitbucketEndpoints) {
|
||||
if (bitbucketEndpoints != null) {
|
||||
this.registeredBitbucketEndpoints =
|
||||
Splitter.on(",")
|
||||
.splitToStream(bitbucketEndpoints)
|
||||
.map(e -> StringUtils.trimEnd(e, '/'))
|
||||
.collect(toList());
|
||||
} else {
|
||||
this.registeredBitbucketEndpoints = Collections.emptyList();
|
||||
}
|
||||
this.bitbucketServerApiClient = bitbucketServerApiClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitUserData fetchGitUserData() throws ScmUnauthorizedException, ScmCommunicationException {
|
||||
GitUserData gitUserData = null;
|
||||
for (String bitbucketServerEndpoint : this.registeredBitbucketEndpoints) {
|
||||
if (bitbucketServerApiClient.isConnected(bitbucketServerEndpoint)) {
|
||||
Subject cheSubject = EnvironmentContext.getCurrent().getSubject();
|
||||
try {
|
||||
BitbucketUser user = bitbucketServerApiClient.getUser(cheSubject);
|
||||
gitUserData = new GitUserData(user.getName(), user.getEmailAddress());
|
||||
} catch (ScmItemNotFoundException e) {
|
||||
throw new ScmCommunicationException(e.getMessage(), e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gitUserData == null) {
|
||||
throw new ScmCommunicationException("Failed to retrieve git user data from Bitbucket");
|
||||
}
|
||||
return gitUserData;
|
||||
}
|
||||
}
|
||||
|
|
@ -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,6 +13,7 @@ package org.eclipse.che.api.factory.server.github;
|
|||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenFetcher;
|
||||
|
||||
public class GithubModule extends AbstractModule {
|
||||
|
|
@ -22,5 +23,8 @@ public class GithubModule extends AbstractModule {
|
|||
Multibinder<PersonalAccessTokenFetcher> tokenFetcherMultibinder =
|
||||
Multibinder.newSetBinder(binder(), PersonalAccessTokenFetcher.class);
|
||||
tokenFetcherMultibinder.addBinding().to(GithubPersonalAccessTokenFetcher.class);
|
||||
Multibinder<GitUserDataFetcher> gitUserDataMultibinder =
|
||||
Multibinder.newSetBinder(binder(), GitUserDataFetcher.class);
|
||||
gitUserDataMultibinder.addBinding().to(GithubUserDataFetcher.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.api.factory.server.github;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.api.auth.shared.dto.OAuthToken;
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.ForbiddenException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.UnauthorizedException;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserData;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
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.env.EnvironmentContext;
|
||||
import org.eclipse.che.commons.subject.Subject;
|
||||
import org.eclipse.che.security.oauth.OAuthAPI;
|
||||
|
||||
/** GitHub user data retriever. */
|
||||
public class GithubUserDataFetcher implements GitUserDataFetcher {
|
||||
private final String apiEndpoint;
|
||||
private final OAuthAPI oAuthAPI;
|
||||
|
||||
/** GitHub API client. */
|
||||
private final GithubApiClient githubApiClient;
|
||||
|
||||
/** Name of this OAuth provider as found in OAuthAPI. */
|
||||
private static final String OAUTH_PROVIDER_NAME = "github";
|
||||
|
||||
/** Collection of OAuth scopes required to make integration with GitHub work. */
|
||||
public static final Set<String> DEFAULT_TOKEN_SCOPES = ImmutableSet.of("repo");
|
||||
|
||||
@Inject
|
||||
public GithubUserDataFetcher(@Named("che.api") String apiEndpoint, OAuthAPI oAuthAPI) {
|
||||
this.apiEndpoint = apiEndpoint;
|
||||
this.oAuthAPI = oAuthAPI;
|
||||
this.githubApiClient = new GithubApiClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitUserData fetchGitUserData() throws ScmUnauthorizedException, ScmCommunicationException {
|
||||
OAuthToken oAuthToken;
|
||||
try {
|
||||
oAuthToken = oAuthAPI.getToken(OAUTH_PROVIDER_NAME);
|
||||
// Find the user associated to the OAuth token by querying the GitHub API.
|
||||
GithubUser user = githubApiClient.getUser(oAuthToken.getToken());
|
||||
return new GitUserData(user.getName(), user.getEmail());
|
||||
} catch (UnauthorizedException e) {
|
||||
Subject cheSubject = EnvironmentContext.getCurrent().getSubject();
|
||||
throw new ScmUnauthorizedException(
|
||||
cheSubject.getUserName()
|
||||
+ " is not authorized in "
|
||||
+ OAUTH_PROVIDER_NAME
|
||||
+ " OAuth provider.",
|
||||
OAUTH_PROVIDER_NAME,
|
||||
"2.0",
|
||||
getLocalAuthenticateUrl());
|
||||
} catch (NotFoundException
|
||||
| ServerException
|
||||
| ForbiddenException
|
||||
| BadRequestException
|
||||
| ScmItemNotFoundException
|
||||
| ScmBadRequestException
|
||||
| ConflictException e) {
|
||||
throw new ScmCommunicationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getLocalAuthenticateUrl() {
|
||||
return apiEndpoint
|
||||
+ "/oauth/authenticate?oauth_provider="
|
||||
+ OAUTH_PROVIDER_NAME
|
||||
+ "&scope="
|
||||
+ Joiner.on(',').join(DEFAULT_TOKEN_SCOPES)
|
||||
+ "&request_method=POST&signature_method=rsa";
|
||||
}
|
||||
}
|
||||
|
|
@ -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,6 +13,7 @@ package org.eclipse.che.api.factory.server.gitlab;
|
|||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenFetcher;
|
||||
|
||||
public class GitlabModule extends AbstractModule {
|
||||
|
|
@ -22,5 +23,8 @@ public class GitlabModule extends AbstractModule {
|
|||
Multibinder<PersonalAccessTokenFetcher> tokenFetcherMultibinder =
|
||||
Multibinder.newSetBinder(binder(), PersonalAccessTokenFetcher.class);
|
||||
tokenFetcherMultibinder.addBinding().to(GitlabOAuthTokenFetcher.class);
|
||||
Multibinder<GitUserDataFetcher> gitUserDataMultibinder =
|
||||
Multibinder.newSetBinder(binder(), GitUserDataFetcher.class);
|
||||
gitUserDataMultibinder.addBinding().to(GitlabUserDataFetcher.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.api.factory.server.gitlab;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.api.auth.shared.dto.OAuthToken;
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.ForbiddenException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
import org.eclipse.che.api.core.UnauthorizedException;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserData;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserDataFetcher;
|
||||
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.StringUtils;
|
||||
import org.eclipse.che.commons.subject.Subject;
|
||||
import org.eclipse.che.inject.ConfigurationException;
|
||||
import org.eclipse.che.security.oauth.OAuthAPI;
|
||||
|
||||
/** Gitlab OAuth token retriever. */
|
||||
public class GitlabUserDataFetcher implements GitUserDataFetcher {
|
||||
private final String apiEndpoint;
|
||||
private final OAuthAPI oAuthAPI;
|
||||
|
||||
/** Name of this OAuth provider as found in OAuthAPI. */
|
||||
private static final String OAUTH_PROVIDER_NAME = "gitlab";
|
||||
|
||||
private final List<String> registeredGitlabEndpoints;
|
||||
|
||||
public static final Set<String> DEFAULT_TOKEN_SCOPES =
|
||||
ImmutableSet.of("api", "write_repository", "openid");
|
||||
|
||||
@Inject
|
||||
public GitlabUserDataFetcher(
|
||||
@Named("che.api") String apiEndpoint,
|
||||
@Nullable @Named("che.integration.gitlab.server_endpoints") String gitlabEndpoints,
|
||||
@Nullable @Named("che.integration.gitlab.oauth_endpoint") String oauthEndpoint,
|
||||
OAuthAPI oAuthAPI) {
|
||||
this.apiEndpoint = apiEndpoint;
|
||||
if (gitlabEndpoints != null) {
|
||||
this.registeredGitlabEndpoints =
|
||||
Splitter.on(",")
|
||||
.splitToStream(gitlabEndpoints)
|
||||
.map(e -> StringUtils.trimEnd(e, '/'))
|
||||
.collect(toList());
|
||||
} else {
|
||||
this.registeredGitlabEndpoints = Collections.emptyList();
|
||||
}
|
||||
if (oauthEndpoint != null) {
|
||||
if (!registeredGitlabEndpoints.contains(StringUtils.trimEnd(oauthEndpoint, '/'))) {
|
||||
throw new ConfigurationException(
|
||||
"GitLab OAuth integration endpoint must be present in registered GitLab endpoints list.");
|
||||
}
|
||||
this.oAuthAPI = oAuthAPI;
|
||||
} else {
|
||||
this.oAuthAPI = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GitUserData fetchGitUserData() throws ScmUnauthorizedException, ScmCommunicationException {
|
||||
if (oAuthAPI == null) {
|
||||
throw new ScmCommunicationException(
|
||||
format(
|
||||
"OAuth 2 is not configured for SCM provider [%s]. For details, refer "
|
||||
+ "the documentation in section of SCM providers configuration.",
|
||||
OAUTH_PROVIDER_NAME));
|
||||
}
|
||||
OAuthToken oAuthToken;
|
||||
try {
|
||||
oAuthToken = oAuthAPI.getToken(OAUTH_PROVIDER_NAME);
|
||||
} catch (UnauthorizedException e) {
|
||||
Subject cheSubject = EnvironmentContext.getCurrent().getSubject();
|
||||
throw new ScmUnauthorizedException(
|
||||
cheSubject.getUserName()
|
||||
+ " is not authorized in "
|
||||
+ OAUTH_PROVIDER_NAME
|
||||
+ " OAuth provider.",
|
||||
OAUTH_PROVIDER_NAME,
|
||||
"2.0",
|
||||
getLocalAuthenticateUrl());
|
||||
} catch (NotFoundException
|
||||
| ServerException
|
||||
| ForbiddenException
|
||||
| BadRequestException
|
||||
| ConflictException e) {
|
||||
throw new ScmCommunicationException(e.getMessage(), e);
|
||||
}
|
||||
GitUserData gitUserData = null;
|
||||
for (String gitlabServerEndpoint : this.registeredGitlabEndpoints) {
|
||||
try {
|
||||
GitlabUser user = new GitlabApiClient(gitlabServerEndpoint).getUser(oAuthToken.getToken());
|
||||
gitUserData = new GitUserData(user.getName(), user.getEmail());
|
||||
break;
|
||||
} catch (ScmItemNotFoundException | ScmBadRequestException e) {
|
||||
throw new ScmCommunicationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (gitUserData == null) {
|
||||
throw new ScmCommunicationException("Failed to retrieve git user data from Gitlab");
|
||||
}
|
||||
return gitUserData;
|
||||
}
|
||||
|
||||
private String getLocalAuthenticateUrl() {
|
||||
return apiEndpoint
|
||||
+ "/oauth/authenticate?oauth_provider="
|
||||
+ OAUTH_PROVIDER_NAME
|
||||
+ "&scope="
|
||||
+ Joiner.on('+').join(DEFAULT_TOKEN_SCOPES)
|
||||
+ "&request_method=POST&signature_method=rsa";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.api.factory.server.scm;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/** Personal SCM user data such as `username` and `email`. Is used to sign git commits. */
|
||||
public class GitUserData {
|
||||
private final String scmUsername;
|
||||
private final String scmUserEmail;
|
||||
|
||||
public GitUserData(String scmUsername, String scmUserEmail) {
|
||||
this.scmUsername = scmUsername;
|
||||
this.scmUserEmail = scmUserEmail;
|
||||
}
|
||||
|
||||
public String getScmUsername() {
|
||||
return scmUsername;
|
||||
}
|
||||
|
||||
public String getScmUserEmail() {
|
||||
return scmUserEmail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
GitUserData that = (GitUserData) o;
|
||||
return Objects.equals(scmUsername, that.scmUsername)
|
||||
&& Objects.equals(scmUserEmail, that.scmUserEmail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(scmUsername, scmUserEmail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GitUserData{"
|
||||
+ ", scmUsername='"
|
||||
+ scmUsername
|
||||
+ '\''
|
||||
+ ", scmUserEmail='"
|
||||
+ scmUserEmail
|
||||
+ '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.api.factory.server.scm;
|
||||
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmCommunicationException;
|
||||
import org.eclipse.che.api.factory.server.scm.exception.ScmUnauthorizedException;
|
||||
|
||||
public interface GitUserDataFetcher {
|
||||
|
||||
/**
|
||||
* Retrieve a {@link GitUserData} object from concrete scm provider
|
||||
*
|
||||
* @return - {@link GitUserData} object.
|
||||
* @throws ScmUnauthorizedException - in case if user is not authorized che server to create a new
|
||||
* token. Further user interaction is needed before calling this method next time.
|
||||
* @throws ScmCommunicationException - Some unexpected problem occurred during communication with
|
||||
* scm provider.
|
||||
*/
|
||||
GitUserData fetchGitUserData() throws ScmUnauthorizedException, ScmCommunicationException;
|
||||
}
|
||||
Loading…
Reference in New Issue