haste_server/auth_n/session/
user.rs1use haste_fhir_model::r4::generated::terminology::IssueType;
2use haste_fhir_operation_error::OperationOutcomeError;
3use haste_repository::{
4 Repository,
5 admin::TenantModelAdmin,
6 types::{
7 mfa::{UserMFACredentialCreate, UserMFASearchClaims},
8 scope::UserId,
9 user::User,
10 },
11};
12use serde::{Deserialize, Serialize};
13use tower_sessions::Session;
14
15static AUTHORIZATION_STATE_KEY: &str = "user_authorization_state";
16
17#[derive(Deserialize, Serialize)]
18pub struct AuthorizationStateCompleted {
19 pub user: User,
20}
21
22#[derive(Deserialize, Serialize)]
23pub enum SessionAuthorizationState {
24 Complete(AuthorizationStateCompleted),
25 MFARequired { user: User },
26 }
30
31pub async fn get_completed_authorization_state(
32 session: &Session,
33) -> Result<AuthorizationStateCompleted, OperationOutcomeError> {
34 let authorization_state = get_authorization_state(session).await?;
35
36 match authorization_state {
37 Some(SessionAuthorizationState::Complete(completed_state)) => Ok(completed_state),
38 _ => Err(OperationOutcomeError::error(
39 IssueType::invalid(),
40 "Authorization state is not complete.".to_string(),
41 )),
42 }
43}
44
45pub async fn get_authorization_state(
46 session: &Session,
47) -> Result<Option<SessionAuthorizationState>, OperationOutcomeError> {
48 let authorization_state = session
49 .get::<SessionAuthorizationState>(AUTHORIZATION_STATE_KEY)
50 .await
51 .map_err(|_e| {
52 OperationOutcomeError::fatal(
53 IssueType::exception(),
54 "Session returned an error when retrieving current user.".to_string(),
55 )
56 })?;
57
58 Ok(authorization_state)
59}
60
61pub async fn set_initial_authorization_state<Repo: Repository>(
62 repo: &Repo,
63 session: &Session,
64 user: User,
65) -> Result<(), OperationOutcomeError> {
66 let active_mfa_credentials = TenantModelAdmin::<UserMFACredentialCreate, _, _, _, _>::search(
67 repo,
68 &user.tenant,
69 &UserMFASearchClaims {
70 tenant: user.tenant.clone(),
71 user_id: UserId::new(user.id.clone()),
72 is_active: Some(true),
73 },
74 )
75 .await?;
76
77 let initial_state = if active_mfa_credentials.is_empty() {
78 SessionAuthorizationState::Complete(AuthorizationStateCompleted { user })
80 } else {
81 SessionAuthorizationState::MFARequired { user }
82 };
83
84 session
85 .insert(AUTHORIZATION_STATE_KEY, initial_state)
86 .await
87 .map_err(|_e| {
88 OperationOutcomeError::fatal(
89 IssueType::exception(),
90 "Failed to set user in session.".to_string(),
91 )
92 })
93}
94
95pub async fn set_completed_authorization_state(
96 session: &Session,
97 user: User,
98) -> Result<(), OperationOutcomeError> {
99 session
100 .insert(
101 AUTHORIZATION_STATE_KEY,
102 SessionAuthorizationState::Complete(AuthorizationStateCompleted { user }),
103 )
104 .await
105 .map_err(|_e| {
106 OperationOutcomeError::fatal(
107 IssueType::exception(),
108 "Failed to set user in session.".to_string(),
109 )
110 })
111}
112
113pub async fn clear_authorization_state(session: &Session) -> Result<(), OperationOutcomeError> {
114 session
115 .remove::<SessionAuthorizationState>(AUTHORIZATION_STATE_KEY)
116 .await
117 .map_err(|_e| {
118 OperationOutcomeError::fatal(
119 IssueType::exception(),
120 "Failed to clear user from session.".to_string(),
121 )
122 })?;
123
124 Ok(())
125}