fix: percent-decode user_id route params for users with spaces in ID (#585)

This commit is contained in:
Xre0uS
2026-05-21 11:23:59 +08:00
committed by nitnelave
parent d293941a44
commit e567d17062
3 changed files with 22 additions and 4 deletions

1
Cargo.lock generated
View File

@@ -2743,6 +2743,7 @@ dependencies = [
"lldap_auth",
"lldap_frontend_options",
"lldap_validation",
"percent-encoding",
"rand 0.8.6",
"serde",
"serde_json",

View File

@@ -24,6 +24,7 @@ rand = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
strum = { workspace = true }
percent-encoding = "2"
url-escape = "0.1.1"
validator = "0.14"
validator_derive = "0.14"

View File

@@ -183,6 +183,16 @@ impl App {
}
}
/// Percent-decode a URL path segment into a user ID string.
/// Returns `None` if the decoded bytes are not valid UTF-8, so the caller
/// can redirect to a safe page rather than silently mangling the ID.
fn decode_user_id(raw: &str) -> Option<String> {
percent_encoding::percent_decode_str(raw)
.decode_utf8()
.ok()
.map(|s| s.into_owned())
}
fn dispatch_route(
switch: &AppRoute,
link: &Scope<Self>,
@@ -248,11 +258,17 @@ impl App {
AppRoute::GroupDetails { group_id } => html! {
<GroupDetails group_id={*group_id} is_admin={is_admin} />
},
AppRoute::UserDetails { user_id } => html! {
<UserDetails username={user_id.clone()} is_admin={is_admin} />
AppRoute::UserDetails { user_id } => match Self::decode_user_id(user_id) {
Some(decoded_id) => html! {
<UserDetails username={decoded_id} is_admin={is_admin} />
},
AppRoute::ChangePassword { user_id } => html! {
<ChangePasswordForm username={user_id.clone()} is_admin={is_admin} />
None => html! { <Redirect to={AppRoute::Login} /> },
},
AppRoute::ChangePassword { user_id } => match Self::decode_user_id(user_id) {
Some(decoded_id) => html! {
<ChangePasswordForm username={decoded_id} is_admin={is_admin} />
},
None => html! { <Redirect to={AppRoute::Login} /> },
},
AppRoute::StartResetPassword => match password_reset_enabled {
Some(true) => html! { <ResetPasswordStep1Form /> },