Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use gitlab-api plugin #66

Merged
merged 6 commits into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 6 additions & 29 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<properties>
<revision>1.16</revision>
<changelist>-SNAPSHOT</changelist>
<jenkins.version>2.249.1</jenkins.version>
<jenkins.version>2.289.3</jenkins.version>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
Expand Down Expand Up @@ -65,8 +65,8 @@
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-2.249.x</artifactId>
<version>984.vb5eaac999a7e</version>
<artifactId>bom-2.289.x</artifactId>
<version>1280.vd669827e38cd</version>
<scope>import</scope>
<type>pom</type>
</dependency>
Expand All @@ -82,32 +82,9 @@
<artifactId>mailer</artifactId>
</dependency>
<dependency>
<groupId>org.gitlab</groupId>
<artifactId>java-gitlab-api</artifactId>
<version>4.1.1</version>
<exclusions>
<!--
Rely on the Jackson 2 API plugin for Jackson.
-->
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>

<!-- Provided by Jenkins core -->
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
<groupId>io.jenkins.plugins</groupId>
<artifactId>gitlab-api</artifactId>
<version>1.0.7-rc68.a_3711d5d3b_1c</version> <!-- TODO https://github.com/jenkinsci/gitlab-api-plugin/pull/7 -->
basil marked this conversation as resolved.
Show resolved Hide resolved
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ of this software and associated documentation files (the "Software"), to deal
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import hudson.security.SecurityRealm;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -48,11 +46,12 @@ of this software and associated documentation files (the "Software"), to deal
import org.acegisecurity.providers.AbstractAuthenticationToken;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.gitlab.api.GitlabAPI;
import org.gitlab.api.TokenType;
import org.gitlab.api.models.GitlabGroup;
import org.gitlab.api.models.GitlabProject;
import org.gitlab.api.models.GitlabUser;
import org.gitlab4j.api.Constants.TokenType;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.User;

/**
* @author mocleiri
Expand All @@ -69,8 +68,8 @@ public class GitLabAuthenticationToken extends AbstractAuthenticationToken {
private final String accessToken;

private final String userName;
private final transient GitlabAPI gitLabAPI;
private final transient GitlabUser me;
private final transient GitLabApi gitLabAPI;
private final transient User me;
private transient GitLabSecurityRealm myRealm = null;

/**
Expand All @@ -88,18 +87,18 @@ public class GitLabAuthenticationToken extends AbstractAuthenticationToken {
private static final Cache<String, Boolean> publicRepositoryCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS).build();

private static final Cache<String, List<GitlabProject>> groupRepositoriesCache = Caffeine.newBuilder()
private static final Cache<String, List<Project>> groupRepositoriesCache = Caffeine.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS).build();

private final List<GrantedAuthority> authorities = new ArrayList<>();

public GitLabAuthenticationToken(String accessToken, String gitlabServer, TokenType tokenType) throws IOException {
public GitLabAuthenticationToken(String accessToken, String gitlabServer, TokenType tokenType) throws GitLabApiException {
super(new GrantedAuthority[] {});

this.accessToken = accessToken;
this.gitLabAPI = GitlabAPI.connect(gitlabServer, accessToken, tokenType);
this.gitLabAPI = new GitLabApi(gitlabServer, tokenType, accessToken);

this.me = Objects.requireNonNull(gitLabAPI.getUser());
this.me = Objects.requireNonNull(gitLabAPI.getUserApi().getCurrentUser());

setAuthenticated(true);

Expand All @@ -114,8 +113,8 @@ public GitLabAuthenticationToken(String accessToken, String gitlabServer, TokenT
// documented online.
// https://developer.gitlab.com/v3/orgs/#list-your-organizations
// https://developer.gitlab.com/v3/orgs/teams/#list-user-teams
List<GitlabGroup> myTeams = gitLabAPI.getGroups();
for (GitlabGroup group : myTeams) {
List<Group> myTeams = gitLabAPI.getGroupApi().getGroups();
for (Group group : myTeams) {
LOGGER.log(Level.FINE, "Fetch teams for user " + userName + " in organization " + group.getName());

GitLabOAuthGroupDetails gitLabOAuthGroupDetails = new GitLabOAuthGroupDetails(group);
Expand Down Expand Up @@ -143,7 +142,7 @@ public String getAccessToken() {
return accessToken;
}

public GitlabAPI getGitLabAPI() {
public GitLabApi getGitLabAPI() {
return gitLabAPI;
}

Expand All @@ -168,7 +167,7 @@ public String getPrincipal() {
/**
* Returns the GHMyself object from this instance.
*/
public GitlabUser getMyself() {
public User getMyself() {
return me;
}

Expand All @@ -188,14 +187,14 @@ public GitlabUser getMyself() {
public boolean hasOrganizationPermission(String candidateName, String organization) {
Set<String> v = userOrganizationCache.get(candidateName, unused -> {
try {
List<GitlabGroup> groups = gitLabAPI.getGroups();
List<Group> groups = gitLabAPI.getGroupApi().getGroups();
Set<String> groupsNames = new HashSet<>();
for (GitlabGroup group : groups) {
for (Group group : groups) {
groupsNames.add(group.getName());
}
return groupsNames;
} catch (IOException e) {
throw new UncheckedIOException("authorization failed for user = " + candidateName, e);
} catch (GitLabApiException e) {
throw new RuntimeException("authorization failed for user = " + candidateName, e);
}
});

Expand All @@ -208,34 +207,38 @@ public boolean hasRepositoryPermission(final String repositoryName) {

public Set<String> myRepositories() {
Set<String> myRepositories = repositoriesByUserCache.get(getName(), unused -> {
try {
// Get user's projects
List<GitlabProject> userRepositoryList = gitLabAPI.getProjects();
List<Project> userRepositoryList = gitLabAPI.getProjectApi().getProjects();
Set<String> repositoryNames = Collections.emptySet();
if (userRepositoryList != null) {
repositoryNames = listToNames(userRepositoryList);
}
// Disable for security reason.
// If enabled, even group guest can manage all group jobs.
// // Get user's groups
// List<GitlabGroup> userGroups = gitLabAPI.getGroups();
// List<Group> userGroups = gitLabAPI.getGroups();
// if (userGroups != null) {
// for (GitlabGroup group : userGroups) {
// List<GitlabProject> groupProjects = getGroupProjects(group);
// for (Group group : userGroups) {
// List<Project> groupProjects = getGroupProjects(group);
// if (groupProjects != null) {
// Set<String> groupProjectNames = listToNames(groupProjects);
// repositoryNames.addAll(groupProjectNames);
// }
// }
// }
return repositoryNames;
} catch (GitLabApiException e) {
throw new RuntimeException(e);
}
});

return myRepositories;
}

public Set<String> listToNames(Collection<GitlabProject> repositories) {
public Set<String> listToNames(Collection<Project> repositories) {
Set<String> names = new HashSet<>();
for (GitlabProject repository : repositories) {
for (Project repository : repositories) {
// String ownerName = repository.getOwner().getUsername();
// String repoName = repository.getName();
// names.add(ownerName + "/" + repoName);
Expand All @@ -247,13 +250,13 @@ public Set<String> listToNames(Collection<GitlabProject> repositories) {

public boolean isPublicRepository(final String repositoryName) {
Boolean isPublic = publicRepositoryCache.get(repositoryName, unused -> {
GitlabProject repository = loadRepository(repositoryName);
Project repository = loadRepository(repositoryName);
if (repository == null) {
// We don't have access so it must not be public (it
// could be non-existant)
return Boolean.FALSE;
} else {
return Boolean.TRUE.equals(repository.isPublic());
return Boolean.TRUE.equals(repository.getPublic());
}
});

Expand All @@ -262,41 +265,41 @@ public boolean isPublicRepository(final String repositoryName) {

private static final Logger LOGGER = Logger.getLogger(GitLabAuthenticationToken.class.getName());

public GitlabUser loadUser(String username) {
public User loadUser(String username) {
try {
if (gitLabAPI != null && isAuthenticated()) {
List<GitlabUser> users = gitLabAPI.findUsers(username);
List<User> users = gitLabAPI.getUserApi().findUsers(username);
if (CollectionUtils.isNotEmpty(users)) {
return users.get(0); // FIXME : find best solution
}
}
} catch (IOException e) {
} catch (GitLabApiException e) {
LOGGER.log(Level.FINEST, e.getMessage(), e);
}
return null;
}

public GitlabGroup loadOrganization(String organization) {
public Group loadOrganization(String organization) {
if (StringUtils.isEmpty(organization)) return null;
try {
if (gitLabAPI != null && isAuthenticated()) {
List<GitlabGroup> gitLabGroups = gitLabAPI.getGroups();
List<Group> gitLabGroups = gitLabAPI.getGroupApi().getGroups();
if (!gitLabGroups.isEmpty()) {
return gitLabGroups.stream().filter(group -> group.getName().equalsIgnoreCase(organization)).findFirst().orElse(null);
}
}
} catch (IOException e) {
} catch (GitLabApiException e) {
LOGGER.log(Level.FINEST, e.getMessage(), e);
}
return null;
}

public GitlabProject loadRepository(String repositoryName) {
public Project loadRepository(String repositoryName) {
try {
if (gitLabAPI != null && isAuthenticated()) {
return gitLabAPI.getProject(repositoryName);
return gitLabAPI.getProjectApi().getProject(repositoryName);
}
} catch (IOException e) {
} catch (GitLabApiException e) {
LOGGER.log(Level.WARNING,
"Looks like a bad GitLab URL OR the Jenkins user does not have access to the repository{0}",
repositoryName);
Expand All @@ -308,25 +311,31 @@ public GitlabProject loadRepository(String repositoryName) {
* @since 0.21
*/
public GitLabOAuthUserDetails getUserDetails(String username) {
GitlabUser user = loadUser(username);
User user = loadUser(username);
if (user != null) {
// FIXME to implement
List<GrantedAuthority> groups = new ArrayList<>();
try {
List<GitlabGroup> gitLabGroups = gitLabAPI.getGroups();
for (GitlabGroup gitlabGroup : gitLabGroups) {
List<Group> gitLabGroups = gitLabAPI.getGroupApi().getGroups();
for (Group gitlabGroup : gitLabGroups) {
groups.add(new GrantedAuthorityImpl(gitlabGroup.getName()));
}
} catch (IOException e) {
} catch (GitLabApiException e) {
LOGGER.log(Level.FINE, e.getMessage(), e);
}
return new GitLabOAuthUserDetails(user, groups.toArray(new GrantedAuthority[0]));
}
return null;
}

public List<GitlabProject> getGroupProjects(final GitlabGroup group) {
List<GitlabProject> groupProjects = groupRepositoriesCache.get(group.getFullPath(), unused -> gitLabAPI.getGroupProjects(group));
public List<Project> getGroupProjects(final Group group) {
List<Project> groupProjects = groupRepositoriesCache.get(group.getFullPath(), unused -> {
try {
return gitLabAPI.getGroupApi().getProjects(group);
} catch (GitLabApiException e) {
throw new RuntimeException(e);
}
});

return groupProjects;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import hudson.security.GroupDetails;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.gitlab.api.models.GitlabGroup;
import org.gitlab4j.api.models.Group;

/**
* Represent a group from GitLab as a group in Jenkins terms.
Expand All @@ -27,14 +27,14 @@
*/
public class GitLabOAuthGroupDetails extends GroupDetails {

private final GitlabGroup gitlabGroup;
private final Group gitlabGroup;
static final String ORG_TEAM_SEPARATOR = "*";

/**
* Group based on organization name
* @param gitlabGroup
*/
public GitLabOAuthGroupDetails(GitlabGroup gitlabGroup) {
public GitLabOAuthGroupDetails(Group gitlabGroup) {
this.gitlabGroup = gitlabGroup;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.userdetails.UserDetails;
import org.gitlab.api.models.GitlabUser;

/**
* @author Mike
Expand All @@ -20,7 +19,7 @@ public class GitLabOAuthUserDetails extends User implements UserDetails {
*/
private static final long serialVersionUID = 1709511212188366292L;

public GitLabOAuthUserDetails(GitlabUser user, GrantedAuthority[] authorities) {
public GitLabOAuthUserDetails(org.gitlab4j.api.models.User user, GrantedAuthority[] authorities) {
super(user.getUsername(), "", true, true, true, true, authorities);
}

Expand Down
Loading