/* Copyright 2004 Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jetspeed.security.impl;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.security.auth.Subject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jetspeed.i18n.KeyedMessage;
import org.apache.jetspeed.security.AuthenticationProviderProxy;
import org.apache.jetspeed.security.HierarchyResolver;
import org.apache.jetspeed.security.SecurityException;
import org.apache.jetspeed.security.SecurityProvider;
import org.apache.jetspeed.security.User;
import org.apache.jetspeed.security.UserManager;
import org.apache.jetspeed.security.UserPrincipal;
import org.apache.jetspeed.security.spi.SecurityMappingHandler;
import org.apache.jetspeed.util.ArgUtil;
/**
* <p>
* Implementation for managing users and provides access to the {@link User}.
* </p>
*
* @author <a href="mailto:dlestrat@apache.org">David Le Strat </a>
* @version $Id: UserManagerImpl.java,v 1.20 2005/03/27 22:38:28 ate Exp $
*/
public class UserManagerImpl implements UserManager
{
private static final Log log = LogFactory.getLog(UserManagerImpl.class);
/** The authenticatino provider proxy. */
private AuthenticationProviderProxy atnProviderProxy = null;
/** The security mapping handler. */
private SecurityMappingHandler securityMappingHandler = null;
private String anonymousUser = "guest";
/**
* @param securityProvider
* The security provider.
*/
public UserManagerImpl(SecurityProvider securityProvider)
{
this.atnProviderProxy = securityProvider
.getAuthenticationProviderProxy();
this.securityMappingHandler = securityProvider
.getSecurityMappingHandler();
}
/**
* @param securityProvider
* The security provider.
* @param anonymousUser
* The anonymous user name
*/
public UserManagerImpl(SecurityProvider securityProvider,
String anonymousUser)
{
this.atnProviderProxy = securityProvider
.getAuthenticationProviderProxy();
this.securityMappingHandler = securityProvider
.getSecurityMappingHandler();
if (anonymousUser != null)
{
this.anonymousUser = anonymousUser;
}
}
/**
* @param securityProvider
* The security provider.
* @param roleHierarchyResolver
* The role hierachy resolver.
* @param groupHierarchyResolver
* The group hierarchy resolver.
*/
public UserManagerImpl(SecurityProvider securityProvider,
HierarchyResolver roleHierarchyResolver,
HierarchyResolver groupHierarchyResolver)
{
securityProvider.getSecurityMappingHandler().setRoleHierarchyResolver(
roleHierarchyResolver);
securityProvider.getSecurityMappingHandler().setGroupHierarchyResolver(
groupHierarchyResolver);
this.atnProviderProxy = securityProvider
.getAuthenticationProviderProxy();
this.securityMappingHandler = securityProvider
.getSecurityMappingHandler();
}
/**
* @param securityProvider
* The security provider.
* @param roleHierarchyResolver
* The role hierachy resolver.
* @param groupHierarchyResolver
* The group hierarchy resolver.
* @param anonymousUser
* The anonymous user name
*/
public UserManagerImpl(SecurityProvider securityProvider,
HierarchyResolver roleHierarchyResolver,
HierarchyResolver groupHierarchyResolver, String anonymousUser)
{
securityProvider.getSecurityMappingHandler().setRoleHierarchyResolver(
roleHierarchyResolver);
securityProvider.getSecurityMappingHandler().setGroupHierarchyResolver(
groupHierarchyResolver);
this.atnProviderProxy = securityProvider
.getAuthenticationProviderProxy();
this.securityMappingHandler = securityProvider
.getSecurityMappingHandler();
if (anonymousUser != null)
{
this.anonymousUser = anonymousUser;
}
}
/*
* (non-Javadoc)
*
* @see org.apache.jetspeed.security.UserManager#getAnonymousUser()
*/
public String getAnonymousUser()
{
return this.anonymousUser;
}
/**
* @see org.apache.jetspeed.security.UserManager#authenticate(java.lang.String,
* java.lang.String)
*/
public boolean authenticate(String username, String password)
{
ArgUtil.notNull(new Object[]
{ username, password}, new String[]
{ "username", "password"},
"authenticate(java.lang.String, java.lang.String)");
boolean authenticated = false;
try
{
if (!getAnonymousUser().equals(username))
{
authenticated = atnProviderProxy.authenticate(username,
password);
if (authenticated && log.isDebugEnabled())
{
log.debug("Authenticated user: " + username);
}
}
} catch (SecurityException e)
{
// ignore: not authenticated
}
return authenticated;
}
/**
* @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
* java.lang.String)
*/
public void addUser(String username, String password)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username}, new String[]
{ "username"}, "addUser(java.lang.String, java.lang.String)");
addUser(username, password, atnProviderProxy
.getDefaultAuthenticationProvider());
}
/**
* @see org.apache.jetspeed.security.UserManager#addUser(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void addUser(String username, String password, String atnProviderName)
throws SecurityException
{
ArgUtil
.notNull(new Object[]
{ username, atnProviderName}, new String[]
{ "username", "atnProviderName"},
"addUser(java.lang.String, java.lang.String, java.lang.String)");
if (getAnonymousUser().equals(username)) { throw new SecurityException(
SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
// Check if user already exists.
if (userExists(username)) {
throw new SecurityException(SecurityException.USER_ALREADY_EXISTS.create(username));
}
UserPrincipal userPrincipal = new UserPrincipalImpl(username);
String fullPath = userPrincipal.getFullPath();
// Add the preferences.
Preferences preferences = Preferences.userRoot().node(fullPath);
if (log.isDebugEnabled())
{
log.debug("Added user preferences node: " + fullPath);
}
try
{
if ((null != preferences)
&& preferences.absolutePath().equals(fullPath))
{
// Add user principal.
atnProviderProxy.addUserPrincipal(userPrincipal);
if (password != null)
{
try
{
// Set private password credential
atnProviderProxy.setPassword(username, null, password,atnProviderName);
}
catch (SecurityException se1)
{
try
{
// rollback created user
atnProviderProxy.removeUserPrincipal(userPrincipal);
}
catch (SecurityException se2)
{
log.error("Failed to rollback created user after its password turned out to be invalid", se2);
}
throw se1;
}
}
if (log.isDebugEnabled())
{
log.debug("Added user: " + fullPath);
}
}
} catch (SecurityException se)
{
log.error(se.getMessage(), se);
// Remove the preferences node.
try
{
preferences.removeNode();
} catch (BackingStoreException bse)
{
bse.printStackTrace();
}
throw se;
}
}
/**
* @see org.apache.jetspeed.security.UserManager#removeUser(java.lang.String)
*
* TODO Enforce that only administrators can do this.
*/
public void removeUser(String username) throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username}, new String[]
{ "username"}, "removeUser(java.lang.String)");
if (getAnonymousUser().equals(username)) { throw new SecurityException(
SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
UserPrincipal userPrincipal = new UserPrincipalImpl(username);
String fullPath = userPrincipal.getFullPath();
atnProviderProxy.removeUserPrincipal(userPrincipal);
// Remove preferences
Preferences preferences = Preferences.userRoot().node(fullPath);
try
{
preferences.removeNode();
} catch (BackingStoreException bse)
{
bse.printStackTrace();
}
}
/**
* @see org.apache.jetspeed.security.UserManager#userExists(java.lang.String)
*/
public boolean userExists(String username)
{
ArgUtil.notNull(new Object[]
{ username}, new String[]
{ "username"}, "userExists(java.lang.String)");
return atnProviderProxy.getUserPrincipal(username) != null;
}
/**
* @see org.apache.jetspeed.security.UserManager#getUser(java.lang.String)
*/
public User getUser(String username) throws SecurityException
{
ArgUtil.notNull(new Object[]
{ username}, new String[]
{ "username"}, "getUser(java.lang.String)");
Set principals = new HashSet();
String fullPath = (new UserPrincipalImpl(username)).getFullPath();
Principal userPrincipal = atnProviderProxy.getUserPrincipal(username);
if (null == userPrincipal) {
throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
}
principals.add(userPrincipal);
principals.addAll(securityMappingHandler.getRolePrincipals(username));
principals.addAll(securityMappingHandler.getGroupPrincipals(username));
Subject subject = null;
if (getAnonymousUser().equals(username))
{
subject = new Subject(true, principals, new HashSet(),
new HashSet());
} else
{
subject = new Subject(true, principals, atnProviderProxy
.getPublicCredentials(username), atnProviderProxy
.getPrivateCredentials(username));
}
Preferences preferences = Preferences.userRoot().node(fullPath);
User user = new UserImpl(subject, preferences);
return user;
}
/**
* @see org.apache.jetspeed.security.UserManager#getUsers(java.lang.String)
*/
public Iterator getUsers(String filter) throws SecurityException
{
List users = new LinkedList();
Iterator userPrincipals = atnProviderProxy.getUserPrincipals(filter)
.iterator();
while (userPrincipals.hasNext())
{
String username = ((Principal) userPrincipals.next()).getName();
User user = getUser(username);
users.add(user);
}
return users.iterator();
}
/**
* @see org.apache.jetspeed.security.UserManager#getUsersInRole(java.lang.String)
*/
public Collection getUsersInRole(String roleFullPathName)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ roleFullPathName}, new String[]
{ "roleFullPathName"}, "getUsersInRole(java.lang.String)");
Collection users = new ArrayList();
Set userPrincipals = securityMappingHandler
.getUserPrincipalsInRole(roleFullPathName);
Iterator userPrincipalsIter = userPrincipals.iterator();
while (userPrincipalsIter.hasNext())
{
Principal userPrincipal = (Principal) userPrincipalsIter.next();
users.add(getUser(userPrincipal.getName()));
}
return users;
}
/**
* @see org.apache.jetspeed.security.UserManager#getUsersInGroup(java.lang.String)
*/
public Collection getUsersInGroup(String groupFullPathName)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ groupFullPathName}, new String[]
{ "groupFullPathName"}, "getUsersInGroup(java.lang.String)");
Collection users = new ArrayList();
Set userPrincipals = securityMappingHandler
.getUserPrincipalsInGroup(groupFullPathName);
Iterator userPrincipalsIter = userPrincipals.iterator();
while (userPrincipalsIter.hasNext())
{
Principal userPrincipal = (Principal) userPrincipalsIter.next();
users.add(getUser(userPrincipal.getName()));
}
return users;
}
/**
* @see org.apache.jetspeed.security.UserManager#setPassword(java.lang.String,
* java.lang.String, java.lang.String)
*
* TODO Enforce that only administrators can do this.
*/
public void setPassword(String username, String oldPassword,
String newPassword) throws SecurityException
{
ArgUtil
.notNull(new Object[]
{ username, newPassword}, new String[]
{ "username", "newPassword"},
"setPassword(java.lang.String, java.lang.String, java.lang.String)");
if (getAnonymousUser().equals(username)) { throw new SecurityException(
SecurityException.ANONYMOUS_USER_PROTECTED.create(username)); }
atnProviderProxy.setPassword(username, oldPassword, newPassword);
}
/**
* @see org.apache.jetspeed.security.UserManager#setPasswordEnabled(java.lang.String,
* boolean)
*/
public void setPasswordEnabled(String userName, boolean enabled)
throws SecurityException
{
ArgUtil.notNull(new Object[]
{ userName,}, new String[]
{ "userName"}, "setPasswordEnabled(java.lang.String, boolean)");
if (getAnonymousUser().equals(userName)) { throw new SecurityException(
SecurityException.ANONYMOUS_USER_PROTECTED.create(userName)); }
atnProviderProxy.setPasswordEnabled(userName, enabled);
}
/**
* @see org.apache.jetspeed.security.UserManager#setPasswordUpdateRequired(java.lang.String,
* boolean)
*/
public void setPasswordUpdateRequired(String userName,
boolean updateRequired) throws SecurityException
{
ArgUtil.notNull(new Object[]
{ userName,}, new String[]
{ "userName"}, "setPasswordUpdateRequired(java.lang.String, boolean)");
if (getAnonymousUser().equals(userName)) { throw new SecurityException(
SecurityException.ANONYMOUS_USER_PROTECTED.create(userName)); }
atnProviderProxy.setPasswordUpdateRequired(userName, updateRequired);
}
}