scufflecloud_core/
http_ext.rs

1use std::sync::Arc;
2
3use axum::http;
4use tonic::Code;
5use tonic_types::ErrorDetails;
6
7use crate::middleware::ExpiredSession;
8use crate::models::UserSession;
9use crate::std_ext::OptionExt;
10
11pub(crate) trait RequestExt {
12    fn extensions(&self) -> &http::Extensions;
13
14    fn global<G: Send + Sync + 'static>(&self) -> Result<Arc<G>, tonic::Status> {
15        self.extensions()
16            .get::<Arc<G>>()
17            .map(Arc::clone)
18            .into_tonic_internal_err("missing global extension")
19    }
20
21    fn session(&self) -> Option<&UserSession> {
22        self.extensions().get::<UserSession>()
23    }
24
25    fn session_or_err(&self) -> Result<&UserSession, tonic::Status> {
26        self.session()
27            .into_tonic_err(Code::Unauthenticated, "you must be logged in", ErrorDetails::new())
28    }
29
30    fn expired_session_or_err(&self) -> Result<&UserSession, tonic::Status> {
31        self.extensions().get::<ExpiredSession>().map(|s| &s.0).into_tonic_err(
32            Code::Unauthenticated,
33            "you must be logged in",
34            ErrorDetails::new(),
35        )
36    }
37
38    fn ip_address_info(&self) -> Result<crate::middleware::IpAddressInfo, tonic::Status> {
39        self.extensions()
40            .get::<crate::middleware::IpAddressInfo>()
41            .copied()
42            .into_tonic_internal_err("missing IpAddressInfo extension")
43    }
44}
45
46impl<T> RequestExt for tonic::Request<T> {
47    fn extensions(&self) -> &http::Extensions {
48        self.extensions()
49    }
50}
51
52impl RequestExt for tonic::Extensions {
53    fn extensions(&self) -> &http::Extensions {
54        self
55    }
56}
57
58impl<T> RequestExt for axum::http::Request<T> {
59    fn extensions(&self) -> &http::Extensions {
60        self.extensions()
61    }
62}