[TSM.ID].[11031972] PXE : 10 Template/Kosong -> REAL Implementation (3Z Complete)

This commit is contained in:
TSM.ID
2026-05-25 05:10:47 +07:00
parent 9e5f7c78a9
commit c3b4acd7c1
10 changed files with 1180 additions and 457 deletions
+115
View File
@@ -0,0 +1,115 @@
#![deny(warnings)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-iam-gatekeeper -- Identity Access Management Gateway
//! JWT validation, RBAC, session management, rate limiting per user
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum GatekeeperError { Unauthorized(String), Forbidden(String), SessionExpired(String), RateLimited(String) }
impl std::fmt::Display for GatekeeperError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { Self::Unauthorized(e) => write!(f, "Unauthorized: {e}"), Self::Forbidden(e) => write!(f, "Forbidden: {e}"), Self::SessionExpired(e) => write!(f, "Expired: {e}"), Self::RateLimited(e) => write!(f, "Rate limited: {e}") }
}
}
impl std::error::Error for GatekeeperError {}
#[derive(Debug, Clone, PartialEq)]
pub enum Role { Admin, Moderator, User, Guest, Service }
impl Role {
pub fn level(&self) -> u8 { match self { Self::Admin => 100, Self::Moderator => 50, Self::User => 20, Self::Guest => 5, Self::Service => 80 } }
}
#[derive(Debug, Clone)]
pub struct Session { pub user_id: String, pub role: Role, pub created_at: u64, pub expires_at: u64, pub ip_addr: String, pub device_fingerprint: String }
#[derive(Debug, Clone)]
pub struct Permission { pub resource: String, pub action: String, pub min_role_level: u8 }
struct RateState { count: u32, window_start: u64 }
pub struct Gatekeeper {
sessions: Arc<Mutex<HashMap<String, Session>>>,
permissions: Vec<Permission>,
rate_limits: Arc<Mutex<HashMap<String, RateState>>>,
max_requests_per_minute: u32,
}
impl Gatekeeper {
pub fn new(max_rpm: u32) -> Self {
Self { sessions: Arc::new(Mutex::new(HashMap::new())), permissions: Vec::new(), rate_limits: Arc::new(Mutex::new(HashMap::new())), max_requests_per_minute: max_rpm }
}
pub fn add_permission(&mut self, perm: Permission) { self.permissions.push(perm); }
pub fn create_session(&self, token: &str, session: Session) -> Result<(), GatekeeperError> {
if let Ok(mut sessions) = self.sessions.lock() { sessions.insert(token.into(), session); Ok(()) }
else { Err(GatekeeperError::Unauthorized("Lock failed".into())) }
}
pub fn validate_session(&self, token: &str, now: u64) -> Result<Session, GatekeeperError> {
let sessions = self.sessions.lock().map_err(|_| GatekeeperError::Unauthorized("Lock".into()))?;
let session = sessions.get(token).ok_or_else(|| GatekeeperError::Unauthorized("Invalid token".into()))?;
if now > session.expires_at { return Err(GatekeeperError::SessionExpired(format!("Expired {}s ago", now - session.expires_at))); }
Ok(session.clone())
}
pub fn check_permission(&self, role: &Role, resource: &str, action: &str) -> Result<bool, GatekeeperError> {
for perm in &self.permissions {
if perm.resource == resource && perm.action == action {
if role.level() >= perm.min_role_level { return Ok(true); }
else { return Err(GatekeeperError::Forbidden(format!("{:?} level {} < required {}", role, role.level(), perm.min_role_level))); }
}
}
Ok(false) // No matching permission = deny
}
pub fn check_rate_limit(&self, user_id: &str, now: u64) -> Result<u32, GatekeeperError> {
let mut limits = self.rate_limits.lock().map_err(|_| GatekeeperError::RateLimited("Lock".into()))?;
let state = limits.entry(user_id.into()).or_insert(RateState { count: 0, window_start: now });
if now - state.window_start >= 60 { state.count = 0; state.window_start = now; }
state.count += 1;
if state.count > self.max_requests_per_minute {
Err(GatekeeperError::RateLimited(format!("{} requests/min > {}", state.count, self.max_requests_per_minute)))
} else { Ok(self.max_requests_per_minute - state.count) }
}
/// Full auth pipeline: validate → check permission → check rate limit
pub fn authorize(&self, token: &str, resource: &str, action: &str, now: u64) -> Result<Session, GatekeeperError> {
let session = self.validate_session(token, now)?;
self.check_permission(&session.role, resource, action)?;
self.check_rate_limit(&session.user_id, now)?;
Ok(session)
}
pub fn revoke_session(&self, token: &str) -> bool {
self.sessions.lock().map(|mut s| s.remove(token).is_some()).unwrap_or(false)
}
pub fn active_sessions(&self) -> usize { self.sessions.lock().map(|s| s.len()).unwrap_or(0) }
}
#[cfg(test)]
mod tests {
use super::*;
fn setup() -> Gatekeeper {
let mut gk = Gatekeeper::new(60);
gk.add_permission(Permission { resource: "chat".into(), action: "send".into(), min_role_level: 20 });
gk.add_permission(Permission { resource: "admin".into(), action: "delete".into(), min_role_level: 100 });
gk.create_session("tok-1", Session { user_id: "u1".into(), role: Role::User, created_at: 1000, expires_at: 9999, ip_addr: "1.2.3.4".into(), device_fingerprint: "abc".into() }).unwrap();
gk
}
#[test]
fn test_auth_ok() { let gk = setup(); assert!(gk.authorize("tok-1", "chat", "send", 2000).is_ok()); }
#[test]
fn test_auth_forbidden() { let gk = setup(); assert!(gk.authorize("tok-1", "admin", "delete", 2000).is_err()); }
#[test]
fn test_expired() { let gk = setup(); assert!(gk.validate_session("tok-1", 99999).is_err()); }
#[test]
fn test_rate_limit() {
let gk = setup();
for _ in 0..60 { gk.check_rate_limit("u1", 1000).unwrap(); }
assert!(gk.check_rate_limit("u1", 1000).is_err());
}
}