Skip to main content

haste_access_control/
context.rs

1use crate::request_reflection::RequestReflection;
2use haste_fhir_client::{
3    FHIRClient,
4    request::{FHIRRequest, FHIRResponse},
5};
6use haste_fhir_operation_error::{OperationOutcomeError, derive::OperationOutcomeError};
7use haste_fhirpath::FPEngine;
8use haste_jwt::{ProjectId, TenantId};
9use haste_reflect::{MetaValue, derive::Reflect};
10use std::{collections::HashMap, sync::Arc};
11
12#[derive(PartialEq, Eq, Debug)]
13pub enum PermissionLevel {
14    Deny,
15    Undetermined,
16    Allow,
17}
18
19impl From<&PermissionLevel> for i8 {
20    fn from(level: &PermissionLevel) -> Self {
21        match level {
22            PermissionLevel::Deny => -1,
23            PermissionLevel::Undetermined => 0,
24            PermissionLevel::Allow => 1,
25        }
26    }
27}
28
29#[derive(Debug, OperationOutcomeError)]
30pub enum PermissionLevelError {
31    #[error(
32        code = "invalid",
33        diagnostic = "Invalid permission level value: '{arg0}'."
34    )]
35    InvalidPermissionLevel(i8),
36}
37
38impl TryFrom<i8> for PermissionLevel {
39    type Error = PermissionLevelError;
40
41    fn try_from(value: i8) -> Result<Self, Self::Error> {
42        match value {
43            -1 => Ok(PermissionLevel::Deny),
44            0 => Ok(PermissionLevel::Undetermined),
45            1 => Ok(PermissionLevel::Allow),
46            _ => Err(PermissionLevelError::InvalidPermissionLevel(value)),
47        }
48    }
49}
50
51#[derive(Debug, Reflect)]
52#[fhir_type = "BackboneElement"]
53pub struct UserInfo {
54    pub id: String,
55}
56
57#[derive(Debug)]
58pub struct PolicyEnvironment {
59    pub tenant: TenantId,
60    pub project: ProjectId,
61    pub request: Arc<RequestReflection>,
62    pub user: Arc<UserInfo>,
63}
64
65impl PolicyEnvironment {
66    #[must_use]
67    pub fn new(
68        tenant: TenantId,
69        project: ProjectId,
70        request: FHIRRequest,
71        user: Arc<UserInfo>,
72    ) -> Self {
73        Self {
74            tenant,
75            project,
76            request: Arc::new(RequestReflection::from(request)),
77            user,
78        }
79    }
80}
81
82pub struct PolicyContext<CTX, Client: FHIRClient<CTX, OperationOutcomeError>> {
83    pub fp_engine: haste_fhirpath::FPEngine,
84    pub client: Arc<Client>,
85    pub client_context: CTX,
86
87    #[allow(dead_code)]
88    attributes_cache: HashMap<String, FHIRResponse>,
89    pub environment: PolicyEnvironment,
90}
91
92impl<CTX, Client: FHIRClient<CTX, OperationOutcomeError>> PolicyContext<CTX, Client> {
93    pub fn new(client: Arc<Client>, client_context: CTX, environment: PolicyEnvironment) -> Self {
94        Self {
95            fp_engine: FPEngine::new(),
96            client,
97            client_context,
98            attributes_cache: HashMap::new(),
99            environment,
100        }
101    }
102}