This commit is contained in:
2026-06-06 17:01:58 +02:00
10 changed files with 65 additions and 23 deletions
+1
View File
@@ -26,3 +26,4 @@ frontend/node_modules/
# Added by cargo # Added by cargo
/target /target
.antigravitycli/
+32 -21
View File
@@ -418,28 +418,39 @@ pub async fn update_user(
State(data): State<Arc<AppState>>, State(data): State<Arc<AppState>>,
Json(body): Json<UserUpdateScheme>, Json(body): Json<UserUpdateScheme>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> { ) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
let argon = Argon2::default(); let update_result = if !body.new_pwd.is_empty() {
let salt = SaltString::generate(&mut OsRng); let argon = Argon2::default();
let hashed_pwd = match argon.hash_password(body.new_pwd.clone().as_bytes(), &salt) { let salt = SaltString::generate(&mut OsRng);
Ok(h) => h.to_string(), let hashed_pwd = match argon.hash_password(body.new_pwd.clone().as_bytes(), &salt) {
Err(e) => panic!("Error hashing {:}", e), Ok(h) => h.to_string(),
}; Err(e) => panic!("Error hashing {:}", e),
};
let update_result = sqlx::query(r#"UPDATE users SET first_name = $1, last_name = $2, username = $3, pwd = $4, is_admin = $5 WHERE id = $6"#) sqlx::query(r#"UPDATE users SET first_name = $1, last_name = $2, username = $3, pwd = $4, is_admin = $5 WHERE id = $6"#)
.bind(body.first_name.to_owned()) .bind(body.first_name.to_owned())
.bind(body.last_name.to_owned()) .bind(body.last_name.to_owned())
.bind(body.username.to_owned()) .bind(body.username.to_owned())
.bind(&hashed_pwd) .bind(hashed_pwd)
.bind(body.make_admin.to_owned()) .bind(body.make_admin.to_owned())
.bind(id) .bind(id)
.execute(&data.db) .execute(&data.db)
.await .await
.map_err(|e| { } else {
( sqlx::query(r#"UPDATE users SET first_name = $1, last_name = $2, username = $3, is_admin = $4 WHERE id = $5"#)
StatusCode::INTERNAL_SERVER_ERROR, .bind(body.first_name.to_owned())
Json(json!({"status": "error", "message": format!("{:?}", e)})), .bind(body.last_name.to_owned())
) .bind(body.username.to_owned())
})?; .bind(body.make_admin.to_owned())
.bind(id)
.execute(&data.db)
.await
}
.map_err(|e| {
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({"status": "error", "message": format!("{:?}", e)})),
)
})?;
if update_result.rows_affected() == 0 { if update_result.rows_affected() == 0 {
let error_response = serde_json::json!({ let error_response = serde_json::json!({
+2
View File
@@ -4,6 +4,8 @@
<head> <head>
<link data-trunk rel="rust" data-bin="bin" /> <link data-trunk rel="rust" data-bin="bin" />
<link data-trunk rel="scss" href="src/styles/main.scss" /> <link data-trunk rel="scss" href="src/styles/main.scss" />
<link data-trunk rel="icon" href="src/assets/favicon.ico" type="image/x-icon" />
<link data-trunk rel="copy-dir" href="src/assets" />
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Yew App</title> <title>Yew App</title>
</head> </head>
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+1
View File
@@ -269,6 +269,7 @@ fn switch(route: Route) -> Html {
pub fn app() -> Html { pub fn app() -> Html {
html! { html! {
<BrowserRouter> <BrowserRouter>
<basic_pages::Icon/>
<Switch<Route> render={switch} /> <Switch<Route> render={switch} />
</BrowserRouter> </BrowserRouter>
} }
+7
View File
@@ -109,3 +109,10 @@ pub fn denied_component() -> Html {
</div> </div>
} }
} }
#[component(Icon)]
pub fn icon_component() -> Html {
html! {
<img src="assets/csg.png" class="csg-icon" />
}
}
+3 -1
View File
@@ -336,7 +336,7 @@ pub fn login_component() -> Html {
value={(*username).clone()} value={(*username).clone()}
oninput={Callback::from(move |e: InputEvent| { oninput={Callback::from(move |e: InputEvent| {
let input: web_sys::HtmlInputElement = e.target_unchecked_into(); let input: web_sys::HtmlInputElement = e.target_unchecked_into();
username.set(input.value()); username.set(input.value());
})} })}
/> />
<input <input
@@ -566,6 +566,7 @@ pub fn user_by_id_component(props: &UserProps) -> Html {
let last_name = (*last_name).clone(); let last_name = (*last_name).clone();
let username = (*username).clone(); let username = (*username).clone();
let make_admin = *make_admin; let make_admin = *make_admin;
let new_pwd_state = new_pwd.clone();
let new_pwd = (*new_pwd).clone(); let new_pwd = (*new_pwd).clone();
saving.set(true); saving.set(true);
@@ -600,6 +601,7 @@ pub fn user_by_id_component(props: &UserProps) -> Html {
if let Ok(updated) = resp.json::<FilteredUser>().await { if let Ok(updated) = resp.json::<FilteredUser>().await {
user_state.set(Some(updated)); user_state.set(Some(updated));
} }
new_pwd_state.set(String::new());
save_success.set(true); save_success.set(true);
} }
Ok(resp) => { Ok(resp) => {
+17
View File
@@ -0,0 +1,17 @@
.csg-icon {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 9999;
width: auto;
height: auto;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
img {
width: auto;
height: auto;
}
}
+2 -1
View File
@@ -6,6 +6,7 @@
@use "components/diagnostics"; @use "components/diagnostics";
@use "components/frontpage"; @use "components/frontpage";
@use "components/home"; @use "components/home";
@use "components/icon";
body { body {
background: variables.$color-bg; background: variables.$color-bg;
@@ -73,4 +74,4 @@ body {
button { button {
margin: 16px 0; margin: 16px 0;
} }
} }