qcs_api_client_common/configuration/
error.rs1use std::{error::Error, path::PathBuf};
2
3use crate::configuration::{oidc::DISCOVERY_REQUIRED_SCOPE, tokens::PkceFlowError};
4
5use super::ClientConfigurationBuilderError;
6
7#[derive(Debug, thiserror::Error)]
9#[non_exhaustive]
10pub enum LoadError {
11 #[error("Failed to load settings: {0}")]
13 Load(Box<dyn Error + Send + Sync + 'static>),
14 #[error("Failed to load value from the environment variable {variable_name}: {message}")]
16 EnvVar {
17 variable_name: String,
19 message: String,
21 },
22 #[error("Failed to load file from path {path:?}: {message}")]
24 Path {
25 path: PathBuf,
27 message: String,
29 },
30 #[error(transparent)]
32 Io(#[from] std::io::Error),
33 #[error("Failed to build the ClientConfiguration: {0}")]
35 Build(#[from] ClientConfigurationBuilderError),
36 #[error("Expected profile {0} in settings.profiles but it does not exist")]
38 ProfileNotFound(String),
39 #[error("Expected auth server {0} in settings.auth_servers but it does not exist")]
41 AuthServerNotFound(String),
42 #[error("Failed to complete PKCE login: {0}")]
44 PkceFlow(#[from] PkceFlowError),
45 #[cfg(feature = "tracing-config")]
46 #[error("Could not parse tracing filter: {0}")]
49 TracingFilterParseError(#[from] crate::tracing_configuration::TracingFilterError),
50}
51
52impl<E: Error + 'static> From<shellexpand::LookupError<E>> for LoadError {
53 fn from(value: shellexpand::LookupError<E>) -> Self {
54 Self::EnvVar {
55 variable_name: value.var_name,
56 message: value.cause.to_string(),
57 }
58 }
59}
60
61impl From<figment::Error> for LoadError {
62 fn from(value: figment::Error) -> Self {
63 Self::Load(Box::new(value))
64 }
65}
66
67#[derive(Debug, thiserror::Error)]
69pub enum TokenError {
70 #[error("No refresh token is configured within the selected QCS credential.")]
72 NoRefreshToken,
73 #[error("No access token has been requested.")]
75 NoAccessToken,
76 #[error("Requested an access token for a configuration without credentials.")]
78 NoCredentials,
79 #[error("The access token is invalid: {0}")]
81 InvalidAccessToken(jsonwebtoken::errors::Error),
82 #[error("No auth server is configured within the selected QCS credential.")]
84 NoAuthServer,
85 #[error("Error fetching new token from the QCS API: {0}")]
87 Fetch(#[from] reqwest::Error),
88 #[error("Failed to request an externally managed access token: {0}")]
90 ExternallyManaged(String),
91 #[error("Failed to write the new access token to the secrets file: {0}")]
93 Write(#[from] WriteError),
94 #[error("Failed to fetch the OIDC discovery document: {0}")]
96 Discovery(#[from] DiscoveryError),
97}
98
99#[derive(Debug, thiserror::Error)]
101pub enum DiscoveryError {
102 #[error("invalid issuer URL: {0}")]
103 Url(#[from] url::ParseError),
104 #[error("error fetching discovery document: {0}")]
105 Fetch(#[from] reqwest::Error),
106 #[error("failed to parse discovery document: {0}")]
107 Json(#[from] serde_json::Error),
108 #[error("issuer URL ({issuer}) is invalid: {reason}")]
109 InvalidIssuer { issuer: String, reason: String },
110 #[error("discovery document is invalid: {reason}")]
111 InvalidDocument { reason: String },
112 #[error("discovery document issuer ({document}) does not match the queried issuer ({query})")]
113 IssuerMismatch { document: String, query: String },
114 #[error("discovery document `supported_scopes` does not include the required minimum scope \"{expected}\", received: {0:?}", expected = DISCOVERY_REQUIRED_SCOPE)]
115 InvalidScopes(Vec<String>),
116}
117
118#[derive(Debug, thiserror::Error)]
120pub enum WriteError {
121 #[error(transparent)]
123 IoWithPath(#[from] IoErrorWithPath),
124 #[error("File could not be read as TOML: {0}")]
126 InvalidToml(#[from] toml_edit::TomlError),
127 #[error("The table `{0}` does not exist.")]
129 MissingTable(String),
130 #[error("Error formatting time: {0}.")]
132 TimeFormat(#[from] time::error::Format),
133 #[error("Error writing or persisting temporary secrets file during access token refresh: {0}")]
135 TempFile(#[from] async_tempfile::Error),
136}
137
138#[derive(Debug)]
140pub enum IoOperation {
141 Open,
142 Read,
143 Write,
144 Rename { dest: PathBuf },
145 GetMetadata,
146 SetPermissions,
147 Flush,
148}
149
150#[derive(Debug, thiserror::Error)]
152#[error("Io error while error performing {operation:?} on {path}: {error}")]
153pub struct IoErrorWithPath {
154 #[source]
155 pub error: std::io::Error,
156 pub path: PathBuf,
157 pub operation: IoOperation,
158}