turned on WAL on db, fix force update of passwords

This commit is contained in:
2025-10-11 03:18:12 +02:00
parent 008fc377ec
commit 11c3fa56d2
15 changed files with 253 additions and 30 deletions

View File

@@ -106,10 +106,15 @@ fn hash_password(password: &str) -> anyhow::Result<String> {
// Verify an incoming password against stored hash
fn verify_password(password: &str, stored_hash: &str) -> bool {
let parsed_hash = PasswordHash::new(stored_hash).unwrap();
let parsed_hash = match PasswordHash::new(&stored_hash) {
Ok(hash) => hash,
Err(_) => return false,
};
Argon2::default()
.verify_password(password.as_bytes(), &parsed_hash)
.is_ok()
.verify_password(password.as_bytes(), &parsed_hash).is_ok()
}
#[derive(Deserialize, Debug)]
@@ -155,6 +160,133 @@ pub async fn register_user (
Ok((StatusCode::CREATED, "User registered successfully"))
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ForceUpdatePasswordValues{
username: String,
newpassword: String,
hotel_id: i32,
admin_pass: String,
}
//pub struct ForceUpdatePasswordPayload (pub ForceUpdatePasswordValues);
pub async fn ForceUpdatePassword(
State(state): State<AppState>,
Json(payload): Json<ForceUpdatePasswordValues>,
) -> impl IntoResponse {
let conn = match state.logs_pool.get() {
Ok(c) => c,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB, conn failed").into_response()
};
let user_row = match conn.query_row(
"SELECT id FROM users WHERE username = ?1 AND hotel_id = ?2",
params![&payload.username, &payload.hotel_id],
|row|{
let user_id: i32 = row.get(0)?;
//let hotel_id: i32 = row.get(1)?;
Ok((user_id))
},
).optional() {
Ok(opt) => opt,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB query error")
.into_response(),
};
let (user_id) = match user_row {
Some(u) => u,
None => return (StatusCode::UNAUTHORIZED, "Not correct user")
.into_response(),
};
let admin_check: String = "my_admin_password".to_string();
if &payload.admin_pass != &admin_check {
return (StatusCode::UNAUTHORIZED, "Invalid Amin Password").into_response()
};
let hashed_password = match hash_password(&payload.newpassword) {
Ok(h) => h,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Password hashing failed").into_response(),
};
let result = conn.execute(
"UPDATE users SET password = ?1 WHERE id = ?2",
params![&hashed_password, &user_id],
);
match result {
Ok(rows) if rows > 0 => (StatusCode::OK, "Password updated").into_response(),
Ok(_) => (StatusCode::NOT_FOUND, "User not found").into_response(),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Failed to update password").into_response(),
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct UpdatePasswordValues{
username: String,
current_password: String,
newpassword: String,
hotel_id: i32,
}
pub async fn UpdatePassword(
State(state): State<AppState>,
Json(payload): Json<UpdatePasswordValues>,
) -> impl IntoResponse {
let conn = match state.logs_pool.get() {
Ok(c) => c,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB, conn failed").into_response()
};
let user_row = match conn.query_row(
"SELECT password, id FROM users WHERE username = ?1 AND current_password = ?2",
params![&payload.username, &payload.current_password],
|row|{
let password: String = row.get(0)?;
let id: i32 = row.get(1)?;
Ok((password, id))
},
).optional() {
Ok(opt) => opt,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "DB query error")
.into_response(),
};
let (password, user_id) = match user_row {
Some(u) => u,
None => return (StatusCode::UNAUTHORIZED, "Not correct user")
.into_response(),
};
if verify_password( &payload.current_password, &password ) {
return (StatusCode::UNAUTHORIZED, "Invalid Password").into_response()
};
let hashed_password = match hash_password(&payload.newpassword) {
Ok(h) => h,
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Password hashing failed").into_response(),
};
let result = conn.execute(
"UPDATE users SET password = ?1 WHERE id = ?2",
params![&hashed_password, &user_id],
);
match result {
Ok(rows) if rows > 0 => (StatusCode::OK, "Password updated").into_response(),
Ok(_) => (StatusCode::NOT_FOUND, "User not found").into_response(),
Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Failed to update password").into_response(),
}
}
#[derive(Deserialize, Debug)]
pub struct LoginValues {
username : String,
@@ -227,11 +359,14 @@ pub async fn clean_auth_loging(
return (StatusCode::UNAUTHORIZED, "Invelid credentials").into_response();
}
let expiration = chrono::Utc::now()
.checked_add_signed(chrono::Duration::hours(15))
.unwrap()
.timestamp() as usize;
let expiration = match chrono::Utc::now().checked_add_signed(chrono::Duration::hours(15)) {
Some(time) => time.timestamp() as usize,
None => {
// Handle overflow — probably a 500, since this should never happen
return (StatusCode::INTERNAL_SERVER_ERROR, "Time overflow".to_string()).into_response();
}
};
let claims = serde_json::json!({
"id": user_id,
@@ -251,6 +386,11 @@ pub async fn clean_auth_loging(
Json(LoginResponse { token }).into_response()
}
fn internal_error<E: std::fmt::Display>(err: E) -> (StatusCode, String) {
(StatusCode::INTERNAL_SERVER_ERROR, format!("Internal error: {}", err))
}

View File

@@ -15,6 +15,8 @@ pub fn utils_routes() -> Router<AppState> {
.route("/register", put(register_user))
.route("/ws/", get(ws_handler))
.route("/tokentest", put(token_tester))
.route("/force_update_password", put(ForceUpdatePassword))
.route("/update_password", put(UpdatePassword))
//.with_state(state)
}