use based::page::{Shell, render_page}; use based::request::api::FallibleApiResponse; use based::request::{RawResponse, RequestContext, StringResponse, respond_with}; use maud::html; use rocket::http::{ContentType, Status}; use rocket::tokio::io::AsyncReadExt; use rocket::{FromForm, get, post}; use serde_json::json; use crate::pkg::{Package, Repository}; // /pkg/// // /pkg/// use rocket::form::Form; use rocket::fs::TempFile; #[derive(FromForm)] pub struct PkgUpload<'r> { name: String, arch: String, version: String, pkg: TempFile<'r>, sig: Option>, } pub async fn tmp_file_to_vec<'r>(tmp: &TempFile<'r>) -> Vec { let mut buf = Vec::with_capacity(tmp.len() as usize); tmp.open() .await .unwrap() .read_to_end(&mut buf) .await .unwrap(); buf } #[post("/pkg//upload", data = "")] pub async fn upload_pkg( repo: &str, upload: Form>, user: based::auth::User, ) -> FallibleApiResponse { let pkg = Package::new(repo, &upload.arch, &upload.name, &upload.version); pkg.save( tmp_file_to_vec(&upload.pkg).await, if let Some(sig) = &upload.sig { Some(tmp_file_to_vec(sig).await) } else { None }, ); Ok(json!({"ok": 1})) } #[get("/pkg///")] pub async fn pkg_route(repo: &str, arch: &str, pkg_name: &str, ctx: RequestContext) -> RawResponse { if let Some(repo) = Repository::new(repo) { if pkg_name.ends_with("db.tar.gz") || pkg_name.ends_with("db") || pkg_name.ends_with("db.tar.gz.sig") || pkg_name.ends_with("db.sig") { if pkg_name.ends_with("sig") { return respond_with( Status::Ok, ContentType::new("application", "pgp-signature"), repo.sig_content(arch).unwrap(), ); } else { return respond_with( Status::Ok, ContentType::new("application", "tar"), repo.db_content(arch).unwrap(), ); } } let pkg = repo.get_pkg(arch, pkg_name).unwrap(); if pkg_name.ends_with("pkg.tar.zst") { return respond_with( Status::Ok, ContentType::new("application", "tar"), pkg.pkg_content().unwrap(), ); } else if pkg_name.ends_with("pkg.tar.zst.sig") { return respond_with( Status::Ok, ContentType::new("application", "pgp-signature"), pkg.sig_content().unwrap(), ); } } respond_with( Status::Ok, ContentType::Plain, "Not found".as_bytes().to_vec(), ) } #[get("/")] pub async fn index_page(ctx: RequestContext) -> StringResponse { let content = html!( h1 { "Hello World!" }; ); render_page( content, "Hello World", ctx, &Shell::new(html! {}, html! {}, Some(String::new())), ) .await }