/*
* Copyright (c) 2009-2011 Lockheed Martin Corporation
*
* 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.eurekastreams.server.service.security.userdetails;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eurekastreams.commons.actions.context.service.ServiceActionContext;
import org.eurekastreams.commons.actions.service.TaskHandlerServiceAction;
import org.eurekastreams.commons.server.service.ActionController;
import org.eurekastreams.server.domain.PersistentLogin;
import org.eurekastreams.server.domain.Person;
import org.eurekastreams.server.persistence.PersonMapper;
import org.eurekastreams.server.search.modelview.AuthenticationType;
import org.eurekastreams.server.service.security.jaas.JaasAuthenticationProviderWrapper;
import org.eurekastreams.server.service.security.persistentlogin.PersistentLoginRepository;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
/**
* Custom implementation of Spring's UserDetailsService interface. Loads user details from data store. Currently returns
* ExtendedUserDetails object that encapsulates Person and PersistentLogin information (plus the standard UserDetails
* stuff).
*
*/
public class UserDetailsServiceImpl implements UserDetailsService
{
/**
* Logger.
*/
private static Log log = LogFactory.getLog(JaasAuthenticationProviderWrapper.class);
/**
* Mapper for Person information.
*/
private final PersonMapper personMapper;
/**
* Mapper for PersistentLoginInformation.
*/
private final PersistentLoginRepository loginRepository;
/**
* The AuthorityProvider for this service to use.
*/
private final AuthorityProvider authorityProvider;
/**
* Authentication type.
*/
private AuthenticationType authenticationType = AuthenticationType.NOTSET;
/**
* {@link ActionController}.
*/
private final ActionController serviceActionController;
/**
* Action to create user from LDAP.
*/
private final TaskHandlerServiceAction createUserfromLdapAction;
/**
* This username will short circut and fail fast.
*/
private final String bypassUserName = "<NOTSET>";
/**
* Constructor.
*
* @param inPersonMapper
* The PersonMapper.
* @param inPersistentLoginRepository
* The PersistentLoginMapper.
* @param inAuthorityProvider
* The AuthorityProvider to use.
* @param inServiceActionController
* {@link ActionController}.
* @param inCreateUserfromLdapAction
* Action to create user from LDAP.
*/
public UserDetailsServiceImpl(final PersonMapper inPersonMapper,
final PersistentLoginRepository inPersistentLoginRepository, final AuthorityProvider inAuthorityProvider,
final ActionController inServiceActionController, final TaskHandlerServiceAction inCreateUserfromLdapAction)
{
Assert.notNull(inPersonMapper);
personMapper = inPersonMapper;
loginRepository = inPersistentLoginRepository;
authorityProvider = inAuthorityProvider;
serviceActionController = inServiceActionController;
createUserfromLdapAction = inCreateUserfromLdapAction;
}
/**
* Returns populated UserDetails object for user.
*
* @param username
* The username.
* @return Populated UserDetails object for user.
*/
@Override
public UserDetails loadUserByUsername(final String username)
{
if (bypassUserName.equalsIgnoreCase(username))
{
String errorMessage = "Configured to skip loading user details for " + username;
log.debug(errorMessage);
throw new UsernameNotFoundException(errorMessage);
}
Person person = null;
PersistentLogin login = null;
List<GrantedAuthority> authorities = null;
try
{
person = personMapper.findByAccountId(username);
login = (loginRepository == null) ? null : loginRepository.getPersistentLogin(username);
authorities = (authorityProvider == null) ? new ArrayList<GrantedAuthority>(0) : authorityProvider
.loadAuthoritiesByUsername(username);
// if user not found in DB, try to create from LDAP
if (person == null)
{
person = (Person) serviceActionController.execute(new ServiceActionContext(username, null),
createUserfromLdapAction);
}
}
catch (Exception e)
{
String errorMessage = "Error loading user details for: " + username;
log.error(errorMessage + " " + e.getMessage());
throw new DataRetrievalFailureException(errorMessage, e);
}
// If user still not found, give up.
if (person == null)
{
String errorMessage = "User not found: " + username;
log.info(errorMessage);
throw new UsernameNotFoundException(errorMessage);
}
return new ExtendedUserDetailsImpl(person, login,
authorities.toArray(new GrantedAuthority[authorities.size()]), authenticationType);
}
/**
* @param inAuthenticationType
* the authenticationType to set
*/
public void setAuthenticationType(final AuthenticationType inAuthenticationType)
{
authenticationType = inAuthenticationType;
}
}