Skip to main content

jax_daemon/http_server/api/v0/bucket/
shares.rs

1use axum::extract::{Json, State};
2use axum::response::{IntoResponse, Response};
3use common::mount::PrincipalRole;
4use common::prelude::MountError;
5use reqwest::{Client, RequestBuilder, Url};
6use serde::{Deserialize, Serialize};
7use uuid::Uuid;
8
9use crate::http_server::api::client::ApiRequest;
10use crate::ServiceState;
11
12#[derive(Debug, Clone, Serialize, Deserialize, clap::Args)]
13pub struct SharesRequest {
14    /// Bucket ID to list shares for
15    #[arg(long)]
16    pub bucket_id: Uuid,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct SharesResponse {
21    pub bucket_id: Uuid,
22    pub self_key: String,
23    pub shares: Vec<ShareInfo>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct ShareInfo {
28    pub public_key: String,
29    pub role: String,
30    pub is_self: bool,
31}
32
33pub async fn handler(
34    State(state): State<ServiceState>,
35    Json(req): Json<SharesRequest>,
36) -> Result<impl IntoResponse, SharesError> {
37    let mount = state.peer().mount_for_read(req.bucket_id).await?;
38    let inner = mount.inner().await;
39    let manifest_shares = inner.manifest().shares();
40
41    let self_key = state.peer().secret().public().to_hex();
42
43    let shares: Vec<ShareInfo> = manifest_shares
44        .iter()
45        .map(|(key_hex, share)| {
46            let role = match share.role() {
47                PrincipalRole::Owner => "Owner",
48                PrincipalRole::Mirror => "Mirror",
49            };
50            ShareInfo {
51                public_key: key_hex.clone(),
52                role: role.to_string(),
53                is_self: *key_hex == self_key,
54            }
55        })
56        .collect();
57
58    Ok((
59        http::StatusCode::OK,
60        Json(SharesResponse {
61            bucket_id: req.bucket_id,
62            self_key,
63            shares,
64        }),
65    )
66        .into_response())
67}
68
69#[derive(Debug, thiserror::Error)]
70pub enum SharesError {
71    #[error("Mount error: {0}")]
72    Mount(#[from] MountError),
73}
74
75impl IntoResponse for SharesError {
76    fn into_response(self) -> Response {
77        (
78            http::StatusCode::INTERNAL_SERVER_ERROR,
79            format!("Error: {}", self),
80        )
81            .into_response()
82    }
83}
84
85impl ApiRequest for SharesRequest {
86    type Response = SharesResponse;
87
88    fn build_request(self, base_url: &Url, client: &Client) -> RequestBuilder {
89        let full_url = base_url.join("/api/v0/bucket/shares").unwrap();
90        client.post(full_url).json(&self)
91    }
92}