wip: work on auth
This commit is contained in:
parent
b029b4b975
commit
c78e386645
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
||||
|
@ -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" }
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
25
src/main.rs
25
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)
|
||||
|
43
templates/admin/login.html
Normal file
43
templates/admin/login.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user