oauth_device_flows/
error.rs

1//! Error types for OAuth device flows
2
3use thiserror::Error;
4
5/// Result type alias for OAuth device flow operations
6pub type Result<T> = std::result::Result<T, DeviceFlowError>;
7
8/// Comprehensive error type for OAuth device flow operations
9#[derive(Error, Debug)]
10pub enum DeviceFlowError {
11    /// Network-related errors during HTTP requests
12    #[error("Network error: {0}")]
13    Network(#[from] reqwest::Error),
14
15    /// JSON parsing errors
16    #[error("JSON parsing error: {0}")]
17    Json(#[from] serde_json::Error),
18
19    /// URL parsing errors
20    #[error("URL parsing error: {0}")]
21    Url(#[from] url::ParseError),
22
23    /// OAuth server returned an error
24    #[error("OAuth error: {error} - {error_description}")]
25    OAuth {
26        error: String,
27        error_description: String,
28    },
29
30    /// Device authorization request was denied
31    #[error("Authorization denied")]
32    AuthorizationDenied,
33
34    /// Device code has expired
35    #[error("Device code expired")]
36    ExpiredToken,
37
38    /// Polling too frequently (slow down)
39    #[error("Polling too frequently, slow down")]
40    SlowDown,
41
42    /// Authorization is still pending
43    #[error("Authorization pending")]
44    AuthorizationPending,
45
46    /// Invalid device code
47    #[error("Invalid device code")]
48    InvalidCode,
49
50    /// Invalid client configuration
51    #[error("Invalid client configuration: {0}")]
52    InvalidClient(String),
53
54    /// Token has expired and refresh failed
55    #[error("Token expired and refresh failed")]
56    TokenExpired,
57
58    /// Unsupported OAuth provider
59    #[error("Unsupported provider: {0}")]
60    UnsupportedProvider(String),
61
62    /// Maximum polling attempts exceeded
63    #[error("Maximum polling attempts ({0}) exceeded")]
64    MaxAttemptsExceeded(u32),
65
66    /// Invalid scope requested
67    #[error("Invalid scope: {0}")]
68    InvalidScope(String),
69
70    /// QR code generation error (when feature is enabled)
71    #[cfg(feature = "qr-codes")]
72    #[error("QR code generation error: {0}")]
73    QrCode(#[from] qrcode::types::QrError),
74
75    /// Generic error for unexpected situations
76    #[error("Unexpected error: {0}")]
77    Other(String),
78}
79
80impl DeviceFlowError {
81    /// Create a new OAuth error
82    pub fn oauth_error(error: impl Into<String>, description: impl Into<String>) -> Self {
83        Self::OAuth {
84            error: error.into(),
85            error_description: description.into(),
86        }
87    }
88
89    /// Create a new invalid client error
90    pub fn invalid_client(message: impl Into<String>) -> Self {
91        Self::InvalidClient(message.into())
92    }
93
94    /// Create a new other error
95    pub fn other(message: impl Into<String>) -> Self {
96        Self::Other(message.into())
97    }
98
99    /// Check if this error is retryable
100    pub fn is_retryable(&self) -> bool {
101        matches!(
102            self,
103            Self::Network(_) | Self::AuthorizationPending | Self::SlowDown
104        )
105    }
106
107    /// Check if this error indicates we should slow down polling
108    pub fn is_slow_down(&self) -> bool {
109        matches!(self, Self::SlowDown)
110    }
111
112    /// Check if this error indicates authorization is still pending
113    pub fn is_pending(&self) -> bool {
114        matches!(self, Self::AuthorizationPending)
115    }
116}