tame_oauth/
error.rs

1use std::{error::Error as Err, fmt};
2
3#[derive(Debug)]
4pub enum Error {
5    /// The private_key field in the [Service Account Key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
6    /// is invalid and cannot be parsed
7    #[cfg(feature = "jwt")]
8    InvalidKeyFormat,
9    /// Unable to deserialize the base64 encoded RSA key
10    Base64Decode(data_encoding::DecodeError),
11    /// An error occurred trying to create an HTTP request
12    Http(http::Error),
13    /// Failed to authenticate and retrieve an oauth token, and were unable to
14    /// deserialize a more exact reason from the error response
15    HttpStatus(http::StatusCode),
16    /// Failed to de/serialize JSON
17    Json(serde_json::Error),
18    /// Failed to authenticate and retrieve an oauth token
19    Auth(AuthError),
20    /// The RSA key seems valid, but is unable to sign a payload
21    #[cfg(feature = "jwt")]
22    InvalidRsaKey(ring::error::Unspecified),
23    /// The RSA key is invalid and cannot be used to sign
24    #[cfg(feature = "jwt")]
25    InvalidRsaKeyRejected(ring::error::KeyRejected),
26    /// A mutex has been poisoned due to a panic while a lock was held
27    Poisoned,
28    /// An I/O error occurred when reading credentials
29    #[cfg(feature = "gcp")]
30    Io(std::io::Error),
31    /// Failed to load valid credentials from a file on disk
32    #[cfg(feature = "gcp")]
33    InvalidCredentials {
34        file: std::path::PathBuf,
35        error: Box<Error>,
36    },
37    /// An error occurred due to [`SystemTime`](std::time::SystemTime)
38    SystemTime(std::time::SystemTimeError),
39    /// Unable to parse the returned token
40    InvalidTokenFormat,
41}
42
43impl fmt::Display for Error {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        #![allow(clippy::enum_glob_use)]
46        use Error::*;
47
48        match self {
49            #[cfg(feature = "jwt")]
50            InvalidKeyFormat => f.write_str("The key format is invalid or unknown"),
51            Base64Decode(err) => write!(f, "{}", err),
52            Http(err) => write!(f, "{}", err),
53            HttpStatus(sc) => write!(f, "HTTP error status: {}", sc),
54            Json(err) => write!(f, "{}", err),
55            Auth(err) => write!(f, "{}", err),
56            #[cfg(feature = "jwt")]
57            InvalidRsaKey(_err) => f.write_str("RSA key is invalid"),
58            #[cfg(feature = "jwt")]
59            InvalidRsaKeyRejected(err) => write!(f, "RSA key is invalid: {}", err),
60            Poisoned => f.write_str("A mutex is poisoned"),
61            #[cfg(feature = "gcp")]
62            Io(inner) => write!(f, "{}", inner),
63            #[cfg(feature = "gcp")]
64            InvalidCredentials { file, error } => {
65                write!(f, "Invalid credentials in '{}': {}", file.display(), error)
66            }
67            SystemTime(te) => {
68                write!(f, "System Time error: {}", te)
69            }
70            InvalidTokenFormat => {
71                write!(f, "Invalid token format")
72            }
73        }
74    }
75}
76
77impl std::error::Error for Error {
78    fn source(&self) -> Option<&(dyn Err + 'static)> {
79        #![allow(clippy::enum_glob_use)]
80        use Error::*;
81
82        match self {
83            Base64Decode(err) => Some(err as &dyn Err),
84            Http(err) => Some(err as &dyn Err),
85            Json(err) => Some(err as &dyn Err),
86            Auth(err) => Some(err as &dyn Err),
87            SystemTime(err) => Some(err as &dyn Err),
88            _ => None,
89        }
90    }
91}
92
93impl From<data_encoding::DecodeError> for Error {
94    fn from(e: data_encoding::DecodeError) -> Self {
95        Error::Base64Decode(e)
96    }
97}
98
99impl From<http::Error> for Error {
100    fn from(e: http::Error) -> Self {
101        Error::Http(e)
102    }
103}
104
105impl From<serde_json::Error> for Error {
106    fn from(e: serde_json::Error) -> Self {
107        Error::Json(e)
108    }
109}
110
111impl From<std::time::SystemTimeError> for Error {
112    fn from(e: std::time::SystemTimeError) -> Self {
113        Error::SystemTime(e)
114    }
115}
116
117#[derive(serde::Deserialize, Debug)]
118pub struct AuthError {
119    /// Top level error type
120    pub error: Option<String>,
121    /// More specific details on the error
122    pub error_description: Option<String>,
123}
124
125impl fmt::Display for AuthError {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        if let Some(ref err) = self.error {
128            write!(f, "{}", err)?;
129
130            if let Some(ref desc) = self.error_description {
131                write!(f, "desc: {}", desc)?;
132            }
133        }
134
135        Ok(())
136    }
137}
138
139impl std::error::Error for AuthError {}