use std::collections::HashMap;
use bon::Builder;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::core::token::{AccessToken, IdToken, RefreshToken};
#[derive(Debug, Clone, Builder, Serialize, Deserialize)]
pub struct TokenResponse {
#[builder(into)]
pub access_token: AccessToken,
#[builder(into)]
pub token_type: String,
#[serde(
default,
deserialize_with = "crate::serde_utils::deserialize_u64_or_string"
)]
pub expires_in: Option<u64>,
#[builder(into)]
#[serde(skip_serializing_if = "Option::is_none")]
pub refresh_token: Option<RefreshToken>,
#[builder(into)]
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<String>,
#[builder(into)]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) id_token: Option<IdToken>,
#[builder(into)]
#[serde(skip_serializing_if = "Option::is_none")]
pub issued_token_type: Option<String>,
#[builder(skip = crate::core::platform::SystemTime::now())]
#[serde(skip, default = "crate::core::platform::SystemTime::now")]
pub received_at: crate::core::platform::SystemTime,
#[serde(flatten)]
extra: Option<HashMap<String, Value>>,
}
impl TokenResponse {
#[must_use]
pub fn get_extra(&self, key: &str) -> Option<&Value> {
self.extra.as_ref().and_then(|extra| extra.get(key))
}
pub fn effective_expiry(
&self,
default_expires_in: crate::core::platform::Duration,
expires_margin: crate::core::platform::Duration,
) -> crate::core::platform::SystemTime {
let expires_in = self.expires_in.map_or(
default_expires_in,
crate::core::platform::Duration::from_secs,
);
self.received_at + expires_in - expires_margin
}
#[must_use]
pub fn is_expired(
&self,
default_expires_in: crate::core::platform::Duration,
expires_margin: crate::core::platform::Duration,
) -> bool {
crate::core::platform::SystemTime::now()
>= self.effective_expiry(default_expires_in, expires_margin)
}
}