jax_daemon/http_server/api/v0/bucket/
shares.rs1use 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 #[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}