lib.rs

  1pub mod api;
  2pub mod auth;
  3pub mod db;
  4pub mod env;
  5#[cfg(test)]
  6mod integration_tests;
  7pub mod rpc;
  8
  9use axum::{http::StatusCode, response::IntoResponse};
 10use db::Database;
 11use serde::Deserialize;
 12use std::{path::PathBuf, sync::Arc};
 13
 14pub type Result<T, E = Error> = std::result::Result<T, E>;
 15
 16pub enum Error {
 17    Http(StatusCode, String),
 18    Database(sea_orm::error::DbErr),
 19    Internal(anyhow::Error),
 20}
 21
 22impl From<anyhow::Error> for Error {
 23    fn from(error: anyhow::Error) -> Self {
 24        Self::Internal(error)
 25    }
 26}
 27
 28impl From<sea_orm::error::DbErr> for Error {
 29    fn from(error: sea_orm::error::DbErr) -> Self {
 30        Self::Database(error)
 31    }
 32}
 33
 34impl From<axum::Error> for Error {
 35    fn from(error: axum::Error) -> Self {
 36        Self::Internal(error.into())
 37    }
 38}
 39
 40impl From<hyper::Error> for Error {
 41    fn from(error: hyper::Error) -> Self {
 42        Self::Internal(error.into())
 43    }
 44}
 45
 46impl From<serde_json::Error> for Error {
 47    fn from(error: serde_json::Error) -> Self {
 48        Self::Internal(error.into())
 49    }
 50}
 51
 52impl IntoResponse for Error {
 53    fn into_response(self) -> axum::response::Response {
 54        match self {
 55            Error::Http(code, message) => (code, message).into_response(),
 56            Error::Database(error) => {
 57                (StatusCode::INTERNAL_SERVER_ERROR, format!("{}", &error)).into_response()
 58            }
 59            Error::Internal(error) => {
 60                (StatusCode::INTERNAL_SERVER_ERROR, format!("{}", &error)).into_response()
 61            }
 62        }
 63    }
 64}
 65
 66impl std::fmt::Debug for Error {
 67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 68        match self {
 69            Error::Http(code, message) => (code, message).fmt(f),
 70            Error::Database(error) => error.fmt(f),
 71            Error::Internal(error) => error.fmt(f),
 72        }
 73    }
 74}
 75
 76impl std::fmt::Display for Error {
 77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 78        match self {
 79            Error::Http(code, message) => write!(f, "{code}: {message}"),
 80            Error::Database(error) => error.fmt(f),
 81            Error::Internal(error) => error.fmt(f),
 82        }
 83    }
 84}
 85
 86impl std::error::Error for Error {}
 87
 88#[derive(Default, Deserialize)]
 89pub struct Config {
 90    pub http_port: u16,
 91    pub database_url: String,
 92    pub api_token: String,
 93    pub invite_link_prefix: String,
 94    pub live_kit_server: Option<String>,
 95    pub live_kit_key: Option<String>,
 96    pub live_kit_secret: Option<String>,
 97    pub rust_log: Option<String>,
 98    pub log_json: Option<bool>,
 99}
100
101#[derive(Default, Deserialize)]
102pub struct MigrateConfig {
103    pub database_url: String,
104    pub migrations_path: Option<PathBuf>,
105}
106
107pub struct AppState {
108    pub db: Arc<Database>,
109    pub live_kit_client: Option<Arc<dyn live_kit_server::api::Client>>,
110    pub config: Config,
111}
112
113impl AppState {
114    pub async fn new(config: Config) -> Result<Arc<Self>> {
115        let mut db_options = db::ConnectOptions::new(config.database_url.clone());
116        db_options.max_connections(5);
117        let db = Database::new(db_options).await?;
118        let live_kit_client = if let Some(((server, key), secret)) = config
119            .live_kit_server
120            .as_ref()
121            .zip(config.live_kit_key.as_ref())
122            .zip(config.live_kit_secret.as_ref())
123        {
124            Some(Arc::new(live_kit_server::api::LiveKitClient::new(
125                server.clone(),
126                key.clone(),
127                secret.clone(),
128            )) as Arc<dyn live_kit_server::api::Client>)
129        } else {
130            None
131        };
132
133        let this = Self {
134            db: Arc::new(db),
135            live_kit_client,
136            config,
137        };
138        Ok(Arc::new(this))
139    }
140}