graph_error/
authorization_failure.rs

1use crate::{ErrorMessage, IdentityResult, WebViewDeviceCodeError};
2use tokio::sync::mpsc::error::SendTimeoutError;
3use url::ParseError;
4
5pub type AF = AuthorizationFailure;
6
7/// Errors typically from missing or invalid configuration using one of the
8/// identity platform clients such as AuthorizationCodeCredential.
9#[derive(Debug, thiserror::Error)]
10pub enum AuthorizationFailure {
11    #[error("Required value missing:\n{0:#?}", name)]
12    RequiredValue {
13        name: String,
14        message: Option<String>,
15    },
16
17    #[error("{0:#?}")]
18    UrlParse(#[from] url::ParseError),
19
20    #[error("{0:#?}")]
21    Uuid(#[from] uuid::Error),
22
23    #[error("{0:#?}")]
24    Openssl(String),
25
26    #[error("{0:#?}")]
27    SerdeJson(#[from] serde_json::Error),
28}
29
30impl AuthorizationFailure {
31    pub fn required<T: AsRef<str>>(name: T) -> AuthorizationFailure {
32        AuthorizationFailure::RequiredValue {
33            name: name.as_ref().to_owned(),
34            message: None,
35        }
36    }
37
38    pub fn result<U>(name: impl AsRef<str>) -> IdentityResult<U> {
39        Err(AuthorizationFailure::RequiredValue {
40            name: name.as_ref().to_owned(),
41            message: None,
42        })
43    }
44
45    pub fn msg_err<T: AsRef<str>>(name: T, message: T) -> AuthorizationFailure {
46        AuthorizationFailure::RequiredValue {
47            name: name.as_ref().to_owned(),
48            message: Some(message.as_ref().to_owned()),
49        }
50    }
51
52    pub fn msg_internal_err<T: AsRef<str>>(name: T) -> AuthorizationFailure {
53        AuthorizationFailure::RequiredValue {
54            name: name.as_ref().to_owned(),
55            message: Some("Internal error please file an issue on GitHub https://github.com/sreeise/graph-rs-sdk/issues".to_owned()),
56        }
57    }
58
59    pub fn msg_result<T>(
60        name: impl AsRef<str>,
61        message: impl ToString,
62    ) -> Result<T, AuthorizationFailure> {
63        Err(AuthorizationFailure::RequiredValue {
64            name: name.as_ref().to_owned(),
65            message: Some(message.to_string()),
66        })
67    }
68
69    pub fn msg_internal_result<T>(name: impl AsRef<str>) -> Result<T, AuthorizationFailure> {
70        Err(AF::msg_internal_err(name))
71    }
72
73    pub fn condition(cond: bool, name: &str, msg: &str) -> IdentityResult<()> {
74        if cond {
75            AF::msg_result(name, msg)
76        } else {
77            Ok(())
78        }
79    }
80
81    pub fn x509(message: impl ToString) -> AuthorizationFailure {
82        AuthorizationFailure::Openssl(message.to_string())
83    }
84
85    pub fn x509_result<T>(message: impl ToString) -> Result<T, AuthorizationFailure> {
86        Err(AuthorizationFailure::Openssl(message.to_string()))
87    }
88}
89
90/// Error either from missing or invalid configuration using one of the
91/// identity platform clients or an error from the result of executing
92/// an http request using the identity platform clients.
93#[derive(Debug, thiserror::Error)]
94pub enum AuthExecutionError {
95    #[error("{0:#?}")]
96    Authorization(#[from] AuthorizationFailure),
97
98    #[error("{0:#?}")]
99    Request(#[from] reqwest::Error),
100
101    #[error("{0:#?}")]
102    Http(#[from] http::Error),
103
104    #[error("message: {0:#?}, response: {1:#?}", message, response)]
105    SilentTokenAuth {
106        message: String,
107        response: http::Response<Result<serde_json::Value, ErrorMessage>>,
108    },
109
110    #[error("{0:#?}")]
111    JsonWebToken(#[from] jsonwebtoken::errors::Error),
112}
113
114impl AuthExecutionError {
115    pub fn silent_token_auth(
116        response: http::Response<Result<serde_json::Value, ErrorMessage>>,
117    ) -> AuthExecutionError {
118        AuthExecutionError::SilentTokenAuth {
119            message: "silent token auth failed".into(),
120            response,
121        }
122    }
123}
124
125impl From<serde_json::error::Error> for AuthExecutionError {
126    fn from(value: serde_json::error::Error) -> Self {
127        AuthExecutionError::Authorization(AuthorizationFailure::from(value))
128    }
129}
130
131impl From<WebViewDeviceCodeError> for AuthExecutionError {
132    fn from(value: WebViewDeviceCodeError) -> Self {
133        AuthExecutionError::Authorization(AuthorizationFailure::msg_err(
134            "Unknown",
135            &value.to_string(),
136        ))
137    }
138}
139
140impl From<url::ParseError> for AuthExecutionError {
141    fn from(value: ParseError) -> Self {
142        AuthExecutionError::Authorization(AuthorizationFailure::UrlParse(value))
143    }
144}
145
146#[derive(Debug, thiserror::Error)]
147pub enum AuthTaskExecutionError<R> {
148    #[error("{0:#?}")]
149    AuthExecutionError(#[from] AuthExecutionError),
150    #[error("Tokio SendTimeoutError - Reason: {0:#?}")]
151    SendTimeoutErrorAsync(#[from] SendTimeoutError<R>),
152    #[error("{0:#?}")]
153    JoinError(#[from] tokio::task::JoinError),
154}