Mirror of https://github.com/roostorg/osprey github.com/roostorg/osprey
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 107 lines 3.1 kB view raw
1use std::time::Instant; 2 3use serde::{self, Deserialize}; 4 5/// Represents an auth token for oauth 6#[derive(Eq, PartialEq, Deserialize, Debug, Clone)] 7pub struct Token { 8 access_token: String, 9 /// How long (in seconds) this token is valid. 10 #[serde(rename = "expires_in")] 11 pub expires_in_secs: u64, 12 pub token_type: String, 13 14 /// Timestamp of when we created this instance, and when `expires_in` takes effect. 15 #[serde(skip, default = "Instant::now")] 16 pub created_at: Instant, 17} 18 19/// Manually implement this so we don't print the `access_token` 20impl std::fmt::Display for Token { 21 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 22 write!( 23 f, 24 "Token: (type: {}, expires_in: {}s, alive_for: {}s)", 25 self.token_type, 26 self.expires_in_secs, 27 self.created_at.elapsed().as_secs(), 28 ) 29 } 30} 31 32impl Token { 33 pub fn new( 34 access_token: String, 35 expires_in_secs: u64, 36 token_type: String, 37 created_at: Instant, 38 ) -> Self { 39 Self { 40 access_token, 41 expires_in_secs, 42 token_type, 43 created_at, 44 } 45 } 46 47 pub fn from_goauth(token: goauth::auth::Token, created_at: Instant) -> Self { 48 Self { 49 access_token: token.access_token().to_string(), 50 expires_in_secs: token.expires_in() as u64, 51 token_type: token.token_type().to_string(), 52 created_at, 53 } 54 } 55 56 pub fn is_expired(&self) -> bool { 57 let secs_since_created = self.created_at.elapsed().as_secs(); 58 secs_since_created > self.expires_in_secs 59 } 60 61 /// Returns an active duration of how much time is left before the token expires. 62 /// `0` is returned if expired. 63 pub fn ttl_secs(&self) -> u64 { 64 let secs_since_created = self.created_at.elapsed().as_secs(); 65 66 self.expires_in_secs.saturating_sub(secs_since_created) 67 } 68 69 /// Returns a header value representation of the token 70 pub fn to_header_rep(&self) -> String { 71 format!("{} {}", self.token_type, self.access_token) 72 } 73} 74 75#[cfg(test)] 76mod tests { 77 use std::time::Duration; 78 79 use super::*; 80 81 #[test] 82 fn test_token_expired() { 83 let token = Token { 84 access_token: "test.Sample".to_string(), 85 expires_in_secs: 3, 86 token_type: "Bearer".to_string(), 87 created_at: Instant::now() - Duration::from_secs(4), 88 }; 89 90 assert!(token.is_expired()); 91 assert_eq!(token.ttl_secs(), 0, "time remaining should be 0"); 92 } 93 94 #[test] 95 fn test_token_not_expired() { 96 let token = Token { 97 access_token: "test.Sample".to_string(), 98 expires_in_secs: 30, 99 token_type: "Bearer".to_string(), 100 created_at: Instant::now() - Duration::from_secs(1), 101 }; 102 103 assert!(!token.is_expired()); 104 let ttl = token.ttl_secs(); 105 assert!(ttl >= 20 && ttl <= 29, "time remaining should be < expires"); 106 } 107}