1
use std::convert::Infallible;
2
use std::fmt::Debug;
3

            
4
use async_trait::async_trait;
5
use bonsaidb_core::connection::Session;
6
use bonsaidb_core::permissions::PermissionDenied;
7
use bonsaidb_core::schema::{InsertError, InvalidNameError};
8

            
9
use crate::server::ConnectedClient;
10
use crate::{CustomServer, Error, ServerConfiguration};
11

            
12
/// Tailors the behavior of a server to your needs.
13
#[async_trait]
14
pub trait Backend: Debug + Send + Sync + Sized + 'static {
15
    /// The error type that can be returned from the backend functions. If a
16
    /// backend doesn't need an error type, [`Infallible`] can be used.
17
    type Error: std::error::Error + Send + Sync;
18
    /// The type of data that can be stored in
19
    /// [`ConnectedClient::set_client_data`]. This allows state to be stored
20
    /// associated with each connected client.
21
    type ClientData: Send + Sync + Debug;
22

            
23
    /// Invoked once before the server is initialized.
24
    #[allow(unused_variables)]
25
92
    fn configure(
26
92
        config: ServerConfiguration<Self>,
27
92
    ) -> Result<ServerConfiguration<Self>, BackendError<Self::Error>> {
28
92
        Ok(config)
29
92
    }
30

            
31
    /// Invoked once after initialization during
32
    /// [`Server::open`/`CustomServer::open`](CustomServer::open).
33
    #[allow(unused_variables)]
34
86
    async fn initialize(
35
86
        &self,
36
86
        server: &CustomServer<Self>,
37
86
    ) -> Result<(), BackendError<Self::Error>> {
38
86
        Ok(())
39
86
    }
40

            
41
    /// A client disconnected from the server. This is invoked before authentication has been performed.
42
    #[allow(unused_variables)]
43
    #[must_use]
44
169
    async fn client_connected(
45
169
        &self,
46
169
        client: &ConnectedClient<Self>,
47
169
        server: &CustomServer<Self>,
48
169
    ) -> Result<ConnectionHandling, BackendError<Self::Error>> {
49
169
        log::info!(
50
            "{:?} client connected from {:?}",
51
            client.transport(),
52
            client.address()
53
        );
54

            
55
169
        Ok(ConnectionHandling::Accept)
56
338
    }
57

            
58
    /// A client disconnected from the server.
59
    #[allow(unused_variables)]
60
100
    async fn client_disconnected(
61
100
        &self,
62
100
        client: ConnectedClient<Self>,
63
100
        server: &CustomServer<Self>,
64
100
    ) -> Result<(), BackendError<Self::Error>> {
65
100
        log::info!(
66
            "{:?} client disconnected ({:?})",
67
            client.transport(),
68
            client.address()
69
        );
70
100
        Ok(())
71
200
    }
72

            
73
    /// A client successfully authenticated.
74
    #[allow(unused_variables)]
75
    async fn client_authenticated(
76
        &self,
77
        client: ConnectedClient<Self>,
78
        session: &Session,
79
        server: &CustomServer<Self>,
80
    ) -> Result<(), BackendError<Self::Error>> {
81
        log::info!(
82
            "{:?} client authenticated as user: {:?}",
83
            client.transport(),
84
            session.authentication
85
        );
86
        Ok(())
87
    }
88

            
89
    /// A client's session has ended.
90
    ///
91
    /// If `disconnecting` is true, the session is ending because the client is
92
    /// in the process of disconnecting.
93
    #[allow(unused_variables)]
94
119
    async fn client_session_ended(
95
119
        &self,
96
119
        session: Session,
97
119
        client: &ConnectedClient<Self>,
98
119
        disconnecting: bool,
99
119
        server: &CustomServer<Self>,
100
119
    ) -> Result<(), BackendError<Self::Error>> {
101
119
        log::info!(
102
            "{:?} client session ended {:?}",
103
            client.transport(),
104
            session.authentication
105
        );
106
119
        Ok(())
107
238
    }
108
}
109

            
110
/// A [`Backend`] with no custom functionality.
111
613
#[derive(Debug, Default)]
112
pub struct NoBackend;
113

            
114
impl Backend for NoBackend {
115
    type ClientData = ();
116
    type Error = Infallible;
117
}
118

            
119
/// Controls how a server should handle a connection.
120
pub enum ConnectionHandling {
121
    /// The server should accept this connection.
122
    Accept,
123
    /// The server should reject this connection.
124
    Reject,
125
}
126

            
127
/// An error that can occur inside of a [`Backend`] function.
128
#[derive(thiserror::Error, Debug)]
129
pub enum BackendError<E = Infallible> {
130
    /// A backend-related error.
131
    #[error("backend error: {0}")]
132
    Backend(E),
133
    /// A server-related error.
134
    #[error("server error: {0}")]
135
    Server(#[from] Error),
136
}
137

            
138
impl<E> From<PermissionDenied> for BackendError<E> {
139
    fn from(permission_denied: PermissionDenied) -> Self {
140
        Self::Server(Error::from(permission_denied))
141
    }
142
}
143

            
144
impl<E> From<bonsaidb_core::Error> for BackendError<E> {
145
    fn from(err: bonsaidb_core::Error) -> Self {
146
        Self::Server(Error::from(err))
147
    }
148
}
149

            
150
impl<E> From<bonsaidb_local::Error> for BackendError<E> {
151
    fn from(err: bonsaidb_local::Error) -> Self {
152
        Self::Server(Error::from(err))
153
    }
154
}
155

            
156
impl<E> From<std::io::Error> for BackendError<E> {
157
    fn from(err: std::io::Error) -> Self {
158
        Self::Server(Error::from(err))
159
    }
160
}
161

            
162
impl<E> From<InvalidNameError> for BackendError<E> {
163
    fn from(err: InvalidNameError) -> Self {
164
        Self::Server(Error::from(err))
165
    }
166
}
167

            
168
#[cfg(feature = "websockets")]
169
impl<E> From<bincode::Error> for BackendError<E> {
170
    fn from(other: bincode::Error) -> Self {
171
        Self::Server(Error::from(bonsaidb_local::Error::from(other)))
172
    }
173
}
174

            
175
impl<E> From<pot::Error> for BackendError<E> {
176
    fn from(other: pot::Error) -> Self {
177
        Self::Server(Error::from(bonsaidb_local::Error::from(other)))
178
    }
179
}
180

            
181
impl<T, E> From<InsertError<T>> for BackendError<E> {
182
    fn from(error: InsertError<T>) -> Self {
183
        Self::Server(Error::from(error.error))
184
    }
185
}