Something went wrong. Try again.
PDS software with bells & whistles you didn’t even know you needed. will move this to its own account when ready.
Something went wrong. Try again.
5.6 kB · 227 lines
Rust
at commit 2f185d97
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228use crate::state::AppState;use axum::{ Json, extract::{Query, State}, http::StatusCode, response::{IntoResponse, Response},};use serde::{Deserialize, Serialize};use serde_json::json;use tracing::error;
#[derive(Deserialize)]pub struct GetLatestCommitParams { pub did: String,}
#[derive(Serialize)]pub struct GetLatestCommitOutput { pub cid: String, pub rev: String,}
pub async fn get_latest_commit( State(state): State<AppState>, Query(params): Query<GetLatestCommitParams>,) -> Response { let did = params.did.trim();
if did.is_empty() { return ( StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidRequest", "message": "did is required"})), ) .into_response(); }
let result = sqlx::query!( r#" SELECT r.repo_root_cid FROM repos r JOIN users u ON r.user_id = u.id WHERE u.did = $1 "#, did ) .fetch_optional(&state.db) .await;
match result { Ok(Some(row)) => { ( StatusCode::OK, Json(GetLatestCommitOutput { cid: row.repo_root_cid, rev: chrono::Utc::now().timestamp_millis().to_string(), }), ) .into_response() } Ok(None) => ( StatusCode::NOT_FOUND, Json(json!({"error": "RepoNotFound", "message": "Could not find repo for DID"})), ) .into_response(), Err(e) => { error!("DB error in get_latest_commit: {:?}", e); ( StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"})), ) .into_response() } }}
#[derive(Deserialize)]pub struct ListReposParams { pub limit: Option<i64>, pub cursor: Option<String>,}
#[derive(Serialize)]#[serde(rename_all = "camelCase")]pub struct RepoInfo { pub did: String, pub head: String, pub rev: String, pub active: bool,}
#[derive(Serialize)]pub struct ListReposOutput { pub cursor: Option<String>, pub repos: Vec<RepoInfo>,}
pub async fn list_repos( State(state): State<AppState>, Query(params): Query<ListReposParams>,) -> Response { let limit = params.limit.unwrap_or(50).clamp(1, 1000); let cursor_did = params.cursor.as_deref().unwrap_or("");
let result = sqlx::query!( r#" SELECT u.did, r.repo_root_cid FROM repos r JOIN users u ON r.user_id = u.id WHERE u.did > $1 ORDER BY u.did ASC LIMIT $2 "#, cursor_did, limit + 1 ) .fetch_all(&state.db) .await;
match result { Ok(rows) => { let has_more = rows.len() as i64 > limit; let repos: Vec<RepoInfo> = rows .iter() .take(limit as usize) .map(|row| { RepoInfo { did: row.did.clone(), head: row.repo_root_cid.clone(), rev: chrono::Utc::now().timestamp_millis().to_string(), active: true, } }) .collect();
let next_cursor = if has_more { repos.last().map(|r| r.did.clone()) } else { None };
( StatusCode::OK, Json(ListReposOutput { cursor: next_cursor, repos, }), ) .into_response() } Err(e) => { error!("DB error in list_repos: {:?}", e); ( StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"})), ) .into_response() } }}
#[derive(Deserialize)]pub struct GetRepoStatusParams { pub did: String,}
#[derive(Serialize)]pub struct GetRepoStatusOutput { pub did: String, pub active: bool, pub rev: Option<String>,}
pub async fn get_repo_status( State(state): State<AppState>, Query(params): Query<GetRepoStatusParams>,) -> Response { let did = params.did.trim();
if did.is_empty() { return ( StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidRequest", "message": "did is required"})), ) .into_response(); }
let result = sqlx::query!( r#" SELECT u.did, r.repo_root_cid FROM users u LEFT JOIN repos r ON u.id = r.user_id WHERE u.did = $1 "#, did ) .fetch_optional(&state.db) .await;
match result { Ok(Some(row)) => { let rev = Some(chrono::Utc::now().timestamp_millis().to_string());
( StatusCode::OK, Json(GetRepoStatusOutput { did: row.did, active: true, rev, }), ) .into_response() } Ok(None) => ( StatusCode::NOT_FOUND, Json(json!({"error": "RepoNotFound", "message": "Could not find repo for DID"})), ) .into_response(), Err(e) => { error!("DB error in get_repo_status: {:?}", e); ( StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"})), ) .into_response() } }}