Skip to content
This repository has been archived by the owner on Feb 14, 2020. It is now read-only.

Commit

Permalink
Implement TokenCache
Browse files Browse the repository at this point in the history
  • Loading branch information
causal-agent committed Feb 5, 2016
1 parent d372518 commit 016acc8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ extern crate yup_oauth2;
pub mod account;
pub mod authenticator;
pub mod generator;
pub mod token_cache;
67 changes: 67 additions & 0 deletions src/token_cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Token caching.
use std::error::Error;
use std::marker::PhantomData;

use hyper::Client as HttpClient;
use inth_oauth2::{Client as OAuth2Client, ClientError, Token};
use inth_oauth2::provider::{Provider, Google};
use yup_oauth2::{GetToken, Token as YupToken};

use authenticator::Authenticator;

/// Token cache for use with Google APIs.
#[allow(missing_debug_implementations)]
pub struct TokenCache<A: Authenticator<Google>> {
oauth2: OAuth2Client<Google>,
http: HttpClient,
scope: String,
token: Option<<Google as Provider>::Token>,
authenticator: PhantomData<A>,
}

impl<A: Authenticator<Google>> TokenCache<A> {
/// Creates a token cache.
pub fn new(
oauth2: OAuth2Client<Google>,
http: HttpClient,
scope: String,
token: Option<<Google as Provider>::Token>
) -> Self {
TokenCache {
oauth2: oauth2,
http: http,
scope: scope,
token: token,
authenticator: PhantomData,
}
}

/// Returns a valid token either from cache, by refreshing, or through the `Authenticator`.
pub fn token(&mut self) -> Result<&<Google as Provider>::Token, ClientError> {
let token = match self.token.take() {
Some(token) => try!(self.oauth2.ensure_token(&self.http, token)),
None => try!(A::authenticate(&self.oauth2, &self.http, &self.scope)),
};
self.token = Some(token);
Ok(self.token.as_ref().unwrap())
}
}

impl<A: Authenticator<Google>> GetToken for TokenCache<A> {
fn token<'b, I, T>(&mut self, _scopes: I) -> Result<YupToken, Box<Error>>
where T: AsRef<str> + Ord + 'b, I: IntoIterator<Item=&'b T>
{
// TODO: Handle scopes in a reasonable way.
let token = try!(self.token());
Ok(YupToken {
access_token: token.access_token().to_owned(),
refresh_token: token.lifetime().refresh_token().to_owned(),
token_type: String::from("Bearer"),
expires_in: Some(3600), // This is probably okay, right?
expires_in_timestamp: Some(token.lifetime().expires().timestamp()),
})
}

fn api_key(&mut self) -> Option<String> { None }
}

0 comments on commit 016acc8

Please sign in to comment.