use async_trait::async_trait;
use gatehouse::*;
use uuid::Uuid;
#[derive(Debug, Clone)]
struct OrganizationAuthorizationDetails {
id: Uuid,
is_org_admin: bool,
permissions: Vec<Permission>,
}
#[derive(Debug, Clone)]
struct Permission {
scope: String,
}
#[derive(Debug, Clone)]
struct SubjectV2 {
id: Uuid,
authorization_details: OrganizationAuthorizationDetails,
}
#[derive(Debug, Clone)]
struct Group {
id: Uuid,
}
#[derive(Debug, Clone)]
struct GroupManagementAction;
#[derive(Debug, Clone)]
struct EmptyContext;
struct OrgAdminPolicy;
#[async_trait]
impl Policy<SubjectV2, Group, GroupManagementAction, EmptyContext> for OrgAdminPolicy {
async fn evaluate(
&self,
ctx: &EvalCtx<'_, SubjectV2, Group, GroupManagementAction, EmptyContext>,
) -> PolicyEvalResult {
if ctx.subject.authorization_details.is_org_admin {
ctx.grant("User is organization admin")
} else {
ctx.deny("User is not organization admin")
}
}
fn policy_type(&self) -> std::borrow::Cow<'static, str> {
std::borrow::Cow::Borrowed("OrgAdminPolicy")
}
}
struct StaffPolicy;
#[async_trait]
impl Policy<SubjectV2, Group, GroupManagementAction, EmptyContext> for StaffPolicy {
async fn evaluate(
&self,
ctx: &EvalCtx<'_, SubjectV2, Group, GroupManagementAction, EmptyContext>,
) -> PolicyEvalResult {
if ctx
.subject
.authorization_details
.permissions
.iter()
.any(|p| p.scope == "staff")
{
ctx.grant("User has staff permission")
} else {
ctx.deny("User lacks staff permission")
}
}
fn policy_type(&self) -> std::borrow::Cow<'static, str> {
std::borrow::Cow::Borrowed("StaffPolicy")
}
}
fn create_group_management_checker(
) -> PermissionChecker<SubjectV2, Group, GroupManagementAction, EmptyContext> {
let mut checker = PermissionChecker::new();
checker.add_policy(OrgAdminPolicy);
checker.add_policy(StaffPolicy);
checker
}
#[tokio::main]
async fn main() {
let subject = SubjectV2 {
id: Uuid::new_v4(),
authorization_details: OrganizationAuthorizationDetails {
id: Uuid::new_v4(),
is_org_admin: false,
permissions: vec![Permission {
scope: "staff".to_string(),
}],
},
};
let group = Group { id: Uuid::new_v4() };
let action = GroupManagementAction;
let context = EmptyContext;
let checker = create_group_management_checker();
let result = checker.check(&subject, &action, &group, &context).await;
assert!(result.is_granted());
println!(
"Evaluating subject {} with org id {} and group {}",
subject.id, subject.authorization_details.id, group.id
);
println!("{}", result.display_trace());
}