package com.imprimelibros.erp.users; import java.util.Locale; import org.springframework.context.MessageSource; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.imprimelibros.erp.config.Sanitizer; import com.imprimelibros.erp.users.validation.ProfileForm; @Controller @RequestMapping("/pages-profile") @PreAuthorize("isAuthenticated()") public class ProfileController { private final UserDao userDao; private final PasswordEncoder passwordEncoder; private final MessageSource messageSource; private final Sanitizer sanitizer; public ProfileController(UserDao userDao, PasswordEncoder passwordEncoder, MessageSource messageSource, Sanitizer sanitizer) { this.userDao = userDao; this.passwordEncoder = passwordEncoder; this.messageSource = messageSource; this.sanitizer = sanitizer; } @GetMapping public String view( Authentication authentication, @RequestParam(name = "success", required = false) String success, Model model, Locale locale) { if (authentication == null) { return "redirect:/login"; } User user = userDao.findByUserNameIgnoreCase(authentication.getName()).orElse(null); if (user == null) { return "redirect:/login"; } ProfileForm form = new ProfileForm(); form.setId(user.getId()); form.setFullName(user.getFullName()); form.setUserName(user.getUserName()); model.addAttribute("user", form); model.addAttribute("success", success != null); return "imprimelibros/users/profile"; } @PostMapping public String update( Authentication authentication, @Validated @ModelAttribute("user") ProfileForm form, BindingResult binding, Model model, RedirectAttributes redirectAttributes, Locale locale) { if (authentication == null) { return "redirect:/login"; } User user = userDao.findByUserNameIgnoreCase(authentication.getName()).orElse(null); if (user == null) { return "redirect:/login"; } String normalized = sanitizer.plain(form.getUserName()); if (normalized != null) { normalized = normalized.trim().toLowerCase(); } if (normalized == null || normalized.isBlank()) { binding.rejectValue("userName", "usuarios.error.email", messageSource.getMessage("usuarios.error.email", null, locale)); } else if (userDao.existsByUserNameIgnoreCaseAndIdNot(normalized, user.getId())) { binding.rejectValue("userName", "usuarios.error.duplicado", messageSource.getMessage("usuarios.error.duplicado", null, locale)); } String cleanName = sanitizer.plain(form.getFullName()); if (cleanName == null || cleanName.isBlank()) { binding.rejectValue("fullName", "usuarios.error.nombre", messageSource.getMessage("usuarios.error.nombre", null, locale)); } boolean wantsPasswordChange = hasText(form.getCurrentPassword()) || hasText(form.getNewPassword()) || hasText(form.getConfirmPassword()); if (wantsPasswordChange) { if (!hasText(form.getCurrentPassword())) { binding.rejectValue("currentPassword", "usuarios.error.password.actual", messageSource.getMessage("usuarios.error.password.actual", null, locale)); } else if (!passwordEncoder.matches(form.getCurrentPassword(), user.getPassword())) { binding.rejectValue("currentPassword", "usuarios.error.password.actual.incorrecta", messageSource.getMessage("usuarios.error.password.actual.incorrecta", null, locale)); } if (!hasText(form.getNewPassword())) { binding.rejectValue("newPassword", "usuarios.error.password.nueva.requerida", messageSource.getMessage("usuarios.error.password.nueva.requerida", null, locale)); } else if (form.getNewPassword().length() < 6) { binding.rejectValue("newPassword", "usuarios.error.password.min", messageSource.getMessage("usuarios.error.password.min", null, locale)); } if (!hasText(form.getConfirmPassword())) { binding.rejectValue("confirmPassword", "usuarios.error.confirmPassword.requerida", messageSource.getMessage("usuarios.error.confirmPassword.requerida", null, locale)); } else if (hasText(form.getNewPassword()) && !form.getNewPassword().equals(form.getConfirmPassword())) { binding.rejectValue("confirmPassword", "usuarios.error.password-coinciden", messageSource.getMessage("usuarios.error.password-coinciden", null, locale)); } } if (binding.hasErrors()) { model.addAttribute("success", false); return "imprimelibros/users/profile"; } user.setFullName(cleanName.trim()); user.setUserName(normalized); if (wantsPasswordChange) { user.setPassword(passwordEncoder.encode(form.getNewPassword())); } userDao.save(user); redirectAttributes.addAttribute("success", "1"); return "redirect:/pages-profile"; } private static boolean hasText(String value) { return value != null && !value.isBlank(); } }