Skip to main content

asteroid_mq/protocol/node/edge/
auth.rs

1use std::{borrow::Cow, future::Future, sync::Arc};
2
3use crate::prelude::NodeId;
4
5use super::EdgeRequestEnum;
6#[derive(Clone)]
7pub struct EdgeAuthService {
8    inner: Arc<dyn sealed::BoxedEdgeAuth>,
9    source: Cow<'static, str>,
10}
11
12impl std::fmt::Debug for EdgeAuthService {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        f.debug_struct("EdgeAuthService")
15            .field("source", &self.source)
16            .finish()
17    }
18}
19
20impl std::fmt::Display for EdgeAuthService {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        write!(f, "EdgeAuthService: {}", self.source)
23    }
24}
25
26#[derive(Debug)]
27pub struct EdgeAuthError {
28    reason: Cow<'static, str>,
29    source: Option<Box<dyn std::error::Error + Send + Sync>>,
30}
31
32impl EdgeAuthError {
33    pub fn new<E: std::error::Error + Send + Sync + 'static>(
34        reason: impl Into<Cow<'static, str>>,
35        source: E,
36    ) -> Self {
37        Self {
38            reason: reason.into(),
39            source: Some(Box::new(source)),
40        }
41    }
42    pub fn new_local(reason: impl Into<Cow<'static, str>>) -> Self {
43        Self {
44            reason: reason.into(),
45            source: None,
46        }
47    }
48}
49impl std::fmt::Display for EdgeAuthError {
50    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        write!(f, "EdgeAuthError: {}", self.reason,)?;
52        if let Some(source) = &self.source {
53            write!(f, "with source: {}", source)?;
54        }
55        Ok(())
56    }
57}
58
59impl EdgeAuthService {
60    pub fn new<T>(inner: T) -> Self
61    where
62        T: EdgeAuth,
63    {
64        Self {
65            inner: Arc::new(inner),
66            source: std::any::type_name::<T>().into(),
67        }
68    }
69
70    pub async fn check(
71        &self,
72        from: NodeId,
73        request: &EdgeRequestEnum,
74    ) -> Result<(), EdgeAuthError> {
75        self.inner.check(from, request).await
76    }
77}
78
79pub trait EdgeAuth: Send + Sync + 'static {
80    fn check<'r>(
81        &'r self,
82        from: NodeId,
83        request: &'r EdgeRequestEnum,
84    ) -> impl Future<Output = Result<(), EdgeAuthError>> + Send + 'r;
85}
86
87mod sealed {
88    use futures_util::future::BoxFuture;
89
90    use super::{EdgeAuth, EdgeAuthError};
91    use crate::protocol::node::edge::EdgeRequestEnum;
92    use crate::protocol::node::NodeId;
93
94    pub(super) trait BoxedEdgeAuth: Send + Sync {
95        fn check<'r>(
96            &'r self,
97            from: NodeId,
98            request: &'r EdgeRequestEnum,
99        ) -> BoxFuture<'r, Result<(), EdgeAuthError>>;
100    }
101
102    impl<T> BoxedEdgeAuth for T
103    where
104        T: EdgeAuth,
105    {
106        fn check<'r>(
107            &'r self,
108            from: NodeId,
109            request: &'r EdgeRequestEnum,
110        ) -> BoxFuture<'r, Result<(), EdgeAuthError>> {
111            Box::pin(async move { self.check(from, request).await })
112        }
113    }
114}