diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 90895e4..7167c40 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] -axum = "0.8.4" +axum = { version = "0.8.4", features = ["query"] } dotenv = "0.15.0" env_logger = "0.11.8" log = "0.4.27" diff --git a/backend/src/api/warrens/create_directory.rs b/backend/src/api/warrens/create_directory.rs new file mode 100644 index 0000000..9896c7e --- /dev/null +++ b/backend/src/api/warrens/create_directory.rs @@ -0,0 +1,24 @@ +use axum::extract::{Path, State}; +use serde::Deserialize; +use uuid::Uuid; + +use crate::{Result, api::AppState, warrens::Warren}; + +#[derive(Debug, Deserialize)] +pub(super) struct CreateWarrenDirectoryPath { + warren_id: Uuid, + rest: String, +} + +pub(super) async fn route( + State(state): State, + Path(path): Path, +) -> Result<()> { + let warren = Warren::get(state.pool(), &path.warren_id).await?; + + warren + .create_directory(state.serve_dir(), path.rest) + .await?; + + Ok(()) +} diff --git a/backend/src/api/warrens/delete_directory.rs b/backend/src/api/warrens/delete_directory.rs new file mode 100644 index 0000000..4f647d8 --- /dev/null +++ b/backend/src/api/warrens/delete_directory.rs @@ -0,0 +1,31 @@ +use axum::extract::{Path, Query, State}; +use serde::Deserialize; +use uuid::Uuid; + +use crate::{Result, api::AppState, fs::FileType, warrens::Warren}; + +#[derive(Deserialize)] +pub(super) struct DeleteWarrenDirectoryPath { + warren_id: Uuid, + rest: String, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DeleteWarrenParams { + file_type: FileType, +} + +pub(super) async fn route( + State(state): State, + Path(path): Path, + Query(DeleteWarrenParams { file_type }): Query, +) -> Result<()> { + let warren = Warren::get(state.pool(), &path.warren_id).await?; + + warren + .delete_entry(state.serve_dir(), path.rest, file_type) + .await?; + + Ok(()) +} diff --git a/backend/src/api/warrens/mod.rs b/backend/src/api/warrens/mod.rs index d1961f9..9d5f3ed 100644 --- a/backend/src/api/warrens/mod.rs +++ b/backend/src/api/warrens/mod.rs @@ -1,7 +1,9 @@ +mod create_directory; +mod delete_directory; mod get_warren_path; mod list_warrens; -use axum::routing::get; +use axum::routing::{delete, get, post}; use crate::server::Router; @@ -10,4 +12,6 @@ pub(super) fn router() -> Router { .route("/", get(list_warrens::route)) .route("/{warren_id}", get(get_warren_path::route)) .route("/{warren_id}/{*rest}", get(get_warren_path::route)) + .route("/{warren_id}/{*rest}", post(create_directory::route)) + .route("/{warren_id}/{*rest}", delete(delete_directory::route)) } diff --git a/backend/src/fs/dir.rs b/backend/src/fs/dir.rs index 4c05911..4b71547 100644 --- a/backend/src/fs/dir.rs +++ b/backend/src/fs/dir.rs @@ -36,3 +36,21 @@ where Ok(files) } + +pub async fn create_dir

(path: P) -> Result<()> +where + P: AsRef, +{ + fs::create_dir(path).await?; + + Ok(()) +} + +pub async fn delete_dir

(path: P) -> Result<()> +where + P: AsRef, +{ + fs::remove_dir_all(path).await?; + + Ok(()) +} diff --git a/backend/src/fs/file.rs b/backend/src/fs/file.rs new file mode 100644 index 0000000..b637da5 --- /dev/null +++ b/backend/src/fs/file.rs @@ -0,0 +1,14 @@ +use std::path::Path; + +use tokio::fs; + +use crate::Result; + +pub async fn delete_file

(path: P) -> Result<()> +where + P: AsRef, +{ + fs::remove_file(path).await?; + + Ok(()) +} diff --git a/backend/src/fs/mod.rs b/backend/src/fs/mod.rs index b213365..f5381d4 100644 --- a/backend/src/fs/mod.rs +++ b/backend/src/fs/mod.rs @@ -1,9 +1,11 @@ mod dir; +mod file; pub use dir::*; +pub use file::*; -use serde::Serialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Copy, Serialize)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub enum FileType { File, diff --git a/backend/src/server.rs b/backend/src/server.rs index 4eb3219..f19c9b3 100644 --- a/backend/src/server.rs +++ b/backend/src/server.rs @@ -22,9 +22,11 @@ pub(super) async fn start(pool: Pool) -> Result<()> { let mut app = Router::new() .nest("/api", api::router()) .layer( - CorsLayer::new().allow_origin(cors::AllowOrigin::exact(HeaderValue::from_str( - &cors_origin, - )?)), + CorsLayer::new() + .allow_origin(cors::AllowOrigin::exact(HeaderValue::from_str( + &cors_origin, + )?)) + .allow_methods(cors::Any), ) .with_state(AppState::new(pool, serve_dir)); diff --git a/backend/src/warrens/mod.rs b/backend/src/warrens/mod.rs index 28d65d3..b655138 100644 --- a/backend/src/warrens/mod.rs +++ b/backend/src/warrens/mod.rs @@ -8,7 +8,7 @@ use uuid::Uuid; use crate::{ Result, - fs::{DirectoryEntry, get_dir_entries}, + fs::{DirectoryEntry, FileType, create_dir, delete_dir, delete_file, get_dir_entries}, }; #[derive(Debug, Clone, Serialize, FromRow)] @@ -40,14 +40,40 @@ impl Warren { serve_path: &str, path: Option, ) -> Result> { - let mut final_path = PathBuf::from(serve_path); + let path = build_path(serve_path, &self.path, path.as_deref()); - final_path.push(self.path.strip_prefix("/").unwrap_or(&self.path)); + get_dir_entries(path).await + } - if let Some(ref rest) = path { - final_path.push(rest); + pub async fn create_directory(&self, serve_path: &str, path: String) -> Result<()> { + let path = build_path(serve_path, &self.path, Some(&path)); + + create_dir(path).await + } + + pub async fn delete_entry( + &self, + serve_path: &str, + path: String, + file_type: FileType, + ) -> Result<()> { + let path = build_path(serve_path, &self.path, Some(&path)); + + match file_type { + FileType::File => delete_file(path).await, + FileType::Directory => delete_dir(path).await, } - - get_dir_entries(final_path).await } } + +fn build_path(serve_path: &str, warren_path: &str, rest_path: Option<&str>) -> PathBuf { + let mut final_path = PathBuf::from(serve_path); + + final_path.push(warren_path.strip_prefix("/").unwrap_or(warren_path)); + + if let Some(ref rest) = rest_path { + final_path.push(rest); + } + + final_path +} diff --git a/frontend/app.vue b/frontend/app.vue index b8dbd7a..b4c5566 100644 --- a/frontend/app.vue +++ b/frontend/app.vue @@ -1,4 +1,7 @@