Skip to main content

haste_jwt/
lib.rs

1use derivative::Derivative;
2use haste_fhir_model::r4::generated::terminology::{BoundCode, UserRole as FHIRUserRole};
3use serde::{Deserialize, Serialize};
4use std::fmt::Display;
5
6#[cfg(feature = "reflect")]
7pub mod reflect;
8
9#[cfg(feature = "sqlx")]
10pub mod sqlx;
11
12pub mod claims;
13pub mod scopes;
14
15// Reserved keyword for system tenant, author and project.
16static SYSTEM: &str = "system";
17
18#[derive(Clone, Debug, PartialEq, PartialOrd, Deserialize, Serialize)]
19#[serde(rename_all = "lowercase")]
20pub enum UserRole {
21    Owner,
22    Admin,
23    Member,
24}
25
26impl From<BoundCode<FHIRUserRole>> for UserRole {
27    fn from(role: BoundCode<FHIRUserRole>) -> Self {
28        if role == FHIRUserRole::owner() {
29            UserRole::Owner
30        } else if role == FHIRUserRole::admin() {
31            UserRole::Admin
32        } else {
33            UserRole::Member
34        }
35    }
36}
37
38#[derive(Derivative, Clone)]
39#[derivative(Debug = "transparent")]
40pub enum AuthorId {
41    // System is used for system level actions such as tenant creation etc..
42    System,
43    User(ResourceId),
44}
45
46impl AuthorId {
47    #[must_use]
48    pub fn new(id: String) -> Self {
49        // Should never be able to create a system author from user.
50        if id == SYSTEM {
51            AuthorId::System
52        } else {
53            AuthorId::User(ResourceId::new(id))
54        }
55    }
56}
57
58impl AsRef<str> for AuthorId {
59    fn as_ref(&self) -> &str {
60        match self {
61            AuthorId::System => SYSTEM,
62            AuthorId::User(id) => id.as_ref(),
63        }
64    }
65}
66
67impl<'de> Deserialize<'de> for AuthorId {
68    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69    where
70        D: serde::Deserializer<'de>,
71    {
72        Ok(AuthorId::new(String::deserialize(deserializer)?))
73    }
74}
75
76impl Serialize for AuthorId {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78    where
79        S: serde::Serializer,
80    {
81        serializer.serialize_str(self.as_ref())
82    }
83}
84
85impl Display for AuthorId {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        match self {
88            AuthorId::System => write!(f, "{SYSTEM}"),
89            AuthorId::User(id) => write!(f, "{}", id.as_ref()),
90        }
91    }
92}
93
94#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
95pub enum AuthorKind {
96    System,
97    Membership,
98    ClientApplication,
99    OperationDefinition,
100}
101
102impl AsRef<str> for AuthorKind {
103    fn as_ref(&self) -> &str {
104        match self {
105            AuthorKind::System => "System",
106            AuthorKind::Membership => "Membership",
107            AuthorKind::ClientApplication => "ClientApplication",
108            AuthorKind::OperationDefinition => "OperationDefinition",
109        }
110    }
111}
112
113impl Display for AuthorKind {
114    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115        write!(f, "{}", self.as_ref())
116    }
117}
118
119#[derive(Derivative, Clone, PartialEq, Eq, Hash)]
120#[derivative(Debug = "transparent")]
121pub enum TenantId {
122    System,
123    #[derivative(Debug = "transparent")]
124    Custom(String),
125}
126
127impl TenantId {
128    #[must_use]
129    pub fn new(id: String) -> Self {
130        // Should never be able to create a system tenant from user.
131        if id == SYSTEM {
132            TenantId::System
133        } else {
134            TenantId::Custom(id)
135        }
136    }
137}
138
139impl From<String> for TenantId {
140    fn from(id: String) -> Self {
141        TenantId::new(id)
142    }
143}
144
145impl AsRef<str> for TenantId {
146    fn as_ref(&self) -> &str {
147        match self {
148            TenantId::System => SYSTEM,
149            TenantId::Custom(id) => id,
150        }
151    }
152}
153
154impl<'de> Deserialize<'de> for TenantId {
155    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
156    where
157        D: serde::Deserializer<'de>,
158    {
159        Ok(TenantId::new(String::deserialize(deserializer)?))
160    }
161}
162
163impl Serialize for TenantId {
164    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
165    where
166        S: serde::Serializer,
167    {
168        serializer.serialize_str(self.as_ref())
169    }
170}
171
172impl Display for TenantId {
173    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174        match self {
175            TenantId::System => write!(f, "{SYSTEM}"),
176            TenantId::Custom(id) => write!(f, "{id}"),
177        }
178    }
179}
180
181#[derive(Derivative, Clone, PartialEq, Eq, Hash)]
182#[derivative(Debug = "transparent")]
183pub enum ProjectId {
184    System,
185    #[derivative(Debug = "transparent")]
186    Custom(String),
187}
188impl ProjectId {
189    #[must_use]
190    pub fn new(id: String) -> Self {
191        // Should never be able to create a system project from user.
192        if id == SYSTEM {
193            ProjectId::System
194        } else {
195            ProjectId::Custom(id)
196        }
197    }
198}
199
200impl AsRef<str> for ProjectId {
201    fn as_ref(&self) -> &str {
202        match self {
203            ProjectId::System => SYSTEM,
204            ProjectId::Custom(id) => id,
205        }
206    }
207}
208
209impl<'de> Deserialize<'de> for ProjectId {
210    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
211    where
212        D: serde::Deserializer<'de>,
213    {
214        Ok(ProjectId::new(String::deserialize(deserializer)?))
215    }
216}
217
218impl Serialize for ProjectId {
219    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
220    where
221        S: serde::Serializer,
222    {
223        serializer.serialize_str(self.as_ref())
224    }
225}
226
227impl Display for ProjectId {
228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229        match self {
230            ProjectId::System => write!(f, "{SYSTEM}"),
231            ProjectId::Custom(id) => write!(f, "{id}"),
232        }
233    }
234}
235
236pub struct VersionIdRef<'a>(&'a str);
237impl<'a> VersionIdRef<'a> {
238    #[must_use]
239    pub fn new(id: &'a str) -> Self {
240        VersionIdRef(id)
241    }
242}
243impl<'a> AsRef<str> for VersionIdRef<'a> {
244    fn as_ref(&self) -> &'a str {
245        self.0
246    }
247}
248impl<'a> From<&'a VersionId> for VersionIdRef<'a> {
249    fn from(version_id: &'a VersionId) -> Self {
250        VersionIdRef::new(&version_id.0)
251    }
252}
253
254#[derive(Derivative, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
255#[derivative(Debug = "transparent")]
256pub struct VersionId(String);
257impl VersionId {
258    #[must_use]
259    pub fn new(id: String) -> Self {
260        VersionId(id)
261    }
262}
263impl From<String> for VersionId {
264    fn from(id: String) -> Self {
265        VersionId(id)
266    }
267}
268impl AsRef<str> for VersionId {
269    fn as_ref(&self) -> &str {
270        &self.0
271    }
272}
273
274#[derive(Derivative, Clone, Deserialize, Serialize)]
275#[derivative(Debug = "transparent")]
276pub struct ResourceId(String);
277impl ResourceId {
278    #[must_use]
279    pub fn new(id: String) -> Self {
280        ResourceId(id)
281    }
282}
283impl AsRef<str> for ResourceId {
284    fn as_ref(&self) -> &str {
285        &self.0
286    }
287}