/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.core.security;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.orcid.core.manager.OrcidSecurityManager;
import org.orcid.core.oauth.OrcidProfileUserDetails;
import org.orcid.jaxb.model.message.OrcidType;
import org.orcid.persistence.dao.EmailDao;
import org.orcid.persistence.dao.ProfileDao;
import org.orcid.persistence.jpa.entities.EmailEntity;
import org.orcid.persistence.jpa.entities.ProfileEntity;
import org.orcid.utils.OrcidStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Declan Newman (declan) Date: 13/02/2012
*/
public class OrcidUserDetailsService implements UserDetailsService {
@Resource
private ProfileDao profileDao;
@Resource
private EmailDao emailDao;
@Resource
private OrcidSecurityManager securityMgr;
@Value("${org.orcid.core.baseUri}")
private String baseUrl;
private static final Logger LOGGER = LoggerFactory.getLogger(OrcidUserDetailsService.class);
/**
* Locates the user based on the username. In the actual implementation, the
* search may possibly be case insensitive, or case insensitive depending on
* how the implementation instance is configured. In this case, the
* <code>UserDetails</code> object that comes back may have a username that
* is of a different case than what was actually requested..
*
* @param username
* the username identifying the user whose data is required.
* @return a fully populated user record (never <code>null</code>)
* @throws org.springframework.security.core.userdetails.UsernameNotFoundException
* if the user could not be found or the user has no
* GrantedAuthority
*/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LOGGER.info("About to load user by username = {}", username);
ProfileEntity profile = obtainEntity(username);
if (profile == null) {
throw new UsernameNotFoundException("Bad username or password");
}
if (profile.getPrimaryRecord() != null) {
throw new DeprecatedProfileException(
"orcid.frontend.security.deprecated_with_primary", profile
.getPrimaryRecord().getId(), profile.getId());
}
if (profile.getDeactivationDate() != null && !securityMgr.isAdmin()) {
throw new DisabledException("Account not active, please call helpdesk");
}
if (!profile.getClaimed() && !securityMgr.isAdmin()) {
throw new UnclaimedProfileExistsException("orcid.frontend.security.unclaimed_exists");
}
String primaryEmail = null;
// Clients doesnt have primary email, so, we need to cover that case.
if (profile.getPrimaryEmail() != null)
primaryEmail = profile.getPrimaryEmail().getId();
OrcidProfileUserDetails userDetails = null;
if (profile.getOrcidType() != null) {
OrcidType orcidType = OrcidType.fromValue(profile.getOrcidType().value());
userDetails = new OrcidProfileUserDetails(profile.getId(), primaryEmail, profile.getEncryptedPassword(), orcidType, profile.getGroupType());
} else {
userDetails = new OrcidProfileUserDetails(profile.getId(), primaryEmail, profile.getEncryptedPassword());
}
return userDetails;
}
private ProfileEntity obtainEntity(String username) {
ProfileEntity profile = null;
if (!StringUtils.isEmpty(username)) {
if (OrcidStringUtils.isValidOrcid(username)) {
profile = profileDao.find(username);
} else {
EmailEntity emailEntity = emailDao.findCaseInsensitive(username);
if (emailEntity != null) {
profile = emailEntity.getProfile();
}
}
}
return profile;
}
}