package edu.ucmerced.idm.adapter;
import java.util.*;
import org.w3c.dom.*;
import com.waveset.adapter.*;
import com.waveset.util.WavesetException;
import com.waveset.object.*;
import com.waveset.msgcat.Message;
import com.waveset.util.EncryptedData;
import com.waveset.logging.trace.WSTrace;
import com.waveset.session.Session;
import com.waveset.session.SessionFactory;
import com.waveset.repository.Repository;
import com.waveset.repository.ServerRepository;
import java.util.ArrayList;
/**
* Allow pass-through authentication using CAS.
* <p/>
* This resource must be assigned to any user you wish to authenticate
* through CAS.
* <p/>
* Known issues:
* <p/>
* - This is often seen when users assigned to this resource are
* checked out or checked in:</br>
* com.waveset.util.WavesetException: The adapter must support iterating accounts in order to reconcile accounts on resource 'CAS'.<br/>
* However, this appears to have no adverse affects on the checkin and
* checkout operations.
*
* @author Brian Koehmstedt (bkoehmstedt@ucmerced.edu)
*/
public class CASResourceAdapter extends ResourceAdapterBase
{
public static final String RESOURCE_TYPE = "CAS";
public static final String LOGIN_MODULE = RESOURCE_TYPE + " Login Module";
public static final String CONFIG_OBJECT = "CAS Configuration Object";
private static ArrayList _refererList;
public static final String USER = "userid";
public static final String IDMATTR = "ldapId";
public static final String REFERER = "Referer";
public CASResourceAdapter(Resource res, ObjectCache cache)
{
super(res, cache);
}
public CASResourceAdapter()
{
super();
}
static final String prototypeXml =
"<Resource name='CAS' class='edu.ucmerced.idm.adapter.CASResourceAdapter' typeString='" + RESOURCE_TYPE + "'>\n" +
" <Template>\n"+
" <AttrDef name='accountId' type='string' />\n" +
" </Template>\n" +
" <LoginConfigEntry name='" + Constants.WS_RESOURCE_LOGIN_MODULE +
"' type='" + RESOURCE_TYPE + "' displayName='" + LOGIN_MODULE + "'>\n" +
" <AuthnProperties>\n" +
" <AuthnProperty name='" + REFERER + "' formFieldType='text' dataSource='" + Constants.HTTP_HEADER_DATA_SOURCE+ "'/>\n" +
" <AuthnProperty name='" + USER + "' formFieldType='text' isId='true' dataSource='" + Constants.HTTP_REMOTE_USER_DATA_SOURCE + "'/>\n" +
" </AuthnProperties>\n" +
" <SupportedApplications>\n" +
" <SupportedApplication name='"+Constants.ADMINCONSOLE+"'/>\n" +
" <SupportedApplication name='"+Constants.SELFPROVISION+"'/>\n "+
" </SupportedApplications>\n" +
" </LoginConfigEntry>\n" +
"</Resource>\n";
public static Resource staticCreatePrototypeResource() throws WavesetException
{
Resource res = new Resource(prototypeXml);
return res;
}
public Resource createPrototypeResource() throws WavesetException
{
return staticCreatePrototypeResource();
}
public GenericObject getFeatures()
{
GenericObject genObj = new GenericObject();
genObj.put(ResourceAdapter.Features.ACCOUNT_CREATE, ResourceAdapter.Features.ACCOUNT_CREATE);
genObj.put(ResourceAdapter.Features.ACCOUNT_UPDATE, ResourceAdapter.Features.ACCOUNT_UPDATE);
genObj.put(ResourceAdapter.Features.ACCOUNT_DELETE, ResourceAdapter.Features.ACCOUNT_DELETE);
genObj.put(ResourceAdapter.Features.ACCOUNT_LOGIN, ResourceAdapter.Features.ACCOUNT_LOGIN);
genObj.put(ResourceAdapter.Features.ACCOUNT_ITERATOR, ResourceAdapter.Features.ACCOUNT_ITERATOR);
return genObj;
}
public WSUser getUser(WSUser user) throws WavesetException
{
final String method = "getUser";
if (_trace.level1(this,method))
{
_trace.entry(WSTrace.LEVEL1, this, method);
}
WSUser newUser = null;
String identity = null;
ResourceInfo resInfo = user.getResourceInfo(_resource);
if (resInfo != null && resInfo.isAccountCreated())
{
identity = resInfo.getAccountID();
if ((identity == null) || (identity.length() <= 0))
{
throw new WavesetException("No identity defined for User '" + user.getName() +
"' on Resource '" + _resource.getName() + "'.");
}
newUser = new WSUser();
newUser.setName(identity);
newUser.setAccountId(identity);
}
if (_trace.level1(this,method)) {
_trace.exit(WSTrace.LEVEL1, this, method);
}
return newUser;
}
public WavesetResult checkCreateAccount(WSUser user) throws WavesetException
{
final String method = "checkCreateAccount";
if (_trace.level1(this,method))
{
_trace.entry(_trace.LEVEL1, this, method, user.getName());
}
WavesetResult result = new WavesetResult();
if (_trace.level1(this,method))
{
_trace.exit(_trace.LEVEL1, this, method);
}
return result;
}
protected void realCreate(WSUser user, WavesetResult result) throws WavesetException
{
final String method = "realCreate";
if (_trace.level1(this,method))
{
_trace.entry(WSTrace.LEVEL1, this, method);
}
String dn = getIdentity(user);
ResourceInfo resInfo = user.getResourceInfo(_resource);
if (resInfo != null)
{
resInfo.setAccountCreated(true);
resInfo.setPassword((EncryptedData)null);
}
if (_trace.level3(this,method))
{
String msg = "Added user '" + dn + "'";
_trace.info(_trace.LEVEL3, this, method, msg);
}
if (_trace.level1(this,method))
{
_trace.exit(_trace.LEVEL1, this, method);
}
}
public WavesetResult checkUpdateAccount(WSUser user) throws WavesetException
{
final String method = "checkUpdateAccount";
if (_trace.level1(this,method))
{
_trace.entry(_trace.LEVEL1, this, method, user.getName());
}
WavesetResult result = new WavesetResult();
if (_trace.level1(this,method))
{
_trace.exit(_trace.LEVEL1, this, method);
}
return result;
}
protected void realUpdate(WSUser user, WavesetResult result) throws WavesetException
{
final String method = "realUpdate";
if (_trace.level1(this,method))
{
_trace.entry(_trace.LEVEL1, this, method, user.getName());
}
String dn = getIdentity(user);
if (_trace.level3(this,method))
{
_trace.info(_trace.LEVEL2, this, method, "Updating user '"+user+"'");
}
ResourceInfo resInfo = user.getResourceInfo(_resource);
if (resInfo != null)
{
resInfo.setPassword((EncryptedData)null);
}
}
public WavesetResult checkDeleteAccount(WSUser user) throws WavesetException
{
final String method = "checkDeleteAccount";
if (_trace.level1(this,method))
{
_trace.entry(_trace.LEVEL1, this, method, user.getName());
}
WavesetResult result = new WavesetResult();
String identity = getIdentity(user);
if (_trace.level1(this,method))
{
_trace.exit(_trace.LEVEL1, this, method);
}
return result;
}
protected void realDelete(WSUser user, WavesetResult result) throws WavesetException
{
final String method = "realDelete";
if (_trace.level1(this,method))
{
_trace.entry(_trace.LEVEL1, this, method, user.getName());
}
String dn = getIdentity(user);
}
public WSAttributes getAccountAttributes(String accountIdentity) throws WavesetException
{
final String method = "getAccountAttributes";
if (_trace.level1(this,method))
{
_trace.entry(_trace.LEVEL1, this, method);
}
WavesetResult result = new WavesetResult();
WSAttributes wsAttrs = null;
if (_trace.level1(this,method))
{
_trace.exit(_trace.LEVEL1, this, method);
}
return wsAttrs;
}
public AccountIterator getAccountIterator() throws WavesetException
{
final String method = "getAccountIterator";
if (_trace.level1(this,method))
_trace.entry(_trace.LEVEL1, this, method);
AccountIterator acctIter = null;
if (_trace.level1(this,method))
_trace.exit(_trace.LEVEL1, this, method);
return acctIter;
}
public WavesetResult authenticate(HashMap loginInfo) throws WavesetException
{
final String method = "authenticate";
if (_trace.level1(this,method))
{
_trace.entry(WSTrace.LEVEL1, this, method);
}
WavesetResult result = new WavesetResult();
String userId = (String)loginInfo.get(USER);
if(_trace.level2(this,method))
{
_trace.info(_trace.LEVEL2, this, method, USER + " = " + userId);
_trace.info(_trace.LEVEL2, this, method, "map: " + loginInfo);
}
if (_trace.level2(this,method))
{
_trace.info(_trace.LEVEL2, this, method, "Obtained user '" + userId + "' from info: " + String.valueOf(loginInfo));
}
String accountId = null;
if (userId != null)
{
HashMap conds = new HashMap();
conds.put(IDMATTR, userId);
List users = executeQuery(Type.USER, conds);
if(users != null && users.size() == 1)
{
accountId = ((RepositoryResult.Row)users.get(0)).getName();
if(_trace.level1(this,method))
_trace.info(_trace.LEVEL1, this, method, "found user with accountId=" + accountId);
}
else
{
if(_trace.level1(this,method))
_trace.info(_trace.LEVEL1, this, method, "couldn't find user with " + IDMATTR + "=" + userId);
}
}
if(accountId == null)
{
throw new WavesetException("Authentication failed using CAS");
}
else
{
result.addResult(Constants.AUTHENTICATED_IDENTITY, accountId);
}
return result;
}
protected void startConnection() throws WavesetException
{
}
protected void stopConnection() throws WavesetException
{
}
private GenericObject loadConfigData() throws WavesetException
{
if (_cache == null)
{
throw new WavesetException("Error looking up Configuration Object");
}
Configuration params =
(Configuration) _cache.getObject(Type.CONFIGURATION, CONFIG_OBJECT);
if (params == null)
{
throw new WavesetException("Configuration named " + CONFIG_OBJECT
+ " not found");
}
GenericObject configObject = (GenericObject) params.getExtension();
return configObject;
}
protected static List executeQuery(Type type, Map attributeMap)
throws com.waveset.util.WavesetException
{
return(executeQuery(type, new WSAttributes(attributeMap)));
}
protected static List executeQuery(Type type, WSAttributes wsattrs)
throws WavesetException
{
LinkedList foundRows = new LinkedList();
Repository repository = ServerRepository.getRepository(true);
RepositoryResult result = repository.list(type, wsattrs);
while(result != null && result.hasNext())
{
RepositoryResult.Row row = result.next();
foundRows.add(row);
}
return(foundRows);
}
}