Skip to main content

openauth_core/options/
origins.rs

1use std::fmt;
2use std::sync::Arc;
3
4use http::Request;
5
6use crate::error::OpenAuthError;
7
8/// Request-aware trusted origin provider.
9pub trait TrustedOriginsProvider: Send + Sync + 'static {
10    fn trusted_origins(
11        &self,
12        request: Option<&Request<Vec<u8>>>,
13    ) -> Result<Vec<String>, OpenAuthError>;
14}
15
16impl<F> TrustedOriginsProvider for F
17where
18    F: for<'a> Fn(Option<&'a Request<Vec<u8>>>) -> Result<Vec<String>, OpenAuthError>
19        + Send
20        + Sync
21        + 'static,
22{
23    fn trusted_origins(
24        &self,
25        request: Option<&Request<Vec<u8>>>,
26    ) -> Result<Vec<String>, OpenAuthError> {
27        self(request)
28    }
29}
30
31#[derive(Clone, Default)]
32pub enum TrustedOriginOptions {
33    #[default]
34    None,
35    Static(Vec<String>),
36    Dynamic {
37        origins: Vec<String>,
38        provider: Arc<dyn TrustedOriginsProvider>,
39    },
40}
41
42impl TrustedOriginOptions {
43    pub fn dynamic<P>(provider: P) -> Self
44    where
45        P: TrustedOriginsProvider,
46    {
47        Self::Dynamic {
48            origins: Vec::new(),
49            provider: Arc::new(provider),
50        }
51    }
52
53    pub fn dynamic_with_static<P>(origins: Vec<String>, provider: P) -> Self
54    where
55        P: TrustedOriginsProvider,
56    {
57        Self::Dynamic {
58            origins,
59            provider: Arc::new(provider),
60        }
61    }
62
63    pub fn as_static_slice(&self) -> &[String] {
64        match self {
65            Self::None => &[],
66            Self::Static(origins) => origins,
67            Self::Dynamic { origins, .. } => origins,
68        }
69    }
70
71    pub fn provider(&self) -> Option<&dyn TrustedOriginsProvider> {
72        match self {
73            Self::Dynamic { provider, .. } => Some(provider.as_ref()),
74            Self::None | Self::Static(_) => None,
75        }
76    }
77}
78
79impl fmt::Debug for TrustedOriginOptions {
80    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
81        match self {
82            Self::None => formatter.write_str("None"),
83            Self::Static(origins) => formatter.debug_tuple("Static").field(origins).finish(),
84            Self::Dynamic { origins, .. } => formatter
85                .debug_struct("Dynamic")
86                .field("origins", origins)
87                .field("provider", &"<request-aware>")
88                .finish(),
89        }
90    }
91}