use std::convert::Infallible;
use std::fmt::Debug;
use async_trait::async_trait;
use bonsaidb_core::connection::Session;
use bonsaidb_core::permissions::PermissionDenied;
use bonsaidb_core::schema::{InsertError, InvalidNameError};
use crate::server::ConnectedClient;
use crate::{CustomServer, Error, ServerConfiguration};
#[async_trait]
pub trait Backend: Debug + Send + Sync + Sized + 'static {
type Error: std::error::Error + Send + Sync;
type ClientData: Send + Sync + Debug;
#[allow(unused_variables)]
fn configure(
config: ServerConfiguration<Self>,
) -> Result<ServerConfiguration<Self>, BackendError<Self::Error>> {
Ok(config)
}
#[allow(unused_variables)]
async fn initialize(
&self,
server: &CustomServer<Self>,
) -> Result<(), BackendError<Self::Error>> {
Ok(())
}
#[allow(unused_variables)]
#[must_use]
async fn client_connected(
&self,
client: &ConnectedClient<Self>,
server: &CustomServer<Self>,
) -> Result<ConnectionHandling, BackendError<Self::Error>> {
log::info!(
"{:?} client connected from {:?}",
client.transport(),
client.address()
);
Ok(ConnectionHandling::Accept)
}
#[allow(unused_variables)]
async fn client_disconnected(
&self,
client: ConnectedClient<Self>,
server: &CustomServer<Self>,
) -> Result<(), BackendError<Self::Error>> {
log::info!(
"{:?} client disconnected ({:?})",
client.transport(),
client.address()
);
Ok(())
}
#[allow(unused_variables)]
async fn client_authenticated(
&self,
client: ConnectedClient<Self>,
session: &Session,
server: &CustomServer<Self>,
) -> Result<(), BackendError<Self::Error>> {
log::info!(
"{:?} client authenticated as user: {:?}",
client.transport(),
session.authentication
);
Ok(())
}
#[allow(unused_variables)]
async fn client_session_ended(
&self,
session: Session,
client: &ConnectedClient<Self>,
disconnecting: bool,
server: &CustomServer<Self>,
) -> Result<(), BackendError<Self::Error>> {
log::info!(
"{:?} client session ended {:?}",
client.transport(),
session.authentication
);
Ok(())
}
}
#[derive(Debug, Default)]
pub struct NoBackend;
impl Backend for NoBackend {
type ClientData = ();
type Error = Infallible;
}
pub enum ConnectionHandling {
Accept,
Reject,
}
#[derive(thiserror::Error, Debug)]
pub enum BackendError<E = Infallible> {
#[error("backend error: {0}")]
Backend(E),
#[error("server error: {0}")]
Server(#[from] Error),
}
impl<E> From<PermissionDenied> for BackendError<E> {
fn from(permission_denied: PermissionDenied) -> Self {
Self::Server(Error::from(permission_denied))
}
}
impl<E> From<bonsaidb_core::Error> for BackendError<E> {
fn from(err: bonsaidb_core::Error) -> Self {
Self::Server(Error::from(err))
}
}
impl<E> From<bonsaidb_local::Error> for BackendError<E> {
fn from(err: bonsaidb_local::Error) -> Self {
Self::Server(Error::from(err))
}
}
impl<E> From<std::io::Error> for BackendError<E> {
fn from(err: std::io::Error) -> Self {
Self::Server(Error::from(err))
}
}
impl<E> From<InvalidNameError> for BackendError<E> {
fn from(err: InvalidNameError) -> Self {
Self::Server(Error::from(err))
}
}
#[cfg(feature = "websockets")]
impl<E> From<bincode::Error> for BackendError<E> {
fn from(other: bincode::Error) -> Self {
Self::Server(Error::from(bonsaidb_local::Error::from(other)))
}
}
impl<E> From<pot::Error> for BackendError<E> {
fn from(other: pot::Error) -> Self {
Self::Server(Error::from(bonsaidb_local::Error::from(other)))
}
}
impl<T, E> From<InsertError<T>> for BackendError<E> {
fn from(error: InsertError<T>) -> Self {
Self::Server(Error::from(error.error))
}
}