Skip to content

Commit

Permalink
JENKINS-21331: include teams as groups
Browse files Browse the repository at this point in the history
duplicate: JENKINS-28575

Conflicts:
	src/main/java/org/jenkinsci/plugins/GithubAuthenticationToken.java
	src/main/java/org/jenkinsci/plugins/GithubSecurityRealm.java
  • Loading branch information
jcarsique authored and sirosen committed Jul 10, 2015
1 parent 24a3f6f commit 7fea114
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 168 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -78,7 +78,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>github-api</artifactId>
<version>1.58</version>
<version>1.67</version>
</dependency>

<dependency>
Expand Down
152 changes: 98 additions & 54 deletions src/main/java/org/jenkinsci/plugins/GithubAuthenticationToken.java
Expand Up @@ -27,7 +27,6 @@ of this software and associated documentation files (the "Software"), to deal
package org.jenkinsci.plugins;

import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -43,6 +42,8 @@ of this software and associated documentation files (the "Software"), to deal
import com.google.common.cache.CacheBuilder;
import hudson.security.SecurityRealm;
import java.util.Collection;

import org.jenkinsci.plugins.GithubOAuthUserDetails;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.AbstractAuthenticationToken;
Expand All @@ -56,24 +57,24 @@ of this software and associated documentation files (the "Software"), to deal

/**
* @author mocleiri
*
*
* to hold the authentication token from the github oauth process.
*
*
*/
public class GithubAuthenticationToken extends AbstractAuthenticationToken {

/**
*
*
*/
private static final long serialVersionUID = 1L;
private final String accessToken;

private final String userName;
private final GitHub gh;
private final GHMyself me;

/**
* Cache for faster organization based security
* Cache for faster organization based security
*/
private static final Cache<String, Set<String>> userOrganizationCache =
CacheBuilder.newBuilder().expireAfterWrite(1,TimeUnit.HOURS).build();
Expand Down Expand Up @@ -103,9 +104,17 @@ public GithubAuthenticationToken(String accessToken, String githubServer) throws

this.userName = this.me.getLogin();
authorities.add(SecurityRealm.AUTHENTICATED_AUTHORITY);
for (String name : gh.getMyOrganizations().keySet())
authorities.add(new GrantedAuthorityImpl(name));
}
Map<String, Set<GHTeam>> myTeams = gh.getMyTeams();
for (String orgLogin : myTeams.keySet()) {
LOGGER.log(Level.FINE, "Fetch teams for user " + userName + " in organization " + orgLogin);
authorities.add(new GrantedAuthorityImpl(orgLogin));
for (GHTeam team : myTeams.get(orgLogin)) {
authorities.add(new GrantedAuthorityImpl(orgLogin + GithubOAuthGroupDetails.ORG_TEAM_SEPARATOR
+ team.getName()));
}
}

}

/**
* Necessary for testing
Expand Down Expand Up @@ -146,12 +155,12 @@ public String getPrincipal() {
/**
* For some reason I can't get the github api to tell me for the current
* user the groups to which he belongs.
*
*
* So this is a slightly larger consideration. If the authenticated user is
* part of any team within the organization then they have permission.
*
*
* It caches user organizations for 24 hours for faster web navigation.
*
*
* @param candidateName
* @param organization
* @return
Expand Down Expand Up @@ -240,55 +249,90 @@ public Boolean call() throws Exception {
}
}

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

public GHUser loadUser(String username) throws IOException {
if (gh != null && isAuthenticated())
return gh.getUser(username);
else
return null;
}
public GHUser loadUser(String username) {
try {
if (gh != null && isAuthenticated())
return gh.getUser(username);
} catch (IOException e) {
LOGGER.log(Level.FINEST, e.getMessage(), e);
}
return null;
}

public GHOrganization loadOrganization(String organization)
throws IOException {
public GHOrganization loadOrganization(String organization) {
try {
if (gh != null && isAuthenticated())
return gh.getOrganization(organization);
} catch (IOException e) {
LOGGER.log(Level.FINEST, e.getMessage(), e);
}
return null;
}

if (gh != null && isAuthenticated())
return gh.getOrganization(organization);
else
return null;
public GHRepository loadRepository(String repositoryName) {
try {
if (gh != null && isAuthenticated()) {
return gh.getRepository(repositoryName);
}
} catch (IOException e) {
LOGGER.log(Level.WARNING,
"Looks like a bad GitHub URL OR the Jenkins user does not have access to the repository{0}",
repositoryName);
}
return null;
}

}
public GHTeam loadTeam(String organization, String team) {
try {
GHOrganization org = loadOrganization(organization);
if (org != null) {
return org.getTeamByName(team);
}
} catch (IOException e) {
LOGGER.log(Level.FINEST, e.getMessage(), e);
}
return null;
}

public GHRepository loadRepository(String repositoryName) {
/**
* @since 0.21
*/
public GithubOAuthUserDetails getUserDetails(String username) {
GHUser user = loadUser(username);
if (user != null) {
List<GrantedAuthority> groups = new ArrayList<GrantedAuthority>();
try {
if (gh != null && isAuthenticated()) {
return gh.getRepository(repositoryName);
} else {
return null;
for (GHOrganization ghOrganization : user.getOrganizations()) {
String orgLogin = ghOrganization.getLogin();
LOGGER.log(Level.FINE, "Fetch teams for user " + username + " in organization " + orgLogin);
groups.add(new GrantedAuthorityImpl(orgLogin));
try {
if (!me.isMemberOf(ghOrganization)) {
continue;
}
Map<String, GHTeam> teams = ghOrganization.getTeams();
for (String team : teams.keySet()) {
if (teams.get(team).hasMember(user)) {
groups.add(new GrantedAuthorityImpl(orgLogin + GithubOAuthGroupDetails.ORG_TEAM_SEPARATOR
+ team));
}
}
} catch (IOException ignore) {
LOGGER.log(Level.FINEST, "not enough rights to list teams from " + orgLogin, ignore);
continue;
} catch (Error ignore) {
LOGGER.log(Level.FINEST, "not enough rights to list teams from " + orgLogin, ignore);
continue;
}
}
} catch(FileNotFoundException e) {
LOGGER.log(Level.WARNING, "Looks like a bad github URL OR the Jenkins user does not have access to the repository{0}", repositoryName);
return null;
} catch(IOException e) {
LOGGER.log(Level.WARNING, "Looks like a bad github URL OR the Jenkins user does not have access to the repository{0}", repositoryName);
return null;
LOGGER.log(Level.FINE, e.getMessage(), e);
}
}

public GHTeam loadTeam(String organization, String team) throws IOException {
if (gh != null && isAuthenticated()) {

GHOrganization org = gh.getOrganization(organization);

if (org != null) {
Map<String, GHTeam> teamMap = org.getTeams();

return teamMap.get(team);
} else
return null;

} else
return null;
}
return new GithubOAuthUserDetails(user, groups.toArray(new GrantedAuthority[groups.size()]));
}
return null;
}
}
57 changes: 38 additions & 19 deletions src/main/java/org/jenkinsci/plugins/GithubOAuthGroupDetails.java
Expand Up @@ -4,6 +4,7 @@
package org.jenkinsci.plugins;

import org.kohsuke.github.GHOrganization;
import org.kohsuke.github.GHTeam;

import hudson.security.GroupDetails;

Expand All @@ -13,24 +14,42 @@
*/
public class GithubOAuthGroupDetails extends GroupDetails {

private final GHOrganization org;

public GithubOAuthGroupDetails(GHOrganization org) {
super();
this.org = org;
}

/* (non-Javadoc)
* @see hudson.security.GroupDetails#getName()
*/
@Override
public String getName() {
if (org != null)
return org.getLogin();
else
return null;
}


private final GHOrganization org;
private final GHTeam team;
static final String ORG_TEAM_SEPARATOR = "*";

/**
* Group based on organization name
* @param org
*/
public GithubOAuthGroupDetails(GHOrganization org) {
super();
this.org = org;
this.team = null;
}

/**
* Group based on team name
* @param ghTeam
*/
public GithubOAuthGroupDetails(GHTeam team) {
super();
this.org = team.getOrganization();
this.team = team;
}

/* (non-Javadoc)
* @see hudson.security.GroupDetails#getName()
*/
@Override
public String getName() {
if (team != null)
return org.getLogin() + ORG_TEAM_SEPARATOR + team.getName();
if (org != null)
return org.getLogin();
return null;
}



}
72 changes: 7 additions & 65 deletions src/main/java/org/jenkinsci/plugins/GithubOAuthUserDetails.java
@@ -1,81 +1,23 @@
/**
*
*
*/
package org.jenkinsci.plugins;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.userdetails.UserDetails;
import org.kohsuke.github.GHUser;

/**
* @author Mike
*
*/
public class GithubOAuthUserDetails implements UserDetails {

private final GHUser user;

/**
*
*/
public GithubOAuthUserDetails(GHUser user) {
this.user = user;
}

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#getAuthorities()
*/
@Override
public GrantedAuthority[] getAuthorities() {
return new GrantedAuthority [] {};
}

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#getPassword()
*/
@Override
public String getPassword() {
return null;
}

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#getUsername()
*/
@Override
public String getUsername() {
return user.getLogin();
}

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#isAccountNonExpired()
*/
@Override
public boolean isAccountNonExpired() {
return true;
}

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#isAccountNonLocked()
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
public class GithubOAuthUserDetails extends User implements UserDetails {

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#isCredentialsNonExpired()
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
private static final long serialVersionUID = 1L;

/* (non-Javadoc)
* @see org.acegisecurity.userdetails.UserDetails#isEnabled()
*/
@Override
public boolean isEnabled() {
return true;
}
public GithubOAuthUserDetails(GHUser user, GrantedAuthority[] authorities) {
super(user.getLogin(), "", true, true, true, true, authorities);
}

}

0 comments on commit 7fea114

Please sign in to comment.