junobuild_auth/state/
heap.rs

1use crate::openid::types::provider::{OpenIdCertificate, OpenIdProvider};
2use crate::state::types::config::AuthenticationConfig;
3use crate::state::types::state::Salt;
4use crate::state::types::state::{AuthenticationHeapState, OpenIdCachedCertificate, OpenIdState};
5use crate::strategies::AuthHeapStrategy;
6use std::collections::hash_map::Entry;
7
8// ---------------------------------------------------------
9// Config
10// ---------------------------------------------------------
11
12pub fn get_config(auth_heap: &impl AuthHeapStrategy) -> Option<AuthenticationConfig> {
13    auth_heap
14        .with_auth_state(|authentication| authentication.as_ref().map(|auth| auth.config.clone()))
15}
16
17pub fn insert_config(auth_heap: &impl AuthHeapStrategy, config: &AuthenticationConfig) {
18    auth_heap.with_auth_state_mut(|authentication| insert_config_impl(config, authentication))
19}
20
21fn insert_config_impl(config: &AuthenticationConfig, state: &mut Option<AuthenticationHeapState>) {
22    match state {
23        None => {
24            *state = Some(AuthenticationHeapState {
25                config: config.clone(),
26                salt: None,
27                openid: None,
28            })
29        }
30        Some(state) => state.config = config.clone(),
31    }
32}
33
34// ---------------------------------------------------------
35// Salt
36// ---------------------------------------------------------
37
38pub fn get_salt(auth_heap: &impl AuthHeapStrategy) -> Option<Salt> {
39    auth_heap.with_auth_state(|authentication| authentication.as_ref().and_then(|auth| auth.salt))
40}
41
42pub fn insert_salt(auth_heap: &impl AuthHeapStrategy, salt: &Salt) {
43    auth_heap.with_auth_state_mut(|authentication| insert_salt_impl(salt, authentication))
44}
45
46fn insert_salt_impl(salt: &Salt, state: &mut Option<AuthenticationHeapState>) {
47    match state {
48        None => {
49            *state = Some(AuthenticationHeapState {
50                config: AuthenticationConfig::default(),
51                salt: Some(*salt),
52                openid: None,
53            })
54        }
55        Some(state) => state.salt = Some(*salt),
56    }
57}
58
59// ---------------------------------------------------------
60// Openid
61// ---------------------------------------------------------
62
63pub fn get_openid_state(auth_heap: &impl AuthHeapStrategy) -> Option<OpenIdState> {
64    auth_heap.with_auth_state(|authentication| {
65        authentication.as_ref().and_then(|auth| auth.openid.clone())
66    })
67}
68
69pub fn get_cached_certificate(
70    provider: &OpenIdProvider,
71    auth_heap: &impl AuthHeapStrategy,
72) -> Option<OpenIdCachedCertificate> {
73    auth_heap
74        .with_auth_state(|authentication| get_cached_certificate_impl(provider, authentication))
75}
76
77pub fn cache_certificate(
78    provider: &OpenIdProvider,
79    certificate: &OpenIdCertificate,
80    auth_heap: &impl AuthHeapStrategy,
81) -> Result<(), String> {
82    auth_heap.with_auth_state_mut(|authentication| {
83        cache_certificate_impl(provider, certificate, authentication)
84    })
85}
86
87pub fn record_fetch_attempt(
88    provider: &OpenIdProvider,
89    reset_streak: bool,
90    auth_heap: &impl AuthHeapStrategy,
91) {
92    auth_heap.with_auth_state_mut(|authentication| {
93        record_fetch_attempt_impl(provider, reset_streak, authentication)
94    })
95}
96
97fn get_cached_certificate_impl(
98    provider: &OpenIdProvider,
99    state: &Option<AuthenticationHeapState>,
100) -> Option<OpenIdCachedCertificate> {
101    state
102        .as_ref()
103        .and_then(|auth| auth.openid.as_ref())
104        .and_then(|openid| openid.certificates.get(provider))
105        .cloned()
106}
107
108fn record_fetch_attempt_impl(
109    provider: &OpenIdProvider,
110    reset_streak: bool,
111    state: &mut Option<AuthenticationHeapState>,
112) {
113    let authentication = state.get_or_insert_with(AuthenticationHeapState::default);
114    let openid_state = authentication
115        .openid
116        .get_or_insert_with(OpenIdState::default);
117
118    openid_state
119        .certificates
120        .entry(provider.clone())
121        .and_modify(|cached_certificate| cached_certificate.record_attempt(reset_streak))
122        .or_insert_with(OpenIdCachedCertificate::init);
123}
124
125fn cache_certificate_impl(
126    provider: &OpenIdProvider,
127    certificate: &OpenIdCertificate,
128    state: &mut Option<AuthenticationHeapState>,
129) -> Result<(), String> {
130    let authentication = state.get_or_insert_with(AuthenticationHeapState::default);
131    let openid_state = authentication
132        .openid
133        .get_or_insert_with(OpenIdState::default);
134
135    match openid_state.certificates.entry(provider.clone()) {
136        Entry::Occupied(mut occ) => {
137            occ.get_mut().update_certificate(certificate);
138            Ok(())
139        }
140        Entry::Vacant(_) => Err("Cannot cache certificate: fetch attempt was not recorded".into()),
141    }
142}