From c78e386645733798d618d3e477749f0ea5e233f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabor=20K=C3=B6rber?= Date: Sun, 14 Jul 2024 07:58:39 +0200 Subject: [PATCH] wip: work on auth --- Cargo.lock | 3 ++ Cargo.toml | 3 ++ entity/src/main.rs | 4 +++ rear_auth/src/user_admin_repository.rs | 6 ++-- rear_auth/src/views.rs | 45 +++++++++++++------------- src/main.rs | 25 ++++++++++++-- templates/admin/login.html | 43 ++++++++++++++++++++++++ 7 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 templates/admin/login.html diff --git a/Cargo.lock b/Cargo.lock index 9dbd8c2..6ce0af2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1872,6 +1872,8 @@ dependencies = [ "anyhow", "async-trait", "axum 0.7.4", + "axum-login", + "axum-messages", "barrel", "chrono", "dotenvy", @@ -1894,6 +1896,7 @@ dependencies = [ "thiserror", "tokio", "tower-http", + "tower-sessions", "tracing", ] diff --git a/Cargo.toml b/Cargo.toml index b4bb3f4..5410295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ sea-orm = { version = "0.12.10", features = [ sqlformat = { version = "0.2.2", optional = true } anyhow = "1.0.75" axum = "0.7" +axum-login = "0.15.3" +axum-messages = "0.6.1" barrel = { version = "0.7.0", optional = true, features = ["pg"] } dotenvy = "0.15.7" mime_guess = "2.0.4" @@ -56,3 +58,4 @@ tracing = "0.1.40" tower-http = { version = "0.5.1", features = ["trace"] } chrono = "0.4.38" thiserror = "1.0.61" +tower-sessions = { version = "0.12.2" } diff --git a/entity/src/main.rs b/entity/src/main.rs index 0432a6c..af7ce01 100644 --- a/entity/src/main.rs +++ b/entity/src/main.rs @@ -29,6 +29,10 @@ where pub async fn create_tables(db: &DbConn) { create_table(db, user::Entity).await; create_table(db, permission::Entity).await; + create_table(db, group::Entity).await; + create_table(db, user_permission::Entity).await; + create_table(db, group_permission::Entity).await; + create_table(db, user_group::Entity).await; } #[tokio::main] diff --git a/rear_auth/src/user_admin_repository.rs b/rear_auth/src/user_admin_repository.rs index 1925f90..b242c18 100644 --- a/rear_auth/src/user_admin_repository.rs +++ b/rear_auth/src/user_admin_repository.rs @@ -183,16 +183,16 @@ impl AdminRepository for UserRepository { } } -pub fn register(registry: &mut AdminRegistry, db: DatabaseConnection) { +pub fn register(registry: &mut AdminRegistry, db: DatabaseConnection) -> UserRepository { let app_key = registry.register_app("Auth"); let repo = UserRepository::new(db); let model_config = AdminModelConfig { app_key: app_key, name: "User".to_owned(), }; - let model_result = registry.register_model(model_config, repo); + let model_result = registry.register_model(model_config, repo.clone()); match model_result { Err(err) => panic!("{}", err), - _ => (), + _ => repo, } } diff --git a/rear_auth/src/views.rs b/rear_auth/src/views.rs index 6c1d96d..fc72774 100644 --- a/rear_auth/src/views.rs +++ b/rear_auth/src/views.rs @@ -6,7 +6,6 @@ use axum::{ Form, Router, }; use axum_messages::{Message, Messages}; -use rear::service::templates::Templates; use serde::{Deserialize, Serialize}; use crate::models::{AuthSession, Credentials}; @@ -24,11 +23,12 @@ pub struct NextUrl { next: Option, } -pub fn router() -> Router { +pub fn routes() -> Router +where { Router::new() .route("/login", post(self::post::login)) - .route("/login", get(self::get::login)) - .route("/logout", get(self::get::logout)) + .route("/login", get(self::get::login::)) + .route("/logout", post(self::post::logout)) } mod post { @@ -44,7 +44,7 @@ mod post { Ok(None) => { messages.error("Invalid credentials"); - let mut login_url = "/login".to_string(); + let mut login_url = "/admin/login".to_string(); if let Some(next) = creds.next { login_url = format!("{}?next={}", login_url, next); }; @@ -67,23 +67,6 @@ mod post { } .into_response() } -} - -mod get { - use super::*; - use axum::extract::State; - - pub async fn login( - messages: Messages, - templates: State, - Query(NextUrl { next }): Query, - ) -> impl IntoResponse { - let context = LoginTemplate { - messages: messages.into_iter().collect(), - next, - }; - templates.render_html("login.html", context) - } pub async fn logout(mut auth_session: AuthSession) -> impl IntoResponse { match auth_session.logout().await { @@ -93,4 +76,22 @@ mod get { } } +mod get { + use super::*; + use axum::extract::State; + + pub async fn login( + messages: Messages, + admin: State, + Query(NextUrl { next }): Query, + ) -> impl IntoResponse { + let templates = admin.get_templates(); + let context = LoginTemplate { + messages: messages.into_iter().collect(), + next, + }; + templates.render_html("admin/login.html", context) + } +} + // this was taken from the axum_login examples and modified. Redirection might need reverse-routing support. diff --git a/src/main.rs b/src/main.rs index 7bad7f2..01ee940 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,11 @@ use axum::{ use axum::{ extract::State, handler::HandlerWithoutStateExt, response::IntoResponse, routing::get, Router, }; +use axum_login::login_required; +use axum_login::tower_sessions::MemoryStore; +use axum_login::tower_sessions::SessionManagerLayer; +use axum_login::AuthManagerLayerBuilder; +use axum_messages::MessagesManagerLayer; use dotenvy::dotenv; use log::info; use rear::admin; @@ -52,7 +57,7 @@ async fn main() { // Register Admin Apps static_repository::register(&mut admin); - //user_repository::register(&mut admin, db_connection); + let admin_user_repo = rear_auth::user_admin_repository::register(&mut admin, db_connection); file_repository::register(&mut admin, "static/admin"); // Create global Application State. @@ -61,12 +66,28 @@ async fn main() { admin: Arc::new(admin), }; + // Session System + let session_store = MemoryStore::default(); + let session_layer = SessionManagerLayer::new(session_store); + // Auth service. + let auth_layer = AuthManagerLayerBuilder::new(admin_user_repo, session_layer).build(); + // Application Route let app = Router::new() .route("/", get(home)) .route("/hello", get(hello_world)) //.merge(admin_router) - .nest("/admin", admin::routes()) + .nest( + "/admin", + admin::routes() + .route_layer(login_required!( + rear_auth::models::UserRepository, + login_url = "/admin/login" + )) + .merge(rear_auth::views::routes()) + .layer(MessagesManagerLayer) + .layer(auth_layer), + ) .nest("/howto", howto::routes()) .route_service("/static/*file", embed::static_handler.into_service()) .fallback(handlers::not_found_handler) diff --git a/templates/admin/login.html b/templates/admin/login.html new file mode 100644 index 0000000..0867306 --- /dev/null +++ b/templates/admin/login.html @@ -0,0 +1,43 @@ + + + + Login + + + + +
    + {% for message in messages %} +
  • + {{ message }} +
  • + {% endfor %} +
+ +
+
+ User login +

+ + +

+

+ + +

+
+ + + + {% if next %} + + {% endif %} +
+ + + \ No newline at end of file