From e81c87f28894dde66724807627d150d73b081cff Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Wed, 26 Oct 2022 09:54:01 +0200 Subject: [PATCH] server,app: Add support for resetting your password with email Instead of just username Fixes #267 --- Cargo.lock | 12 +++++- app/Cargo.toml | 1 + app/src/components/reset_password_step1.rs | 2 +- app/src/infra/api.rs | 2 +- server/src/infra/auth_service.rs | 43 ++++++++++++++++------ 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 173c595..f8e8d6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2163,7 +2163,7 @@ dependencies = [ "tracing-log", "tracing-subscriber", "uuid", - "webpki-roots 0.21.1", + "webpki-roots 0.22.4", ] [[package]] @@ -2182,6 +2182,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "url-escape", "validator", "validator_derive", "wasm-bindgen", @@ -4205,6 +4206,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "url-escape" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44e0ce4d1246d075ca5abec4b41d33e87a6054d08e2366b63205665e950db218" +dependencies = [ + "percent-encoding", +] + [[package]] name = "uuid" version = "0.8.2" diff --git a/app/Cargo.toml b/app/Cargo.toml index d41c0a6..1769536 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -22,6 +22,7 @@ yew-router = "0.15" # Needed because of https://github.com/tkaitchuck/aHash/issues/95 indexmap = "=1.6.2" +url-escape = "0.1.1" [dependencies.web-sys] version = "0.3" diff --git a/app/src/components/reset_password_step1.rs b/app/src/components/reset_password_step1.rs index b23ef49..7dd7d1a 100644 --- a/app/src/components/reset_password_step1.rs +++ b/app/src/components/reset_password_step1.rs @@ -97,7 +97,7 @@ impl Component for ResetPasswordStep1Form { class_valid="has-success" form=&self.form field_name="username" - placeholder="Username" + placeholder="Username or email" autocomplete="username" oninput=self.common.callback(|_| Msg::Update) /> diff --git a/app/src/infra/api.rs b/app/src/infra/api.rs index ba86114..a210b9a 100644 --- a/app/src/infra/api.rs +++ b/app/src/infra/api.rs @@ -268,7 +268,7 @@ impl HostService { callback: Callback>, ) -> Result { call_server_empty_response_with_error_message( - &format!("/auth/reset/step1/{}", username), + &format!("/auth/reset/step1/{}", url_escape::encode_query(username)), yew::format::Nothing, callback, "Could not initiate password reset", diff --git a/server/src/infra/auth_service.rs b/server/src/infra/auth_service.rs index 344d2ef..fdb18a4 100644 --- a/server/src/infra/auth_service.rs +++ b/server/src/infra/auth_service.rs @@ -22,6 +22,7 @@ use tracing::{debug, instrument, warn}; use lldap_auth::{login, password_reset, registration, JWTClaims}; +use crate::domain::handler::UserRequestFilter; use crate::{ domain::{ error::DomainError, @@ -139,21 +140,39 @@ async fn get_password_reset_step1( where Backend: TcpBackendHandler + BackendHandler + 'static, { - let user_id = match request.match_info().get("user_id") { - None => return Err(TcpError::BadRequest("Missing user ID".to_string())), - Some(id) => UserId::new(id), - }; - let token = match data.backend_handler.start_password_reset(&user_id).await? { + let user_string = request + .match_info() + .get("user_id") + .ok_or_else(|| TcpError::BadRequest("Missing user ID".to_string()))?; + let user_results = data + .backend_handler + .list_users( + Some(UserRequestFilter::Or(vec![ + UserRequestFilter::UserId(UserId::new(user_string)), + UserRequestFilter::Equality( + crate::domain::sql_tables::UserColumn::Email, + user_string.to_owned(), + ), + ])), + false, + ) + .await?; + if user_results.is_empty() { + return Ok(()); + } else if user_results.len() > 1 { + return Err(TcpError::InternalServerError( + "Ambiguous user id or email".to_owned(), + )); + } + let user = &user_results[0].user; + let token = match data + .backend_handler + .start_password_reset(&user.user_id) + .await? + { None => return Ok(()), Some(token) => token, }; - let user = match data.backend_handler.get_user_details(&user_id).await { - Err(e) => { - warn!("Error getting used details: {:#?}", e); - return Ok(()); - } - Ok(u) => u, - }; if let Err(e) = super::mail::send_password_reset_email( &user.display_name, &user.email,