use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Clone)]
pub struct JQuantsAuth {
pub refresh_token: String,
id_token: Option<String>,
id_token_expiry: Option<u64>,
}
impl JQuantsAuth {
pub fn new(refresh_token: impl Into<String>) -> Self {
Self {
refresh_token: refresh_token.into(),
id_token: None,
id_token_expiry: None,
}
}
pub fn from_env() -> Self {
let refresh_token = std::env::var("JQUANTS_REFRESH_TOKEN")
.unwrap_or_default();
Self::new(refresh_token)
}
pub fn refresh_token(&self) -> &str {
&self.refresh_token
}
pub fn has_valid_id_token(&self) -> bool {
if let (Some(_token), Some(expiry)) = (&self.id_token, self.id_token_expiry) {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time is before UNIX epoch")
.as_secs();
now < expiry
} else {
false
}
}
pub fn get_cached_id_token(&self) -> Option<&str> {
if self.has_valid_id_token() {
self.id_token.as_deref()
} else {
None
}
}
pub fn cache_id_token(&mut self, id_token: String) {
let expiry = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time is before UNIX epoch")
.as_secs() + (23 * 3600);
self.id_token = Some(id_token);
self.id_token_expiry = Some(expiry);
}
pub fn clear_id_token(&mut self) {
self.id_token = None;
self.id_token_expiry = None;
}
pub fn sign_headers(&self, headers: &mut HashMap<String, String>, id_token: &str) {
headers.insert("Authorization".to_string(), format!("Bearer {}", id_token));
headers.insert("Content-Type".to_string(), "application/json".to_string());
}
pub fn get_auth_headers(&self) -> Option<HashMap<String, String>> {
if let Some(id_token) = self.get_cached_id_token() {
let mut headers = HashMap::new();
self.sign_headers(&mut headers, id_token);
Some(headers)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_auth() {
let auth = JQuantsAuth::new("test_refresh_token");
assert_eq!(auth.refresh_token(), "test_refresh_token");
assert!(!auth.has_valid_id_token());
}
#[test]
fn test_cache_id_token() {
let mut auth = JQuantsAuth::new("refresh");
auth.cache_id_token("id_token_123".to_string());
assert!(auth.has_valid_id_token());
assert_eq!(auth.get_cached_id_token(), Some("id_token_123"));
}
#[test]
fn test_clear_id_token() {
let mut auth = JQuantsAuth::new("refresh");
auth.cache_id_token("id_token_123".to_string());
auth.clear_id_token();
assert!(!auth.has_valid_id_token());
assert_eq!(auth.get_cached_id_token(), None);
}
#[test]
fn test_sign_headers() {
let auth = JQuantsAuth::new("refresh");
let mut headers = HashMap::new();
auth.sign_headers(&mut headers, "test_id_token");
assert_eq!(headers.get("Authorization"), Some(&"Bearer test_id_token".to_string()));
assert_eq!(headers.get("Content-Type"), Some(&"application/json".to_string()));
}
}