Make Authenticator Clone

This commit is contained in:
Lewin Bormann
2021-03-04 19:32:04 +01:00
parent eafdaaa4be
commit 010668cc62
2 changed files with 18 additions and 11 deletions

View File

@@ -14,15 +14,21 @@ use std::borrow::Cow;
use std::fmt;
use std::io;
use std::path::PathBuf;
use std::sync::Arc;
/// Authenticator is responsible for fetching tokens, handling refreshing tokens,
/// and optionally persisting tokens to disk.
pub struct Authenticator<C> {
struct InnerAuthenticator<C> {
hyper_client: hyper::Client<C>,
storage: Storage,
auth_flow: AuthFlow,
}
/// Authenticator is responsible for fetching tokens, handling refreshing tokens,
/// and optionally persisting tokens to disk.
#[derive(Clone)]
pub struct Authenticator<C> {
inner: Arc<InnerAuthenticator<C>>
}
struct DisplayScopes<'a, T>(&'a [T]);
impl<'a, T> fmt::Display for DisplayScopes<'a, T>
where
@@ -81,8 +87,8 @@ where
);
let hashed_scopes = storage::ScopeSet::from(scopes);
match (
self.storage.get(hashed_scopes).await,
self.auth_flow.app_secret(),
self.inner.storage.get(hashed_scopes).await,
self.inner.auth_flow.app_secret(),
) {
(Some(t), _) if !t.is_expired() && !force_refresh => {
// unexpired token found
@@ -98,15 +104,15 @@ where
) => {
// token is expired but has a refresh token.
let token_info =
RefreshFlow::refresh_token(&self.hyper_client, app_secret, &refresh_token)
RefreshFlow::refresh_token(&self.inner.hyper_client, app_secret, &refresh_token)
.await?;
self.storage.set(hashed_scopes, token_info.clone()).await?;
self.inner.storage.set(hashed_scopes, token_info.clone()).await?;
Ok(token_info.into())
}
_ => {
// no token in the cache or the token returned can't be refreshed.
let token_info = self.auth_flow.token(&self.hyper_client, scopes).await?;
self.storage.set(hashed_scopes, token_info.clone()).await?;
let token_info = self.inner.auth_flow.token(&self.inner.hyper_client, scopes).await?;
self.inner.storage.set(hashed_scopes, token_info.clone()).await?;
Ok(token_info.into())
}
}
@@ -221,11 +227,11 @@ impl<C, F> AuthenticatorBuilder<C, F> {
StorageType::Disk(path) => Storage::Disk(storage::DiskStorage::new(path).await?),
};
Ok(Authenticator {
Ok(Authenticator{ inner: Arc::new(InnerAuthenticator {
hyper_client,
storage,
auth_flow,
})
})})
}
fn with_auth_flow(auth_flow: F) -> AuthenticatorBuilder<DefaultHyperClient, F> {

View File

@@ -118,6 +118,7 @@ async fn test_device_no_code() {
}))),
);
let auth = create_device_flow_auth(&server).await;
let auth = auth.clone();
let res = auth.token(&["https://www.googleapis.com/scope/1"]).await;
assert!(res.is_err());
assert!(format!("{}", res.unwrap_err()).contains("invalid_client_id"));