155 lines
4.5 KiB
Rust
155 lines
4.5 KiB
Rust
use std::sync::{Arc, Mutex};
|
|
|
|
use application::{
|
|
ResolveAgentSystemPermissions, ResolveAgentSystemPermissionsInput,
|
|
UpdateAgentSystemPermissions, UpdateAgentSystemPermissionsInput,
|
|
UpdateProjectSystemPermissions, UpdateProjectSystemPermissionsInput,
|
|
};
|
|
use async_trait::async_trait;
|
|
use domain::ids::{AgentId, ProjectId};
|
|
use domain::ports::{RuntimeError, RuntimePermissionProbe, StoreError, SystemPermissionStore};
|
|
use domain::project::{Project, ProjectPath};
|
|
use domain::remote::RemoteRef;
|
|
use domain::{
|
|
NetworkPolicy, ProjectSystemPermissions, RuntimeLockState, RuntimePermissionSnapshot,
|
|
SystemPermissionControlMode, SystemPermissionSet,
|
|
};
|
|
|
|
#[derive(Default)]
|
|
struct FakeSystemPermissionStore {
|
|
doc: Mutex<ProjectSystemPermissions>,
|
|
saves: Mutex<usize>,
|
|
}
|
|
|
|
#[async_trait]
|
|
impl SystemPermissionStore for FakeSystemPermissionStore {
|
|
async fn load_system_permissions(
|
|
&self,
|
|
_project: &Project,
|
|
) -> Result<ProjectSystemPermissions, StoreError> {
|
|
Ok(self.doc.lock().unwrap().clone())
|
|
}
|
|
|
|
async fn save_system_permissions(
|
|
&self,
|
|
_project: &Project,
|
|
permissions: &ProjectSystemPermissions,
|
|
) -> Result<(), StoreError> {
|
|
*self.doc.lock().unwrap() = permissions.clone();
|
|
*self.saves.lock().unwrap() += 1;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
struct LockedProbe;
|
|
|
|
#[async_trait]
|
|
impl RuntimePermissionProbe for LockedProbe {
|
|
async fn probe_runtime_permissions(
|
|
&self,
|
|
_project: &Project,
|
|
_agent_id: AgentId,
|
|
) -> Result<RuntimePermissionSnapshot, RuntimeError> {
|
|
Ok(RuntimePermissionSnapshot::locked_uninspectable())
|
|
}
|
|
}
|
|
|
|
fn project() -> Project {
|
|
Project::new(
|
|
ProjectId::new_random(),
|
|
"system-permissions",
|
|
ProjectPath::new("/home/me/proj").unwrap(),
|
|
RemoteRef::local(),
|
|
1_700_000_000_000,
|
|
)
|
|
.unwrap()
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_project_system_permissions_replaces_defaults_and_persists() {
|
|
let store = Arc::new(FakeSystemPermissionStore::default());
|
|
let use_case = UpdateProjectSystemPermissions::new(store.clone());
|
|
|
|
let out = use_case
|
|
.execute(UpdateProjectSystemPermissionsInput {
|
|
project: project(),
|
|
permissions: Some(SystemPermissionSet::new(Some(NetworkPolicy::Ask))),
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
out.permissions.project_default.unwrap().network,
|
|
Some(NetworkPolicy::Ask)
|
|
);
|
|
assert_eq!(*store.saves.lock().unwrap(), 1);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_agent_system_permissions_adds_and_removes_sparse_override() {
|
|
let store = Arc::new(FakeSystemPermissionStore::default());
|
|
let use_case = UpdateAgentSystemPermissions::new(store.clone());
|
|
let agent = AgentId::new_random();
|
|
|
|
use_case
|
|
.execute(UpdateAgentSystemPermissionsInput {
|
|
project: project(),
|
|
agent_id: agent,
|
|
permissions: Some(SystemPermissionSet::new(Some(NetworkPolicy::Deny))),
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
assert_eq!(
|
|
store
|
|
.doc
|
|
.lock()
|
|
.unwrap()
|
|
.agent_permissions(agent)
|
|
.unwrap()
|
|
.network,
|
|
Some(NetworkPolicy::Deny)
|
|
);
|
|
|
|
let out = use_case
|
|
.execute(UpdateAgentSystemPermissionsInput {
|
|
project: project(),
|
|
agent_id: agent,
|
|
permissions: None,
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
assert!(out.permissions.agent_permissions(agent).is_none());
|
|
assert_eq!(*store.saves.lock().unwrap(), 2);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn resolve_agent_system_permissions_exposes_locked_runtime_read_only() {
|
|
let agent = AgentId::new_random();
|
|
let store = Arc::new(FakeSystemPermissionStore {
|
|
doc: Mutex::new(ProjectSystemPermissions::new(
|
|
Some(SystemPermissionSet::new(Some(NetworkPolicy::Allow))),
|
|
vec![],
|
|
)),
|
|
saves: Mutex::new(0),
|
|
});
|
|
let use_case = ResolveAgentSystemPermissions::new(store, Arc::new(LockedProbe));
|
|
|
|
let out = use_case
|
|
.execute(ResolveAgentSystemPermissionsInput {
|
|
project: project(),
|
|
agent_id: agent,
|
|
})
|
|
.await
|
|
.unwrap();
|
|
|
|
assert_eq!(out.permissions.wanted, Some(NetworkPolicy::Allow));
|
|
assert_eq!(out.permissions.effective, NetworkPolicy::Deny);
|
|
assert_eq!(out.permissions.runtime_lock.state, RuntimeLockState::Locked);
|
|
assert_eq!(
|
|
out.permissions.control.mode,
|
|
SystemPermissionControlMode::ReadOnly
|
|
);
|
|
}
|