use api_bones::error::{ApiError, ErrorCode};
use api_bones::org_context::OrganizationContext;
use api_bones::org_id::OrgId;
pub trait OrgPolicy: Send + Sync {
fn allows(&self, caller: &OrganizationContext, target: &OrgId) -> Result<(), ApiError>;
fn check_target(&self, caller: &OrganizationContext, target: &OrgId) -> Result<(), ApiError> {
self.allows(caller, target).map_err(|_| {
ApiError::new(ErrorCode::Forbidden, "cross-org access denied")
.with_request_id(caller.request_id.as_uuid())
})
}
}
pub struct AncestryOrgPolicy;
impl OrgPolicy for AncestryOrgPolicy {
fn allows(&self, caller: &OrganizationContext, target: &OrgId) -> Result<(), ApiError> {
if &caller.org_id == target {
return Ok(());
}
let self_pos = caller.org_path.iter().position(|id| id == &caller.org_id);
if let Some(pos) = self_pos {
if caller.org_path[pos + 1..].contains(target) {
return Ok(());
}
}
Err(ApiError::new(
ErrorCode::Forbidden,
"cross-org access denied",
))
}
}