1use crate::{
2 AuthorId, AuthorKind, ProjectId, SupportedFHIRVersions, TenantId, UserRole, VersionId,
3 scopes::Scopes,
4};
5use derivative::Derivative;
6use haste_fhir_model::r4::generated::{terminology::IssueType, types::FHIRUrl};
7use haste_fhir_operation_error::OperationOutcomeError;
8use serde::{Deserialize, Serialize};
9
10#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
11pub enum SubscriptionTier {
12 #[serde(rename = "free")]
13 Free,
14 #[serde(rename = "professional")]
15 Professional,
16 #[serde(rename = "team")]
17 Team,
18 #[serde(rename = "unlimited")]
19 Unlimited,
20}
21
22impl From<SubscriptionTier> for String {
23 fn from(tier: SubscriptionTier) -> Self {
24 match tier {
25 SubscriptionTier::Free => "free",
26 SubscriptionTier::Professional => "professional",
27 SubscriptionTier::Team => "team",
28 SubscriptionTier::Unlimited => "unlimited",
29 }
30 .to_string()
31 }
32}
33
34impl TryFrom<String> for SubscriptionTier {
35 type Error = OperationOutcomeError;
36 fn try_from(value: String) -> Result<Self, Self::Error> {
37 match value.as_str() {
38 "free" => Ok(SubscriptionTier::Free),
39 "professional" => Ok(SubscriptionTier::Professional),
40 "team" => Ok(SubscriptionTier::Team),
41 "unlimited" => Ok(SubscriptionTier::Unlimited),
42 _ => Err(OperationOutcomeError::error(
43 IssueType::invalid(),
44 format!("Invalid subscription tier: '{value}'"),
45 )),
46 }
47 }
48}
49
50#[derive(Derivative, Serialize, Deserialize, Clone)]
51#[derivative(Debug = "transparent")]
52pub struct UserTokenClaims {
53 pub sub: AuthorId,
54 #[derivative(Debug = "ignore")]
55 pub exp: usize,
56 #[derivative(Debug = "ignore")]
57 pub aud: String,
58 #[derivative(Debug = "ignore")]
59 pub scope: Scopes,
60
61 #[derivative(Debug = "ignore")]
63 #[serde(rename = "fhirUser")]
64 pub fhir_user: Option<FHIRUrl>,
65 #[serde(
68 rename = "https://haste.health/patient",
69 default,
70 skip_serializing_if = "Option::is_none"
71 )]
72 #[derivative(Debug = "ignore")]
73 pub patient: Option<String>,
74 #[serde(
77 rename = "https://haste.health/encounter",
78 default,
79 skip_serializing_if = "Option::is_none"
80 )]
81 #[derivative(Debug = "ignore")]
82 pub encounter: Option<String>,
83 #[serde(default, skip_serializing_if = "Option::is_none")]
87 #[derivative(Debug = "ignore")]
88 pub client_id: Option<String>,
89
90 #[serde(rename = "https://haste.health/tenant")]
92 #[derivative(Debug = "ignore")]
93 pub tenant: TenantId,
94 #[serde(rename = "https://haste.health/subscription_tier")]
95 #[derivative(Debug = "ignore")]
96 pub subscription_tier: SubscriptionTier,
97 #[serde(rename = "https://haste.health/project")]
98 #[derivative(Debug = "ignore")]
99 pub project: Option<ProjectId>,
100 #[serde(rename = "https://haste.health/user_role")]
101 #[derivative(Debug = "ignore")]
102 pub user_role: UserRole,
103 #[serde(rename = "https://haste.health/user_id")]
104 #[derivative(Debug = "ignore")]
105 pub user_id: AuthorId,
106 #[serde(rename = "https://haste.health/resource_type")]
107 #[derivative(Debug = "ignore")]
108 pub resource_type: AuthorKind,
109 #[serde(rename = "https://haste.health/access_policies")]
110 #[derivative(Debug = "ignore")]
111 pub access_policy_version_ids: Vec<VersionId>,
112 #[serde(rename = "https://haste.health/membership")]
113 #[derivative(Debug = "ignore")]
114 pub membership: Option<String>,
115 #[serde(rename = "https://haste.health/fhir_version")]
120 #[derivative(Debug = "ignore")]
121 pub fhir_version: SupportedFHIRVersions,
122}
123
124#[derive(Serialize, Deserialize, Clone)]
130pub struct IdTokenClaims {
131 pub iss: String,
132 pub sub: String,
133 pub aud: String,
134 pub exp: usize,
135 pub iat: usize,
136 #[serde(default, skip_serializing_if = "Option::is_none")]
138 pub email: Option<String>,
139 #[serde(default, skip_serializing_if = "Option::is_none")]
140 pub email_verified: Option<bool>,
141 #[serde(rename = "fhirUser", default, skip_serializing_if = "Option::is_none")]
143 pub fhir_user: Option<FHIRUrl>,
144 #[serde(rename = "https://haste.health/tenant")]
146 pub tenant: TenantId,
147 #[serde(rename = "https://haste.health/project")]
148 pub project: ProjectId,
149 #[serde(rename = "https://haste.health/user_role")]
150 pub user_role: UserRole,
151}