Skip to main content

pubhubs/servers/phc/
hub.rs

1//! Hub endpoints
2use std::rc::Rc;
3
4use actix_web::web;
5
6use crate::api::ApiResultExt as _;
7use crate::api::OpenError;
8use crate::api::{self, NoPayload};
9
10use super::server::*;
11use api::phc::hub::*;
12
13impl App {
14    pub(super) async fn handle_hub_ticket(
15        app: Rc<Self>,
16        signed_req: web::Json<api::Signed<TicketReq>>,
17    ) -> api::Result<TicketResp> {
18        let signed_req = signed_req.into_inner();
19
20        let req = signed_req
21            .clone()
22            .open_without_checking_signature()
23            .map_err(|oe| {
24                log::debug!("received invalid ticket request: {oe}");
25
26                match oe {
27                    OpenError::OtherConstellation(..)
28                    | OpenError::InternalError
29                    | OpenError::InvalidSignature => api::ErrorCode::InternalError,
30                    OpenError::OtherwiseInvalid | OpenError::Expired => api::ErrorCode::BadRequest,
31                }
32            })?;
33
34        let Some(hub) = app.shared.hubs.get(&req.handle) else {
35            return Ok(TicketResp::UnknownHub);
36        };
37
38        let resp = app
39            .client
40            .query::<api::hub::InfoEP>(&hub.url, NoPayload)
41            .await
42            .into_server_result()?;
43
44        let Some(verifying_key) = resp.verifying_key else {
45            return Ok(TicketResp::NoVerifyingKey);
46        };
47
48        let Ok(hub_verifying_key) = verifying_key.decode() else {
49            log::warn!("hub {} returned a malformed verifying key", req.handle);
50            return Err(api::ErrorCode::BadRequest);
51        };
52
53        // check that the request indeed came from the hub
54        signed_req.open(&hub_verifying_key, None).map_err(|oe| {
55            log::warn!(
56                "could not verify authenticity of hub ticket request for hub {}: {oe}",
57                req.handle,
58            );
59
60            match oe {
61                OpenError::OtherConstellation(..) | OpenError::InternalError => {
62                    api::ErrorCode::InternalError
63                }
64                OpenError::OtherwiseInvalid | OpenError::Expired | OpenError::InvalidSignature => {
65                    api::ErrorCode::BadRequest
66                }
67            }
68        })?;
69
70        // if so, hand out ticket
71        Ok(TicketResp::Success(api::Signed::new(
72            &app.shared.signing_key,
73            &TicketContent {
74                handle: req.handle,
75                verifying_key,
76            },
77            std::time::Duration::from_secs(3600 * 24), /* = one day */
78        )?))
79    }
80
81    /// Implements [`api::server::HubPingEP`].
82    pub(super) async fn handle_hub_ping(
83        app: Rc<Self>,
84        signed_req: web::Json<TicketSigned<api::server::PingReq>>,
85    ) -> api::Result<api::server::PingResp> {
86        crate::servers::AppBase::<Server>::handle_hub_ping(app, signed_req).await
87    }
88}