inth_oauth2_async/token/
expiring.rs

1use serde_json::Value;
2use std::time::{Duration, SystemTime};
3
4use crate::client::response::{FromResponse, ParseError};
5use crate::token::Lifetime;
6
7/// An expiring token.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Expiring {
10    expires: SystemTime,
11}
12
13impl Expiring {
14    /// Returns the expiry time of the access token.
15    pub fn expires(&self) -> SystemTime { self.expires }
16}
17
18impl Lifetime for Expiring {
19    fn expired(&self) -> bool { self.expires < SystemTime::now() }
20}
21
22impl FromResponse for Expiring {
23    fn from_response(json: &Value) -> Result<Self, ParseError> {
24        let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
25
26        if obj.contains_key("refresh_token") {
27            return Err(ParseError::UnexpectedField("refresh_token"));
28        }
29
30        let expires_in = obj.get("expires_in")
31            .and_then(Value::as_i64)
32            .ok_or(ParseError::ExpectedFieldType("expires_in", "i64"))?;
33
34        Ok(Expiring {
35            expires: SystemTime::now() + Duration::from_secs(expires_in.try_into().unwrap_or(0)),
36        })
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn from_response() {
46        let json = r#"{"expires_in":3600}"#.parse().unwrap();
47        let expiring = Expiring::from_response(&json).unwrap();
48        assert!(expiring.expires > SystemTime::now());
49        assert!(expiring.expires <= SystemTime::now() + Duration::from_secs(3600));
50    }
51}