use super::identifiers::{SamlInstant, SessionIndex};
use crate::error::{SamlError, TimeWindowField};
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuthnSession {
session_index: Option<SessionIndex>,
authn_instant: Option<SamlInstant>,
not_on_or_after: Option<SamlInstant>,
}
pub(super) static EMPTY_AUTHN_SESSION: AuthnSession = AuthnSession {
session_index: None,
authn_instant: None,
not_on_or_after: None,
};
pub(crate) fn earliest_authn_session_expiration<'a>(
values: impl IntoIterator<Item = &'a str>,
error_field: TimeWindowField,
) -> Result<Option<OffsetDateTime>, SamlError> {
let mut earliest = None;
for value in values {
let candidate = OffsetDateTime::parse(value, &Rfc3339)
.map_err(|_| SamlError::TimeWindowInvalid { field: error_field })?;
if earliest.is_none_or(|current| candidate < current) {
earliest = Some(candidate);
}
}
Ok(earliest)
}
impl AuthnSession {
pub fn new(
session_index: Option<SessionIndex>,
authn_instant: Option<SamlInstant>,
not_on_or_after: Option<SamlInstant>,
) -> Self {
Self {
session_index,
authn_instant,
not_on_or_after,
}
}
pub fn session_index(&self) -> Option<&SessionIndex> {
self.session_index.as_ref()
}
pub fn authn_instant(&self) -> Option<&SamlInstant> {
self.authn_instant.as_ref()
}
pub fn not_on_or_after(&self) -> Option<&SamlInstant> {
self.not_on_or_after.as_ref()
}
}