151 lines
3.8 KiB
Rust
151 lines
3.8 KiB
Rust
/// Mock implementations for testing (pluggable traits)
|
|||
|
|
|
||
|
|
use std::sync::Arc;
|
||
|
|
use std::sync::Mutex;
|
||
|
|
use super::builders::{AccessPolicy, OidcClaims};
|
||
|
|
use anyhow::Result;
|
||
|
|
|
||
|
|
/// Mock PolicyProvider for testing (no Vault dependency)
|
||
|
|
pub struct MockPolicyProvider {
|
||
|
|
policies: Arc<Mutex<std::collections::HashMap<String, AccessPolicy>>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl MockPolicyProvider {
|
||
|
|
pub fn new() -> Self {
|
||
|
|
Self {
|
||
|
|
policies: Arc::new(Mutex::new(std::collections::HashMap::new())),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn with_policy(
|
||
|
|
mut self,
|
||
|
|
resource_type: &str,
|
||
|
|
resource_name: &str,
|
||
|
|
policy: AccessPolicy,
|
||
|
|
) -> Self {
|
||
|
|
let key = format!("{}:{}", resource_type, resource_name);
|
||
|
|
self.policies.lock().unwrap().insert(key, policy);
|
||
|
|
self
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn get_policy(
|
||
|
|
&self,
|
||
|
|
resource_type: &str,
|
||
|
|
resource_name: &str,
|
||
|
|
) -> Result<AccessPolicy> {
|
||
|
|
let key = format!("{}:{}", resource_type, resource_name);
|
||
|
|
self.policies
|
||
|
|
.lock()
|
||
|
|
.unwrap()
|
||
|
|
.get(&key)
|
||
|
|
.cloned()
|
||
|
|
.ok_or_else(|| anyhow::anyhow!("Policy not found: {}", key))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Mock AuditLogger for testing (records decisions, no I/O)
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub struct AccessDecision {
|
||
|
|
pub user_id: String,
|
||
|
|
pub resource_type: String,
|
||
|
|
pub resource_name: String,
|
||
|
|
pub decision: String,
|
||
|
|
pub reason: String,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub struct MockAuditLogger {
|
||
|
|
decisions: Arc<Mutex<Vec<AccessDecision>>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl MockAuditLogger {
|
||
|
|
pub fn new() -> Self {
|
||
|
|
Self {
|
||
|
|
decisions: Arc::new(Mutex::new(Vec::new())),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn log_decision(&self, decision: AccessDecision) -> Result<()> {
|
||
|
|
self.decisions.lock().unwrap().push(decision);
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn decisions(&self) -> Vec<AccessDecision> {
|
||
|
|
self.decisions.lock().unwrap().clone()
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn last_decision(&self) -> Option<AccessDecision> {
|
||
|
|
self.decisions.lock().unwrap().last().cloned()
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn clear(&self) {
|
||
|
|
self.decisions.lock().unwrap().clear();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Mock DocumentScorer for testing (returns constant score)
|
||
|
|
pub struct ConstantScorer {
|
||
|
|
score: f32,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl ConstantScorer {
|
||
|
|
pub fn new(score: f32) -> Self {
|
||
|
|
Self { score }
|
||
|
|
}
|
||
|
|
|
||
|
|
pub async fn score(&self, _query: &str, _doc_id: &str) -> Result<f32> {
|
||
|
|
Ok(self.score)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn name(&self) -> &str {
|
||
|
|
"constant-mock"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn test_mock_policy_provider() {
|
||
|
|
let provider = MockPolicyProvider::new();
|
||
|
|
let policy = AccessPolicy {
|
||
|
|
access_level: "public".to_string(),
|
||
|
|
owner_group: "".to_string(),
|
||
|
|
allowed_groups: vec![],
|
||
|
|
required_role: None,
|
||
|
|
required_permission: None,
|
||
|
|
};
|
||
|
|
|
||
|
|
let provider = provider.with_policy("project", "poimen", policy.clone());
|
||
|
|
let retrieved = provider.get_policy("project", "poimen").await.unwrap();
|
||
|
|
|
||
|
|
assert_eq!(retrieved, policy);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn test_mock_audit_logger() {
|
||
|
|
let logger = MockAuditLogger::new();
|
||
|
|
|
||
|
|
logger
|
||
|
|
.log_decision(AccessDecision {
|
||
|
|
user_id: "charlie".to_string(),
|
||
|
|
resource_type: "project".to_string(),
|
||
|
|
resource_name: "poimen".to_string(),
|
||
|
|
decision: "allow".to_string(),
|
||
|
|
reason: "in_allowed_group".to_string(),
|
||
|
|
})
|
||
|
|
.await
|
||
|
|
.unwrap();
|
||
|
|
|
||
|
|
let decisions = logger.decisions();
|
||
|
|
assert_eq!(decisions.len(), 1);
|
||
|
|
assert_eq!(decisions[0].user_id, "charlie");
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_constant_scorer() {
|
||
|
|
let scorer = ConstantScorer::new(0.75);
|
||
|
|
assert_eq!(scorer.name(), "constant-mock");
|
||
|
|
}
|
||
|
|
}
|