inth_oauth2/token/
expiring.rs

1use chrono::{DateTime, Utc, Duration};
2use serde_json::Value;
3
4use client::response::{FromResponse, ParseError};
5use token::Lifetime;
6
7/// An expiring token.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Expiring {
10    expires: DateTime<Utc>,
11}
12
13impl Expiring {
14    /// Returns the expiry time of the access token.
15    pub fn expires(&self) -> &DateTime<Utc> { &self.expires }
16}
17
18impl Lifetime for Expiring {
19    fn expired(&self) -> bool { self.expires < Utc::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: Utc::now() + Duration::seconds(expires_in),
36        })
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use chrono::{Utc, Duration};
43
44    use client::response::FromResponse;
45    use super::Expiring;
46
47    #[test]
48    fn from_response() {
49        let json = r#"{"expires_in":3600}"#.parse().unwrap();
50        let expiring = Expiring::from_response(&json).unwrap();
51        assert!(expiring.expires > Utc::now());
52        assert!(expiring.expires <= Utc::now() + Duration::seconds(3600));
53    }
54}