haste_access_control/
lib.rs

1use haste_fhir_client::{FHIRClient, request::FHIRRequest};
2use haste_fhir_model::r4::generated::{
3    resources::AccessPolicyV2,
4    terminology::{AccessPolicyv2Engine, IssueType},
5};
6use haste_fhir_operation_error::OperationOutcomeError;
7use haste_jwt::{ProjectId, TenantId, claims::UserTokenClaims};
8
9mod engine;
10mod utilities;
11
12#[allow(unused)]
13#[derive(Debug)]
14pub struct PolicyEnvironment<'a> {
15    tenant: &'a TenantId,
16    project: &'a ProjectId,
17    request: &'a FHIRRequest,
18    user: &'a UserTokenClaims,
19}
20
21#[derive(Debug)]
22pub struct PolicyContext<'a, CTX, Client: FHIRClient<CTX, OperationOutcomeError>> {
23    pub client: &'a Client,
24    pub client_context: CTX,
25
26    pub environment: Option<PolicyEnvironment<'a>>,
27}
28
29pub async fn evaluate_policy<'a, CTX, Client: FHIRClient<CTX, OperationOutcomeError>>(
30    _context: &PolicyContext<'a, CTX, Client>,
31    policy: &AccessPolicyV2,
32) -> Result<(), OperationOutcomeError> {
33    match &*policy.engine {
34        AccessPolicyv2Engine::FullAccess(_) => engine::full_access::evaluate(policy),
35        AccessPolicyv2Engine::RuleEngine(_) => Err(OperationOutcomeError::fatal(
36            haste_fhir_model::r4::generated::terminology::IssueType::Forbidden(None),
37            "Access policy denies access.".to_string(),
38        )),
39        AccessPolicyv2Engine::Null(_) => Err(OperationOutcomeError::fatal(
40            haste_fhir_model::r4::generated::terminology::IssueType::Forbidden(None),
41            "Access policy denies access.".to_string(),
42        )),
43    }
44}
45
46pub async fn evaluate_policies<'a, CTX, Client: FHIRClient<CTX, OperationOutcomeError>>(
47    _context: &PolicyContext<'a, CTX, Client>,
48    policies: &Vec<AccessPolicyV2>,
49) -> Result<(), OperationOutcomeError> {
50    let mut outcomes = vec![];
51    for policy in policies {
52        if let Err(e) = evaluate_policy(_context, policy).await {
53            outcomes.push(e);
54        } else {
55            return Ok(());
56        }
57    }
58
59    Err(OperationOutcomeError::error(
60        IssueType::Forbidden(None),
61        format!("No policy has granted access to your request."),
62    ))
63}