use crate::{error::Error, token_cache::CacheableToken};
use std::time::SystemTime;
#[derive(Clone, PartialEq, Eq, Debug, serde::Deserialize)]
pub struct Token {
pub access_token: String,
pub refresh_token: String,
pub token_type: String,
pub expires_in: Option<i64>,
pub expires_in_timestamp: Option<SystemTime>,
}
impl CacheableToken for Token {
#[inline]
fn has_expired(&self) -> bool {
if self.access_token.is_empty() {
return true;
}
let expiry = self.expires_in_timestamp.unwrap_or_else(SystemTime::now);
expiry <= SystemTime::now()
}
}
#[derive(Debug)]
pub enum RequestReason {
Expired,
ParametersChanged,
}
#[derive(Debug)]
pub enum TokenOrRequest {
Token(Token),
Request {
request: http::Request<Vec<u8>>,
reason: RequestReason,
scope_hash: u64,
},
}
pub trait TokenProvider {
#[inline]
fn get_token<'a, S, I>(&self, scopes: I) -> Result<TokenOrRequest, Error>
where
S: AsRef<str> + 'a,
I: IntoIterator<Item = &'a S> + Clone,
{
self.get_token_with_subject::<S, I, String>(None, scopes)
}
fn get_token_with_subject<'a, S, I, T>(
&self,
subject: Option<T>,
scopes: I,
) -> Result<TokenOrRequest, Error>
where
S: AsRef<str> + 'a,
I: IntoIterator<Item = &'a S> + Clone,
T: Into<String>;
fn parse_token_response<S>(
&self,
hash: u64,
response: http::Response<S>,
) -> Result<Token, Error>
where
S: AsRef<[u8]>;
}
impl std::convert::TryInto<http::header::HeaderValue> for Token {
type Error = crate::Error;
fn try_into(self) -> Result<http::header::HeaderValue, crate::Error> {
let auth_header_val = format!("{} {}", self.token_type, self.access_token);
http::header::HeaderValue::from_str(&auth_header_val)
.map_err(|e| crate::Error::from(http::Error::from(e)))
}
}