mod auth;
mod error;
mod phonemes;
mod user;
mod util;
use axum_login::AuthManagerLayerBuilder;
use error::AppError;
use surrealdb::{
engine::remote::ws::{Client, Ws},
opt::auth::Root,
Surreal,
};
use axum::{
extract::{FromRef, FromRequest},
response::{IntoResponse, Response},
Router,
};
use tower_sessions::{cookie::time::Duration, ExpiredDeletion, Expiry, SessionManagerLayer};
use tower_sessions_surrealdb_store::SurrealSessionStore;
use tracing_subscriber::EnvFilter;
use user::Backend;
// Do the special error handling stuff
#[derive(FromRequest)]
#[from_request(via(axum::Json), rejection(AppError))]
struct AppJson<T>(T);
impl<T> IntoResponse for AppJson<T>
where
axum::Json<T>: IntoResponse,
{
fn into_response(self) -> Response {
axum::Json(self.0).into_response()
}
}
#[derive(Clone)]
struct AppState {
db: Surreal<Client>,
}
impl FromRef<AppState> for Surreal<Client> {
fn from_ref(input: &AppState) -> Self {
input.db.clone()
}
}
#[tokio::main]
async fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
tracing_subscriber::fmt().pretty().with_env_filter(EnvFilter::from_default_env()).init();
let db = Surreal::new::<Ws>("127.0.0.1:8000").await?;
db.use_ns("noteboek").use_db("noteboek").await?;
// Log in as DB root
db.signin(Root { username: "root", password: "root" }).await?;
// Session stuff
let session_store = SurrealSessionStore::new(db.clone(), "sessions".to_string());
let expired_session_cleanup_interval: u64 = 1;
tokio::task::spawn(session_store.clone().continuously_delete_expired(
tokio::time::Duration::from_secs(60 * expired_session_cleanup_interval),
));
let session_layer = SessionManagerLayer::new(session_store)
.with_secure(false)
.with_expiry(Expiry::OnInactivity(Duration::hours(1)));
// Auth stuff
let backend = Backend::new(db.clone());
let auth_layer = AuthManagerLayerBuilder::new(backend, session_layer).build();
let state = AppState { db };
let router = Router::new()
.nest("/phonemes", phonemes::router())
.merge(auth::router())
.layer(auth_layer)
.with_state(state);
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?;
Ok(axum::serve(listener, router).await?)
}