use std::collections::HashSet;
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Permission {
pub name: String,
pub resource: String,
pub actions: HashSet<Action>,
pub conditions: Vec<PermissionCondition>,
}
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub enum Action {
Read,
Write,
Delete,
Execute,
Admin,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PermissionCondition {
TimeBasedAccess {
start_hour: u8,
end_hour: u8,
allowed_days: Vec<Weekday>,
},
IPBasedAccess {
allowed_ips: Vec<String>,
allowed_ranges: Vec<String>,
},
MFARequired,
}
impl Permission {
pub fn new(name: &str, resource: &str) -> Self {
Self {
name: name.to_string(),
resource: resource.to_string(),
actions: HashSet::new(),
conditions: Vec::new(),
}
}
pub fn add_action(&mut self, action: Action) {
self.actions.insert(action);
}
pub fn add_condition(&mut self, condition: PermissionCondition) {
self.conditions.push(condition);
}
pub fn check_conditions(&self, context: &AccessContext) -> bool {
for condition in &self.conditions {
match condition {
PermissionCondition::TimeBasedAccess { start_hour, end_hour, allowed_days } => {
if !self.check_time_based_access(*start_hour, *end_hour, allowed_days) {
return false;
}
}
PermissionCondition::IPBasedAccess { allowed_ips, allowed_ranges } => {
if !self.check_ip_based_access(context.ip_address, allowed_ips, allowed_ranges) {
return false;
}
}
PermissionCondition::MFARequired => {
if !context.mfa_verified {
return false;
}
}
}
}
true
}
fn check_time_based_access(&self, start_hour: u8, end_hour: u8, allowed_days: &[Weekday]) -> bool {
use chrono::{Local, Weekday};
let now = Local::now();
let current_hour = now.hour() as u8;
let current_day = now.weekday();
current_hour >= start_hour &&
current_hour <= end_hour &&
allowed_days.contains(¤t_day)
}
fn check_ip_based_access(&self, ip: &str, allowed_ips: &[String], allowed_ranges: &[String]) -> bool {
if allowed_ips.contains(&ip.to_string()) {
return true;
}
for range in allowed_ranges {
if self.ip_in_range(ip, range) {
return true;
}
}
false
}
fn ip_in_range(&self, ip: &str, range: &str) -> bool {
true }
}
#[derive(Debug)]
pub struct AccessContext {
pub ip_address: String,
pub timestamp: i64,
pub mfa_verified: bool,
pub user_agent: String,
}