axum-admin 0.1.1

A modern admin dashboard framework for Axum
Documentation
mod csrf;
mod helpers;
mod auth;
#[cfg(feature = "seaorm")]
mod entity;
#[cfg(feature = "seaorm")]
mod users;
#[cfg(feature = "seaorm")]
mod roles;

use crate::{app::AdminApp, middleware::require_auth};
use axum::{
    http::header,
    middleware,
    response::{IntoResponse, Redirect},
    routing::{delete, get, post},
    Router,
};
use axum::extract::DefaultBodyLimit;
use tower_cookies::CookieManagerLayer;
use axum::extract::Extension;

async fn serve_htmx() -> impl IntoResponse {
    (
        [(header::CONTENT_TYPE, "application/javascript")],
        include_str!("../../static/htmx.min.js"),
    )
}

async fn serve_alpine() -> impl IntoResponse {
    (
        [(header::CONTENT_TYPE, "application/javascript")],
        include_str!("../../static/alpine.min.js"),
    )
}

async fn serve_admin_css() -> impl IntoResponse {
    (
        [(header::CONTENT_TYPE, "text/css")],
        include_str!("../../static/admin.css"),
    )
}

impl AdminApp {
    pub async fn into_router(self) -> Router {
        #[cfg(feature = "seaorm")]
        let entity_names: Vec<String> = self
            .entities
            .iter()
            .map(|e| e.entity_name.clone())
            .collect();

        #[cfg(feature = "seaorm")]
        if let Some(ref seaorm_auth) = self.seaorm_auth {
            seaorm_auth
                .seed_roles(&entity_names)
                .await
                .expect("failed to seed RBAC roles");
        }

        let (auth, state, upload_limit) = self.into_state();

        #[cfg(feature = "seaorm")]
        let protected = {
            use axum::extract::Path;
            Router::new()
                .route("/admin", get(|| async { Redirect::permanent("/admin/") }))
                .route("/admin/", get(entity::admin_home))
                .route("/admin/logout", get(auth::logout))
                .route("/admin/change-password", get(auth::change_password_page))
                .route("/admin/change-password", post(auth::change_password_submit))
                .route("/admin/users/", get(users::user_list))
                .route("/admin/users/new", get(users::user_create_form))
                .route("/admin/users/new", post(users::user_create_submit))
                .route("/admin/users/:id/", get(users::user_edit_form))
                .route("/admin/users/:id/", post(users::user_edit_submit))
                .route("/admin/users/:id/delete", delete(users::user_delete))
                .route("/admin/roles/", get(roles::role_list))
                .route("/admin/roles/new", get(roles::role_create_form))
                .route("/admin/roles/new", post(roles::role_create_submit))
                .route("/admin/roles/:role/", get(roles::role_edit_form))
                .route("/admin/roles/:role/", post(roles::role_edit_submit))
                .route("/admin/roles/:role/delete", delete(roles::role_delete))
                .route("/admin/:entity", get(|Path(e): Path<String>| async move {
                    Redirect::permanent(&format!("/admin/{}/", e))
                }))
                .route("/admin/:entity/", get(entity::entity_list))
                .route("/admin/:entity/new", get(entity::entity_create_form))
                .route("/admin/:entity/new", post(entity::entity_create_submit))
                .route("/admin/:entity/:id/", get(entity::entity_edit_form))
                .route("/admin/:entity/:id/", post(entity::entity_edit_submit))
                .route("/admin/:entity/:id/delete", delete(entity::entity_delete))
                .route("/admin/:entity/action/:action_name", post(entity::entity_action))
                .route_layer(middleware::from_fn(require_auth))
                .layer(DefaultBodyLimit::max(upload_limit))
        };

        #[cfg(not(feature = "seaorm"))]
        let protected = {
            Router::new()
                .route("/admin", get(|| async { Redirect::permanent("/admin/") }))
                .route("/admin/", get(|| async { axum::response::Html("<h1>axum-admin</h1><p>Enable the <code>seaorm</code> feature to use the admin dashboard.</p>") }))
                .route("/admin/logout", get(auth::logout))
                .route("/admin/change-password", get(auth::change_password_page))
                .route("/admin/change-password", post(auth::change_password_submit))
                .route_layer(middleware::from_fn(require_auth))
                .layer(DefaultBodyLimit::max(upload_limit))
        };

        Router::new()
            .route("/admin/login", get(auth::login_page))
            .route("/admin/login", post(auth::login_submit))
            .route("/admin/_static/htmx.min.js", get(serve_htmx))
            .route("/admin/_static/alpine.min.js", get(serve_alpine))
            .route("/admin/_static/admin.css", get(serve_admin_css))
            .merge(protected)
            .layer(Extension(state))
            .layer(Extension(auth))
            .layer(CookieManagerLayer::new())
    }
}