use crate::openid::types::provider::{OpenIdCertificate, OpenIdProvider};
use crate::state::types::automation::AutomationConfig;
use crate::state::types::config::AuthenticationConfig;
use crate::state::types::state::Salt;
use crate::state::types::state::{AuthenticationHeapState, OpenIdCachedCertificate, OpenIdState};
use crate::strategies::AuthHeapStrategy;
use std::collections::hash_map::Entry;
pub fn get_config(auth_heap: &impl AuthHeapStrategy) -> Option<AuthenticationConfig> {
auth_heap
.with_auth_state(|authentication| authentication.as_ref().map(|auth| auth.config.clone()))
}
pub fn insert_config(auth_heap: &impl AuthHeapStrategy, config: &AuthenticationConfig) {
auth_heap.with_auth_state_mut(|authentication| insert_config_impl(config, authentication))
}
fn insert_config_impl(config: &AuthenticationConfig, state: &mut Option<AuthenticationHeapState>) {
match state {
None => {
*state = Some(AuthenticationHeapState {
config: config.clone(),
automation: None,
salt: None,
openid: None,
})
}
Some(state) => state.config = config.clone(),
}
}
pub fn get_automation(auth_heap: &impl AuthHeapStrategy) -> Option<AutomationConfig> {
auth_heap.with_auth_state(|authentication| {
authentication
.as_ref()
.and_then(|auth| auth.automation.clone())
})
}
pub fn insert_automation(auth_heap: &impl AuthHeapStrategy, automation: &AutomationConfig) {
auth_heap
.with_auth_state_mut(|authentication| insert_automation_impl(automation, authentication))
}
fn insert_automation_impl(
automation: &AutomationConfig,
state: &mut Option<AuthenticationHeapState>,
) {
match state {
None => {
*state = Some(AuthenticationHeapState {
config: AuthenticationConfig::default(),
automation: Some(automation.clone()),
salt: None,
openid: None,
})
}
Some(state) => state.automation = Some(automation.clone()),
}
}
pub fn get_salt(auth_heap: &impl AuthHeapStrategy) -> Option<Salt> {
auth_heap.with_auth_state(|authentication| authentication.as_ref().and_then(|auth| auth.salt))
}
pub fn insert_salt(auth_heap: &impl AuthHeapStrategy, salt: &Salt) {
auth_heap.with_auth_state_mut(|authentication| insert_salt_impl(salt, authentication))
}
fn insert_salt_impl(salt: &Salt, state: &mut Option<AuthenticationHeapState>) {
match state {
None => {
*state = Some(AuthenticationHeapState {
config: AuthenticationConfig::default(),
automation: None,
salt: Some(*salt),
openid: None,
})
}
Some(state) => state.salt = Some(*salt),
}
}
pub fn get_openid_state(auth_heap: &impl AuthHeapStrategy) -> Option<OpenIdState> {
auth_heap.with_auth_state(|authentication| {
authentication.as_ref().and_then(|auth| auth.openid.clone())
})
}
pub fn get_cached_certificate(
provider: &OpenIdProvider,
auth_heap: &impl AuthHeapStrategy,
) -> Option<OpenIdCachedCertificate> {
auth_heap
.with_auth_state(|authentication| get_cached_certificate_impl(provider, authentication))
}
pub fn cache_certificate(
provider: &OpenIdProvider,
certificate: &OpenIdCertificate,
auth_heap: &impl AuthHeapStrategy,
) -> Result<(), String> {
auth_heap.with_auth_state_mut(|authentication| {
cache_certificate_impl(provider, certificate, authentication)
})
}
pub fn record_fetch_attempt(
provider: &OpenIdProvider,
reset_streak: bool,
auth_heap: &impl AuthHeapStrategy,
) {
auth_heap.with_auth_state_mut(|authentication| {
record_fetch_attempt_impl(provider, reset_streak, authentication)
})
}
fn get_cached_certificate_impl(
provider: &OpenIdProvider,
state: &Option<AuthenticationHeapState>,
) -> Option<OpenIdCachedCertificate> {
state
.as_ref()
.and_then(|auth| auth.openid.as_ref())
.and_then(|openid| openid.certificates.get(provider))
.cloned()
}
fn record_fetch_attempt_impl(
provider: &OpenIdProvider,
reset_streak: bool,
state: &mut Option<AuthenticationHeapState>,
) {
let authentication = state.get_or_insert_with(AuthenticationHeapState::default);
let openid_state = authentication
.openid
.get_or_insert_with(OpenIdState::default);
openid_state
.certificates
.entry(provider.clone())
.and_modify(|cached_certificate| cached_certificate.record_attempt(reset_streak))
.or_insert_with(OpenIdCachedCertificate::init);
}
fn cache_certificate_impl(
provider: &OpenIdProvider,
certificate: &OpenIdCertificate,
state: &mut Option<AuthenticationHeapState>,
) -> Result<(), String> {
let authentication = state.get_or_insert_with(AuthenticationHeapState::default);
let openid_state = authentication
.openid
.get_or_insert_with(OpenIdState::default);
match openid_state.certificates.entry(provider.clone()) {
Entry::Occupied(mut occ) => {
occ.get_mut().update_certificate(certificate);
Ok(())
}
Entry::Vacant(_) => Err("Cannot cache certificate: fetch attempt was not recorded".into()),
}
}