diff --git a/server/src/fs/list.rs b/server/src/fs/list.rs new file mode 100644 index 0000000..dc7b474 --- /dev/null +++ b/server/src/fs/list.rs @@ -0,0 +1,68 @@ +use std::fs; + +use axum::{extract::rejection::JsonRejection, Extension, Json}; +use axum_auth::AuthBearer; +use homedisk_database::{Database, Error}; +use homedisk_types::{ + config::types::Config, + errors::{AuthError, FsError, ServerError}, + fs::list::{Request, Response}, +}; + +use crate::middleware::{validate_json, validate_jwt}; + +pub async fn handle( + db: Extension, + config: Extension, + AuthBearer(token): AuthBearer, + request: Result, JsonRejection>, +) -> Result, ServerError> { + let Json(request) = validate_json::(request)?; + let token = validate_jwt(config.jwt.secret.as_bytes(), &token)?; + + let response = match db.find_user_by_id(token.claims.sub).await { + Ok(res) => { + let user_path = format!( + "{path}/{username}/{request_path}", + path = config.storage.path, + username = res.username, + request_path = request.path, + ); + + let paths = fs::read_dir(&user_path) + .map_err(|err| ServerError::FsError(FsError::ReadDir(err.to_string())))?; + + let mut files = vec![]; + let mut dirs = vec![]; + + for path in paths { + let path = path + .map_err(|err| ServerError::FsError(FsError::UnknowError(err.to_string())))?; + let metadata = path + .metadata() + .map_err(|err| ServerError::FsError(FsError::UnknowError(err.to_string())))?; + + let name = path.path().display().to_string().replace(&user_path, ""); + + if metadata.is_dir() { + dirs.push(name) + } else { + files.push(name) + } + } + + Response { files, dirs } + } + + Err(err) => match err { + Error::UserNotFound => return Err(ServerError::AuthError(AuthError::UserNotFound)), + _ => { + return Err(ServerError::AuthError(AuthError::UnknowError( + err.to_string(), + ))) + } + }, + }; + + Ok(Json(response)) +} diff --git a/server/src/fs/mod.rs b/server/src/fs/mod.rs index f22c877..650c651 100644 --- a/server/src/fs/mod.rs +++ b/server/src/fs/mod.rs @@ -1,7 +1,10 @@ +pub mod list; pub mod upload; pub fn app() -> axum::Router { use axum::routing::post; - axum::Router::new().route("/upload", post(upload::handle)) + axum::Router::new() + .route("/list", post(list::handle)) + .route("/upload", post(upload::handle)) } diff --git a/types/src/errors/fs.rs b/types/src/errors/fs.rs index 6996982..ab99b0a 100644 --- a/types/src/errors/fs.rs +++ b/types/src/errors/fs.rs @@ -5,12 +5,15 @@ pub enum Error { #[error("file already exists")] FileAlreadyExists, - #[error("file already exists")] + #[error("write file error - {0}")] WriteFile(String), #[error("base64 - {0}")] Base64(String), + #[error("read dir error - {0}")] + ReadDir(String), + #[error("unknow error")] UnknowError(String), } diff --git a/types/src/errors/mod.rs b/types/src/errors/mod.rs index e8048db..fc92624 100644 --- a/types/src/errors/mod.rs +++ b/types/src/errors/mod.rs @@ -51,6 +51,7 @@ impl axum::response::IntoResponse for ServerError { FsError::FileAlreadyExists => StatusCode::BAD_REQUEST, FsError::WriteFile(_) => StatusCode::INTERNAL_SERVER_ERROR, FsError::Base64(_) => StatusCode::BAD_REQUEST, + FsError::ReadDir(_) => StatusCode::BAD_REQUEST, FsError::UnknowError(_) => StatusCode::INTERNAL_SERVER_ERROR, }, Self::TooManyRequests => StatusCode::TOO_MANY_REQUESTS, diff --git a/types/src/fs/list.rs b/types/src/fs/list.rs new file mode 100644 index 0000000..6b69503 --- /dev/null +++ b/types/src/fs/list.rs @@ -0,0 +1,12 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Request { + pub path: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Response { + pub files: Vec, + pub dirs: Vec, +} diff --git a/types/src/fs/mod.rs b/types/src/fs/mod.rs index 709ebba..b3f8ba9 100644 --- a/types/src/fs/mod.rs +++ b/types/src/fs/mod.rs @@ -1 +1,2 @@ +pub mod list; pub mod upload;