1
use std::{fmt::Debug, marker::PhantomData};
2

            
3
use async_trait::async_trait;
4
use bonsaidb_core::{
5
    api::{self, Api, ApiError, Infallible},
6
    arc_bytes::serde::Bytes,
7
    permissions::PermissionDenied,
8
    schema::{InsertError, InvalidNameError},
9
};
10

            
11
use crate::{Backend, ConnectedClient, CustomServer, Error, NoBackend};
12

            
13
/// A trait that can dispatch requests for a [`Api`].
14
#[async_trait]
15
pub trait Handler<B: Backend, Api: api::Api>: Send + Sync {
16
    /// Returns a dispatcher to handle custom api requests. The parameters are
17
    /// provided so that they can be cloned if needed during the processing of
18
    /// requests.
19
    async fn handle(session: HandlerSession<'_, B>, request: Api) -> HandlerResult<Api>;
20
}
21

            
22
/// A session for a [`Handler`], providing ways to access the server and
23
/// connected client.
24
pub struct HandlerSession<'a, B: Backend = NoBackend> {
25
    /// The [`Handler`]'s server reference. This server instance is not limited
26
    /// to the permissions of the connected user.
27
    pub server: &'a CustomServer<B>,
28
    /// The connected client's server reference. This server instance will
29
    /// reject any database operations that the connected client is not
30
    /// explicitly authorized to perform based on its authentication state.
31
    pub as_client: CustomServer<B>,
32
    /// The connected client making the API request.
33
    pub client: &'a ConnectedClient<B>,
34
}
35

            
36
#[async_trait]
37
pub(crate) trait AnyHandler<B: Backend>: Send + Sync + Debug {
38
    async fn handle(&self, session: HandlerSession<'_, B>, request: &[u8]) -> Result<Bytes, Error>;
39
}
40

            
41
pub(crate) struct AnyWrapper<D: Handler<B, A>, B: Backend, A: Api>(
42
    pub(crate) PhantomData<(D, B, A)>,
43
);
44

            
45
impl<D, B, A> Debug for AnyWrapper<D, B, A>
46
where
47
    D: Handler<B, A>,
48
    B: Backend,
49
    A: Api,
50
{
51
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52
        f.debug_tuple("AnyWrapper").finish()
53
    }
54
}
55

            
56
#[async_trait]
57
impl<T, B, A> AnyHandler<B> for AnyWrapper<T, B, A>
58
where
59
    B: Backend,
60
    T: Handler<B, A>,
61
    A: Api,
62
{
63
70629
    async fn handle(&self, client: HandlerSession<'_, B>, request: &[u8]) -> Result<Bytes, Error> {
64
70629
        let request = pot::from_slice(request)?;
65
101380
        let response = match T::handle(client, request).await {
66
70072
            Ok(response) => Ok(response),
67
            Err(HandlerError::Api(err)) => Err(err),
68
557
            Err(HandlerError::Server(err)) => return Err(err),
69
        };
70
70072
        Ok(Bytes::from(pot::to_vec(&response)?))
71
141257
    }
72
}
73

            
74
/// An error that can occur inside of a [`Backend`] function.
75
#[derive(thiserror::Error, Debug)]
76
pub enum HandlerError<E: ApiError = Infallible> {
77
    /// An api-related error.
78
    #[error("api error: {0}")]
79
    Api(E),
80
    /// A server-related error.
81
    #[error("server error: {0}")]
82
    Server(#[from] Error),
83
}
84

            
85
impl<E: ApiError> From<PermissionDenied> for HandlerError<E> {
86
    fn from(permission_denied: PermissionDenied) -> Self {
87
        Self::Server(Error::from(permission_denied))
88
    }
89
}
90

            
91
impl<E: ApiError> From<bonsaidb_core::Error> for HandlerError<E> {
92
557
    fn from(err: bonsaidb_core::Error) -> Self {
93
557
        Self::Server(Error::from(err))
94
557
    }
95
}
96

            
97
impl<E: ApiError> From<bonsaidb_local::Error> for HandlerError<E> {
98
    fn from(err: bonsaidb_local::Error) -> Self {
99
        Self::Server(Error::from(err))
100
    }
101
}
102

            
103
impl<E: ApiError> From<InvalidNameError> for HandlerError<E> {
104
    fn from(err: InvalidNameError) -> Self {
105
        Self::Server(Error::from(err))
106
    }
107
}
108

            
109
#[cfg(feature = "websockets")]
110
impl<E: ApiError> From<bincode::Error> for HandlerError<E> {
111
    fn from(other: bincode::Error) -> Self {
112
        Self::Server(Error::from(bonsaidb_local::Error::from(other)))
113
    }
114
}
115

            
116
impl<E: ApiError> From<pot::Error> for HandlerError<E> {
117
    fn from(other: pot::Error) -> Self {
118
        Self::Server(Error::from(other))
119
    }
120
}
121

            
122
impl<T, E> From<InsertError<T>> for HandlerError<E>
123
where
124
    E: ApiError,
125
{
126
    fn from(error: InsertError<T>) -> Self {
127
        Self::Server(Error::from(error.error))
128
    }
129
}
130

            
131
/// The return type from a [`Handler`]'s [`handle()`](Handler::handle)
132
/// function.
133
pub type HandlerResult<Api> =
134
    Result<<Api as api::Api>::Response, HandlerError<<Api as api::Api>::Error>>;