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}