bstlboard-back/src/main/java/de/bstly/board/businesslogic/UserManager.java

468 lines
14 KiB
Java

/**
*
*/
package de.bstly.board.businesslogic;
import java.util.List;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.google.common.collect.Lists;
import de.bstly.board.model.Entry;
import de.bstly.board.model.LocalUser;
import de.bstly.board.model.QEntry;
import de.bstly.board.model.QLocalUser;
import de.bstly.board.repository.EntryRepository;
import de.bstly.board.repository.LocalUserRepository;
import de.bstly.board.security.LocalUserDetails;
/**
* The Class UserManager.
*/
@Service
public class UserManager implements UserDetailsService, SmartInitializingSingleton {
private Logger logger = LoggerFactory.getLogger(UserManager.class);
@Autowired
private LocalUserRepository localUserRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private EntryManager entryManager;
@Autowired
private EntryRepository entryRepository;
private QLocalUser qLocalUser = QLocalUser.localUser;
private QEntry qEntry = QEntry.entry;
@Value("${admin.password:}")
private String adminPassword;
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
/*
* @see org.springframework.security.core.userdetails.UserDetailsService#
* loadUserByUsername(java.lang.String)
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LocalUser localUser = getByUsername(username);
if (localUser == null) {
throw new UsernameNotFoundException(username);
}
List<GrantedAuthority> authorities = Lists.newArrayList();
if (localUser.getRoles() != null) {
for (String role : localUser.getRoles()) {
authorities.add(new SimpleGrantedAuthority(role));
}
}
String passwordHash = localUser.getPasswordHash();
if (passwordHash == null) {
passwordHash = "";
}
LocalUserDetails userDetails = new LocalUserDetails(username, passwordHash, authorities);
return userDetails;
}
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
/*
* @see org.springframework.beans.factory.SmartInitializingSingleton#
* afterSingletonsInstantiated()
*/
@Override
public void afterSingletonsInstantiated() {
if (!localUserRepository.exists(qLocalUser.roles.contains("ROLE_ADMIN"))) {
if (!StringUtils.hasText(adminPassword)) {
adminPassword = RandomStringUtils.random(24, true, true);
logger.error("password for 'admin': " + adminPassword);
}
LocalUser admin = new LocalUser();
admin.setUsername("admin");
admin.setRoles(Lists.newArrayList("ROLE_ADMIN"));
admin.setPasswordHash(passwordEncoder.encode(adminPassword));
admin.setLocale("en");
localUserRepository.save(admin);
}
}
/**
* Gets the by username.
*
* @param username the username
* @return the by username
*/
public LocalUser getByUsername(String username) {
return localUserRepository.findOne(qLocalUser.username.equalsIgnoreCase(username)).orElse(null);
}
/**
* Gets the by external id.
*
* @param externalId the external id
* @return the by external id
*/
public LocalUser getByExternalId(String externalId) {
return localUserRepository.findOne(qLocalUser.externalId.eq(externalId)).orElse(null);
}
/**
* Gets the by auth.
*
* @param authentication the authentication
* @return the by auth
*/
public LocalUser getByAuth(Authentication authentication) {
if (authentication != null) {
if (authentication instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
return getByUsername(token.getName());
} else if (authentication instanceof OAuth2AuthenticationToken) {
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) authentication;
String externalId = token.getAuthorizedClientRegistrationId() + "-" + token.getName();
LocalUser localUser = getByExternalId(externalId);
if (localUser == null) {
localUser = new LocalUser();
localUser.setExternalId(externalId);
String tmpUsername = token.getPrincipal().getAttribute("preferred_username");
if (!StringUtils.hasText(tmpUsername)) {
tmpUsername = token.getPrincipal().getAttribute("username");
}
if (!StringUtils.hasText(tmpUsername)) {
tmpUsername = token.getPrincipal().getAttribute("name");
}
if (!StringUtils.hasText(tmpUsername)) {
tmpUsername = token.getName();
}
int count = 1;
String username = tmpUsername;
while (localUserRepository.exists(qLocalUser.username.equalsIgnoreCase(username))) {
username = tmpUsername + "-" + count;
count++;
}
localUser.setUsername(username);
localUser.setEmail(token.getPrincipal().getAttribute("email"));
String locale = token.getPrincipal().getAttribute("locale");
if (!StringUtils.hasText(locale)) {
locale = "de";
}
localUser.setLocale(locale);
String darkTheme = token.getPrincipal().getAttribute("darkTheme");
if (!StringUtils.hasText(darkTheme)) {
darkTheme = "false";
}
localUser.setDarkTheme(Boolean.valueOf(darkTheme));
localUser = localUserRepository.save(localUser);
}
return localUser;
}
}
return null;
}
/**
* Apply metadata.
*
* @param username the username
* @param user the user
*/
public void applyMetadata(String username, LocalUser user) {
if (user.getUsername().equalsIgnoreCase(username) && !user.getMetadata().containsKey("self")) {
user.getMetadata().put("self", true);
}
if (!user.getMetadata().containsKey("points")) {
user.getMetadata().put("points", getKarma(user.getUsername()));
}
}
/**
* Gets the karma.
*
* @param username the username
* @return the karma
*/
public long getKarma(String username) {
long karma = 0;
for (Entry entry : entryRepository.findAll(qEntry.author.equalsIgnoreCase(username))) {
karma += entryManager.getUserPoints(entry.getId(), username);
}
return karma;
}
/**
* Save.
*
* @param localUser the local user
* @return the local user
*/
public LocalUser save(LocalUser localUser) {
return localUserRepository.save(localUser);
}
/**
* Exists.
*
* @param username the username
* @return true, if successful
*/
public boolean exists(String username) {
return localUserRepository.exists(qLocalUser.username.equalsIgnoreCase(username));
}
}