From 633e67084095a672dc029e9bdbb7974ae897c226 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Mon, 27 May 2024 09:50:10 +0200 Subject: [PATCH] feat: partially implemented package GET request --- Cargo.lock | 1 + server/Cargo.toml | 1 + server/src/cli.rs | 3 ++ server/src/db/query/package.rs | 18 ++++++-- server/src/main.rs | 1 + server/src/repo/manager_new.rs | 13 ++++-- server/src/repo/mod.rs | 79 +++++++++++++--------------------- 7 files changed, 61 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 333bc72..d0c00b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1660,6 +1660,7 @@ dependencies = [ "futures", "http-body-util", "libarchive", + "regex", "sea-orm", "sea-orm-migration", "serde", diff --git a/server/Cargo.toml b/server/Cargo.toml index c2c5d74..1d5dc1d 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -13,6 +13,7 @@ clap = { version = "4.3.12", features = ["env", "derive"] } futures = "0.3.28" http-body-util = "0.1.1" libarchive = { path = "../libarchive" } +regex = "1.10.4" sea-orm-migration = "0.12.1" serde = { version = "1.0.178", features = ["derive"] } sha256 = "1.1.4" diff --git a/server/src/cli.rs b/server/src/cli.rs index 0c802f2..35245c2 100644 --- a/server/src/cli.rs +++ b/server/src/cli.rs @@ -91,10 +91,13 @@ impl Cli { }; let repo_manager = MetaRepoMgr::new(&config.repo_dir, &self.pkg_dir); + let pkg_filename_re = regex::Regex::new(r"^([a-z0-9@_+][a-z0-9@_+-.]*)-((?:[0-9]+:)?[a-z0-9._]+-[0-9.]+)-([a-z0-9_]+)\.pkg\.tar\.([a-z0-9]+)$").unwrap(); + let global = Global { config, repo_manager: Arc::new(RwLock::new(repo_manager)), db, + pkg_filename_re, }; // build our application with a single route diff --git a/server/src/db/query/package.rs b/server/src/db/query/package.rs index ecd306e..c5ad135 100644 --- a/server/src/db/query/package.rs +++ b/server/src/db/query/package.rs @@ -47,13 +47,23 @@ pub async fn by_fields( repo_id: i32, arch: &str, name: &str, + version: Option<&str>, + compression: Option<&str>, ) -> Result> { - Package::find() + let mut query = Package::find() .filter(package::Column::RepoId.eq(repo_id)) .filter(package::Column::Name.eq(name)) - .filter(package::Column::Arch.eq(arch)) - .one(conn) - .await + .filter(package::Column::Arch.eq(arch)); + + if let Some(version) = version { + query = query.filter(package::Column::Version.eq(version)); + } + + if let Some(compression) = compression { + query = query.filter(package::Column::Compression.eq(compression)); + } + + query.one(conn).await } pub async fn delete_with_arch(conn: &DbConn, repo_id: i32, arch: &str) -> Result { diff --git a/server/src/main.rs b/server/src/main.rs index 7038203..6ea2a04 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -25,6 +25,7 @@ pub struct Global { config: Config, repo_manager: Arc>, db: sea_orm::DbConn, + pkg_filename_re: regex::Regex, } #[tokio::main] diff --git a/server/src/repo/manager_new.rs b/server/src/repo/manager_new.rs index 9728764..05cdc16 100644 --- a/server/src/repo/manager_new.rs +++ b/server/src/repo/manager_new.rs @@ -135,7 +135,7 @@ impl MetaRepoMgr { let repo = db::query::repo::by_name(conn, repo).await?; if let Some(repo) = repo { - let pkg = db::query::package::by_fields(conn, repo.id, arch, name).await?; + let pkg = db::query::package::by_fields(conn, repo.id, arch, name, None, None).await?; if let Some(pkg) = pkg { // Remove package from database @@ -180,8 +180,15 @@ impl MetaRepoMgr { }; // If the package already exists in the database, we remove it first - let res = - db::query::package::by_fields(conn, repo_id, &pkg.info.arch, &pkg.info.name).await?; + let res = db::query::package::by_fields( + conn, + repo_id, + &pkg.info.arch, + &pkg.info.name, + None, + None, + ) + .await?; if let Some(entry) = res { entry.delete(conn).await?; diff --git a/server/src/repo/mod.rs b/server/src/repo/mod.rs index 1992e22..f63a489 100644 --- a/server/src/repo/mod.rs +++ b/server/src/repo/mod.rs @@ -19,6 +19,7 @@ use axum::routing::{delete, post}; use axum::Router; use futures::TryStreamExt; use futures::{Stream, StreamExt}; +use regex::Regex; use sea_orm::ModelTrait; use std::sync::Arc; use tokio::{fs, io::AsyncWriteExt}; @@ -56,52 +57,43 @@ pub fn router(api_key: &str) -> Router { /// is returned. async fn get_file( State(global): State, - Path((repo, arch, mut file_name)): Path<(String, String, String)>, + Path((repo, _arch, file_name)): Path<(String, String, String)>, req: Request, ) -> crate::Result { - let repo_dir = global.config.repo_dir.join(&repo).join(&arch); - let repo_exists = tokio::fs::try_exists(&repo_dir).await?; + // Query the repo to see if it exists + let repo = db::query::repo::by_name(&global.db, &repo) + .await? + .ok_or(StatusCode::NOT_FOUND)?; - let res = if DB_FILE_EXTS.iter().any(|ext| file_name.ends_with(ext)) { - // Append tar extension to ensure we find the file - if !file_name.ends_with(".tar.gz") { - file_name.push_str(".tar.gz"); - }; + // Match the filename + let caps = global + .pkg_filename_re + .captures(&file_name) + .ok_or(StatusCode::NOT_FOUND)?; + let arch = caps.get(3).unwrap().as_str(); - if repo_exists { - ServeFile::new(repo_dir.join(file_name)).oneshot(req).await - } else { - let path = global - .config - .repo_dir - .join(repo) - .join(manager::ANY_ARCH) - .join(file_name); + // Query the package to see if it exists + let pkg = db::query::package::by_fields( + &global.db, + repo.id, + arch, + caps.get(1).unwrap().as_str(), + Some(caps.get(2).unwrap().as_str()), + Some(caps.get(4).unwrap().as_str()), + ) + .await? + .ok_or(StatusCode::NOT_FOUND)?; - ServeFile::new(path).oneshot(req).await - } - } else { - let any_file = global - .config - .pkg_dir - .join(repo) - .join(manager::ANY_ARCH) - .join(file_name); - - if repo_exists { - ServeDir::new(global.config.pkg_dir) - .fallback(ServeFile::new(any_file)) - .oneshot(req) - .await - } else { - ServeFile::new(any_file).oneshot(req).await - } - }; - - Ok(res) + // Serve the file if it idoes + let pkg_path = global + .config + .pkg_dir + .join(repo.name) + .join(arch) + .join(package::filename(&pkg)); + Ok(ServeFile::new(pkg_path).oneshot(req).await.unwrap()) } -#[axum::debug_handler] async fn post_package_archive( State(global): State, Path(repo): Path, @@ -122,7 +114,6 @@ async fn post_package_archive( //tracing::info!("Added '{}' to repository '{}'", pkg.file_name(), repo); } -#[axum::debug_handler] async fn delete_repo( State(global): State, Path(repo): Path, @@ -207,11 +198,3 @@ async fn delete_package( // Ok(StatusCode::NOT_FOUND) //} } - -fn help_me_figure_this_out(_: impl Send) {} - -#[allow(dead_code)] -fn assert_my_handler_is_ok() { - // This is the fun part: we need to call our handler, and *not* await it's Future. - help_me_figure_this_out(delete_repo) -}