resend verification mail
This commit is contained in:
@@ -185,6 +185,62 @@ fn verified_view(v: &TeraView, jar: &CookieJar, ok: bool) -> Result<Response> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Resend the email-verification link. Throttled per account (see
|
||||
/// [`users::Model::verification_resend_wait_secs`]) so it can't be used to spam
|
||||
/// an inbox, and always returns the same neutral message so it can't be used to
|
||||
/// probe which addresses are registered.
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct ResendVerificationForm {
|
||||
email: String,
|
||||
}
|
||||
|
||||
fn resend_verification_view(v: &TeraView, jar: &CookieJar, done: bool) -> Result<Response> {
|
||||
format::view(
|
||||
v,
|
||||
"auth/resend_verification.html",
|
||||
json!({
|
||||
"done": done,
|
||||
"logged_in_admin": false,
|
||||
"lang": current_lang(jar),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
async fn resend_verification_page(
|
||||
jar: CookieJar,
|
||||
ViewEngine(v): ViewEngine<TeraView>,
|
||||
) -> Result<Response> {
|
||||
resend_verification_view(&v, &jar, false)
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
async fn resend_verification(
|
||||
jar: CookieJar,
|
||||
ViewEngine(v): ViewEngine<TeraView>,
|
||||
State(ctx): State<AppContext>,
|
||||
Form(form): Form<ResendVerificationForm>,
|
||||
) -> Result<Response> {
|
||||
// Resend only for a real, still-unverified account that is past its cooldown.
|
||||
// Anything else (unknown email, already verified, too soon) silently does
|
||||
// nothing — the response is identical either way.
|
||||
if let Ok(user) = users::Model::find_by_email(&ctx.db, form.email.trim()).await {
|
||||
if user.email_verified_at.is_none() && user.verification_resend_wait_secs() == 0 {
|
||||
match user.into_active_model().set_email_verification_sent(&ctx.db).await {
|
||||
Ok(user) => {
|
||||
if let Err(err) = AuthMailer::send_welcome(&ctx, &user).await {
|
||||
tracing::error!(error = %err, "failed to resend verification email");
|
||||
}
|
||||
}
|
||||
Err(err) => tracing::error!(error = %err, "failed to refresh verification token"),
|
||||
}
|
||||
} else {
|
||||
tracing::info!("verification resend skipped (already verified or within cooldown)");
|
||||
}
|
||||
}
|
||||
resend_verification_view(&v, &jar, true)
|
||||
}
|
||||
|
||||
/// Set-password form for accounts created during checkout (and any account that
|
||||
/// has a valid reset token). Reuses the password-reset token machinery.
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
@@ -276,6 +332,8 @@ pub fn routes() -> Routes {
|
||||
.add("/register", get(register_page))
|
||||
.add("/register", post(register))
|
||||
.add("/verify/{token}", get(verify))
|
||||
.add("/resend-verification", get(resend_verification_page))
|
||||
.add("/resend-verification", post(resend_verification))
|
||||
.add("/set-password/{token}", get(set_password_page))
|
||||
.add("/set-password", post(set_password))
|
||||
.add("/logout", post(logout))
|
||||
|
||||
Reference in New Issue
Block a user