Started perms middleware UNFINISHED

This commit is contained in:
2025-12-02 00:42:56 +01:00
parent fb7f3c4aa6
commit 89b01a3921
5 changed files with 107 additions and 10 deletions

View File

@@ -1,4 +1,70 @@
use axum::http::Method;
use std::collections::HashMap;
use crate::domain::user_prems::UserActions;
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
pub struct RouteKey {
pub method: Method,
pub path: String,
}
#[derive(Debug)]
pub struct AppCfg {
pub db_path: String,
pub route_perms: HashMap<RouteKey, Vec<UserActions>>,
}
impl AppCfg {
pub fn new(db_path: String) -> Self {
Self {
db_path,
route_perms: HashMap::new(),
}
}
pub fn insert_route_perms(
&mut self,
method: Method,
path: impl Into<String>,
perms: Vec<UserActions>,
) {
let key = RouteKey {
method,
path: path.into(),
};
self.route_perms.insert(key, perms);
}
pub fn get_route_perms(&self, method: &Method, path: &str) -> Option<&Vec<UserActions>> {
let key = RouteKey {
method: method.clone(),
path: path.to_string(),
};
self.route_perms.get(&key)
}
pub fn route_allows(&self, method: &Method, path: &str, user_perms: &[UserActions]) -> bool {
if user_perms.contains(&UserActions::Root) {
return true;
}
let key = RouteKey {
method: method.clone(),
path: path.to_string(),
};
let required = match self.route_perms.get(&key) {
Some(perms) => perms,
None => return true, // no perms required → allow
};
if required.contains(&UserActions::Root) {
return false;
}
required.iter().all(|p| user_perms.contains(p))
}
}

View File

@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
use sqlx::prelude::FromRow;
use uuid::Uuid;
#[derive(Debug)]
#[derive(Debug, Eq, PartialEq)]
pub enum UserActions {
Root,
ManageUsers,

View File

@@ -1,8 +1,10 @@
use std::sync::Arc;
use std::{collections::HashMap, sync::Arc};
use anyhow::{Ok, Result};
use axum::http::Method;
use rustymine_daemon::{
config::AppCfg,
domain::user_prems::UserActions,
router,
state::{AppState, check_root},
};
@@ -56,11 +58,15 @@ async fn main() -> Result<()> {
);
let db_path: String = "postgres://rustymine:minecraft@localhost:5432/rustymine_dev".to_string();
let config = AppCfg {
let mut config = AppCfg {
db_path: db_path.clone(),
route_perms: HashMap::new(),
};
let state = Arc::new(AppState::new(&config).await);
config.insert_route_perms(Method::GET, "/api/login", vec![UserActions::Login]);
config.insert_route_perms(Method::GET, "/api/users", vec![UserActions::Login]);
let state = Arc::new(AppState::new(config).await);
check_root(state.clone()).await;
let app_result = router::init_router(state.clone()).await;

View File

@@ -1,8 +1,9 @@
use crate::{core::user_routines, prelude::*};
use crate::{core::user_routines, domain::user::InternalUser, prelude::*};
use std::sync::Arc;
use axum::{
extract::{Request, State},
Extension,
extract::{MatchedPath, Request, State},
http::{self, Method, StatusCode, header::AUTHORIZATION},
middleware::{Next, from_fn_with_state},
response::Response,
@@ -69,6 +70,23 @@ pub async fn auth(
Ok(next.run(req).await)
}
pub async fn perms(
State(state): State<Arc<AppState>>,
Extension(user): Extension<InternalUser>,
mut req: Request,
next: Next,
) -> Result<Response, StatusCode> {
let method: Method = req.method().clone();
let path = req
.extensions()
.get::<MatchedPath>()
.map(|p| p.as_str().to_string())
.ok_or(StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(next.run(req).await)
}
pub fn cors() -> CorsLayer {
debug!("build cors layer");
CorsLayer::new()

View File

@@ -1,8 +1,11 @@
use std::{process::exit, sync::Arc};
use std::{collections::HashMap, process::exit, sync::Arc};
use crate::{
core,
domain::user::{InternalNewUser, NewUser},
domain::{
user::{InternalNewUser, NewUser},
user_prems::UserActions,
},
prelude::*,
};
@@ -12,10 +15,11 @@ use crate::{config::AppCfg, infra::db};
pub struct AppState {
pub db_pool: PgPool,
pub config: AppCfg,
}
impl AppState {
pub async fn new(config: &AppCfg) -> Self {
pub async fn new(config: AppCfg) -> Self {
debug!("init app state");
debug!("establish database connection");
let db_pool = db::connect(&config.db_path)
@@ -36,7 +40,10 @@ impl AppState {
.unwrap();
info!("database ready after connect and migrate");
Self { db_pool: db_pool }
Self {
db_pool: db_pool,
config: config,
}
}
}