scufflecloud_core/
http_ext.rs

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