wip: work on auth

This commit is contained in:
Gabor Körber 2024-07-14 07:58:39 +02:00
parent b029b4b975
commit c78e386645
7 changed files with 102 additions and 27 deletions

3
Cargo.lock generated
View File

@ -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",
]

View File

@ -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" }

View File

@ -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]

View File

@ -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,
}
}

View File

@ -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<String>,
}
pub fn router() -> Router<Templates> {
pub fn routes<S: rear::admin::state::AdminState + Clone + Send + Sync + 'static>() -> Router<S>
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::<S>))
.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<Templates>,
Query(NextUrl { next }): Query<NextUrl>,
) -> 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<S: rear::admin::state::AdminState + Clone + Send + Sync + 'static>(
messages: Messages,
admin: State<S>,
Query(NextUrl { next }): Query<NextUrl>,
) -> 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.

View File

@ -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)

View File

@ -0,0 +1,43 @@
<html>
<head>
<title>Login</title>
<style>
label {
display: block;
margin-bottom: 5px;
}
</style>
</head>
<body>
<ul>
{% for message in messages %}
<li>
<span><strong>{{ message }}</strong></span>
</li>
{% endfor %}
</ul>
<form method="post">
<fieldset>
<legend>User login</legend>
<p>
<label for="username">Username</label>
<input name="username" id="username" value="ferris" />
</p>
<p>
<label for="password">Password</label>
<input name="password" id="password" type="password" value="hunter42" />
</p>
</fieldset>
<input type="submit" value="login" />
{% if next %}
<input type="hidden" name="next" value="{{next}}" />
{% endif %}
</form>
</body>
</html>