add pc boot support, update cargo.lock
All checks were successful
build docker container automatically / build (push) Successful in 7m7s

This commit is contained in:
2026-07-10 22:33:37 +02:00
parent 0e05fbf08f
commit 4684b0c5ea
7 changed files with 788 additions and 611 deletions

1293
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@ dioxus-asset-resolver = "0.7.4"
dioxus-html = "0.7.3" dioxus-html = "0.7.3"
dioxus-primitives = { git = "https://github.com/DioxusLabs/components", version = "0.0.1", default-features = false } dioxus-primitives = { git = "https://github.com/DioxusLabs/components", version = "0.0.1", default-features = false }
futures = "0.3.32" futures = "0.3.32"
pbkdf2 = { version = "0.13.0", features = ["sha2", "password-hash", "mcf", "alloc"] }
random-string = "1.1.0" random-string = "1.1.0"
reqwest = { version = "0.13.2", features = ["stream"] } reqwest = { version = "0.13.2", features = ["stream"] }
serde = "1.0.228" serde = "1.0.228"

10
gen_pass.py Normal file
View File

@ -0,0 +1,10 @@
from passlib.hash import pbkdf2_sha512
def pbkdf2_sha512_mcf(password: str) -> str:
return pbkdf2_sha512.using(
rounds=100_000,
salt_size=16,
).hash(password)
p = input("pass (will echo) :")
print(pbkdf2_sha512_mcf(p))

87
src/api/boot.rs Normal file
View File

@ -0,0 +1,87 @@
use dioxus::prelude::*;
use httpserver::config::ServerConfig;
use pbkdf2::{
Algorithm::Pbkdf2Sha512, PasswordVerifier, Pbkdf2, mcf::PasswordHash
};
use tokio::net::TcpStream;
use tokio::io::AsyncWriteExt;
use tokio::io::AsyncReadExt;
use std::error::Error;
static COMMANDS: [(&str, u8); 3] = [("start", 0x1) , ("stop", 0x2), ("reboot", 0x3)];
#[post("/api/pc/boot")]
async fn pc_boot(command: String, pass: String) -> Result<String, HttpError> {
let conf = ServerConfig::load();
let pbkdf_conf = pbkdf2::Params::new(10000).expect("invalid pdkdf2 iterations number");
let hash = Pbkdf2::new(Pbkdf2Sha512, pbkdf_conf); //iterations ignored on verify
let ref_pass = PasswordHash::new(&conf.pc_boot_pass_hash).expect("invalid password set");
let pass_bytes = pass.as_bytes();
if let Err(e) = hash.verify_password(&pass_bytes, &ref_pass)
{
println!("invalid password : {}", e);
return HttpError::forbidden("Invalid password provided");
}
let found_command = COMMANDS.iter().find(|&x| x.0 == command.to_lowercase());
if found_command == None {
return HttpError::bad_request("Invalid command")
}
let res = match esp_boot_request(found_command.unwrap().1).await {
Ok(r) => r,
Err(_) => { return HttpError::internal_server_error("esp unavailable"); }
};
match res {
0 => { return Ok("Success".to_string()) },
1 => { return Ok("Failed".to_string()) },
_ => { return Ok("Invalid response".to_string()) }
}
Ok("Hello".to_string())
}
#[get("/api/pc/status")]
async fn pc_status() -> Result<i32, HttpError> {
let res = match esp_boot_request(0x00).await {
Ok(r) => r,
Err(_) => { return HttpError::internal_server_error("esp unavailable"); }
};
return Ok(res);
}
async fn esp_boot_request(command: u8) -> Result<i32, tokio::io::Error> {
let mut stream = None;
let mut retry = 3;
println!("send request to esp");
loop {
if retry == 0 {
return Err(tokio::io::ErrorKind::ConnectionRefused.into());
}
if let Ok(strm) = TcpStream::connect("192.168.1.40:80").await {
stream = Some(strm);
break;
};
retry -= 1;
}
let mut buf = [command ;1];
stream.as_mut().unwrap().write_all(&buf).await?;
let read_bytes = stream.as_mut().unwrap().read(&mut buf).await?;
if read_bytes != 1 {
panic!("invalid response");
}
Ok(buf[0].into())
}

1
src/api/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod boot;

View File

@ -5,6 +5,8 @@ pub struct ServerConfig {
pub upload_storage_limit_soft: u64, pub upload_storage_limit_soft: u64,
pub upload_storage_limit_hard: u64, pub upload_storage_limit_hard: u64,
pub pc_boot_pass_hash: String,
} }
#[cfg(feature = "server")] #[cfg(feature = "server")]
@ -14,6 +16,8 @@ impl ServerConfig {
upload_folder: "./uploads/".to_string(), upload_folder: "./uploads/".to_string(),
db_url: std::env::var("HTTPSERVER_DATABASE_URL").expect("missing HTTPSERVER_DATABASE_URL"), db_url: std::env::var("HTTPSERVER_DATABASE_URL").expect("missing HTTPSERVER_DATABASE_URL"),
pc_boot_pass_hash: std::env::var("PC_BOOT_PASS_HASH").expect("missing PC_BOOT_PASS_HASH env var"),
upload_storage_limit_soft: 1024 * 1024 * 1024 * 200, upload_storage_limit_soft: 1024 * 1024 * 1024 * 200,
upload_storage_limit_hard: 1024 * 1024 * 1024 * 300, upload_storage_limit_hard: 1024 * 1024 * 1024 * 300,
} }

View File

@ -31,6 +31,9 @@ use tasks::scheduled_tasks_loop;
mod components; mod components;
mod views; mod views;
#[cfg(feature = "server")]
mod api;
#[derive(Debug, Clone, Routable, PartialEq)] #[derive(Debug, Clone, Routable, PartialEq)]
#[rustfmt::skip] #[rustfmt::skip]
enum Route { enum Route {