1use std::error::Error;
2use std::fmt::Error as FormatterError;
3use std::fmt::{Debug, Display, Formatter};
4use std::marker::PhantomData;
5use std::time::Duration;
6
7use serde::de::DeserializeOwned;
8use serde::{Deserialize, Serialize};
9
10use super::{
11 DeviceCode, EndUserVerificationUrl, ErrorResponse, ErrorResponseType, RequestTokenError,
12 StandardErrorResponse, TokenResponse, TokenType, UserCode,
13};
14use crate::basic::BasicErrorResponseType;
15use crate::types::VerificationUriComplete;
16
17fn default_devicecode_interval() -> u64 {
21 5
22}
23
24pub trait ExtraDeviceAuthorizationFields: DeserializeOwned + Debug + Serialize {}
28
29#[derive(Clone, Debug, Deserialize, Serialize)]
30pub struct EmptyExtraDeviceAuthorizationFields {}
34impl ExtraDeviceAuthorizationFields for EmptyExtraDeviceAuthorizationFields {}
35
36#[derive(Clone, Debug, Deserialize, Serialize)]
40pub struct DeviceAuthorizationResponse<EF>
41where
42 EF: ExtraDeviceAuthorizationFields,
43{
44 device_code: DeviceCode,
46
47 user_code: UserCode,
49
50 #[serde(alias = "verification_url")]
57 verification_uri: EndUserVerificationUrl,
58
59 #[serde(skip_serializing_if = "Option::is_none")]
63 verification_uri_complete: Option<VerificationUriComplete>,
64
65 expires_in: u64,
67
68 #[serde(default = "default_devicecode_interval")]
72 interval: u64,
73
74 #[serde(bound = "EF: ExtraDeviceAuthorizationFields", flatten)]
75 extra_fields: EF,
76}
77
78impl<EF> DeviceAuthorizationResponse<EF>
79where
80 EF: ExtraDeviceAuthorizationFields,
81{
82 pub fn device_code(&self) -> &DeviceCode {
84 &self.device_code
85 }
86
87 pub fn user_code(&self) -> &UserCode {
89 &self.user_code
90 }
91
92 pub fn verification_uri(&self) -> &EndUserVerificationUrl {
96 &self.verification_uri
97 }
98
99 pub fn verification_uri_complete(&self) -> Option<&VerificationUriComplete> {
103 self.verification_uri_complete.as_ref()
104 }
105
106 pub fn expires_in(&self) -> Duration {
108 Duration::from_secs(self.expires_in)
109 }
110
111 pub fn interval(&self) -> Duration {
115 Duration::from_secs(self.interval)
116 }
117
118 pub fn extra_fields(&self) -> &EF {
120 &self.extra_fields
121 }
122}
123
124pub type StandardDeviceAuthorizationResponse =
129 DeviceAuthorizationResponse<EmptyExtraDeviceAuthorizationFields>;
130
131#[derive(Clone, PartialEq)]
139pub enum DeviceCodeErrorResponseType {
140 AuthorizationPending,
150 SlowDown,
155 AccessDenied,
159 ExpiredToken,
165 Basic(BasicErrorResponseType),
169}
170impl DeviceCodeErrorResponseType {
171 fn from_str(s: &str) -> Self {
172 match BasicErrorResponseType::from_str(s) {
173 BasicErrorResponseType::Extension(ext) => match ext.as_str() {
174 "authorization_pending" => DeviceCodeErrorResponseType::AuthorizationPending,
175 "slow_down" => DeviceCodeErrorResponseType::SlowDown,
176 "access_denied" => DeviceCodeErrorResponseType::AccessDenied,
177 "expired_token" => DeviceCodeErrorResponseType::ExpiredToken,
178 _ => DeviceCodeErrorResponseType::Basic(BasicErrorResponseType::Extension(ext)),
179 },
180 basic => DeviceCodeErrorResponseType::Basic(basic),
181 }
182 }
183}
184impl AsRef<str> for DeviceCodeErrorResponseType {
185 fn as_ref(&self) -> &str {
186 match self {
187 DeviceCodeErrorResponseType::AuthorizationPending => "authorization_pending",
188 DeviceCodeErrorResponseType::SlowDown => "slow_down",
189 DeviceCodeErrorResponseType::AccessDenied => "access_denied",
190 DeviceCodeErrorResponseType::ExpiredToken => "expired_token",
191 DeviceCodeErrorResponseType::Basic(basic) => basic.as_ref(),
192 }
193 }
194}
195impl<'de> serde::Deserialize<'de> for DeviceCodeErrorResponseType {
196 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
197 where
198 D: serde::de::Deserializer<'de>,
199 {
200 let variant_str = String::deserialize(deserializer)?;
201 Ok(Self::from_str(&variant_str))
202 }
203}
204impl serde::ser::Serialize for DeviceCodeErrorResponseType {
205 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
206 where
207 S: serde::ser::Serializer,
208 {
209 serializer.serialize_str(self.as_ref())
210 }
211}
212impl ErrorResponseType for DeviceCodeErrorResponseType {}
213impl Debug for DeviceCodeErrorResponseType {
214 fn fmt(&self, f: &mut Formatter) -> Result<(), FormatterError> {
215 Display::fmt(self, f)
216 }
217}
218
219impl Display for DeviceCodeErrorResponseType {
220 fn fmt(&self, f: &mut Formatter) -> Result<(), FormatterError> {
221 write!(f, "{}", self.as_ref())
222 }
223}
224
225pub type DeviceCodeErrorResponse = StandardErrorResponse<DeviceCodeErrorResponseType>;
229
230pub(crate) enum DeviceAccessTokenPollResult<TR, RE, TE, TT>
231where
232 TE: ErrorResponse + 'static,
233 TR: TokenResponse<TT>,
234 TT: TokenType,
235 RE: Error + 'static,
236{
237 ContinueWithNewPollInterval(Duration),
238 Done(Result<TR, RequestTokenError<RE, TE>>, PhantomData<TT>),
239}