package com.pollex.pam.web.rest; import com.pollex.pam.business.domain.User; import com.pollex.pam.business.repository.UserRepository; import com.pollex.pam.business.security.SecurityUtils; import com.pollex.pam.service.CustomerService; import com.pollex.pam.business.service.MailService; import com.pollex.pam.business.service.UserService; import com.pollex.pam.business.service.dto.AdminUserDTO; import com.pollex.pam.business.service.dto.PasswordChangeDTO; import com.pollex.pam.business.web.errors.*; import com.pollex.pam.business.web.vm.KeyAndPasswordVM; import com.pollex.pam.business.web.vm.ManagedUserVM; import java.util.*; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * REST controller for managing the current user's account. */ @RestController @RequestMapping("/api") public class AccountResource { private static class AccountResourceException extends RuntimeException { private AccountResourceException(String message) { super(message); } } private final Logger log = LoggerFactory.getLogger(AccountResource.class); private final UserRepository userRepository; private final UserService userService; private final MailService mailService; @Autowired CustomerService customerService; public AccountResource(UserRepository userRepository, UserService userService, MailService mailService) { this.userRepository = userRepository; this.userService = userService; this.mailService = mailService; } /** * {@code GET /activate} : activate the registered user. * * @param key the activation key. * @throws RuntimeException {@code 500 (Internal Server Error)} if the user couldn't be activated. */ @GetMapping("/activate") public void activateAccount(@RequestParam(value = "key") String key) { Optional user = userService.activateRegistration(key); if (!user.isPresent()) { throw new AccountResourceException("No user was found for this activation key"); } } /** * {@code GET /authenticate} : check if the user is authenticated, and return its login. * * @param request the HTTP request. * @return the login if the user is authenticated. */ @GetMapping("/authenticate") public String isAuthenticated(HttpServletRequest request) { log.debug("REST request to check if the current user is authenticated"); return request.getRemoteUser(); } /** * {@code GET /account} : get the current user. * * @return the current user. * @throws RuntimeException {@code 500 (Internal Server Error)} if the user couldn't be returned. */ @GetMapping("/account") public AdminUserDTO getAccount() { return userService .getUserWithAuthorities() .map(AdminUserDTO::new) .orElseThrow(() -> new AccountResourceException("User could not be found")); } /** * {@code POST /account} : update the current user information. * * @param userDTO the current user information. * @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already used. * @throws RuntimeException {@code 500 (Internal Server Error)} if the user login wasn't found. */ @PostMapping("/account") public void saveAccount(@Valid @RequestBody AdminUserDTO userDTO) { String userLogin = SecurityUtils .getCurrentUserLogin() .orElseThrow(() -> new AccountResourceException("Current user login not found")); Optional existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()); if (existingUser.isPresent() && (!existingUser.get().getLogin().equalsIgnoreCase(userLogin))) { throw new EmailAlreadyUsedException(); } Optional user = userRepository.findOneByLogin(userLogin); if (!user.isPresent()) { throw new AccountResourceException("User could not be found"); } userService.updateUser( userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(), userDTO.getLangKey(), userDTO.getImageUrl() ); } @PostMapping(path = "/account/change-password") public void changePassword(@RequestBody PasswordChangeDTO passwordChangeDto) { if (isPasswordLengthInvalid(passwordChangeDto.getNewPassword())) { throw new InvalidPasswordException(); } userService.changePassword(passwordChangeDto.getCurrentPassword(), passwordChangeDto.getNewPassword()); } @PostMapping(path = "/account/reset-password/init") public void requestPasswordReset(@RequestBody String mail) { Optional user = userService.requestPasswordReset(mail); if (user.isPresent()) { mailService.sendPasswordResetMail(user.get()); } else { // Pretend the request has been successful to prevent checking which emails really exist // but log that an invalid attempt has been made log.warn("Password reset requested for non existing mail"); } } @PostMapping(path = "/account/reset-password/finish") public void finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) { if (isPasswordLengthInvalid(keyAndPassword.getNewPassword())) { throw new InvalidPasswordException(); } Optional user = userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey()); if (!user.isPresent()) { throw new AccountResourceException("No user was found for this reset key"); } } private static boolean isPasswordLengthInvalid(String password) { return ( StringUtils.isEmpty(password) || password.length() < ManagedUserVM.PASSWORD_MIN_LENGTH || password.length() > ManagedUserVM.PASSWORD_MAX_LENGTH ); } }