diff --git a/mdf-bouncer/src/main.rs b/mdf-bouncer/src/main.rs index 63d4ddb..6c550f8 100644 --- a/mdf-bouncer/src/main.rs +++ b/mdf-bouncer/src/main.rs @@ -1,6 +1,8 @@ use std::{env::{args, var}, io, sync::Arc}; -use axum::{Router, body::{Body, Bytes}, extract::{DefaultBodyLimit, Path, State}, routing::{delete, post, put}}; +use axum::{Router, body::{Body, Bytes}, extract::{DefaultBodyLimit, Path, State}, http::StatusCode, routing::{delete, post, put}}; +use log::info; +use tokio::fs; use std::path::PathBuf; const MAXIMUM_PACKET_SIZE: usize = (2 << 20) * 10; @@ -12,6 +14,7 @@ struct AppState { #[tokio::main] async fn main() -> io::Result<()> { + pretty_env_logger::init(); // get secret from secret file let mut args = args().skip(1); let target_path = args.next().expect("need to specify target path"); @@ -39,13 +42,41 @@ async fn main() -> io::Result<()> { Ok(()) } -async fn delete_file(State(state): State>, Path(path): Path) { - println!("about to delete: {path}"); +async fn delete_file(State(state): State>, Path(path): Path) -> Result { + let full_path = safe_join(&state.root, &path)?; + info!("about to delete: {:?}", full_path); + + fs::remove_file(full_path) + .await + .map_err(|_| StatusCode::NOT_FOUND)?; + + Ok(StatusCode::NO_CONTENT) } -async fn put_file(State(state): State>, Path(path): Path, body: Bytes) { - println!("about to put: {path}"); - let bytes = Vec::from(body); - println!("body: {:?}", bytes); +async fn put_file(State(state): State>, Path(path): Path, body: Bytes) -> Result { + let full_path = safe_join(&state.root, &path)?; + info!("about to put: {:?}", full_path); + + if let Some(parent) = full_path.parent() { + fs::create_dir_all(parent).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + } + fs::write(full_path, body) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + Ok(StatusCode::CREATED) } +/// Make supplied path does not contain anything other than relative +/// paths. +fn safe_join(base: &PathBuf, user_path: &str) -> Result { + let mut full = base.clone(); + let path = PathBuf::from(user_path); + for comp in path.components() { + match comp { + std::path::Component::Normal(p) => full.push(p), + _ => return Err(StatusCode::BAD_REQUEST), + } + } + Ok(full) +}