Commit b7171112 by Jan Hrabal

b

parent 6aaa7772
package com.jh.boot.security;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
/**
* TODO.
*
* @author jh
*/
public interface AuthService {
/**
* Authenticate.
*
* @param username the username
* @param password the password
* @return the authentication
* @throws BadCredentialsException the bad credentials exception
*/
Authentication authenticate(String username, String password) throws BadCredentialsException;
/**
* Register.
*
* @param signup the signup
*/
void register(String login, String password) throws AuthenticationException;
/**
* This method is responsible for creating new reset password request
* for provided login (or should do nothing if the login is unknown).
*
* <p>The way of letting the user know the token is up to the implementation</p>
*
* @param login
*/
String generateResetToken(String login);
/**
* TODO
* @param resetPassword
* @throws AuthenticationException TODO
*/
void resetPassword(String login, String token, String newPassword) throws AuthenticationException;
}
package com.jh.boot.security;
import java.util.Locale;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import com.jh.boot.security.model.AppUser;
/**
* TODO.
*
* @author jh
*/
public interface AuthService {
/**
* Authenticate.
*
* @param username the username
* @param password the password
* @return the authentication
* @throws BadCredentialsException the bad credentials exception
*/
Authentication authenticate(String username, String password) throws BadCredentialsException;
/**
* Register.
* @param locale TODO
* @param signup the signup
*/
void register(String login, String password, Locale locale) throws AuthenticationException;
/**
* This method is responsible for creating new reset password request
* for provided login (or should do nothing if the login is unknown).
*
* <p>The way of letting the user know the token is up to the implementation</p>
*
* @param login
*/
String generateResetToken(String login);
/**
* TODO
* @param resetPassword
* @throws AuthenticationException TODO
*/
void resetPassword(String login, String token, String newPassword) throws AuthenticationException;
/**
* TODO
*
* @param login
*/
void delete(AppUser login);
}
package com.jh.boot.security;
import com.jh.boot.security.model.AppUser;
import com.jh.boot.security.model.ResetPasswordToken;
public interface AuthServiceListener {
void registerUser(AppUser user);
void generateResetToken(AppUser user, ResetPasswordToken token);
}
package com.jh.boot.security;
import com.jh.boot.security.model.AppUser;
import com.jh.boot.security.model.ResetPasswordToken;
public interface AuthServiceListener {
default void registerUser(AppUser user) {
}
default void initializeUser(AppUser user) {
}
default void generateResetToken(AppUser user, ResetPasswordToken token) {
}
default void deleteUser(AppUser user) {
}
}
......@@ -113,7 +113,7 @@ public class AuthApiController {
* @return the response entity
*/
@RequestMapping(path = "/auth/signup", method = RequestMethod.POST)
public @ResponseBody LoginResponse signup(@RequestBody Signup signup) {
public @ResponseBody LoginResponse signup(@RequestBody Signup signup, Locale locale) {
if (!signupEnabled) {
throw new NotFoundException();
}
......@@ -145,11 +145,12 @@ public class AuthApiController {
}
try {
authService.register(signup.getLogin(), signup.getPassword());
authService.register(signup.getLogin(), signup.getPassword(), locale);
} catch (BadCredentialsException e) {
errors.add(ErrorMessage.withCode(e.getMessage()));
} catch (Exception e) {
errors.add(ErrorMessage.withMessage(e.getMessage()));
e.printStackTrace();
}
if (errors.isEmpty()) {
......@@ -227,11 +228,16 @@ public class AuthApiController {
@DeleteMapping("/auth/user")
public ResponseEntity<Void> deleteUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// if (auth instanceof AppUserAuthentication) {
// return ((AppUserAuthentication) auth).getUser();
// }
//TODO other auth types?
AppUser user = null;
if (auth instanceof AppUserAuthentication) {
user = ((AppUserAuthentication) auth).getUser();
}
if (user == null) {
return ResponseEntity.notFound().build();
}
authService.delete(user);
return ResponseEntity.accepted().build();
}
......
package com.jh.boot.security.repository;
import javax.persistence.Query;
import org.springframework.util.StringUtils;
import com.jh.boot.jpa.AbstractHibernateRepository;
import com.jh.boot.security.PasswordHash;
import com.jh.boot.security.PasswordUtils;
import com.jh.boot.security.model.AppUser;
import com.jh.boot.security.model.ResetPasswordToken;
public class AppUserRepository extends AbstractHibernateRepository {
public AppUser findByLogin(String username) {
if (!StringUtils.hasText(username)) {
return null;
}
Query q = entityManager.createQuery("select au from AppUser au where lower(au.email) = :email");
q.setParameter("email", username.trim().toLowerCase());
return singleResult(q);
}
public AppUser fetchByLoginDetached(String username) {
if (!StringUtils.hasText(username)) {
return null;
}
Query q = entityManager.createQuery("select au from AppUser au left join fetch au.roles where lower(au.email) = :email");
q.setParameter("email", username.trim().toLowerCase());
AppUser user = singleResult(q);
if (user == null) {
return null;
}
entityManager.detach(user);
return user;
}
public AppUser registerUser(String username, String password) {
AppUser user = new AppUser();
user.setEmail(username);
PasswordHash hash = PasswordUtils.hashPassword(password);
user.setPassword(hash.getHash());
user.setPasswordSalt(hash.getSalt());
entityManager.persist(user);
return user;
}
public ResetPasswordToken saveResetPasswordToken(ResetPasswordToken token) {
entityManager.persist(token);
return token;
}
public ResetPasswordToken findResetPasswordToken(String login, String token) {
if (!StringUtils.hasText(login) || StringUtils.hasText(token)) {
return null;
}
Query q = entityManager.createQuery("select au from ResetPasswordToken au where lower(au.login) = :login and au.token = :token and (au.used is null or au.used = :used)");
q.setParameter("login", login.trim().toLowerCase());
q.setParameter("token", token.trim().toLowerCase());
q.setParameter("used", Boolean.TRUE);
return singleResult(q);
}
}
package com.jh.boot.security.repository;
import javax.persistence.Query;
import org.springframework.util.StringUtils;
import com.jh.boot.jpa.AbstractHibernateRepository;
import com.jh.boot.security.PasswordHash;
import com.jh.boot.security.PasswordUtils;
import com.jh.boot.security.model.AppUser;
import com.jh.boot.security.model.ResetPasswordToken;
public class AppUserRepository extends AbstractHibernateRepository {
public AppUser findByLogin(String username) {
if (!StringUtils.hasText(username)) {
return null;
}
Query q = entityManager.createQuery("select au from AppUser au where lower(au.email) = :email and (au.deleted is null or au.deleted = false)");
q.setParameter("email", username.trim().toLowerCase());
return singleResult(q);
}
public AppUser fetchByLoginDetached(String username) {
if (!StringUtils.hasText(username)) {
return null;
}
Query q = entityManager.createQuery("select au from AppUser au left join fetch au.roles where lower(au.email) = :email and (au.deleted is null or au.deleted = false)");
q.setParameter("email", username.trim().toLowerCase());
AppUser user = singleResult(q);
if (user == null) {
return null;
}
entityManager.detach(user);
return user;
}
public AppUser registerUser(String username, String password) {
AppUser user = new AppUser();
user.setEmail(username);
PasswordHash hash = PasswordUtils.hashPassword(password);
user.setPassword(hash.getHash());
user.setPasswordSalt(hash.getSalt());
entityManager.persist(user);
return user;
}
public ResetPasswordToken saveResetPasswordToken(ResetPasswordToken token) {
entityManager.persist(token);
return token;
}
public ResetPasswordToken findResetPasswordToken(String login, String token) {
if (!StringUtils.hasText(login) || StringUtils.hasText(token)) {
return null;
}
Query q = entityManager.createQuery("select au from ResetPasswordToken au where lower(au.login) = :login and au.token = :token and (au.used is null or au.used = :used)");
q.setParameter("login", login.trim().toLowerCase());
q.setParameter("token", token.trim().toLowerCase());
q.setParameter("used", Boolean.TRUE);
return singleResult(q);
}
}
......@@ -3,6 +3,7 @@ package com.jh.boot.security.service;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
......@@ -61,7 +62,7 @@ public class AppUserAuthService implements AuthService {
@Override
@Transactional
public void register(String login, String password) throws AuthenticationException {
public void register(String login, String password, Locale locale) throws AuthenticationException {
AppUser user = appUserRepository.findByLogin(login);
if (user != null) {
throw new BadCredentialsException("AUTH.USER_ALREADY_EXISTS");
......@@ -117,6 +118,21 @@ public class AppUserAuthService implements AuthService {
}
@Override
@Transactional
public void delete(AppUser user) throws AuthenticationException {
if (user == null) {
throw new BadCredentialsException("AUTH.USER_NOT_FOUND");
}
user = appUserRepository.findByLogin(user.getEmail());
if (user == null) {
throw new BadCredentialsException("AUTH.USER_NOT_FOUND");
}
user.setDeleted(true);
}
@Autowired(required = false)
public void setAppUserRepository(AppUserRepository appUserRepository) {
this.appUserRepository = appUserRepository;
......
package com.jh.boot.security.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import com.jh.boot.email.Email;
import com.jh.boot.email.EmailRecipient;
import com.jh.boot.email.EmailService;
import com.jh.boot.email.RecipientType;
import com.jh.boot.security.AuthServiceListener;
import com.jh.boot.security.model.AppUser;
import com.jh.boot.security.model.ResetPasswordToken;
import com.jh.boot.template.TemplateService;
public class TemplateEmailAuthServiceListener implements AuthServiceListener {
@Autowired
private EmailService emailService;
@Autowired
private TemplateService templateService;
@Value("${template.email.layout:email.layout}")
private String layoutTemplateCode;
@Value("${template.email.signup.subject:email.signup.subject}")
private String signupSubjectCode;
@Value("${template.email.signup.text:template.email.signup.text}")
private String signupTemplateCode;
@Value("${template.email.signup.html:template.email.signup.html}")
private String signupTemplateHtmlCode;
@Value("${template.email.password.subject:email.password.subject}")
private String passwordSubjectCode;
@Value("${template.email.password.text:email.password.text}")
private String passwordTemplateCode;
@Value("${template.email.password.html:email.password.html}")
private String passwordTemplateHtmlCode;
@Override
public void registerUser(AppUser user) {
sendEmail(signupSubjectCode, signupTemplateCode, signupTemplateHtmlCode, user, Collections.singletonMap("user", user));
}
@Override
public void generateResetToken(AppUser user, ResetPasswordToken token) {
Map<String, Object> data = new HashMap<>();
data.put("user", user);
data.put("token", token.getToken());
sendEmail(passwordSubjectCode, passwordTemplateCode, passwordTemplateHtmlCode, user, data);
}
protected void sendEmail(String subject, String content, String html, AppUser user, Map<String, Object> data) {
Locale locale = new Locale(user.getLocale());
subject = templateService.evaluate(subject, data, locale);
content = templateService.evaluate(content, data, locale);
html = templateService.evaluate(html, data, locale);
//is layout defined?
String layout = templateService.evaluate(layoutTemplateCode, Collections.singletonMap("content", html), locale);
Email email = new Email();
email.setRecipients(Collections.singleton(new EmailRecipient(user.getEmail(), RecipientType.TO)));
email.setSubject(subject);
email.setText(content);
email.setHtml(StringUtils.hasText(layout) ? layout : html);
emailService.sendEmail(email);
}
}
package com.jh.boot.security.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import com.jh.boot.email.Email;
import com.jh.boot.email.EmailRecipient;
import com.jh.boot.email.EmailService;
import com.jh.boot.email.RecipientType;
import com.jh.boot.security.AuthServiceListener;
import com.jh.boot.security.model.AppUser;
import com.jh.boot.security.model.ResetPasswordToken;
import com.jh.boot.template.TemplateService;
public class TemplateEmailAuthServiceListener implements AuthServiceListener {
@Autowired
private EmailService emailService;
@Autowired
private TemplateService templateService;
@Value("${template.email.layout:email.layout}")
private String layoutTemplateCode;
@Value("${template.email.signup.subject:email.signup.subject}")
private String signupSubjectCode;
@Value("${template.email.signup.text:template.email.signup.text}")
private String signupTemplateCode;
@Value("${template.email.signup.html:template.email.signup.html}")
private String signupTemplateHtmlCode;
@Value("${template.email.password.subject:email.password.subject}")
private String passwordSubjectCode;
@Value("${template.email.password.text:email.password.text}")
private String passwordTemplateCode;
@Value("${template.email.password.html:email.password.html}")
private String passwordTemplateHtmlCode;
@Override
public void registerUser(AppUser user) {
sendEmail(signupSubjectCode, signupTemplateCode, signupTemplateHtmlCode, user, Collections.singletonMap("user", user));
}
@Override
public void generateResetToken(AppUser user, ResetPasswordToken token) {
Map<String, Object> data = new HashMap<>();
data.put("user", user);
data.put("token", token.getToken());
sendEmail(passwordSubjectCode, passwordTemplateCode, passwordTemplateHtmlCode, user, data);
}
@Override
public void deleteUser(AppUser user) {
//TODO
}
protected void sendEmail(String subject, String content, String html, AppUser user, Map<String, Object> data) {
Locale locale = user.getLocale() == null ? Locale.getDefault() : new Locale(user.getLocale());
subject = templateService.evaluate(subject, data, locale);
content = templateService.evaluate(content, data, locale);
html = templateService.evaluate(html, data, locale);
//is layout defined?
String layout = templateService.evaluate(layoutTemplateCode, Collections.singletonMap("content", html), locale);
Email email = new Email();
email.setRecipients(Collections.singleton(new EmailRecipient(user.getEmail(), RecipientType.TO)));
email.setSubject(subject);
email.setText(content);
email.setHtml(StringUtils.hasText(layout) ? layout : html);
emailService.sendEmail(email);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment