inth_oauth2/token/
expiring.rs1use chrono::{DateTime, Utc, Duration};
2use serde_json::Value;
3
4use client::response::{FromResponse, ParseError};
5use token::Lifetime;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Expiring {
10 expires: DateTime<Utc>,
11}
12
13impl Expiring {
14 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}