service_authenticator/
error.rs1use std::borrow::Cow;
4use std::error::Error as StdError;
5use std::fmt;
6use std::io;
7
8use actix_web::client::SendRequestError;
9use serde::Deserialize;
10#[derive(Deserialize, Debug, PartialEq, Eq)]
14pub struct AuthError {
15 pub error: AuthErrorCode,
17 pub error_description: Option<String>,
19 pub error_uri: Option<String>,
21}
22impl fmt::Display for AuthError {
23 fn fmt(
24 &self,
25 f: &mut fmt::Formatter,
26 ) -> fmt::Result {
27 write!(f, "{}", &self.error.as_str())?;
28 if let Some(desc) = &self.error_description {
29 write!(f, ": {}", desc)?;
30 }
31 if let Some(uri) = &self.error_uri {
32 write!(f, "; See {} for more info", uri)?;
33 }
34 Ok(())
35 }
36}
37impl StdError for AuthError {}
38
39#[derive(Debug, Clone, Eq, PartialEq)]
41pub enum AuthErrorCode {
42 InvalidRequest,
44 InvalidClient,
46 InvalidGrant,
48 UnauthorizedClient,
50 UnsupportedGrantType,
52 InvalidScope,
54 AccessDenied,
56 ExpiredToken,
58 Other(String),
60}
61
62impl AuthErrorCode {
63 pub fn as_str(&self) -> &str {
65 match self {
66 AuthErrorCode::InvalidRequest => "invalid_request",
67 AuthErrorCode::InvalidClient => "invalid_client",
68 AuthErrorCode::InvalidGrant => "invalid_grant",
69 AuthErrorCode::UnauthorizedClient => "unauthorized_client",
70 AuthErrorCode::UnsupportedGrantType => "unsupported_grant_type",
71 AuthErrorCode::InvalidScope => "invalid_scope",
72 AuthErrorCode::AccessDenied => "access_denied",
73 AuthErrorCode::ExpiredToken => "expired_token",
74 AuthErrorCode::Other(s) => s.as_str(),
75 }
76 }
77
78 fn from_string<'a>(s: impl Into<Cow<'a, str>>) -> AuthErrorCode {
79 let s = s.into();
80 match s.as_ref() {
81 "invalid_request" => AuthErrorCode::InvalidRequest,
82 "invalid_client" => AuthErrorCode::InvalidClient,
83 "invalid_grant" => AuthErrorCode::InvalidGrant,
84 "unauthorized_client" => AuthErrorCode::UnauthorizedClient,
85 "unsupported_grant_type" => AuthErrorCode::UnsupportedGrantType,
86 "invalid_scope" => AuthErrorCode::InvalidScope,
87 "access_denied" => AuthErrorCode::AccessDenied,
88 "expired_token" => AuthErrorCode::ExpiredToken,
89 _ => AuthErrorCode::Other(s.into_owned()),
90 }
91 }
92}
93
94impl From<String> for AuthErrorCode {
95 fn from(s: String) -> Self {
96 AuthErrorCode::from_string(s)
97 }
98}
99
100impl<'a> From<&'a str> for AuthErrorCode {
101 fn from(s: &str) -> Self {
102 AuthErrorCode::from_string(s)
103 }
104}
105
106impl<'de> Deserialize<'de> for AuthErrorCode {
107 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108 where
109 D: serde::Deserializer<'de>,
110 {
111 struct V;
112 impl<'de> serde::de::Visitor<'de> for V {
113 type Value = AuthErrorCode;
114 fn expecting(
115 &self,
116 f: &mut std::fmt::Formatter,
117 ) -> std::fmt::Result {
118 f.write_str("any string")
119 }
120 fn visit_string<E: serde::de::Error>(
121 self,
122 value: String,
123 ) -> Result<Self::Value, E> {
124 Ok(value.into())
125 }
126 fn visit_str<E: serde::de::Error>(
127 self,
128 value: &str,
129 ) -> Result<Self::Value, E> {
130 Ok(value.into())
131 }
132 }
133 deserializer.deserialize_string(V)
134 }
135}
136
137#[derive(Deserialize, Debug)]
139#[serde(untagged)]
140pub(crate) enum AuthErrorOr<T> {
141 AuthError(AuthError),
142 Data(T),
143}
144
145impl<T> AuthErrorOr<T> {
146 pub(crate) fn into_result(self) -> Result<T, AuthError> {
147 match self {
148 AuthErrorOr::AuthError(err) => Result::Err(err),
149 AuthErrorOr::Data(value) => Result::Ok(value),
150 }
151 }
152}
153
154#[derive(Debug)]
156pub enum Error {
157 HttpError(SendRequestError),
159 AuthError(AuthError),
161 JSONError(serde_json::Error),
163 UserError(String),
165 LowLevelError(io::Error),
167 PayloadError(actix_http::error::PayloadError),
169}
170
171impl From<SendRequestError> for Error {
172 fn from(error: SendRequestError) -> Error {
173 Error::HttpError(error)
174 }
175}
176
177impl From<actix_http::error::PayloadError> for Error {
178 fn from(error: actix_http::error::PayloadError) -> Error {
179 Error::PayloadError(error)
180 }
181}
182
183impl From<AuthError> for Error {
184 fn from(value: AuthError) -> Error {
185 Error::AuthError(value)
186 }
187}
188impl From<serde_json::Error> for Error {
189 fn from(value: serde_json::Error) -> Error {
190 Error::JSONError(value)
191 }
192}
193
194impl From<io::Error> for Error {
195 fn from(value: io::Error) -> Error {
196 Error::LowLevelError(value)
197 }
198}
199
200impl fmt::Display for Error {
201 fn fmt(
202 &self,
203 f: &mut fmt::Formatter,
204 ) -> Result<(), fmt::Error> {
205 match *self {
206 Error::HttpError(ref err) => err.fmt(f),
207 Error::AuthError(ref err) => err.fmt(f),
208 Error::JSONError(ref e) => {
209 write!(
210 f,
211 "JSON Error; this might be a bug with unexpected server responses! {}",
212 e
213 )?;
214 Ok(())
215 }
216 Error::UserError(ref s) => s.fmt(f),
217 Error::LowLevelError(ref e) => e.fmt(f),
218 Error::PayloadError(ref e) => e.fmt(f),
219 }
220 }
221}
222
223impl StdError for Error {
224 #[cfg(test)]
225 fn source(&self) -> Option<&(dyn StdError + 'static)> {
226 match *self {
227 Error::HttpError(ref err) => Some(err),
228 Error::AuthError(ref err) => Some(err),
229 Error::JSONError(ref err) => Some(err),
230 Error::LowLevelError(ref err) => Some(err),
231 _ => None,
232 }
233 }
234}