Rename PollInformation DeviceAuthResponse.

Have it correctly handle either verification_uri or verification_url and
deserialize into a struct that has the data types desired.
This commit is contained in:
Glenn Griffin
2019-11-22 10:29:55 -08:00
parent 0525926bb2
commit 4521e2f246
2 changed files with 78 additions and 49 deletions

View File

@@ -1,4 +1,5 @@
//! Module containing types related to delegates.
use crate::error::{AuthErrorOr, Error};
use std::pin::Pin;
use std::time::Duration;
@@ -8,12 +9,13 @@ use futures::prelude::*;
/// Contains state of pending authentication requests
#[derive(Clone, Debug, PartialEq)]
pub struct PollInformation {
pub struct DeviceAuthResponse {
/// The device verification code.
pub device_code: String,
/// Code the user must enter ...
pub user_code: String,
/// ... at the verification URL
pub verification_url: String,
/// ... at the verification URI
pub verification_uri: String,
/// The `user_code` expires at the given time
/// It's the time the user has left to authenticate your application
pub expires_at: DateTime<Utc>,
@@ -22,17 +24,66 @@ pub struct PollInformation {
pub interval: Duration,
}
impl DeviceAuthResponse {
pub(crate) fn from_json(json_data: &[u8]) -> Result<Self, Error> {
Ok(serde_json::from_slice::<AuthErrorOr<_>>(json_data)?.into_result()?)
}
}
impl<'de> serde::Deserialize<'de> for DeviceAuthResponse {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(serde::Deserialize)]
struct RawDeviceAuthResponse {
device_code: String,
user_code: String,
// The standard dictates that verification_uri is required, but
// sadly google uses verification_url currently. One of these two
// fields need to be set and verification_uri takes precedence if
// they both are set.
verification_uri: Option<String>,
verification_url: Option<String>,
expires_in: i64,
interval: Option<u64>,
}
let RawDeviceAuthResponse {
device_code,
user_code,
verification_uri,
verification_url,
expires_in,
interval,
} = RawDeviceAuthResponse::deserialize(deserializer)?;
let verification_uri = verification_uri.or(verification_url).ok_or_else(|| {
serde::de::Error::custom("neither verification_uri nor verification_url specified")
})?;
let expires_at = Utc::now() + chrono::Duration::seconds(expires_in);
let interval = Duration::from_secs(interval.unwrap_or(5));
Ok(DeviceAuthResponse {
device_code,
user_code,
verification_uri,
expires_at,
interval,
})
}
}
/// DeviceFlowDelegate methods are called when a device flow needs to ask the
/// application what to do in certain cases.
pub trait DeviceFlowDelegate: Send + Sync {
/// The server has returned a `user_code` which must be shown to the user,
/// along with the `verification_url`.
/// along with the `verification_uri`.
/// # Notes
/// * Will be called exactly once, provided we didn't abort during `request_code` phase.
fn present_user_code(&self, pi: &PollInformation) {
fn present_user_code(&self, pi: &DeviceAuthResponse) {
println!(
"Please enter {} at {} and grant access to this application",
pi.user_code, pi.verification_url
pi.user_code, pi.verification_uri
);
println!("Do not close this application until you either denied or granted access.");
println!(