use crate::workspace::mock_environment::MockEnvironmentName;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub type Permission = String;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnvironmentPermissionPolicy {
pub id: String,
pub org_id: Option<String>,
pub workspace_id: Option<String>,
pub environment: MockEnvironmentName,
pub permission: String, pub allowed_roles: Vec<String>, pub created_at: chrono::DateTime<chrono::Utc>,
}
impl EnvironmentPermissionPolicy {
pub fn new(
environment: MockEnvironmentName,
permission: Permission,
allowed_roles: Vec<String>,
) -> Self {
Self {
id: uuid::Uuid::new_v4().to_string(),
org_id: None,
workspace_id: None,
environment,
permission: permission.to_string(),
allowed_roles,
created_at: chrono::Utc::now(),
}
}
pub fn allows_role(&self, role: &str) -> bool {
self.allowed_roles.iter().any(|r| r.eq_ignore_ascii_case(role))
}
}
pub struct EnvironmentPermissionChecker {
policies: HashMap<(MockEnvironmentName, String), Vec<EnvironmentPermissionPolicy>>,
}
impl EnvironmentPermissionChecker {
pub fn new() -> Self {
Self {
policies: HashMap::new(),
}
}
pub fn add_policy(&mut self, policy: EnvironmentPermissionPolicy) {
let key = (policy.environment, policy.permission.clone());
self.policies.entry(key).or_default().push(policy);
}
pub fn has_permission(
&self,
role: &str,
permission: Permission,
environment: MockEnvironmentName,
) -> bool {
let key = (environment, permission.to_string());
if let Some(policies) = self.policies.get(&key) {
policies.iter().any(|policy| policy.allows_role(role))
} else {
true
}
}
pub fn get_policies_for_environment(
&self,
environment: MockEnvironmentName,
) -> Vec<&EnvironmentPermissionPolicy> {
self.policies
.iter()
.filter_map(|((env, _), policies)| {
if *env == environment {
Some(policies.iter())
} else {
None
}
})
.flatten()
.collect()
}
pub fn get_policies_for_permission(
&self,
permission: Permission,
) -> Vec<&EnvironmentPermissionPolicy> {
let perm_str = permission.to_string();
self.policies
.iter()
.filter_map(|((_, perm), policies)| {
if *perm == perm_str {
Some(policies.iter())
} else {
None
}
})
.flatten()
.collect()
}
}
impl Default for EnvironmentPermissionChecker {
fn default() -> Self {
Self::new()
}
}
pub fn check_environment_permission(
checker: &EnvironmentPermissionChecker,
role: &str,
permission: Permission,
environment: Option<MockEnvironmentName>,
) -> bool {
let env = match environment {
Some(e) => e,
None => return true, };
checker.has_permission(role, permission, env)
}