/*
* Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) and
* Steven Grimm <koreth[remove] at midwinter dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: DatabaseUsers.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.authentication.credentialsmanagers;
import com.uwyn.rife.authentication.credentialsmanagers.exceptions.*;
import com.uwyn.rife.database.*;
import com.uwyn.rife.database.queries.*;
import com.uwyn.rife.authentication.Credentials;
import com.uwyn.rife.authentication.CredentialsManager;
import com.uwyn.rife.authentication.PasswordEncrypting;
import com.uwyn.rife.authentication.credentials.RoleUserCredentials;
import com.uwyn.rife.authentication.exceptions.CredentialsManagerException;
import com.uwyn.rife.database.exceptions.DatabaseException;
import com.uwyn.rife.tools.exceptions.InnerClassException;
import com.uwyn.rife.tools.StringEncryptor;
import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.SQLException;
public abstract class DatabaseUsers extends DbQueryManager implements CredentialsManager, RoleUsersManager, PasswordEncrypting
{
protected StringEncryptor mPasswordEncryptor = null;
protected DatabaseUsers(Datasource datasource)
{
super(datasource);
}
public abstract boolean install()
throws CredentialsManagerException;
public abstract boolean remove()
throws CredentialsManagerException;
public StringEncryptor getPasswordEncryptor()
{
return mPasswordEncryptor;
}
public void setPasswordEncryptor(StringEncryptor passwordEncryptor)
{
mPasswordEncryptor = passwordEncryptor;
}
protected boolean _install(final CreateSequence createSequenceRole, final CreateTable createTableRole, final CreateTable createTableUser, final CreateTable createTableRoleLink)
throws CredentialsManagerException
{
assert createSequenceRole != null;
assert createTableRole != null;
assert createTableUser != null;
assert createTableRoleLink != null;
try
{
executeUpdate(createSequenceRole);
executeUpdate(createTableRole);
executeUpdate(createTableUser);
executeUpdate(createTableRoleLink);
}
catch (DatabaseException e)
{
throw new InstallCredentialsErrorException(e);
}
return true;
}
protected boolean _remove(final DropSequence dropSequenceRole, final DropTable dropTableRole, final DropTable dropTableUser, final DropTable dropTableRoleLink)
throws CredentialsManagerException
{
assert dropSequenceRole != null;
assert dropTableRole != null;
assert dropTableUser != null;
assert dropTableRoleLink != null;
try
{
executeUpdate(dropTableRoleLink);
executeUpdate(dropTableUser);
executeUpdate(dropTableRole);
executeUpdate(dropSequenceRole);
}
catch (DatabaseException e)
{
throw new RemoveCredentialsErrorException(e);
}
return true;
}
protected long _verifyCredentials(Select verifyCredentialsNoRole, Select verifyCredentialsRole, Credentials credentials)
throws CredentialsManagerException
{
assert verifyCredentialsNoRole != null;
assert verifyCredentialsRole != null;
if (null == credentials)
{
return -1;
}
long result = -1;
RoleUserCredentials role_user = null;
if (credentials instanceof RoleUserCredentials)
{
role_user = (RoleUserCredentials)credentials;
}
else
{
throw new UnsupportedCredentialsTypeException(credentials);
}
try
{
Select query = null;
// check if the role should be verified too and get the appropriate query
if (null == role_user.getRole())
{
query = verifyCredentialsNoRole;
}
else
{
query = verifyCredentialsRole;
}
ProcessVerifyCredentials process_verify_credentials = new ProcessVerifyCredentials();
if (executeFetchFirst(query, process_verify_credentials, new DbPreparedStatementHandler<RoleUserCredentials>(role_user) {
public void setParameters(DbPreparedStatement statement)
{
statement.setString("login", mData.getLogin());
// handle automatic password encoding
if (null == mPasswordEncryptor)
{
statement.setString("passwd", mData.getPassword());
}
else
{
try
{
statement.setString("passwd", mPasswordEncryptor.encrypt(mData.getPassword()));
}
catch (NoSuchAlgorithmException e)
{
throw new DatabaseException(e);
}
}
// set the role if that's required
if (mData.getRole() != null)
{
statement.setString("role", mData.getRole());
}
}
}))
{
result = process_verify_credentials.getUserId();
}
}
catch (DatabaseException e)
{
throw new VerifyCredentialsErrorException(credentials, e);
}
return result;
}
protected void _addRole(final SequenceValue getRoleId, final Insert addRole, final String role)
throws CredentialsManagerException
{
assert getRoleId != null;
assert addRole != null;
if (null == role ||
0 == role.length())
{
throw new AddRoleErrorException(role);
}
try
{
try
{
inTransaction(new DbTransactionUserWithoutResult() {
public void useTransactionWithoutResult()
throws InnerClassException
{
// get the id of the new role
final int role_id = executeGetFirstInt(getRoleId);
if (-1 == role_id)
{
throwException(new AddRoleErrorException(role));
}
// store the new role with the obtained id
if (0 == executeUpdate(addRole, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setInt("roleId", role_id)
.setString("name", role);
}
}))
{
throwException(new AddRoleErrorException(role));
}
}});
}
catch (InnerClassException e)
{
throw (CredentialsManagerException)e.getCause();
}
}
catch (DatabaseException e)
{
throw new AddRoleErrorException(role, e);
}
}
protected boolean _containsRole(Select containsRole, final String role)
throws CredentialsManagerException
{
assert containsRole != null;
if (null == role ||
0 == role.length())
{
return false;
}
boolean result = false;
try
{
result = executeHasResultRows(containsRole, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("name", role);
}
});
}
catch (DatabaseException e)
{
throw new ContainsRoleErrorException(role, e);
}
return result;
}
protected long _countRoles(Select countRoles)
throws CredentialsManagerException
{
assert countRoles != null;
try
{
return executeGetFirstLong(countRoles);
}
catch (DatabaseException e)
{
throw new CountRolesErrorException(e);
}
}
protected boolean _listRoles(Select listRolesQuery, ListRoles processor)
throws CredentialsManagerException
{
assert listRolesQuery != null;
if (null == processor)
{
return false;
}
boolean result = false;
try
{
result = executeFetchAll(listRolesQuery, new ListDatabaseRoles(processor));
}
catch (DatabaseException e)
{
throw new ListRolesErrorException(e);
}
return result;
}
protected void _addUser(final Insert addUserWithId, final Select getFreeUserId, final Select getRoleId, final Insert addRoleLink, final String login, final RoleUserAttributes attributes)
throws CredentialsManagerException
{
assert addUserWithId != null;
assert getFreeUserId != null;
assert getRoleId != null;
assert addRoleLink != null;
if (null == login ||
0 == login.length() ||
null == attributes)
{
throw new AddUserErrorException(login, attributes);
}
try
{
try
{
inTransaction(new DbTransactionUserWithoutResult() {
public void useTransactionWithoutResult()
throws InnerClassException
{
// ensure that the password is encoded if an encoder has been set
String password = null;
if (null == mPasswordEncryptor ||
attributes.getPassword().startsWith(mPasswordEncryptor.toString()))
{
password = attributes.getPassword();
}
else
{
try
{
password = mPasswordEncryptor.encrypt(attributes.getPassword());
}
catch (NoSuchAlgorithmException e)
{
throwException(new AddUserErrorException(login, attributes, e));
}
}
synchronized (getFreeUserId)
{
final String adapted_password = password;
// get a new user id if it has not been provided
if (attributes.getUserId() < 0)
{
attributes.setUserId(executeGetFirstLong(getFreeUserId));
}
if (0 == executeUpdate(addUserWithId, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setLong("userId", attributes.getUserId())
.setString("login", login)
.setString("passwd", adapted_password);
}
}))
{
throwException(new AddUserErrorException(login, attributes));
}
}
// assign the correct roles to the user
if (attributes.getRoles() != null)
{
// insert the role link
if (0 == executeUpdate(addRoleLink, new DbPreparedStatementHandler() {
public int performUpdate(DbPreparedStatement statement)
{
for (String role : attributes.getRoles())
{
// obtain the role id
int roleid = executeGetFirstInt(getRoleId, new DbPreparedStatementHandler<String>(role) {
public void setParameters(DbPreparedStatement statement)
{
statement.setString("name", mData);
}
});
if (-1 == roleid)
{
throw new UnknownRoleErrorException(role, login, attributes);
}
statement
.setLong("userId", attributes.getUserId())
.setInt("roleId", roleid);
if (0 == statement.executeUpdate())
{
return 0;
}
statement.clearParameters();
}
return 1;
}
}))
{
throwException(new AddUserErrorException(login, attributes));
}
}
}});
}
catch (InnerClassException e)
{
throw (CredentialsManagerException)e.getCause();
}
}
catch (DatabaseException e)
{
throw new AddUserErrorException(login, attributes, e);
}
}
protected RoleUserAttributes _getAttributes(Select getAttributes, Select getUserRoles, final String login)
throws CredentialsManagerException
{
assert getAttributes != null;
assert getUserRoles != null;
if (null == login ||
0 == login.length())
{
return null;
}
RoleUserAttributes attributes = null;
try
{
attributes = executeFetchFirstBean(getAttributes, RoleUserAttributes.class, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("login", login);
}
});
if (attributes != null)
{
final long userid = attributes.getUserId();
RoleFetcher fetcher = new RoleFetcher(attributes);
executeFetchAll(getUserRoles, fetcher, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setLong("userId", userid);
}
});
}
}
catch (DatabaseException e)
{
throw new GetAttributesErrorException(login, e);
}
return attributes;
}
protected class RoleFetcher extends DbRowProcessor
{
private RoleUserAttributes mAttributes = null;
public RoleFetcher(RoleUserAttributes attributes)
{
mAttributes = attributes;
}
public boolean processRow(ResultSet resultSet)
throws SQLException
{
mAttributes.addRole(resultSet.getString("name"));
return true;
}
}
protected boolean _containsUser(Select containsUser, final String login)
throws CredentialsManagerException
{
assert containsUser != null;
if (null == login ||
0 == login.length())
{
return false;
}
boolean result = false;
try
{
result = executeHasResultRows(containsUser, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("login", login);
}
});
}
catch (DatabaseException e)
{
throw new ContainsUserErrorException(login, e);
}
return result;
}
protected long _countUsers(Select countUsers)
throws CredentialsManagerException
{
assert countUsers != null;
long result = -1;
try
{
result = executeGetFirstLong(countUsers);
}
catch (DatabaseException e)
{
throw new CountUsersErrorException(e);
}
return result;
}
protected String _getLogin(Select getLogin, final long userId)
throws CredentialsManagerException
{
assert getLogin != null;
if (userId < 0)
{
return null;
}
String result = null;
try
{
result = executeGetFirstString(getLogin, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setLong("userId", userId);
}
});
}
catch (DatabaseException e)
{
throw new GetLoginErrorException(e, userId);
}
return result;
}
protected long _getUserId(Select getUserId, final String login)
throws CredentialsManagerException
{
assert getUserId != null;
if (null == login ||
0 == login.length())
{
return -1;
}
long result = -1;
try
{
result = executeGetFirstLong(getUserId, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("login", login);
}
});
}
catch (DatabaseException e)
{
throw new GetUserIdErrorException(e, login);
}
return result;
}
protected boolean _listUsers(Select listUsersQuery, ListUsers processor)
throws CredentialsManagerException
{
assert listUsersQuery != null;
if (null == processor)
{
return false;
}
boolean result = false;
try
{
ListDatabaseUsers row_processor = new ListDatabaseUsers(processor);
result = executeFetchAll(listUsersQuery, row_processor);
}
catch (DatabaseException e)
{
throw new ListUsersErrorException(e);
}
return result;
}
protected boolean _listUsers(Select listUsersRangedQuery, ListUsers processor, final int limit, final int offset)
throws CredentialsManagerException
{
assert listUsersRangedQuery != null;
if (null == processor ||
limit <= 0)
{
return false;
}
boolean result = false;
try
{
ListDatabaseUsers row_processor = new ListDatabaseUsers(processor);
result = executeFetchAll(listUsersRangedQuery, row_processor, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setInt("limit", limit)
.setInt("offset", offset);
}
});
}
catch (DatabaseException e)
{
throw new ListUsersErrorException(e);
}
return result;
}
protected boolean _isUserInRole(Select isUserInRole, final long userId, final String role)
throws CredentialsManagerException
{
assert isUserInRole != null;
if (userId < 0 ||
null == role ||
0 == role.length())
{
return false;
}
boolean result = false;
try
{
result = executeHasResultRows(isUserInRole, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setLong("userId", userId)
.setString("role", role);
}
});
}
catch (DatabaseException e)
{
throw new IsUserInRoleErrorException(userId, role, e);
}
return result;
}
protected boolean _listUsersInRole(Select listUsersInRole, ListUsers processor, final String role)
throws CredentialsManagerException
{
assert listUsersInRole != null;
if (null == processor)
{
return false;
}
if (null == role ||
0 == role.length())
{
return false;
}
boolean result = false;
try
{
ListDatabaseUsers row_processor = new ListDatabaseUsers(processor);
result = executeFetchAll(listUsersInRole, row_processor, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("role", role);
}
});
}
catch (DatabaseException e)
{
throw new ListUsersErrorException(e);
}
return result;
}
protected boolean _updateUser(final Update updateUser, final Delete removeRoleLinksByUser, final Select getRoleId, final Insert addRoleLink, final String login, final RoleUserAttributes attributes)
throws CredentialsManagerException
{
assert updateUser != null;
assert removeRoleLinksByUser != null;
assert getRoleId != null;
assert addRoleLink != null;
if (null == login ||
0 == login.length() ||
null == attributes)
{
throw new UpdateUserErrorException(login, attributes);
}
boolean result = false;
try
{
try
{
result = ((Boolean)inTransaction(new DbTransactionUser() {
public Boolean useTransaction()
throws InnerClassException
{
// obtain the user id
try
{
final long userid = getUserId(login);
if (userid < 0)
{
throwException(new UpdateUserErrorException(login, attributes));
}
// only handle the password if it has been provided
if (attributes.getPassword() != null)
{
// ensure that the password is encoded if an encoder has been set
String password = null;
if (null == mPasswordEncryptor ||
attributes.getPassword().startsWith(mPasswordEncryptor.toString()))
{
password = attributes.getPassword();
}
else
{
try
{
password = mPasswordEncryptor.encrypt(attributes.getPassword());
}
catch (NoSuchAlgorithmException e)
{
throwException(new UpdateUserErrorException(login, attributes, e));
}
}
// update the user password
final String adapted_password = password;
if (0 == executeUpdate(updateUser, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("passwd", adapted_password)
.setString("login", login);
}
}))
{
// no update was performed
return false;
}
}
// remove the previous roles
executeUpdate(removeRoleLinksByUser, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setLong("userId", userid);
}
});
// assign the correct roles to the user
if (attributes.getRoles() != null)
{
if (0 == executeUpdate(addRoleLink, new DbPreparedStatementHandler() {
public int performUpdate(DbPreparedStatement statement)
{
for (String role : attributes.getRoles())
{
// obtain the role id
int roleid = executeGetFirstInt(getRoleId, new DbPreparedStatementHandler<String>(role) {
public void setParameters(DbPreparedStatement statement)
{
statement.setString("name", mData);
}
});
if (-1 == roleid)
{
throwException(new UnknownRoleErrorException(role, login, attributes));
}
statement
.setLong("userId", userid)
.setInt("roleId", roleid);
if (0 == statement.executeUpdate())
{
return 0;
}
statement.clearParameters();
}
return 1;
}
}))
{
throwException(new UpdateUserErrorException(login, attributes));
}
}
}
catch (CredentialsManagerException e)
{
throwException(new UpdateUserErrorException(login, attributes, e));
}
// update was successful
return true;
}})).booleanValue();
}
catch (InnerClassException e)
{
throw (CredentialsManagerException)e.getCause();
}
}
catch (DatabaseException e)
{
throw new UpdateUserErrorException(login, attributes, e);
}
return result;
}
protected boolean _removeUser(Delete removeUserByLogin, final String login)
throws CredentialsManagerException
{
assert removeUserByLogin != null;
if (null == login ||
0 == login.length())
{
return false;
}
boolean result = false;
try
{
if (0 != executeUpdate(removeUserByLogin, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("login", login);
}
}))
{
result = true;
}
}
catch (DatabaseException e)
{
throw new RemoveUserErrorException(login, e);
}
return result;
}
protected boolean _removeUser(Delete removeUserByUserId, final long userId)
throws CredentialsManagerException
{
assert removeUserByUserId != null;
if (userId < 0)
{
return false;
}
boolean result = false;
try
{
if (0 != executeUpdate(removeUserByUserId, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setLong("userId", userId);
}
}))
{
result = true;
}
}
catch (DatabaseException e)
{
throw new RemoveUserErrorException(userId, e);
}
return result;
}
protected boolean _removeRole(Delete removeRole, final String name)
throws CredentialsManagerException
{
assert removeRole != null;
if (null == name ||
0 == name.length())
{
return false;
}
boolean result = false;
try
{
if (0 != executeUpdate(removeRole, new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("role", name);
}
}))
{
result = true;
}
}
catch (DatabaseException e)
{
throw new RemoveRoleErrorException(name, e);
}
return result;
}
protected void _clearUsers(Delete clearUsers)
throws CredentialsManagerException
{
assert clearUsers != null;
try
{
executeUpdate(clearUsers);
}
catch (DatabaseException e)
{
throw new ClearUsersErrorException(e);
}
}
protected boolean _listUserRoles(Select listUserRolesQuery, final String login, final ListRoles processor)
throws CredentialsManagerException
{
assert listUserRolesQuery != null;
if (null == processor)
{
return false;
}
boolean result = false;
try
{
result = executeFetchAll(listUserRolesQuery, new ListDatabaseRoles(processor), new DbPreparedStatementHandler() {
public void setParameters(DbPreparedStatement statement)
{
statement
.setString("login", login);
}
});
}
catch (DatabaseException e)
{
throw new ListRolesErrorException(e);
}
return result;
}
protected class ProcessVerifyCredentials extends DbRowProcessor
{
private long mUserId = -1;
public boolean processRow(ResultSet resultSet)
throws SQLException
{
assert resultSet != null;
mUserId = resultSet.getLong(1);
return true;
}
public long getUserId()
{
return mUserId;
}
}
protected static class ListDatabaseRoles extends DbRowProcessor
{
private ListRoles mListRoles = null;
public ListDatabaseRoles(ListRoles listRoles)
{
mListRoles = listRoles;
}
public boolean processRow(ResultSet resultSet)
throws SQLException
{
return mListRoles.foundRole(resultSet.getString("name"));
}
}
protected static class ListDatabaseUsers extends DbRowProcessor
{
private ListUsers mListUsers = null;
public ListDatabaseUsers(ListUsers listUsers)
{
mListUsers = listUsers;
}
public boolean processRow(ResultSet resultSet)
throws SQLException
{
return mListUsers.foundUser(resultSet.getLong("userId"), resultSet.getString("login"), resultSet.getString("passwd"));
}
}
}