password forgot hecho

This commit is contained in:
2025-10-04 16:51:22 +02:00
parent b66ceee85c
commit dbc2038f9f
14 changed files with 366 additions and 248 deletions

View File

@ -5,4 +5,19 @@ email.verify.button=Verificar cuenta
email.verify.link-instruction=Si no funciona, copia y pega esta URL en tu navegador:
email.verify.expiration=Este enlace caduca en {0} minutos.
email.verify.ignoreMessage=Si no solicitaste este cambio, puedes ignorar este mensaje.
email.footer=Imprimelibros - Todos los derechos reservados.
email.reset-password.title=Restablecer contraseña
email.reset-password.body=Haz clic en el siguiente botón para restablecer tu contraseña:
email.reset-password.button=Restablecer contraseña
email.reset-password.link-instruction=Si no funciona, copia y pega esta URL en tu navegador:
email.reset-password.expiration=Este enlace caduca en {0} minutos.
email.reset-password.ignoreMessage=Si no solicitaste este cambio, puedes ignorar este mensaje.
email.reset.title=Restablecer tu contraseña
email.reset.hello=Hola,
email.reset.instructions=Has solicitado restablecer tu contraseña.
email.reset.button=Restablecer contraseña
email.reset.ignore=Si no solicitaste este cambio, puedes ignorar este correo.
email.verify.expiration=Este enlace caduca en {0} minutos.
email.footer=Imprimelibros - Todos los derechos reservados.

View File

@ -17,6 +17,14 @@ login.sign-up=Regístrate
login.sign-up-button=Crear cuenta
login.sign-up.title=Crear una cuenta
login.sign-up.name=Nombre completo
login.password-recovery.title=Recuperar contraseña
login.password-recovery.button=Recuperar contraseña
login.password-recovery.email-info=Se te ha enviado un correo con instrucciones para restablecer tu contraseña.
login.change-password.title=Cambiar contraseña
login.change-password.subtitle=Introduce tu nueva contraseña a continuación.
login.change-password.new-password=Nueva contraseña
login.change-password.confirm-password=Confirmar nueva contraseña
login.change-password.button=Cambiar contraseña
login.error=Credenciales inválidas
login.signup.error.email.exists=El correo electrónico ya está en uso.
@ -25,5 +33,10 @@ login.signup.error.password.mismatch=Las contraseñas no coinciden.
login.signup.error.review=Por favor, revisa el formulario.
login.signup.error.token.invalid=Enlace inválido o caducado. Solicita uno nuevo.
login.password-reset.error=Las contraseñas no coinciden o son demasiado cortas.
login.password-reset.error-link=El enlace no es válido o ha expirado.
login.signup.success=Cuenta creada con éxito. Por favor, revisa tu correo para activar tu cuenta.
login.signup.success.verified=¡Cuenta verificada! Ya puedes iniciar sesión.
login.signup.success.verified=¡Cuenta verificada! Ya puedes iniciar sesión.
login.password-reset.success=Contraseña cambiada correctamente. Ya puedes iniciar sesión.

View File

@ -1,33 +1,45 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="es" xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="content">
<p style="margin:0 0 12px; color:#333333 !important;">
<span th:text="#{email.greeting}">Hola</span>
<span th:text="${fullName} ?: 'Usuario'">Usuario</span>,
</p>
<head>
<meta charset="UTF-8">
<title th:text="#{email.resetPassword.title}">Recuperación de contraseña</title>
<link rel="stylesheet" th:href="@{/css/email.css}">
</head>
<p style="margin:0 0 12px; color:#333333 !important;">
<span th:text="#{email.reset-password.body}">
Haz clic en el siguiente botón para restablecer tu contraseña:
</span>
</p>
<body>
<div class="container">
<div class="header">
<!-- Logo insertado como imagen inline -->
<img th:src="@{cid:companyLogo}" alt="Logo Imprimelibros" width="150">
</div>
<p style="margin:0 0 16px;">
<a th:href="${resetUrl}"
style="display:inline-block; padding:12px 20px; border-radius:6px; font-weight:bold;
background:#2563eb; color:#ffffff !important; text-decoration:none;">
<span th:text="#{email.reset-password.button}">Restablecer contraseña</span>
</a>
</p>
<p><span th:text="#{email.greeting}">Hola</span> <b th:text="${username}">Usuario</b>,</p>
<p th:text="#{email.resetPassword.body}">Hemos recibido una solicitud para restablecer tu contraseña. Haz clic en el siguiente botón:</p>
<p style="margin:0 0 8px; color:#333333 !important;">
<span th:text="#{email.reset-password.link-instruction}">
Si no funciona, copia y pega esta URL en tu navegador:
</span>
</p>
<p style="text-align:center;">
<a th:href="${resetLink}" class="btn" th:text="#{email.resetPassword.button}">Restablecer contraseña</a>
</p>
<p style="margin:0 0 12px; color:#333333 !important;">
<span th:text="${resetUrl}">https://...</span>
</p>
<p th:text="#{email.resetPassword.ignoreMessage}">Si no solicitaste este cambio, puedes ignorar este mensaje.</p>
<p style="margin:0 0 12px; color:#333333 !important;">
<span th:text="#{email.reset-password.expiration(${minutes})}">
Este enlace caduca en 60 minutos.
</span>
</p>
<div class="footer">
© <span th:text="${year}">2025</span> <span th:text="#{email.footer}">Imprimelibros - Todos los derechos reservados.</span>
</div>
</div>
</body>
</html>
<p style="margin:0; color:#333333 !important;">
<span th:text="#{email.reset-password.ignoreMessage}">
Si no solicitaste este cambio, puedes ignorar este mensaje.
</span>
</p>
</th:block>
</html>

View File

@ -0,0 +1,21 @@
<div th:fragment="_forgot-password">
<div>
<h5 class="text-primary" th:text="#{login.password-recovery.title}">Recuperar contraseña</h5>
</div>
<form th:if="${form == '_forgot-password'}" th:action="@{/auth/password/forgot}" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<div class="mb-3">
<label for="username" class="form-label" th:text="#{login.email}">Correo electrónico</label>
<input type="email" class="form-control" id="username" th:placeholder="#{login.email-placeholder}"
name="username">
</div>
<div class="mt-4">
<button class="btn btn-secondary w-100" type="submit" th:text="#{login.password-recovery.button}">Recuperar
contraseña</button>
</div>
</form>
</div>

View File

@ -22,7 +22,7 @@
<div class="mb-3">
<div class="float-end">
<a href="/auth-pass-reset-cover" class="text-muted" th:text="#{login.forgotPassword}">¿Olvidó su
<a href="/auth/password/forgot" class="text-muted" th:text="#{login.forgotPassword}">¿Olvidó su
contraseña?</a>
</div>
<label class="form-label" for="password-input" th:text="#{login.password}">Contraseña</label>

View File

@ -0,0 +1,41 @@
<div th:fragment="_reset-password">
<div>
<h5 class="text-primary" th:text="#{login.change-password.title}">Cambiar contraseña</h5>
</div>
<form th:if="${form == '_reset-password'} and ${valid}" th:action="@{/auth/password/reset}" method="post"
autocomplete="off">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<input type="hidden" name="uid" th:value="${uid}" />
<input type="hidden" name="token" th:value="${token}" />
<div class="mb-3">
<label class="form-label" for="password-input" th:text="#{login.change-password.new-password}">Nueva
contraseña</label>
<input type="password" class="form-control" id="password-input" name="password" required minlength="8"
autocomplete="new-password" th:placeholder="#{login.password-placeholder}">
</div>
<div class="mb-3">
<label class="form-label" for="password-confirm-input"
th:text="#{login.change-password.confirm-password}">Confirmar contraseña</label>
<input type="password" class="form-control" id="password-confirm-input" name="password2" required
minlength="8" autocomplete="new-password" th:placeholder="#{login.password-placeholder}">
</div>
<div class="mt-4">
<button class="btn btn-secondary w-100" type="submit" th:text="#{login.change-password.button}">Cambiar
contraseña</button>
</div>
</form>
<!-- Si el token no es válido, sugerir pedir otro -->
<div th:if="${form == '_reset-password'} and ${valid != null and !valid}" class="mt-3">
<a class="btn btn-outline-primary w-100" th:href="@{/auth/password/forgot}"
th:text="#{login.password-reset.request-new}">
Solicitar nuevo enlace
</a>
</div>
</div>

View File

@ -1,7 +1,5 @@
<div th:fragment="_signup">
<div>
<h5 class="text-primary" th:text="#{login.welcome}">¡Bienvenido!</h5>
<p class="text-muted" th:text="#{login.sign-up.title}">Crear cuenta</p>
@ -10,8 +8,6 @@
<!-- En el caso del formulario de signup, asegúrate de bindear el DTO -->
<form th:if="${form == '_signup'}" th:action="@{/signup}" method="post" th:object="${signupForm}">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<div class="mb-3">