Skip to main content

axum_admin/router/
mod.rs

1mod csrf;
2mod helpers;
3mod auth;
4#[cfg(feature = "seaorm")]
5mod entity;
6#[cfg(feature = "seaorm")]
7mod users;
8#[cfg(feature = "seaorm")]
9mod roles;
10
11use crate::{app::AdminApp, middleware::require_auth};
12use axum::{
13    http::header,
14    middleware,
15    response::{IntoResponse, Redirect},
16    routing::{delete, get, post},
17    Router,
18};
19use axum::extract::DefaultBodyLimit;
20use tower_cookies::CookieManagerLayer;
21use axum::extract::Extension;
22
23async fn serve_htmx() -> impl IntoResponse {
24    (
25        [(header::CONTENT_TYPE, "application/javascript")],
26        include_str!("../../static/htmx.min.js"),
27    )
28}
29
30async fn serve_alpine() -> impl IntoResponse {
31    (
32        [(header::CONTENT_TYPE, "application/javascript")],
33        include_str!("../../static/alpine.min.js"),
34    )
35}
36
37async fn serve_admin_css() -> impl IntoResponse {
38    (
39        [(header::CONTENT_TYPE, "text/css")],
40        include_str!("../../static/admin.css"),
41    )
42}
43
44impl AdminApp {
45    pub async fn into_router(self) -> Router {
46        #[cfg(feature = "seaorm")]
47        let entity_names: Vec<String> = self
48            .entities
49            .iter()
50            .map(|e| e.entity_name.clone())
51            .collect();
52
53        #[cfg(feature = "seaorm")]
54        if let Some(ref seaorm_auth) = self.seaorm_auth {
55            seaorm_auth
56                .seed_roles(&entity_names)
57                .await
58                .expect("failed to seed RBAC roles");
59        }
60
61        let (auth, state, upload_limit) = self.into_state();
62
63        #[cfg(feature = "seaorm")]
64        let protected = {
65            use axum::extract::Path;
66            Router::new()
67                .route("/admin", get(|| async { Redirect::permanent("/admin/") }))
68                .route("/admin/", get(entity::admin_home))
69                .route("/admin/logout", get(auth::logout))
70                .route("/admin/change-password", get(auth::change_password_page))
71                .route("/admin/change-password", post(auth::change_password_submit))
72                .route("/admin/users/", get(users::user_list))
73                .route("/admin/users/new", get(users::user_create_form))
74                .route("/admin/users/new", post(users::user_create_submit))
75                .route("/admin/users/:id/", get(users::user_edit_form))
76                .route("/admin/users/:id/", post(users::user_edit_submit))
77                .route("/admin/users/:id/delete", delete(users::user_delete))
78                .route("/admin/roles/", get(roles::role_list))
79                .route("/admin/roles/new", get(roles::role_create_form))
80                .route("/admin/roles/new", post(roles::role_create_submit))
81                .route("/admin/roles/:role/", get(roles::role_edit_form))
82                .route("/admin/roles/:role/", post(roles::role_edit_submit))
83                .route("/admin/roles/:role/delete", delete(roles::role_delete))
84                .route("/admin/:entity", get(|Path(e): Path<String>| async move {
85                    Redirect::permanent(&format!("/admin/{}/", e))
86                }))
87                .route("/admin/:entity/", get(entity::entity_list))
88                .route("/admin/:entity/new", get(entity::entity_create_form))
89                .route("/admin/:entity/new", post(entity::entity_create_submit))
90                .route("/admin/:entity/:id/", get(entity::entity_edit_form))
91                .route("/admin/:entity/:id/", post(entity::entity_edit_submit))
92                .route("/admin/:entity/:id/delete", delete(entity::entity_delete))
93                .route("/admin/:entity/action/:action_name", post(entity::entity_action))
94                .route_layer(middleware::from_fn(require_auth))
95                .layer(DefaultBodyLimit::max(upload_limit))
96        };
97
98        #[cfg(not(feature = "seaorm"))]
99        let protected = {
100            Router::new()
101                .route("/admin", get(|| async { Redirect::permanent("/admin/") }))
102                .route("/admin/", get(|| async { axum::response::Html("<h1>axum-admin</h1><p>Enable the <code>seaorm</code> feature to use the admin dashboard.</p>") }))
103                .route("/admin/logout", get(auth::logout))
104                .route("/admin/change-password", get(auth::change_password_page))
105                .route("/admin/change-password", post(auth::change_password_submit))
106                .route_layer(middleware::from_fn(require_auth))
107                .layer(DefaultBodyLimit::max(upload_limit))
108        };
109
110        Router::new()
111            .route("/admin/login", get(auth::login_page))
112            .route("/admin/login", post(auth::login_submit))
113            .route("/admin/_static/htmx.min.js", get(serve_htmx))
114            .route("/admin/_static/alpine.min.js", get(serve_alpine))
115            .route("/admin/_static/admin.css", get(serve_admin_css))
116            .merge(protected)
117            .layer(Extension(state))
118            .layer(Extension(auth))
119            .layer(CookieManagerLayer::new())
120    }
121}