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.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        // check that the request indeed came from the hub
49        signed_req.open(&*verifying_key, None).map_err(|oe| {
50            log::warn!(
51                "could not verify authenticity of hub ticket request for hub {}: {oe}",
52                req.handle,
53            );
54
55            match oe {
56                OpenError::OtherConstellation(..) | OpenError::InternalError => {
57                    api::ErrorCode::InternalError
58                }
59                OpenError::OtherwiseInvalid | OpenError::Expired | OpenError::InvalidSignature => {
60                    api::ErrorCode::BadRequest
61                }
62            }
63        })?;
64
65        // if so, hand out ticket
66        Ok(TicketResp::Success(api::Signed::new(
67            &*app.jwt_key,
68            &TicketContent {
69                handle: req.handle,
70                verifying_key,
71            },
72            std::time::Duration::from_secs(3600 * 24), /* = one day */
73        )?))
74    }
75
76    /// Implements [`api::server::HubPingEP`].
77    pub(super) async fn handle_hub_ping(
78        app: Rc<Self>,
79        signed_req: web::Json<TicketSigned<api::server::PingReq>>,
80    ) -> api::Result<api::server::PingResp> {
81        crate::servers::AppBase::<Server>::handle_hub_ping(app, signed_req).await
82    }
83}