pub mod accounts; pub mod backups; pub mod dashboard; pub mod instances; pub mod mods; pub mod players; use askama::Template; use axum::{Router, response::Html}; use tower_http::services::ServeDir; use crate::auth::CurrentUser; use crate::config::Config; use crate::db::Database; use crate::docker::DockerManager; #[derive(Clone)] pub struct AppState { pub config: Config, pub db: Database, pub docker: DockerManager, } pub fn build_router(state: AppState) -> Router { let auth_required = axum::middleware::from_fn_with_state(state.clone(), crate::auth::require_auth); let protected = Router::new() .route("/change-password", axum::routing::get(change_password_page)) .route( "/change-password", axum::routing::post(accounts::change_password), ) .route("/logout", axum::routing::post(crate::auth::logout)) .merge(dashboard::router()) .merge(instances::router()) .merge(players::router()) .merge(accounts::router()) .merge(backups::router()) .merge(mods::router()) .layer(auth_required); Router::new() .route("/login", axum::routing::get(login_page)) .route("/login", axum::routing::post(crate::auth::authenticate)) .merge(protected) .nest_service("/static", ServeDir::new("static")) .with_state(state) } #[derive(Template)] #[template(path = "login.html")] struct LoginPageTemplate; async fn login_page() -> Html { let template = LoginPageTemplate; Html(template.render().unwrap_or_default()) } #[derive(Template)] #[template(path = "change_password.html")] struct ChangePasswordPageTemplate { username: String, is_superuser: bool, password_change_required: bool, error: String, } async fn change_password_page(CurrentUser(account): CurrentUser) -> Html { let template = ChangePasswordPageTemplate { username: account.username, is_superuser: account.is_superuser, password_change_required: account.password_change_required, error: String::new(), }; Html(template.render().unwrap_or_default()) }