graph_error/
graph_failure.rs

1use crate::download::AsyncDownloadError;
2use crate::internal::GraphRsError;
3use crate::{AuthExecutionError, AuthorizationFailure, ErrorMessage};
4use reqwest::header::HeaderMap;
5use std::cell::BorrowMutError;
6use std::error::Error;
7use std::io;
8use std::io::ErrorKind;
9use std::num::ParseIntError;
10use std::str::Utf8Error;
11use std::sync::mpsc;
12
13#[derive(Debug, thiserror::Error)]
14#[allow(clippy::large_enum_variant)]
15pub enum GraphFailure {
16    #[error("{0:#?}")]
17    Io(#[from] io::Error),
18
19    #[error("{0:#?}")]
20    Utf8Error(#[from] Utf8Error),
21
22    #[error("{0:#?}")]
23    ReqwestError(#[from] reqwest::Error),
24
25    #[error("{0:#?}")]
26    SerdeJson(#[from] serde_json::Error),
27
28    #[error("{0:#?}")]
29    DecodeError(#[from] base64::DecodeError),
30
31    #[error("{0:#?}")]
32    RecvError(#[from] mpsc::RecvError),
33
34    #[error("{0:#?}")]
35    BorrowMutError(#[from] BorrowMutError),
36
37    #[error("{0:#?}")]
38    UrlParse(#[from] url::ParseError),
39
40    #[error("{0:#?}")]
41    HttpError(#[from] http::Error),
42
43    #[error("{0:#?}")]
44    GraphRsError(#[from] GraphRsError),
45
46    #[error("{0:#?}")]
47    HandlebarsRenderError(#[from] handlebars::RenderError),
48
49    #[error("{0:?}")]
50    HandlebarsTemplateRenderError(#[from] handlebars::TemplateRenderError),
51
52    #[error("Crypto Error (Unknown)")]
53    CryptoError,
54
55    #[error("{0:#?}")]
56    AsyncDownloadError(#[from] AsyncDownloadError),
57
58    #[error(
59        "Error building or processing request prior to being sent:\n{0:#?}",
60        error
61    )]
62    PreFlightError {
63        url: Option<reqwest::Url>,
64        headers: Option<HeaderMap>,
65        error: Option<Box<GraphFailure>>,
66        message: String,
67    },
68
69    #[error("{0:#?}", message)]
70    Default {
71        url: Option<reqwest::Url>,
72        headers: Option<HeaderMap>,
73        message: String,
74    },
75
76    #[error("{0:#?}")]
77    ErrorMessage(#[from] ErrorMessage),
78
79    #[error("Temporary Graph API Error")]
80    TemporaryError,
81
82    #[error("Parse Int error:\n{0:#?}")]
83    ParseIntError(#[from] ParseIntError),
84
85    #[error("message: {0:#?}, response: {1:#?}", message, response)]
86    SilentTokenAuth {
87        message: String,
88        response: http::Response<Result<serde_json::Value, ErrorMessage>>,
89    },
90
91    #[error("{0:#?}")]
92    JsonWebToken(#[from] jsonwebtoken::errors::Error),
93}
94
95impl GraphFailure {
96    pub fn error_kind(error_kind: io::ErrorKind, message: &str) -> Self {
97        let e = io::Error::new(error_kind, message);
98        GraphFailure::from(e)
99    }
100
101    pub fn internal(err: GraphRsError) -> GraphFailure {
102        GraphFailure::GraphRsError(err)
103    }
104
105    pub fn not_found(msg: &str) -> GraphFailure {
106        GraphFailure::error_kind(ErrorKind::NotFound, msg)
107    }
108
109    pub fn invalid(msg: &str) -> Self {
110        GraphFailure::internal(GraphRsError::InvalidOrMissing { msg: msg.into() })
111    }
112}
113
114impl Default for GraphFailure {
115    fn default() -> Self {
116        GraphFailure::Default {
117            url: None,
118            headers: None,
119            message: "Unknown Error".into(),
120        }
121    }
122}
123
124impl From<ring::error::Unspecified> for GraphFailure {
125    fn from(_: ring::error::Unspecified) -> Self {
126        GraphFailure::CryptoError
127    }
128}
129
130impl From<AuthExecutionError> for GraphFailure {
131    fn from(value: AuthExecutionError) -> Self {
132        match value {
133            AuthExecutionError::Authorization(authorization_failure) => match authorization_failure
134            {
135                AuthorizationFailure::RequiredValue { name, message } => {
136                    GraphFailure::PreFlightError {
137                        url: None,
138                        headers: None,
139                        error: None,
140                        message: format!("name: {:#?}, message: {:#?}", name, message),
141                    }
142                }
143                AuthorizationFailure::UrlParse(error) => GraphFailure::UrlParse(error),
144                AuthorizationFailure::Uuid(error) => GraphFailure::PreFlightError {
145                    url: None,
146                    headers: None,
147                    error: None,
148                    message: format!(
149                        "name: client_id, message: {:#?}, source: {:#?}",
150                        "Client Id is not a valid Uuid",
151                        error.to_string()
152                    ),
153                },
154                AuthorizationFailure::Openssl(message) => GraphFailure::PreFlightError {
155                    url: None,
156                    headers: None,
157                    error: None,
158                    message,
159                },
160                AuthorizationFailure::SerdeJson(error) => GraphFailure::SerdeJson(error),
161            },
162            AuthExecutionError::Request(e) => GraphFailure::ReqwestError(e),
163            AuthExecutionError::Http(e) => GraphFailure::HttpError(e),
164            AuthExecutionError::SilentTokenAuth { message, response } => {
165                GraphFailure::SilentTokenAuth { message, response }
166            }
167            AuthExecutionError::JsonWebToken(error) => GraphFailure::JsonWebToken(error),
168        }
169    }
170}
171
172impl From<Box<dyn Error + Send + Sync>> for GraphFailure {
173    fn from(value: Box<dyn Error + Send + Sync>) -> Self {
174        value.into()
175    }
176}