package hudson.plugins.collabnet.auth;
import com.collabnet.ce.webservices.CTFProject;
import com.collabnet.ce.webservices.CTFUser;
import com.collabnet.ce.webservices.CollabNetApp;
import hudson.model.Hudson;
import hudson.security.Permission;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.logging.Logger;
/**
* Authentication class for CollabNet.
*/
public class CNAuthentication implements Authentication {
public static final String SUPER_USER = "SuperUser";
private final String principal;
private final CTFUser myself;
private final CollabNetApp cna;
private GrantedAuthority[] authorities;
private Collection<String> groups;
private boolean authenticated = false;
private boolean cnauthed = false;
private CNAuthorizationCache mAuthCache = null;
private static Logger log = Logger.getLogger("CNAuthentication");
public CNAuthentication(Object principal, Object credentials) throws RemoteException {
this.principal = (String) principal;
this.cna = (CollabNetApp) credentials;
this.myself = cna.getMyself();
this.setupAuthorities();
this.setupGroups();
this.setAuthenticated(true);
mAuthCache = new CNAuthorizationCache();
}
/**
* The only granted authority is superuser-ness.
*/
private void setupAuthorities() {
boolean isSuper = false;
try {
isSuper = myself.isSuperUser();
} catch (RemoteException re) {
log.info("setupAuthoritites: failed with RemoteException: " +
re.getMessage());
}
if (isSuper) {
this.authorities = new GrantedAuthority[1];
this.authorities[0] =
new GrantedAuthorityImpl(CNAuthentication.SUPER_USER);
} else {
this.authorities = new GrantedAuthority[0];
}
}
/**
* Check which groups this user belongs to.
*/
private void setupGroups() {
this.groups = Collections.emptyList();
try {
this.groups = myself.getGroupNames();
} catch (RemoteException re) {
// not much we can do
}
}
public void setAuthenticated(boolean authenticated) {
this.authenticated = authenticated;
}
public boolean isAuthenticated() {
return this.authenticated;
}
/**
* @return a copy of the granted authorities.
*/
public GrantedAuthority[] getAuthorities() {
GrantedAuthority[] authCopy =
new GrantedAuthority[this.authorities.length];
System.arraycopy(this.authorities, 0, authCopy, 0,
this.authorities.length);
return authCopy;
}
public String getPrincipal() {
return this.principal;
}
public String getName() {
return this.getPrincipal();
}
public Object getDetails() {
return null;
}
public CollabNetApp getCredentials() {
return this.cna;
}
/**
* @param group name of a CN group.
* @return true if the user is a member of the given group.
*/
public boolean isMember(String group) {
return this.groups.contains(group);
}
public String toString() {
return "CNAuthentication [for: " + this.getPrincipal() +
", authenticated=" + this.isAuthenticated() + "]";
}
/**
* Determine whether we have authenticated to CTF in the browser.
* @return true if authenticated
*/
public boolean isCNAuthed() {
return this.cnauthed;
}
/**
* Set whether we have authenticated to CTF in the browser.
* @param cnauthed true if current session is CTF authenticated in browser
*/
public void setCNAuthed(boolean cnauthed) {
this.cnauthed = cnauthed;
}
/**
* Determines if the authenticated user is a super user.
* This is currently from data that's calculated once (on login).
* If this ever turns out to be insufficient, we could change this
* method to get the data on the fly.
*/
public boolean isSuperUser() {
for (GrantedAuthority authority: getAuthorities()) {
if (authority.getAuthority().equals(CNAuthentication.SUPER_USER)) {
return true;
}
}
return false;
}
/**
* Determines if the authenticated user belongs to any of the groups.
* This is currently from data that's calculated once (on login).
* If this ever turns out to be insufficient, we could change this
* method to get the data on the fly.
*
* @param groups
* @return true if the user is a member of any of the groups.
*/
public boolean isMemberOfAny(Collection<String> groups) {
for (String group: groups) {
if (this.isMember(group)) {
return true;
}
}
return false;
}
/**
* Determines if the authenticated user is a project admin.
*
* @return true if the user is a project admin.
*/
public boolean isProjectAdmin(CTFProject p) {
try {
return p.getAdmins().contains(cna.getMyself());
} catch (RemoteException re) {
log.info("isProjectAdmin: failed with RemoteException: " + re.getMessage());
return false;
}
}
public String getSessionId() {
return this.getCredentials().getSessionId();
}
/**
* Get a set of all permission that a user has for a given project.
* @param username user name
* @param projectId project id
* @return set of permissions
*/
public Set<Permission> getUserProjectPermSet(String username, String projectId) {
return mAuthCache.getUserProjectPermSet(username, projectId);
}
/**
* If the current thread carries the {@link CNAuthentication} object as the context,
* returns it. Or else null.
*/
public static CNAuthentication get() {
return cast(Hudson.getAuthentication());
}
public static CNAuthentication cast(Authentication a) {
if (a instanceof CNAuthentication) {
return (CNAuthentication) a;
} else {
return null;
}
}
}