repositories.rs
1 use rocket::{serde::json::Json, State}; 2 use serde::Serialize; 3 use sqlx::{ 4 types::chrono::{DateTime, Utc}, 5 Pool, 6 }; 7 8 use crate::{ 9 db::DB, 10 models::repository::ViewableRepository, 11 services::{ 12 get_all_repositories_service, 13 get_repository_service::{self, RepositoryInfo}, 14 }, 15 }; 16 17 #[derive(Responder, Debug)] 18 pub enum GetRepositoriesResponse { 19 #[response(status = 200)] 20 Success(Json<GetRepositoriesResponseData>), 21 #[response(status = 500)] 22 Failure(String), 23 } 24 25 #[derive(Debug, Clone, Serialize)] 26 pub struct GetRepositoriesResponseData { 27 repositories: Vec<Repository>, 28 } 29 30 #[derive(Debug, Clone, Serialize)] 31 #[serde(rename_all = "camelCase")] 32 pub struct Repository { 33 name: String, 34 author: String, 35 last_modified: DateTime<Utc>, 36 } 37 38 impl From<ViewableRepository> for Repository { 39 fn from(value: ViewableRepository) -> Self { 40 Self { 41 name: value.namespace_name, 42 author: value.username, 43 last_modified: value.created_at, 44 } 45 } 46 } 47 48 #[get("/repositories")] 49 pub async fn get_all_repositories(db_pool: &State<Pool<DB>>) -> GetRepositoriesResponse { 50 let repos = match get_all_repositories_service::get_all_repositories(db_pool).await { 51 Ok(repos) => repos, 52 Err(err) => { 53 error!("Failed to retrieve all repositories, err: {err:?}"); 54 return GetRepositoriesResponse::Failure("Failed to retrieve repositories".to_string()); 55 } 56 }; 57 58 GetRepositoriesResponse::Success(Json(GetRepositoriesResponseData { 59 repositories: repos 60 .into_iter() 61 .map(|r| r.into()) 62 .collect::<Vec<Repository>>(), 63 })) 64 } 65 66 #[derive(Responder, Debug)] 67 pub enum GetRepositoryResponse { 68 #[response(status = 200)] 69 Success(Json<GetRepositoryResponseData>), 70 #[response(status = 404)] 71 RepositoryNotFound(String), 72 #[response(status = 500)] 73 Failure(String), 74 } 75 76 #[derive(Debug, Clone, Serialize)] 77 #[serde(rename_all = "camelCase")] 78 pub struct GetRepositoryResponseData { 79 name: String, 80 author: String, 81 tags: Vec<Tag>, 82 } 83 84 impl From<RepositoryInfo> for GetRepositoryResponseData { 85 fn from(value: RepositoryInfo) -> Self { 86 Self { 87 name: value.name, 88 author: value.owner_username, 89 tags: value 90 .tags 91 .into_iter() 92 .map(|manifest| Tag { 93 name: manifest.tag.unwrap_or("latest".to_string()), 94 created_at: manifest.created_at, 95 }) 96 .collect::<Vec<Tag>>(), 97 } 98 } 99 } 100 101 #[derive(Debug, Clone, Serialize)] 102 #[serde(rename_all = "camelCase")] 103 pub struct Tag { 104 name: String, 105 created_at: DateTime<Utc>, 106 } 107 108 #[get("/repositories/<repository>")] 109 pub async fn get_repository(db_pool: &State<Pool<DB>>, repository: &str) -> GetRepositoryResponse { 110 let repository = match get_repository_service::get_repository(db_pool, repository).await { 111 Ok(data) => data, 112 Err(err) => { 113 // TODO: Handle not found 114 warn!("Failed to retrieve repository, err: {err:?}"); 115 return GetRepositoryResponse::Failure("Failed to retrieve repository".to_string()); 116 } 117 }; 118 119 return GetRepositoryResponse::Success(Json(repository.into())); 120 }