use actix_web::{web, HttpResponse, Responder}; use maud::html; use serde::Deserialize; use sqlx::PgPool; use crate::{ mail::Mailer, models::{PasswordReset, User}, utils::{password_change::PasswordChangeBuilder, ApplicationError}, }; #[derive(Deserialize, Debug)] struct ResetPasswordForm { email: Option, token: Option, password: Option, passwordretyped: Option, dry: Option, } #[actix_web::post("/reset-password")] async fn post( form: web::Form, pool: web::Data, mailer: web::Data, ) -> Result { if form.email.is_some() && form.token.is_none() && form.password.is_none() && form.passwordretyped.is_none() { if let Ok(user) = User::read_for_login(pool.get_ref(), form.email.as_ref().unwrap()).await { let reset = PasswordReset::insert_new_for_user(pool.get_ref(), user.id).await?; mailer .send_forgot_password_mail(&user, &reset.token) .await?; } Ok(HttpResponse::Ok().body("E-Mail versandt!")) } else if form.email.is_none() && form.token.is_some() && form.password.is_some() && form.passwordretyped.is_some() { // TODO: refactor into check if HX-TARGET = #password-strength exists let is_dry = form.dry.is_some_and(|b| b); let token = if let Some(token) = PasswordReset::does_token_exist(pool.get_ref(), form.token.as_ref().unwrap()).await? { token } else { return Ok(HttpResponse::NoContent().finish()); }; let mut builder = PasswordChangeBuilder::::new( pool.get_ref(), token.userid, &form.password.as_ref().unwrap(), &form.passwordretyped.as_ref().unwrap(), ) .with_token(token); let change = builder.build(); let response = if is_dry { change.validate_for_input().await? } else { change.validate().await?; change.commit().await?; HttpResponse::Ok().body( html! { div class="block mb-3" { "Passwort erfolgreich geƤndert." } a class="block button is-primary" hx-boost="true" href="/login"{ "Zum Login" } } .into_string(), ) }; return Ok(response); } else { return Ok(HttpResponse::BadRequest().finish()); } }