this repo has no description
1use crate::api::error::ApiError;
2use crate::state::AppState;
3use crate::types::AtIdentifier;
4use axum::{
5 Json,
6 extract::{Query, State},
7 response::{IntoResponse, Response},
8};
9use serde::Deserialize;
10use serde_json::json;
11
12#[derive(Deserialize)]
13pub struct DescribeRepoInput {
14 pub repo: AtIdentifier,
15}
16
17pub async fn describe_repo(
18 State(state): State<AppState>,
19 Query(input): Query<DescribeRepoInput>,
20) -> Response {
21 let hostname = std::env::var("PDS_HOSTNAME").unwrap_or_else(|_| "localhost".to_string());
22 let user_row = if input.repo.is_did() {
23 sqlx::query!(
24 "SELECT id, handle, did FROM users WHERE did = $1",
25 input.repo.as_str()
26 )
27 .fetch_optional(&state.db)
28 .await
29 .map(|opt| opt.map(|r| (r.id, r.handle, r.did)))
30 } else {
31 let repo_str = input.repo.as_str();
32 let handle = if !repo_str.contains('.') {
33 format!("{}.{}", repo_str, hostname)
34 } else {
35 repo_str.to_string()
36 };
37 sqlx::query!(
38 "SELECT id, handle, did FROM users WHERE handle = $1",
39 handle
40 )
41 .fetch_optional(&state.db)
42 .await
43 .map(|opt| opt.map(|r| (r.id, r.handle, r.did)))
44 };
45 let (user_id, handle, did) = match user_row {
46 Ok(Some((id, handle, did))) => (id, handle, did),
47 Ok(None) => {
48 return ApiError::RepoNotFound(Some("Repo not found".into())).into_response();
49 }
50 Err(_) => {
51 return ApiError::InternalError(None).into_response();
52 }
53 };
54 let collections_query = sqlx::query!(
55 "SELECT DISTINCT collection FROM records WHERE repo_id = $1",
56 user_id
57 )
58 .fetch_all(&state.db)
59 .await;
60 let collections: Vec<String> = match collections_query {
61 Ok(rows) => rows.iter().map(|r| r.collection.clone()).collect(),
62 Err(_) => Vec::new(),
63 };
64 let did_doc = json!({
65 "id": did,
66 "alsoKnownAs": [format!("at://{}", handle)]
67 });
68 Json(json!({
69 "handle": handle,
70 "did": did,
71 "didDoc": did_doc,
72 "collections": collections,
73 "handleIsCorrect": true
74 }))
75 .into_response()
76}