oauth-device-flows 0.1.0

A specialized Rust library implementing OAuth 2.0 Device Authorization Grant (RFC 8628)
Documentation
//! Error types for OAuth device flows

use thiserror::Error;

/// Result type alias for OAuth device flow operations
pub type Result<T> = std::result::Result<T, DeviceFlowError>;

/// Comprehensive error type for OAuth device flow operations
#[derive(Error, Debug)]
pub enum DeviceFlowError {
    /// Network-related errors during HTTP requests
    #[error("Network error: {0}")]
    Network(#[from] reqwest::Error),

    /// JSON parsing errors
    #[error("JSON parsing error: {0}")]
    Json(#[from] serde_json::Error),

    /// URL parsing errors
    #[error("URL parsing error: {0}")]
    Url(#[from] url::ParseError),

    /// OAuth server returned an error
    #[error("OAuth error: {error} - {error_description}")]
    OAuth {
        error: String,
        error_description: String,
    },

    /// Device authorization request was denied
    #[error("Authorization denied")]
    AuthorizationDenied,

    /// Device code has expired
    #[error("Device code expired")]
    ExpiredToken,

    /// Polling too frequently (slow down)
    #[error("Polling too frequently, slow down")]
    SlowDown,

    /// Authorization is still pending
    #[error("Authorization pending")]
    AuthorizationPending,

    /// Invalid device code
    #[error("Invalid device code")]
    InvalidCode,

    /// Invalid client configuration
    #[error("Invalid client configuration: {0}")]
    InvalidClient(String),

    /// Token has expired and refresh failed
    #[error("Token expired and refresh failed")]
    TokenExpired,

    /// Unsupported OAuth provider
    #[error("Unsupported provider: {0}")]
    UnsupportedProvider(String),

    /// Maximum polling attempts exceeded
    #[error("Maximum polling attempts ({0}) exceeded")]
    MaxAttemptsExceeded(u32),

    /// Invalid scope requested
    #[error("Invalid scope: {0}")]
    InvalidScope(String),

    /// QR code generation error (when feature is enabled)
    #[cfg(feature = "qr-codes")]
    #[error("QR code generation error: {0}")]
    QrCode(#[from] qrcode::types::QrError),

    /// Generic error for unexpected situations
    #[error("Unexpected error: {0}")]
    Other(String),
}

impl DeviceFlowError {
    /// Create a new OAuth error
    pub fn oauth_error(error: impl Into<String>, description: impl Into<String>) -> Self {
        Self::OAuth {
            error: error.into(),
            error_description: description.into(),
        }
    }

    /// Create a new invalid client error
    pub fn invalid_client(message: impl Into<String>) -> Self {
        Self::InvalidClient(message.into())
    }

    /// Create a new other error
    pub fn other(message: impl Into<String>) -> Self {
        Self::Other(message.into())
    }

    /// Check if this error is retryable
    pub fn is_retryable(&self) -> bool {
        matches!(
            self,
            Self::Network(_) | Self::AuthorizationPending | Self::SlowDown
        )
    }

    /// Check if this error indicates we should slow down polling
    pub fn is_slow_down(&self) -> bool {
        matches!(self, Self::SlowDown)
    }

    /// Check if this error indicates authorization is still pending
    pub fn is_pending(&self) -> bool {
        matches!(self, Self::AuthorizationPending)
    }
}