package org.ei.drishti.web.security;
import ch.lambdaj.Lambda;
import ch.lambdaj.function.convert.Converter;
import org.ei.drishti.domain.DrishtiUser;
import org.ei.drishti.repository.AllDrishtiUsers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.List;
import static java.text.MessageFormat.format;
@Component
public class DrishtiAuthenticationProvider implements AuthenticationProvider {
private static Logger logger = LoggerFactory.getLogger(DrishtiAuthenticationProvider.class.toString());
public static final String USER_NOT_FOUND = "The username or password you entered is incorrect. Please enter the correct credentials.";
public static final String USER_NOT_ACTIVATED = "The user has been registered but not activated. Please contact your local administrator.";
public static final String INTERNAL_ERROR = "Failed to authenticate user due to internal server error.";
private AllDrishtiUsers allDrishtiUsers;
private PasswordEncoder passwordEncoder;
@Autowired
public DrishtiAuthenticationProvider(AllDrishtiUsers allDrishtiUsers, @Qualifier("shaPasswordEncoder") PasswordEncoder passwordEncoder) {
this.allDrishtiUsers = allDrishtiUsers;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
DrishtiUser user = getDrishtiUser(authentication);
if (user == null) {
throw new BadCredentialsException(USER_NOT_FOUND);
}
String credentials = (String) authentication.getCredentials();
String hashedCredentials = passwordEncoder.encodePassword(credentials, user.getSalt());
if (!user.getPassword().equals(hashedCredentials)) {
throw new BadCredentialsException(USER_NOT_FOUND);
}
if (!user.isActive()) {
throw new BadCredentialsException(USER_NOT_ACTIVATED);
}
return new UsernamePasswordAuthenticationToken(authentication.getName(), credentials, getRolesAsAuthorities(user));
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)
&& authentication.equals(UsernamePasswordAuthenticationToken.class);
}
private List<SimpleGrantedAuthority> getRolesAsAuthorities(DrishtiUser user) {
return Lambda.convert(user.getRoles(), new Converter<String, SimpleGrantedAuthority>() {
@Override
public SimpleGrantedAuthority convert(String role) {
return new SimpleGrantedAuthority(role);
}
});
}
public DrishtiUser getDrishtiUser(Authentication authentication) {
DrishtiUser user;
try {
user = allDrishtiUsers.findByUsername((String) authentication.getPrincipal());
} catch (Exception e) {
logger.error(format("{0}. Exception: {1}", INTERNAL_ERROR, e));
throw new BadCredentialsException(INTERNAL_ERROR);
}
return user;
}
public DrishtiUser getDrishtiUser(String username) {
DrishtiUser user;
try {
user = allDrishtiUsers.findByUsername(username);
} catch (Exception e) {
logger.error(format("{0}. Exception: {1}", INTERNAL_ERROR, e));
throw new BadCredentialsException(INTERNAL_ERROR);
}
return user;
}
}