graph_error/
authorization_failure.rs

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