Thanks, Ben. Surely I didn' t give the ACL capability of Acegi the proper attention. Indeed, I was able to get things working using a similar approach to the Context modification: I wrote an adapter to the user retrieved by Authentication.getPrincipal() to store the contract id in connection with a Custom AuthenticationDao. The code is below.
Code:
//Created on 05/02/2005
package com.iservport.acegisecurity;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.iservport.admin.Authority;
import com.iservport.admin.Role;
import com.iservport.admin.User;
import com.iservport.admin.dao.ContractDao;
import com.iservport.admin.dao.ModeratorDao;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.UserDetails;
/**
* @author <a href="mauricio@iservport.com">Maurício Fernandes de Castro</a>
*/
public class PrincipalImpl implements UserDetails {
protected User user;
public PrincipalImpl(User user) {
this.user = user;
}
/**
* @return Returns the user.
*/
public User getUser() {
return user;
}
/**
* @param user The user to set.
*/
public void setUser(User user) {
this.user = user;
}
/* (non-Javadoc)
* @see net.sf.acegisecurity.UserDetails#getAuthorities()
*/
public GrantedAuthority[] getAuthorities() {
Set authorities = user.getAuthorities();
List list = new ArrayList();
for (Iterator it = authorities.iterator(); it.hasNext();) {
Role role = ((Authority) it.next()).getRole();
String roleToAuthority = "ROLE_"+role.getService().getServiceName()+"_"+role.getRoleName();
list.add(new GrantedAuthorityImpl(roleToAuthority));
}
return (GrantedAuthority[]) list.toArray(new GrantedAuthority[authorities.size()]);
}
/* (non-Javadoc)
* @see net.sf.acegisecurity.UserDetails#getPassword()
*/
public String getPassword() {
return this.user.getCredential().getPassword();
}
/* (non-Javadoc)
* @see net.sf.acegisecurity.UserDetails#getUsername()
*/
public String getUsername() {
return this.user.getCredential().getEmail();
}
/* (non-Javadoc)
* @see net.sf.acegisecurity.UserDetails#isAccountNonExpired()
*/
public boolean isAccountNonExpired() {
return (this.user.getContract().getStatus()==ContractDao.ACTIVE_CONTRACT);
}
/* (non-Javadoc)
* @see net.sf.acegisecurity.UserDetails#isCredentialsNonExpired()
*/
public boolean isCredentialsNonExpired() {
return true;
}
/* (non-Javadoc)
* @see net.sf.acegisecurity.UserDetails#isEnabled()
*/
public boolean isEnabled() {
return (this.getUser().getCredential().getState()==ModeratorDao.STATE_CONFIRMED);
}
}
So, when I need the Contract id, it is aggregated into User as user.getContract(). Here is the AuthenticationDao (ServiceAuthenticationDao is a super interface):
Code:
//Created on 05/02/2005
package com.iservport.acegisecurity;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
import com.iservport.admin.Credential;
import com.iservport.admin.Region;
import com.iservport.admin.User;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
/**
* @author <a href="mauricio@iservport.com">Maurício Fernandes de Castro </a>
*/
public class AuthenticationDaoImpl extends HibernateDaoSupport implements
ServiceAuthenticationDao {
private String regionName = "default";
private String serviceName = "research";
/* (non-Javadoc)
* @see com.iservport.acegisecurity.ServiceAuthenticationDao#getRegionName()
*/
public String getRegionName() {
return regionName;
}
/* (non-Javadoc)
* @see com.iservport.acegisecurity.ServiceAuthenticationDao#setRegionName(java.lang.String)
*/
public void setRegionName(String regionName) {
this.regionName = regionName;
}
/* (non-Javadoc)
* @see com.iservport.acegisecurity.ServiceAuthenticationDao#getServiceName()
*/
public String getServiceName() {
return serviceName;
}
/* (non-Javadoc)
* @see com.iservport.acegisecurity.ServiceAuthenticationDao#setServiceName(java.lang.String)
*/
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
/*
* (non-Javadoc)
*
* @see net.sf.acegisecurity.providers.dao.AuthenticationDao#loadUserByUsername(java.lang.String)
*/
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
// TODO enforce uniqueness in AuthenticationDaoImpl
Credential credential = (Credential) this.getHibernateTemplate().find(
"from Credential where email = ?", username).get(0);
if (credential == null) {
throw new UsernameNotFoundException("User not found!");
}
Region region = (Region) this.getHibernateTemplate().find(
"from Region where uniqueRegion = ?", regionName).get(0);
// TODO instead of first user contract, take preferred contract in AuthenticationDaoImpl
Object[] args = new Object[3];
args[0] = credential.getId();
args[1] = region.getLocale();
args[2] = serviceName;
List users = this.getHibernateTemplate().find(
"from User user where " + "user.credential.id = ? and "
+ "user.contract.service.locale = ? and "
+ "user.contract.service.serviceName = ?", args);
if (users != null && users.size()>0) {
PrincipalImpl principal = new PrincipalImpl((User) users.get(0));
return principal;
}
throw new UsernameNotFoundException("User not authorized!");
}
}
And that is it!
Thanks for the help.