diff --git a/server/src/auth/logic/rbac.rs b/server/src/auth/logic/rbac.rs index bdfa973..20ce438 100644 --- a/server/src/auth/logic/rbac.rs +++ b/server/src/auth/logic/rbac.rs @@ -1,102 +1,36 @@ // src/auth/logic/rbac.rs -use tonic::{Request, Status}; -use crate::auth::logic::jwt; -// Define roles constants to match database constraints -pub const ROLE_VIEWER: &str = "viewer"; -pub const ROLE_ACCOUNTANT: &str = "accountant"; -pub const ROLE_MODERATOR: &str = "moderator"; -pub const ROLE_ADMIN: &str = "admin"; +use tower::ServiceBuilder; +use crate::auth::logic::rbac; -// Role-check interceptor functions -pub fn require_roles(roles: Vec, req: Request) -> Result, Status> { - let token = match req.metadata().get("authorization") { - Some(token) => match token.to_str() { - Ok(t) => t, - Err(_) => return Err(Status::unauthenticated("Invalid authorization header")), - }, - None => return Err(Status::unauthenticated("Missing authorization header")), - }; - - // Strip 'Bearer ' prefix if present - let token = token.strip_prefix("Bearer ") - .unwrap_or(token); - - // Validate the token and get claims - let claims = match jwt::validate_token(token) { - Ok(claims) => claims, - Err(_) => return Err(Status::unauthenticated("Invalid token")), - }; - - // Check if user role is allowed - if !roles.contains(&claims.role) { - tracing::warn!( - user_id = %claims.sub, - user_role = %claims.role, - required_roles = ?roles, - "Access denied: insufficient permissions" - ); - return Err(Status::permission_denied("Insufficient permissions")); - } - - // Add claims to request extensions for handler access - let mut req = req; - req.extensions_mut().insert(claims); - - Ok(req) -} - -// Convenience function for admin-only endpoints -pub fn admin_only(req: Request) -> Result, Status> { - require_roles(vec![ROLE_ADMIN.to_string()], req) -} - -// Convenience function for admin and moderator endpoints -pub fn admin_moderator(req: Request) -> Result, Status> { - require_roles( - vec![ - ROLE_MODERATOR.to_string(), - ROLE_ADMIN.to_string() - ], - req - ) -} - -// Convenience function for accountants and higher (more privileges) -pub fn accountant_and_higher(req: Request) -> Result, Status> { - require_roles( - vec![ - ROLE_ACCOUNTANT.to_string(), - ROLE_MODERATOR.to_string(), - ROLE_ADMIN.to_string() - ], - req - ) -} - -// Convenience function for any authenticated user -pub fn any_authenticated_user(req: Request) -> Result, Status> { - require_roles( - vec![ - ROLE_VIEWER.to_string(), - ROLE_ACCOUNTANT.to_string(), - ROLE_MODERATOR.to_string(), - ROLE_ADMIN.to_string() - ], - req - ) -} - -// Helper to get a user's role from the request -pub fn get_user_role(req: &Request) -> Option<&str> { - req.extensions() - .get::() - .map(|claims| claims.role.as_str()) -} - -// Helper to get a user's ID from the request -pub fn get_user_id(req: &Request) -> Option { - req.extensions() - .get::() - .map(|claims| claims.sub) +pub async fn run_server(db_pool: sqlx::PgPool) -> Result<(), Box> { + // ... existing setup code ... + + // Create service layers + let adresar_layer = ServiceBuilder::new() + .layer(rbac::create_adresar_layer()) + .into_inner(); + + let uctovnictvo_layer = ServiceBuilder::new() + .layer(rbac::create_uctovnictvo_layer()) + .into_inner(); + + // Create services with layers + let adresar_service = AdresarServer::new(AdresarService { db_pool: db_pool.clone() }) + .layer(adresar_layer); + + let uctovnictvo_service = UctovnictvoServer::new(UctovnictvoService { db_pool: db_pool.clone() }) + .layer(uctovnictvo_layer); + + // ... repeat for other services ... + + Server::builder() + .add_service(auth_server) + .add_service(adresar_service) + .add_service(uctovnictvo_service) + // ... other services ... + .serve(addr) + .await?; + + Ok(()) }