El enlace de restablecer deja de servir una vez usado
La página pintaba el formulario sin mirar el token: rellenabas la contraseña nueva y solo al enviarla te enterabas de que el enlace ya no valía. El API sí marcaba `used = 1` y rechazaba el reintento, pero la pantalla no lo reflejaba. Ahora la página comprueba el token al abrirse con `isResetTokenValid()` (mismas condiciones que `resetPassword` —existe, sin usar, dentro de la hora— pero SIN consumirlo) y, si no vale, muestra el aviso del tema en vez del formulario. Textos: `invalidLink` pasa a «El enlace de restablecer la contraseña es inválido» y se añade `needHelp`, como en la página de activación. Verificado en producción con enlaces reales: válido -> formulario; usado, caducado, inexistente y sin token -> aviso, sin formulario. Y el ciclo entero: restablecer con un enlace válido lo marca usado y al reabrirlo ya sale el aviso. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,6 +144,26 @@ export async function requestRecovery(type: string, value: string): Promise<Resu
|
||||
return { success: false, error: 'invalidType' }
|
||||
}
|
||||
|
||||
/**
|
||||
* ¿El enlace de restablecer sigue sirviendo? Mismas condiciones que `resetPassword`
|
||||
* (existe, sin usar y dentro de la hora) pero SIN consumirlo: lo llama la página al
|
||||
* abrirse, para no enseñar el formulario de un enlace que ya no vale.
|
||||
*/
|
||||
export async function isResetTokenValid(token: string): Promise<boolean> {
|
||||
if (!token) return false
|
||||
try {
|
||||
const [rows] = await db(DB.default).query<RowDataPacket[]>(
|
||||
'SELECT created_at FROM passwordreset WHERE token = ? AND used = 0',
|
||||
[token],
|
||||
)
|
||||
const pr = rows[0]
|
||||
if (!pr) return false
|
||||
return Date.now() - new Date(pr.created_at).getTime() <= 3600_000
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function resetPassword(token: string, newPassword: string, confPassword: string): Promise<Result> {
|
||||
const [rows] = await db(DB.default).query<RowDataPacket[]>(
|
||||
'SELECT id, email, created_at FROM passwordreset WHERE token = ? AND used = 0',
|
||||
|
||||
Reference in New Issue
Block a user