mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
trabajando en el signup. problema con el mismo username aunque este delete at
This commit is contained in:
@ -27,28 +27,49 @@ public class EmailService {
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
public void sendPasswordResetMail(String to, String username, String resetLink, Locale locale) throws MessagingException {
|
||||
MimeMessage message = mailSender.createMimeMessage();
|
||||
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
|
||||
public void sendPasswordResetMail(String to, String fullName, String resetUrl, Locale locale) {
|
||||
String subject = messageSource.getMessage("email.resetPassword.title", null, locale);
|
||||
Map<String, Object> variables = Map.of(
|
||||
"fullName", fullName,
|
||||
"resetUrl", resetUrl);
|
||||
sendEmail(to, subject, "imprimelibros/email/reset-password", variables);
|
||||
}
|
||||
|
||||
helper.setFrom("no-reply@imprimelibros.com");
|
||||
helper.setTo(to);
|
||||
helper.setSubject(messageSource.getMessage("email.resetPassword.title", null, locale));
|
||||
public void sendVerificationEmail(String to, String fullName, String verifyUrl, Locale locale) {
|
||||
String subject = messageSource.getMessage("email.verify.title", null, locale);
|
||||
Map<String, Object> variables = Map.of(
|
||||
"fullName", fullName,
|
||||
"verifyUrl", verifyUrl);
|
||||
sendEmail(to, subject, "imprimelibros/email/verify", variables);
|
||||
}
|
||||
|
||||
// Variables para la plantilla
|
||||
Context context = new Context();
|
||||
context.setVariables(Map.of(
|
||||
"username", username,
|
||||
"resetLink", resetLink,
|
||||
"year", String.valueOf(java.time.Year.now().getValue())
|
||||
));
|
||||
|
||||
// Procesar plantilla HTML
|
||||
String html = templateEngine.process("email/password-reset", context);
|
||||
helper.setText(html, true);
|
||||
// ->>>>>>>> PRIVATE METHODS <<<<<<<<<<<-
|
||||
|
||||
helper.addInline("companyLogo", new ClassPathResource("static/images/logo-light.png"));
|
||||
/******************
|
||||
* Envía un email usando una plantilla Thymeleaf.
|
||||
* @param to
|
||||
* @param subject
|
||||
* @param template
|
||||
* @param variables
|
||||
**********************************************/
|
||||
|
||||
mailSender.send(message);
|
||||
private void sendEmail(String to, String subject, String template, Map<String, Object> variables) {
|
||||
try {
|
||||
Context context = new Context();
|
||||
context.setVariables(variables);
|
||||
String html = templateEngine.process(template, context);
|
||||
|
||||
MimeMessage message = mailSender.createMimeMessage();
|
||||
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
|
||||
helper.setFrom("no-reply@imprimelibros.com");
|
||||
helper.setTo(to);
|
||||
helper.setSubject(subject);
|
||||
helper.setText(html, true);
|
||||
|
||||
mailSender.send(message);
|
||||
} catch (MessagingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,6 +125,8 @@ public class SecurityConfig {
|
||||
"/",
|
||||
"/login",
|
||||
"/signup",
|
||||
"/verify",
|
||||
"/reset-password",
|
||||
"/assets/**",
|
||||
"/css/**",
|
||||
"/js/**",
|
||||
|
||||
@ -4,11 +4,26 @@ import java.util.Locale;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
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.RequestParam;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import com.imprimelibros.erp.login.dto.SignupForm;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Controller
|
||||
public class LoginController {
|
||||
|
||||
private final SignupService signupService;
|
||||
|
||||
public LoginController(SignupService signupService) {
|
||||
this.signupService = signupService;
|
||||
}
|
||||
|
||||
@GetMapping("/login")
|
||||
public String index(Model model, Locale locale) {
|
||||
model.addAttribute("form", "_login");
|
||||
@ -17,9 +32,44 @@ public class LoginController {
|
||||
|
||||
@GetMapping("/signup")
|
||||
public String signup(Model model, Locale locale) {
|
||||
if (!model.containsAttribute("signupForm")) {
|
||||
model.addAttribute("signupForm", new SignupForm());
|
||||
}
|
||||
model.addAttribute("form", "_signup");
|
||||
return "imprimelibros/login/login";
|
||||
}
|
||||
|
||||
@PostMapping("/signup")
|
||||
public String doSignup(@Valid @ModelAttribute("signupForm") SignupForm form,
|
||||
BindingResult br,
|
||||
RedirectAttributes ra,
|
||||
Locale locale) {
|
||||
if (br.hasErrors()) {
|
||||
ra.addFlashAttribute("org.springframework.validation.BindingResult.signupForm", br);
|
||||
ra.addFlashAttribute("signupForm", form);
|
||||
ra.addFlashAttribute("signup_error", "Revisa el formulario");
|
||||
return "redirect:/signup";
|
||||
}
|
||||
try {
|
||||
signupService.register(form, locale);
|
||||
ra.addFlashAttribute("info", "Te hemos enviado un email para confirmar tu correo.");
|
||||
return "redirect:/login";
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ra.addFlashAttribute("signup_error", ex.getMessage());
|
||||
ra.addFlashAttribute("signupForm", form);
|
||||
return "redirect:/signup";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/verify")
|
||||
public String verify(@RequestParam("token") String token, RedirectAttributes ra) {
|
||||
boolean ok = signupService.verify(token);
|
||||
if (ok) {
|
||||
ra.addFlashAttribute("info", "¡Cuenta verificada! Ya puedes iniciar sesión.");
|
||||
} else {
|
||||
ra.addFlashAttribute("danger", "Enlace inválido o caducado. Solicita uno nuevo.");
|
||||
}
|
||||
return "redirect:/login";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package com.imprimelibros.erp.login;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -9,6 +11,8 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||
|
||||
import com.imprimelibros.erp.common.email.EmailService;
|
||||
import com.imprimelibros.erp.login.dto.SignupForm;
|
||||
import com.imprimelibros.erp.users.Role;
|
||||
import com.imprimelibros.erp.users.RoleDao;
|
||||
import com.imprimelibros.erp.users.User;
|
||||
import com.imprimelibros.erp.users.UserDao;
|
||||
|
||||
@ -18,6 +22,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
public class SignupService {
|
||||
|
||||
private final UserDao userRepository;
|
||||
private final RoleDao roleRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final VerificationTokenRepository tokenRepository;
|
||||
private final EmailService emailService;
|
||||
@ -26,31 +31,36 @@ public class SignupService {
|
||||
private static final long TOKEN_MINUTES = 60;
|
||||
|
||||
public SignupService(UserDao userRepository,
|
||||
PasswordEncoder passwordEncoder,
|
||||
VerificationTokenRepository tokenRepository,
|
||||
EmailService emailService) {
|
||||
RoleDao roleRepository,
|
||||
PasswordEncoder passwordEncoder,
|
||||
VerificationTokenRepository tokenRepository,
|
||||
EmailService emailService) {
|
||||
this.userRepository = userRepository;
|
||||
this.roleRepository = roleRepository;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.tokenRepository = tokenRepository;
|
||||
this.emailService = emailService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void register(SignupForm form) {
|
||||
public void register(SignupForm form, Locale locale) {
|
||||
if (!form.getPassword().equals(form.getPasswordConfirm())) {
|
||||
throw new IllegalArgumentException("Las contraseñas no coinciden");
|
||||
}
|
||||
|
||||
if (userRepository.existsByUsername(form.getUsername())) {
|
||||
if (userRepository.existsByUserNameIgnoreCase(form.getUsername())) {
|
||||
throw new IllegalArgumentException("El correo ya está registrado");
|
||||
}
|
||||
|
||||
// Crear usuario deshabilitado
|
||||
User user = new User();
|
||||
user.setUsername(form.getUsername().trim().toLowerCase());
|
||||
user.setUserName(form.getUsername().trim().toLowerCase());
|
||||
user.setFullName(form.getName().trim());
|
||||
user.setPassword(passwordEncoder.encode(form.getPassword()));
|
||||
user.setEnabled(false);
|
||||
// TODO: asignar rol por defecto si aplica (e.g., ROLE_USER)
|
||||
var roles = new HashSet<Role>();
|
||||
roles.add(roleRepository.findRoleByName("USER").orElseThrow());
|
||||
user.setRoles(roles);
|
||||
user = userRepository.save(user);
|
||||
|
||||
// Generar token
|
||||
@ -68,20 +78,23 @@ public class SignupService {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put("verifyUrl", verifyUrl);
|
||||
model.put("minutes", TOKEN_MINUTES);
|
||||
emailService.sendTemplate(
|
||||
user.getUsername(),
|
||||
"Confirma tu correo | ImprimeLibros ERP",
|
||||
"mail/verify-email",
|
||||
model);
|
||||
emailService.sendVerificationEmail(
|
||||
user.getUserName(),
|
||||
user.getFullName(),
|
||||
verifyUrl,
|
||||
locale);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public boolean verify(String tokenValue) {
|
||||
var tokenOpt = tokenRepository.findByToken(tokenValue);
|
||||
if (tokenOpt.isEmpty()) return false;
|
||||
if (tokenOpt.isEmpty())
|
||||
return false;
|
||||
|
||||
var token = tokenOpt.get();
|
||||
if (token.isUsed() || token.isExpired()) return false;
|
||||
if (token.isUsed() || token.isExpired())
|
||||
return false;
|
||||
|
||||
var user = userRepository.findById(token.getUserId())
|
||||
.orElseThrow(() -> new IllegalStateException("Usuario no encontrado para el token"));
|
||||
|
||||
@ -5,18 +5,26 @@ import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class SignupForm {
|
||||
@NotBlank @Email
|
||||
|
||||
@NotBlank(message = "{usuarios.error.correo}")
|
||||
@Email(message = "{usuarios.error.correo.invalido}")
|
||||
private String username;
|
||||
|
||||
@NotBlank @Size(min = 8, message = "La contraseña debe tener al menos 8 caracteres")
|
||||
@NotBlank(message = "{usuarios.error.nombre}")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "{usuarios.error.contraseña}")
|
||||
@Size(min = 6, message = "{usuarios.error.contraseña.tamaño}")
|
||||
private String password;
|
||||
|
||||
@NotBlank
|
||||
@NotBlank(message = "{usuarios.error.confirmPassword.requerida}")
|
||||
private String passwordConfirm;
|
||||
|
||||
// getters/setters
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String u) { this.username = u; }
|
||||
public String getName() { return name; }
|
||||
public void setName(String n) { this.name = n; }
|
||||
public String getPassword() { return password; }
|
||||
public void setPassword(String p) { this.password = p; }
|
||||
public String getPasswordConfirm() { return passwordConfirm; }
|
||||
|
||||
Reference in New Issue
Block a user