Merge pull request #305 from eclipse-che/che-20938
chore: Apply git user data configmap to mount to /etc/gitconfigpull/309/head
commit
68c1af03aa
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
@ -53,6 +53,7 @@ public abstract class AbstractWorkspaceServiceAccount<
|
|||
public static final String CONFIGMAPS_ROLE_NAME = "workspace-configmaps";
|
||||
public static final String CREDENTIALS_SECRET_NAME = "workspace-credentials-secret";
|
||||
public static final String PREFERENCES_CONFIGMAP_NAME = "workspace-preferences-configmap";
|
||||
public static final String GIT_USERDATA_CONFIGMAP_NAME = "workspace-userdata-gitconfig-configmap";
|
||||
|
||||
protected final String namespace;
|
||||
protected final String serviceAccountName;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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 static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.GIT_USERDATA_CONFIGMAP_NAME;
|
||||
|
||||
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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GitconfigUserDataConfigurator implements NamespaceConfigurator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GitconfigUserDataConfigurator.class);
|
||||
private final KubernetesClientFactory clientFactory;
|
||||
private final Set<GitUserDataFetcher> gitUserDataFetchers;
|
||||
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 e) {
|
||||
LOG.debug("No GitUserDataFetcher is configured. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
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(GIT_USERDATA_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(GIT_USERDATA_CONFIGMAP_NAME)
|
||||
.withLabels(labels)
|
||||
.withAnnotations(annotations)
|
||||
.endMetadata()
|
||||
.build();
|
||||
configMap.setData(
|
||||
singletonMap(
|
||||
CONFIGMAP_DATA_KEY,
|
||||
String.format(
|
||||
"[user]\n\tname = %1$s\n\temail = %2$s",
|
||||
gitUserData.getScmUsername(), gitUserData.getScmUserEmail())));
|
||||
client.configMaps().inNamespace(namespaceName).create(configMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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 static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.AbstractWorkspaceServiceAccount.GIT_USERDATA_CONFIGMAP_NAME;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
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;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class GitconfigUserdataConfiguratorTest {
|
||||
|
||||
private NamespaceConfigurator configurator;
|
||||
|
||||
@Mock private KubernetesClientFactory clientFactory;
|
||||
@Mock private GitUserDataFetcher gitUserDataFetcher;
|
||||
private KubernetesServer serverMock;
|
||||
|
||||
private NamespaceResolutionContext namespaceResolutionContext;
|
||||
private final String TEST_NAMESPACE_NAME = "namespace123";
|
||||
private final String TEST_WORKSPACE_ID = "workspace123";
|
||||
private final String TEST_USER_ID = "user123";
|
||||
private final String TEST_USERNAME = "jondoe";
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp()
|
||||
throws InfrastructureException, ScmCommunicationException, ScmUnauthorizedException {
|
||||
configurator = new GitconfigUserDataConfigurator(clientFactory, Set.of(gitUserDataFetcher));
|
||||
|
||||
serverMock = new KubernetesServer(true, true);
|
||||
serverMock.before();
|
||||
KubernetesClient client = spy(serverMock.getClient());
|
||||
when(clientFactory.create()).thenReturn(client);
|
||||
|
||||
namespaceResolutionContext =
|
||||
new NamespaceResolutionContext(TEST_WORKSPACE_ID, TEST_USER_ID, TEST_USERNAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createUserdataConfigmapWhenDoesNotExist()
|
||||
throws ScmCommunicationException, ScmUnauthorizedException, InfrastructureException,
|
||||
InterruptedException {
|
||||
// given
|
||||
when(gitUserDataFetcher.fetchGitUserData()).thenReturn(new GitUserData("gitUser", "gitEmail"));
|
||||
|
||||
// when
|
||||
configurator.configure(namespaceResolutionContext, TEST_NAMESPACE_NAME);
|
||||
|
||||
// then create a secret
|
||||
Assert.assertEquals(serverMock.getLastRequest().getMethod(), "POST");
|
||||
Assert.assertNotNull(
|
||||
serverMock
|
||||
.getClient()
|
||||
.configMaps()
|
||||
.inNamespace(TEST_NAMESPACE_NAME)
|
||||
.withName(GIT_USERDATA_CONFIGMAP_NAME)
|
||||
.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNothingWhenGitUserDataIsNull()
|
||||
throws InfrastructureException, InterruptedException {
|
||||
// when
|
||||
configurator.configure(namespaceResolutionContext, TEST_NAMESPACE_NAME);
|
||||
|
||||
// then - don't create the configmap
|
||||
var configMaps =
|
||||
serverMock.getClient().configMaps().inNamespace(TEST_NAMESPACE_NAME).list().getItems();
|
||||
Assert.assertEquals(configMaps.size(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNothingWhenSecretAlreadyExists()
|
||||
throws InfrastructureException, InterruptedException, ScmCommunicationException,
|
||||
ScmUnauthorizedException {
|
||||
// given
|
||||
when(gitUserDataFetcher.fetchGitUserData()).thenReturn(new GitUserData("gitUser", "gitEmail"));
|
||||
Map<String, String> annotations =
|
||||
ImmutableMap.of(
|
||||
"controller.devfile.io/mount-as",
|
||||
"subpath",
|
||||
"controller.devfile.io/mount-path",
|
||||
"/etc/",
|
||||
"already",
|
||||
"created");
|
||||
Map<String, String> labels =
|
||||
ImmutableMap.of(
|
||||
"controller.devfile.io/mount-to-devworkspace",
|
||||
"true",
|
||||
"controller.devfile.io/watch-configmap",
|
||||
"true",
|
||||
"already",
|
||||
"created");
|
||||
ConfigMap configMap =
|
||||
new ConfigMapBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(GIT_USERDATA_CONFIGMAP_NAME)
|
||||
.withLabels(labels)
|
||||
.withAnnotations(annotations)
|
||||
.endMetadata()
|
||||
.build();
|
||||
configMap.setData(Collections.singletonMap("gitconfig", "empty"));
|
||||
serverMock.getClient().configMaps().inNamespace(TEST_NAMESPACE_NAME).create(configMap);
|
||||
|
||||
// when
|
||||
configurator.configure(namespaceResolutionContext, TEST_NAMESPACE_NAME);
|
||||
|
||||
// then - don't create the configmap
|
||||
Assert.assertEquals(serverMock.getLastRequest().getMethod(), "GET");
|
||||
var configMaps =
|
||||
serverMock.getClient().configMaps().inNamespace(TEST_NAMESPACE_NAME).list().getItems();
|
||||
Assert.assertEquals(configMaps.size(), 1);
|
||||
Assert.assertEquals(configMaps.get(0).getMetadata().getAnnotations().get("already"), "created");
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
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.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.commons.subject.SubjectImpl;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class BitbucketServerUserDataFetcherTest {
|
||||
String someBitbucketURL = "https://some.bitbucketserver.com";
|
||||
Subject subject;
|
||||
@Mock BitbucketServerApiClient bitbucketServerApiClient;
|
||||
BitbucketUser bitbucketUser;
|
||||
BitbucketServerUserDataFetcher fetcher;
|
||||
|
||||
@BeforeMethod
|
||||
public void setup() throws MalformedURLException {
|
||||
subject = new SubjectImpl("another_user", "user987", "token111", false);
|
||||
bitbucketUser =
|
||||
new BitbucketUser("User", "user", 32423523, "NORMAL", true, "user", "user@users.com");
|
||||
fetcher = new BitbucketServerUserDataFetcher(bitbucketServerApiClient, someBitbucketURL);
|
||||
EnvironmentContext context = new EnvironmentContext();
|
||||
context.setSubject(subject);
|
||||
EnvironmentContext.setCurrent(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToFetchPersonalAccessToken()
|
||||
throws ScmUnauthorizedException, ScmCommunicationException, ScmItemNotFoundException,
|
||||
ScmBadRequestException {
|
||||
// given
|
||||
when(bitbucketServerApiClient.isConnected(eq(someBitbucketURL))).thenReturn(true);
|
||||
when(bitbucketServerApiClient.getUser(eq(subject))).thenReturn(bitbucketUser);
|
||||
// when
|
||||
GitUserData gitUserData = fetcher.fetchGitUserData();
|
||||
// then
|
||||
assertEquals(gitUserData.getScmUsername(), "user");
|
||||
assertEquals(gitUserData.getScmUserEmail(), "user@users.com");
|
||||
}
|
||||
}
|
||||
|
|
@ -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,100 @@
|
|||
/*
|
||||
* 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, oAuthAPI, new GithubApiClient());
|
||||
}
|
||||
|
||||
/** Constructor used for testing only. */
|
||||
public GithubUserDataFetcher(
|
||||
String apiEndpoint, OAuthAPI oAuthAPI, GithubApiClient githubApiClient) {
|
||||
this.apiEndpoint = apiEndpoint;
|
||||
this.oAuthAPI = oAuthAPI;
|
||||
this.githubApiClient = 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";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
|
||||
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.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.common.Slf4jNotifier;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import org.eclipse.che.api.auth.shared.dto.OAuthToken;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserData;
|
||||
import org.eclipse.che.security.oauth.OAuthAPI;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class GithubGitUserDataFetcherTest {
|
||||
|
||||
@Mock OAuthAPI oAuthAPI;
|
||||
GithubUserDataFetcher githubGUDFetcher;
|
||||
|
||||
final int httpPort = 3301;
|
||||
WireMockServer wireMockServer;
|
||||
WireMock wireMock;
|
||||
|
||||
final String githubOauthToken = "gho_token1";
|
||||
|
||||
@BeforeMethod
|
||||
void start() {
|
||||
wireMockServer =
|
||||
new WireMockServer(wireMockConfig().notifier(new Slf4jNotifier(false)).port(httpPort));
|
||||
wireMockServer.start();
|
||||
WireMock.configureFor("localhost", httpPort);
|
||||
wireMock = new WireMock("localhost", httpPort);
|
||||
githubGUDFetcher =
|
||||
new GithubUserDataFetcher(
|
||||
"http://che.api", oAuthAPI, new GithubApiClient(wireMockServer.url("/")));
|
||||
stubFor(
|
||||
get(urlEqualTo("/user"))
|
||||
.withHeader(HttpHeaders.AUTHORIZATION, equalTo("token " + githubOauthToken))
|
||||
.willReturn(
|
||||
aResponse()
|
||||
.withHeader("Content-Type", "application/json; charset=utf-8")
|
||||
.withHeader(GithubApiClient.GITHUB_OAUTH_SCOPES_HEADER, "repo")
|
||||
.withBodyFile("github/rest/user/response.json")));
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
void stop() {
|
||||
wireMockServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFetchGitUserData() throws Exception {
|
||||
OAuthToken oAuthToken = newDto(OAuthToken.class).withToken(githubOauthToken).withScope("repo");
|
||||
when(oAuthAPI.getToken(anyString())).thenReturn(oAuthToken);
|
||||
|
||||
GitUserData gitUserData = githubGUDFetcher.fetchGitUserData();
|
||||
|
||||
assertEquals(gitUserData.getScmUsername(), "Github User");
|
||||
assertEquals(gitUserData.getScmUserEmail(), "github-user@acme.com");
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
@Nullable @Named("che.integration.gitlab.server_endpoints") String gitlabEndpoints,
|
||||
@Nullable @Named("che.integration.gitlab.oauth_endpoint") String oauthEndpoint,
|
||||
@Named("che.api") String apiEndpoint,
|
||||
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,84 @@
|
|||
/*
|
||||
* 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 com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
|
||||
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.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import com.github.tomakehurst.wiremock.common.Slf4jNotifier;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import org.eclipse.che.api.auth.shared.dto.OAuthToken;
|
||||
import org.eclipse.che.api.factory.server.scm.GitUserData;
|
||||
import org.eclipse.che.security.oauth.OAuthAPI;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class GitlabUserDataFetcherTest {
|
||||
|
||||
@Mock OAuthAPI oAuthAPI;
|
||||
|
||||
GitlabUserDataFetcher gitlabUserDataFetcher;
|
||||
|
||||
WireMockServer wireMockServer;
|
||||
WireMock wireMock;
|
||||
|
||||
@BeforeMethod
|
||||
void start() {
|
||||
wireMockServer =
|
||||
new WireMockServer(wireMockConfig().notifier(new Slf4jNotifier(false)).dynamicPort());
|
||||
wireMockServer.start();
|
||||
WireMock.configureFor("localhost", wireMockServer.port());
|
||||
wireMock = new WireMock("localhost", wireMockServer.port());
|
||||
gitlabUserDataFetcher =
|
||||
new GitlabUserDataFetcher(
|
||||
wireMockServer.url("/"), wireMockServer.url("/"), "http://che.api", oAuthAPI);
|
||||
|
||||
stubFor(
|
||||
get(urlEqualTo("/api/v4/user"))
|
||||
.withHeader(HttpHeaders.AUTHORIZATION, equalTo("Bearer oauthtoken"))
|
||||
.willReturn(
|
||||
aResponse()
|
||||
.withHeader("Content-Type", "application/json; charset=utf-8")
|
||||
.withBodyFile("gitlab/rest/api/v4/user/response.json")));
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
void stop() {
|
||||
wireMockServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFetchGitUserData() throws Exception {
|
||||
OAuthToken oAuthToken =
|
||||
newDto(OAuthToken.class).withToken("oauthtoken").withScope("api write_repository openid");
|
||||
when(oAuthAPI.getToken(anyString())).thenReturn(oAuthToken);
|
||||
|
||||
GitUserData gitUserData = gitlabUserDataFetcher.fetchGitUserData();
|
||||
assertEquals(gitUserData.getScmUsername(), "John Smith");
|
||||
assertEquals(gitUserData.getScmUserEmail(), "john@example.com");
|
||||
}
|
||||
}
|
||||
|
|
@ -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