Commit b7171112 by Jan Hrabal

b

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