
org.identityconnectors.googleapps.GoogleAppsUserOps Maven / Gradle / Ivy
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.identityconnectors.googleapps;
import static org.identityconnectors.common.CollectionUtil.isEmpty;
import com.google.gdata.data.appsforyourdomain.Quota;
import com.google.gdata.data.appsforyourdomain.provisioning.UserEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.identityconnectors.common.logging.Log;
import org.identityconnectors.common.security.GuardedString;
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.identityconnectors.framework.common.objects.AttributesAccessor;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
import org.identityconnectors.framework.common.objects.Name;
import org.identityconnectors.framework.common.objects.ObjectClass;
import org.identityconnectors.framework.common.objects.OperationOptions;
import org.identityconnectors.framework.common.objects.ResultsHandler;
import org.identityconnectors.framework.common.objects.Uid;
/**
*
* @author warrenstrange
*/
public class GoogleAppsUserOps {
GoogleAppsConnection gc;
Log log = Log.getLog(GoogleAppsUserOps.class);
GoogleAppsUserOps(GoogleAppsConnection gc) {
this.gc = gc;
}
/**
* Create a user
* @param name
* @param a
* @return
*/
Uid createUser(Name name, AttributesAccessor a) {
final String accountId = a.getName().getNameValue();
final GoogleAppsClient g = gc.getConnection();
//log.info("Extracting Attrs {0}", attrs);
// todo: this craters if the attribute does not exist (NPE)
// we should throw a better error
final String givenName = a.findString(GoogleAppsConnector.ATTR_GIVEN_NAME);
final String familyName = a.findString(GoogleAppsConnector.ATTR_FAMILY_NAME);
final Integer quota = a.findInteger(GoogleAppsConnector.ATTR_QUOTA);
// Password is Operational
GuardedString password = a.getPassword();
if (password == null) {
throw new IllegalArgumentException("The Password attribute cannot be null.");
}
final boolean suspended = !a.getEnabled(true);
String clearPw = getPlainPassword(password);
UserEntry ue = g.setUserEntry(null, accountId, clearPw, givenName, familyName, suspended, quota);
log.info("Creating User {0} givenName: {1} familyName {2} ", accountId, givenName, familyName);
ue = g.createUser(ue);
List nicks = a.findStringList(GoogleAppsConnector.ATTR_NICKNAME_LIST);
if (nicks != null) {
for (String nickname : nicks) {
log.info("Adding nickname {0} to account {1}", nickname, accountId);
g.createNickname(accountId, nickname);
}
}
List groups = a.findStringList(GoogleAppsConnector.ATTR_GROUP_LIST);
if( ! isEmpty(groups)) {
for(String group: groups) {
g.addGroupMember(group, accountId);
}
}
List owners = a.findStringList(GoogleAppsConnector.ATTR_OWNER_LIST);
if( ! isEmpty(owners)) {
for(String owner: owners) {
g.addGroupMember(owner, accountId);
}
}
return new Uid(accountId);
}
/**
* Utility method to unguard the password.
* @param password - Guarded password
* @return plain text password
*/
public static String getPlainPassword(GuardedString password) {
if (password == null) {
return null;
}
final StringBuffer buf = new StringBuffer();
password.access(new GuardedString.Accessor() {
public void access(char[] clearChars) {
buf.append(clearChars);
}
});
return buf.toString();
}
void delete(String id) {
GoogleAppsClient g = gc.getConnection();
g.deleteUser(id);
}
void query(String query, ResultsHandler handler, OperationOptions ops) {
GoogleAppsClient g = gc.getConnection();
boolean fetchNicknames = false; // by default nicknames and groups are not fetched
boolean fetchGroups = false;
//boolean fetchOwners = false;
if (ops != null) {
String attrs[] = ops.getAttributesToGet();
if (attrs != null) {
List alist = Arrays.asList(attrs);
if (alist.contains(GoogleAppsConnector.ATTR_NICKNAME_LIST))
fetchNicknames = true;
if (alist.contains(GoogleAppsConnector.ATTR_GROUP_LIST))
fetchGroups = true;
}
}
if (query == null) { // return all users;
log.info("Fetching All Users");
Iterator i = g.getIterator();
while (i.hasNext()) {
UserEntry ue = (UserEntry) i.next();
List nicknames = new ArrayList();
List groups = new ArrayList();
String accountId = ue.getLogin().getUserName();
if (fetchNicknames) {
nicknames = g.getNicknamesAsList(accountId);
}
if (fetchGroups) {
groups = g.getGroupMembershipsForUser(accountId);
}
handler.handle(makeConnectorObject(ue, nicknames, groups));
}
} else { // get a single user
ConnectorObject obj = get(query, fetchNicknames, fetchGroups);
log.info("ConnectorObj {0}", obj);
if (obj != null) {
handler.handle(obj);
}
}
}
/**
* Given a google apps user entry and associated nicknames, create
* a ConnectorObject.
*
* @param ue google apps UesrEntry object
* @param nicknames list of nicknames
* @param groups - list of groups this user belongs to
* @return a connectorOject
*/
private ConnectorObject makeConnectorObject(UserEntry ue, List nicknames, List groups) {
if (ue == null)
return null; // must have a userentry object
ObjectClass objectClass = ObjectClass.ACCOUNT;
ConnectorObjectBuilder builder = new ConnectorObjectBuilder();
Uid uid = new Uid(ue.getLogin().getUserName());
builder.setUid(uid);
builder.setName(uid.getUidValue());
String familyName = ue.getName().getFamilyName();
String givenName = ue.getName().getGivenName();
boolean suspended = ue.getLogin().getSuspended().booleanValue();
builder.addAttribute(AttributeBuilder.build(GoogleAppsConnector.ATTR_FAMILY_NAME, familyName));
builder.addAttribute(AttributeBuilder.build(GoogleAppsConnector.ATTR_GIVEN_NAME, givenName));
builder.addAttribute(AttributeBuilder.buildEnabled(!suspended));
// if either nicknames or groups are empty lists, return them anyway
builder.addAttribute(AttributeBuilder.build(GoogleAppsConnector.ATTR_NICKNAME_LIST, nicknames));
builder.addAttribute(AttributeBuilder.build(GoogleAppsConnector.ATTR_GROUP_LIST, groups));
Quota quota = ue.getQuota();
if (quota != null) {
builder.addAttribute(AttributeBuilder.build(GoogleAppsConnector.ATTR_QUOTA, quota.getLimit()));
}
log.info("Make object uid={0} fn={1} gn={2} nicks={3} groups={4}", uid, familyName, givenName, nicknames, groups);
return builder.build();
}
private final List emptyList = new ArrayList(1);
/**
* Retrive the user with the given uid
*
* @param id - the user id for the account
* @param fetchNicknames - if true we should also fetch associated nicknames. This can be expensive
* @return The user object if it exists, null otherwise
*/
private ConnectorObject get(String id, boolean fetchNicknames, boolean fetchGroups) {
UserEntry ue = null;
GoogleAppsClient g = gc.getConnection();
log.info("Fetching google apps user {0}", id);
ue = g.getUserEntry(id);
log.info("UserEntry = {0}", GoogleAppsClient.userEntrytoString(ue));
if (ue != null) {
List nicks = (fetchNicknames ? g.getNicknamesAsList(id) :emptyList );
List groups = (fetchGroups ? g.getGroupMembershipsForUser(id) : emptyList);
return makeConnectorObject(ue, nicks, groups);
}
return null;
}
/**
* Update the user entry - including associated nicknames (aliases)
* @param uid
* @param replaceAttrs
* @param options
* @return
*/
Uid updateUser(Uid uid, Set replaceAttrs, OperationOptions options) {
AttributesAccessor a = new AttributesAccessor(replaceAttrs);
final String accountId = uid.getUidValue();
final GoogleAppsClient g = gc.getConnection();
// this an optimization in case the update only includes nicknames
// we can skip the update on the other attributes
boolean justDoNicknames = replaceAttrs.size() == 1 && a.findStringList(GoogleAppsConnector.ATTR_NICKNAME_LIST) != null;
if (!justDoNicknames) {
// fetch the complete object so we can merge in the changes
final UserEntry userEntry = g.getUserEntry(accountId);
if (userEntry == null) {
throw new ConnectorException("Update failed. Could not read current state for user " + accountId);
}
// set the updated values
log.info("Rerieved UserEntry {0}", GoogleAppsClient.userEntrytoString(userEntry));
String password = getPlainPassword(a.getPassword());
final String first = a.findString(GoogleAppsConnector.ATTR_FAMILY_NAME);
final String given = a.findString(GoogleAppsConnector.ATTR_GIVEN_NAME);
// note google apps uses suspend instead of enable - so we have to
// negate the result
final boolean suspended = !a.getEnabled(true);
// merge in replace attributes
UserEntry ue = g.setUserEntry(userEntry, accountId, password, given, first, suspended, null);
// update the user. Throws an exception if it fails.
ue = g.updateUser(accountId, ue);
}
// Update the nicknames
List nicknamesToUpdate = a.findStringList(GoogleAppsConnector.ATTR_NICKNAME_LIST);
if (nicknamesToUpdate != null) {
// we don't get a list of the deltas - so we need to
// read the current list to compare what we need to add/delete
// google apps does not have a "delete all" nicknames request -
// so we don't have the option to delete all and then add in the update list
List currentNames = g.getNicknamesAsList(accountId);
log.info("Existing nickname for account {0} are: {1}", accountId, currentNames);
// we don't get a list of the deltas - so we need to
// read the current list to compare what we need to add/delete
// google apps does not have a "delete all" nicknames request -
// so we don't have the option to delete all and then add in the update list
//ChangeSet changes = new ChangeSet(currentNames, nicknamesToUpdate);
new ChangeSetExecutor(currentNames, nicknamesToUpdate) {
@Override
public void doAdd(String nickname) {
log.info("Adding nickname ${0} to user {1}", nickname, accountId);
g.createNickname(accountId, nickname);
}
@Override
public void doRemove(String nickname) {
log.info("Removing nickname {0}", nickname);
g.deleteNickname(nickname);
}
}.execute();
}
// update group membership
List groupsToUpdate = a.findStringList(GoogleAppsConnector.ATTR_GROUP_LIST);
if (groupsToUpdate != null) {
// we don't get a list of the deltas - so we need to
// read the current list to compare what we need to add/delete
// google apps does not have a "delete all" nicknames request -
// so we don't have the option to delete all and then add in the update list
List currentGroups = g.getGroupMembershipsForUser(accountId);
log.info("Existing groups for account {0} are: {1}", accountId, currentGroups);
new ChangeSetExecutor(currentGroups, groupsToUpdate) {
@Override
public void doAdd(String group) {
log.info("Adding group ${0} to user {1}", group, accountId);
g.addGroupMember(group, accountId);
}
@Override
public void doRemove(String group) {
log.info("Removing user from group {0}", group);
g.removeGroupMember(group,accountId);
}
}.execute();
}
return new Uid((accountId));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy