diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 5dc678be6..d25d0bbcd 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -63,6 +63,9 @@ pub async fn match_websocket_operation( UserOperation::SaveUserSettings => { do_websocket_operation::(context, id, op, data).await } + UserOperation::ChangePassword => { + do_websocket_operation::(context, id, op, data).await + } UserOperation::GetReportCount => { do_websocket_operation::(context, id, op, data).await } diff --git a/crates/api/src/local_user.rs b/crates/api/src/local_user.rs index 656ddf971..d19171496 100644 --- a/crates/api/src/local_user.rs +++ b/crates/api/src/local_user.rs @@ -191,44 +191,9 @@ impl Perform for SaveUserSettings { let local_user_id = local_user_view.local_user.id; let person_id = local_user_view.person.id; - let password_encrypted = match &data.new_password { - Some(new_password) => { - match &data.new_password_verify { - Some(new_password_verify) => { - password_length_check(&new_password)?; - - // Make sure passwords match - if new_password != new_password_verify { - return Err(ApiError::err("passwords_dont_match").into()); - } - - // Check the old password - match &data.old_password { - Some(old_password) => { - let valid: bool = - verify(old_password, &local_user_view.local_user.password_encrypted) - .unwrap_or(false); - if !valid { - return Err(ApiError::err("password_incorrect").into()); - } - let new_password = new_password.to_owned(); - let user = blocking(context.pool(), move |conn| { - LocalUser::update_password(conn, local_user_id, &new_password) - }) - .await??; - user.password_encrypted - } - None => return Err(ApiError::err("password_incorrect").into()), - } - } - None => return Err(ApiError::err("passwords_dont_match").into()), - } - } - None => local_user_view.local_user.password_encrypted, - }; - let default_listing_type = data.default_listing_type; let default_sort_type = data.default_sort_type; + let password_encrypted = local_user_view.local_user.password_encrypted; let person_form = PersonForm { name: local_user_view.person.name, @@ -301,6 +266,49 @@ impl Perform for SaveUserSettings { } } +#[async_trait::async_trait(?Send)] +impl Perform for ChangePassword { + type Response = LoginResponse; + + async fn perform( + &self, + context: &Data, + _websocket_id: Option, + ) -> Result { + let data: &ChangePassword = &self; + let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; + + password_length_check(&data.new_password)?; + + // Make sure passwords match + if data.new_password != data.new_password_verify { + return Err(ApiError::err("passwords_dont_match").into()); + } + + // Check the old password + let valid: bool = verify( + &data.old_password, + &local_user_view.local_user.password_encrypted, + ) + .unwrap_or(false); + if !valid { + return Err(ApiError::err("password_incorrect").into()); + } + + let local_user_id = local_user_view.local_user.id; + let new_password = data.new_password.to_owned(); + let updated_local_user = blocking(context.pool(), move |conn| { + LocalUser::update_password(conn, local_user_id, &new_password) + }) + .await??; + + // Return the jwt + Ok(LoginResponse { + jwt: Claims::jwt(updated_local_user.id.0)?, + }) + } +} + #[async_trait::async_trait(?Send)] impl Perform for AddAdmin { type Response = AddAdminResponse; diff --git a/crates/api_common/src/person.rs b/crates/api_common/src/person.rs index 7767da460..53033a920 100644 --- a/crates/api_common/src/person.rs +++ b/crates/api_common/src/person.rs @@ -57,14 +57,19 @@ pub struct SaveUserSettings { pub email: Option, pub bio: Option, pub matrix_user_id: Option, - pub new_password: Option, - pub new_password_verify: Option, - pub old_password: Option, pub show_avatars: Option, pub send_notifications_to_email: Option, pub auth: String, } +#[derive(Deserialize)] +pub struct ChangePassword { + pub new_password: String, + pub new_password_verify: String, + pub old_password: String, + pub auth: String, +} + #[derive(Serialize)] pub struct LoginResponse { pub jwt: String, diff --git a/crates/websocket/src/lib.rs b/crates/websocket/src/lib.rs index 0b2a9fb4f..f5f5f0804 100644 --- a/crates/websocket/src/lib.rs +++ b/crates/websocket/src/lib.rs @@ -123,6 +123,7 @@ pub enum UserOperation { PostJoin, CommunityJoin, ModJoin, + ChangePassword, } #[derive(EnumString, ToString, Debug, Clone)] diff --git a/src/api_routes.rs b/src/api_routes.rs index e0158c338..f8e8f7e18 100644 --- a/src/api_routes.rs +++ b/src/api_routes.rs @@ -182,6 +182,10 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { "/save_user_settings", web::put().to(route_post::), ) + .route( + "/change_password", + web::put().to(route_post::), + ) .route("/report_count", web::get().to(route_get::)), ) // Admin Actions