Refactor error handling and as a consequence delegates.

This Removes RefreshError and PollError. Both those types can be fully
represented within Error and there seems little value in distinguishing
that they were resulting from device polling or refreshes. In either
case the user will need to handle the response from token() calls
similarly. This also removes the AuthenticatorDelegate since it only
served to notify users when refreshes failed, which can already be done
by looking at the return code from token. DeviceFlow no longer has the
ability to set a wait_timeout. This is trivial to do by wrapping the
token() call in a tokio::Timeout future so there's little benefit for
users specifying this value. The DeviceFlowDelegate also no longer has
the ability to specify when to abort, or alter the interval polling
happens on, but it does gain understanding of the 'slow_down' response
as documented in the oauth rfc. It seemed very unlikely the delegate was
going to do anything other that timeout after a given time and that's
already possible using tokio::Timeout so it needlessly complicated the
implementation.
This commit is contained in:
Glenn Griffin
2019-11-21 16:49:10 -08:00
parent fe5ea9bdb2
commit d0880d07db
7 changed files with 214 additions and 305 deletions

View File

@@ -1,25 +1,11 @@
//! Module containing types related to delegates.
use crate::error::RefreshError;
use std::fmt;
use std::pin::Pin;
use std::time::Duration;
use chrono::{DateTime, Local, Utc};
use futures::prelude::*;
/// A utility type to indicate how operations DeviceFlowHelper operations should be retried
pub enum Retry {
/// Signal you don't want to retry
Abort,
/// Signals you want to retry after the given duration
After(Duration),
/// Instruct the caller to attempt to keep going, or choose an alternate path.
/// If this is not supported, it will have the same effect as `Abort`
Skip,
}
/// Contains state of pending authentication requests
#[derive(Clone, Debug, PartialEq)]
pub struct PollInformation {
@@ -36,43 +22,9 @@ pub struct PollInformation {
pub interval: Duration,
}
impl fmt::Display for PollInformation {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
writeln!(f, "Proceed with polling until {}", self.expires_at)
}
}
/// A partially implemented trait to interact with the `Authenticator`
///
/// The only method that needs to be implemented manually is `present_user_code(...)`,
/// as no assumptions are made on how this presentation should happen.
pub trait AuthenticatorDelegate: Send + Sync {
/// Called if we could not acquire a refresh token for a reason possibly specified
/// by the server.
/// This call is made for the delegate's information only.
fn token_refresh_failed(&self, _: &RefreshError) {}
}
/// DeviceFlowDelegate methods are called when a device flow needs to ask the
/// application what to do in certain cases.
pub trait DeviceFlowDelegate: Send + Sync {
/// Called if the request code is expired. You will have to start over in this case.
/// This will be the last call the delegate receives.
/// Given `DateTime` is the expiration date
fn expired(&self, _: DateTime<Utc>) {}
/// Called if the user denied access. You would have to start over.
/// This will be the last call the delegate receives.
fn denied(&self) {}
/// Called as long as we are waiting for the user to authorize us.
/// Can be used to print progress information, or decide to time-out.
///
/// If the returned `Retry` variant is a duration.
fn pending(&self, _: &PollInformation) -> Retry {
Retry::After(Duration::from_secs(5))
}
/// The server has returned a `user_code` which must be shown to the user,
/// along with the `verification_url`.
/// # Notes
@@ -136,12 +88,6 @@ async fn present_user_url(url: &str, need_code: bool) -> Result<String, String>
}
}
/// Uses all default implementations by AuthenticatorDelegate, and makes the trait's
/// implementation usable in the first place.
#[derive(Copy, Clone)]
pub struct DefaultAuthenticatorDelegate;
impl AuthenticatorDelegate for DefaultAuthenticatorDelegate {}
/// Uses all default implementations in the DeviceFlowDelegate trait.
#[derive(Copy, Clone)]
pub struct DefaultDeviceFlowDelegate;