pub mod auth; pub mod browse; pub mod meta; pub mod stream; pub mod transcoder; use std::path::PathBuf; use std::sync::Arc; use axum::{ Router, middleware, routing::get, }; /// Shared state passed to all web handlers. #[derive(Clone)] pub struct WebState { pub root: Arc, pub token: Arc, pub oidc: Option>, } pub struct OidcState { pub client: openidconnect::core::CoreClient, pub session_secret: Vec, } /// Build the axum Router for the web player. pub fn build_router(root: PathBuf, token: String, oidc: Option>) -> Router { let state = WebState { root: Arc::new(root), token: Arc::new(token), oidc, }; let api = Router::new() .route("/browse", get(browse::handler)) .route("/stream/*path", get(stream::handler)) .route("/meta/*path", get(meta::handler)); let authed_routes = Router::new() .route("/", get(player_html)) .nest("/api", api) .route_layer(middleware::from_fn_with_state(state.clone(), auth::require_auth)); Router::new() .route("/login", get(auth::login_page).post(auth::login_submit)) .route("/logout", get(auth::logout)) .route("/auth/login", get(auth::oidc_login)) .route("/auth/callback", get(auth::oidc_callback)) .merge(authed_routes) .with_state(state) } #[derive(Clone)] pub struct AuthUserInfo(pub String); async fn player_html( axum::extract::Extension(user_info): axum::extract::Extension, ) -> axum::response::Html { let html = include_str!("player.html") .replace("", &user_info.0) .replace("", option_env!("FURUMI_VERSION").unwrap_or(env!("CARGO_PKG_VERSION"))); axum::response::Html(html) }