twitch_oauth2/tokens/
errors.rs

1//! Errors
2
3/// General errors for talking with twitch, used in [`AppAccessToken::get_app_access_token`](crate::tokens::AppAccessToken::get_app_access_token)
4#[allow(missing_docs)]
5#[derive(thiserror::Error, Debug, displaydoc::Display)]
6#[cfg(feature = "client")]
7#[non_exhaustive]
8pub enum AppAccessTokenError<RE: std::error::Error + Send + Sync + 'static> {
9    /// request for token failed
10    Request(#[source] RE),
11    /// could not parse response when getting app access token
12    RequestParseError(#[from] crate::RequestParseError),
13}
14
15/// Errors for [AccessToken::validate_token][crate::AccessTokenRef::validate_token] and [UserToken::from_response][crate::tokens::UserToken::from_response]
16#[derive(thiserror::Error, Debug, displaydoc::Display)]
17#[non_exhaustive]
18pub enum ValidationError<RE: std::error::Error + Send + Sync + 'static> {
19    /// token is not authorized for use
20    NotAuthorized,
21    /// could not parse response when validating token
22    RequestParseError(#[from] crate::RequestParseError),
23    /// failed to request validation
24    Request(#[source] RE),
25    /// given token is not of the correct token type: {0}
26    InvalidToken(&'static str),
27}
28
29impl ValidationError<std::convert::Infallible> {
30    /// Convert this error from a infallible to another
31    pub fn into_other<RE: std::error::Error + Send + Sync + 'static>(self) -> ValidationError<RE> {
32        match self {
33            ValidationError::NotAuthorized => ValidationError::NotAuthorized,
34            ValidationError::RequestParseError(e) => ValidationError::RequestParseError(e),
35            ValidationError::InvalidToken(s) => ValidationError::InvalidToken(s),
36            ValidationError::Request(_) => unreachable!(),
37        }
38    }
39}
40
41/// Errors for [AccessToken::revoke_token][crate::AccessTokenRef::revoke_token]
42#[allow(missing_docs)]
43#[derive(thiserror::Error, Debug, displaydoc::Display)]
44#[non_exhaustive]
45#[cfg(feature = "client")]
46pub enum RevokeTokenError<RE: std::error::Error + Send + Sync + 'static> {
47    /// could not parse response when revoking token
48    RequestParseError(#[from] crate::RequestParseError),
49    /// failed to do revokation
50    RequestError(#[source] RE),
51}
52
53/// Errors for [TwitchToken::refresh_token][crate::TwitchToken::refresh_token]
54#[allow(missing_docs)]
55#[derive(thiserror::Error, Debug, displaydoc::Display)]
56#[non_exhaustive]
57#[cfg(feature = "client")]
58pub enum RefreshTokenError<RE: std::error::Error + Send + Sync + 'static> {
59    /// request when refreshing token failed
60    RequestError(#[source] RE),
61    /// could not parse response when refreshing token.
62    RequestParseError(#[from] crate::RequestParseError),
63    /// no client secret found
64    // TODO: Include this in doc
65    // A client secret is needed to request a refreshed token.
66    NoClientSecretFound,
67    /// no refresh token found
68    NoRefreshToken,
69    /// no expiration found on new token
70    NoExpiration,
71}
72
73/// Errors for [`UserTokenBuilder::get_user_token`](crate::tokens::UserTokenBuilder::get_user_token) and [`UserToken::mock_token`](crate::tokens::UserToken::mock_token)
74#[derive(thiserror::Error, Debug, displaydoc::Display)]
75#[non_exhaustive]
76#[cfg(feature = "client")]
77pub enum UserTokenExchangeError<RE: std::error::Error + Send + Sync + 'static> {
78    /// request for user token failed
79    RequestError(#[source] RE),
80    /// could not parse response when getting user token
81    RequestParseError(#[from] crate::RequestParseError),
82    /// state CSRF does not match when exchanging user token
83    StateMismatch,
84    /// could not get validation for user token
85    ValidationError(#[from] ValidationError<RE>),
86}
87
88/// Errors for [ImplicitUserTokenBuilder::get_user_token][crate::tokens::ImplicitUserTokenBuilder::get_user_token]
89#[derive(thiserror::Error, Debug, displaydoc::Display)]
90#[non_exhaustive]
91#[cfg(feature = "client")]
92pub enum ImplicitUserTokenExchangeError<RE: std::error::Error + Send + Sync + 'static> {
93    // FIXME: should be TwitchTokenErrorResponse
94    /// twitch returned an error: {error:?} - {description:?}
95    TwitchError {
96        /// Error type
97        error: Option<String>,
98        /// Description of error
99        description: Option<String>,
100    },
101    /// state CSRF does not match
102    StateMismatch,
103    /// could not get validation for token
104    ValidationError(#[from] ValidationError<RE>),
105}
106/// Errors for [`DeviceUserTokenBuilder`][crate::tokens::DeviceUserTokenBuilder]
107#[derive(thiserror::Error, Debug, displaydoc::Display)]
108#[non_exhaustive]
109#[cfg(feature = "client")]
110pub enum DeviceUserTokenExchangeError<RE: std::error::Error + Send + Sync + 'static> {
111    /// request for exchange token failed
112    DeviceExchangeRequestError(#[source] RE),
113    /// could not parse response when getting exchange token
114    DeviceExchangeParseError(#[source] crate::RequestParseError),
115    /// request for user token failed
116    TokenRequestError(#[source] RE),
117    /// could not parse response when getting user token
118    TokenParseError(#[source] crate::RequestParseError),
119    /// could not get validation for token
120    ValidationError(#[from] ValidationError<RE>),
121    /// no device code found, exchange not started
122    NoDeviceCode,
123    /// the device code has expired
124    Expired,
125}
126
127#[cfg(feature = "client")]
128impl<RE: std::error::Error + Send + Sync + 'static> DeviceUserTokenExchangeError<RE> {
129    /// Check if the error is due to the authorization request being pending
130    pub fn is_pending(&self) -> bool {
131        matches!(self, DeviceUserTokenExchangeError::TokenParseError(
132                crate::RequestParseError::TwitchError(crate::id::TwitchTokenErrorResponse {
133                    message,
134                    ..
135                }),
136            ) if message == "authorization_pending")
137    }
138}