Skip to main content

openstack_keystone_core/
error.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//! # Error
15//!
16//! Diverse errors that can occur during the Keystone processing (not the API).
17use thiserror::Error;
18
19use crate::application_credential::error::ApplicationCredentialProviderError;
20use crate::assignment::error::AssignmentProviderError;
21use crate::catalog::error::CatalogProviderError;
22use crate::federation::error::FederationProviderError;
23use crate::identity::error::IdentityProviderError;
24use crate::identity_mapping::error::IdentityMappingProviderError;
25use crate::k8s_auth::error::K8sAuthProviderError;
26use crate::policy::PolicyError;
27use crate::resource::error::ResourceProviderError;
28use crate::revoke::error::RevokeProviderError;
29use crate::role::error::RoleProviderError;
30use crate::token::TokenProviderError;
31use crate::trust::TrustProviderError;
32//use crate::webauthn::WebauthnError;
33
34/// Keystone error.
35#[derive(Debug, Error)]
36pub enum KeystoneError {
37    /// Application credential provider.
38    #[error(transparent)]
39    ApplicationCredential {
40        /// The source of the error.
41        #[from]
42        source: ApplicationCredentialProviderError,
43    },
44
45    /// Assignment provider.
46    #[error(transparent)]
47    AssignmentProvider {
48        /// The source of the error.
49        #[from]
50        source: AssignmentProviderError,
51    },
52
53    /// Catalog provider.
54    #[error(transparent)]
55    CatalogProvider {
56        /// The source of the error.
57        #[from]
58        source: CatalogProviderError,
59    },
60
61    /// Federation provider.
62    #[error(transparent)]
63    FederationProvider {
64        /// The source of the error.
65        #[from]
66        source: FederationProviderError,
67    },
68
69    /// Identity provider.
70    #[error(transparent)]
71    IdentityProvider {
72        /// The source of the error.
73        #[from]
74        source: IdentityProviderError,
75    },
76
77    /// Identity mapping provider.
78    #[error(transparent)]
79    IdentityMapping {
80        /// The source of the error.
81        #[from]
82        source: IdentityMappingProviderError,
83    },
84
85    /// IO error.
86    #[error(transparent)]
87    IO {
88        /// The source of the error.
89        #[from]
90        source: std::io::Error,
91    },
92
93    /// Json serialization error.
94    #[error("json serde error: {}", source)]
95    Json {
96        /// The source of the error.
97        #[from]
98        source: serde_json::Error,
99    },
100
101    /// K8s auth provider.
102    #[error(transparent)]
103    K8sAuthProvider {
104        /// The source of the error.
105        #[from]
106        source: K8sAuthProviderError,
107    },
108
109    /// Policy engine.
110    #[error(transparent)]
111    Policy {
112        /// The source of the error.
113        #[from]
114        source: PolicyError,
115    },
116
117    /// Policy engine is not available.
118    #[error("policy enforcement is requested, but not available with the enabled features")]
119    PolicyEnforcementNotAvailable,
120
121    /// Resource provider.
122    #[error(transparent)]
123    ResourceProvider {
124        /// The source of the error.
125        #[from]
126        source: ResourceProviderError,
127    },
128
129    /// Revoke provider error.
130    #[error(transparent)]
131    RevokeProvider {
132        /// The source of the error.
133        #[from]
134        source: RevokeProviderError,
135    },
136
137    /// Role provider.
138    #[error(transparent)]
139    RoleProvider {
140        /// The source of the error.
141        #[from]
142        source: RoleProviderError,
143    },
144
145    /// Token provider.
146    #[error(transparent)]
147    TokenProvider {
148        /// The source of the error.
149        #[from]
150        source: TokenProviderError,
151    },
152
153    /// Trust provider.
154    #[error(transparent)]
155    TrustProvider {
156        /// The source of the error.
157        #[from]
158        source: TrustProviderError,
159    },
160
161    /// Url parsing error.
162    #[error(transparent)]
163    UrlParse {
164        #[from]
165        source: url::ParseError,
166    },
167
168    #[error("provider error: {}", source)]
169    Provider {
170        #[source]
171        source: Box<dyn std::error::Error + Send + Sync + 'static>,
172    },
173    //    /// WebauthN error.
174    //    #[error(transparent)]
175    //    Webauthn {
176    //        /// The source of the error.
177    //        #[from]
178    //        source: WebauthnError,
179    //    },
180}
181
182/// Builder error.
183///
184/// A wrapper error that is used instead of the error generated by the
185/// `derive_builder`.
186#[derive(Debug, Error)]
187#[non_exhaustive]
188pub enum BuilderError {
189    /// Uninitialized field.
190    #[error("{0}")]
191    UninitializedField(String),
192    /// Custom validation error.
193    #[error("{0}")]
194    Validation(String),
195}
196
197impl From<String> for BuilderError {
198    fn from(s: String) -> Self {
199        Self::Validation(s)
200    }
201}
202
203impl From<openstack_keystone_api_types::error::BuilderError> for BuilderError {
204    fn from(value: openstack_keystone_api_types::error::BuilderError) -> Self {
205        match value {
206            openstack_keystone_api_types::error::BuilderError::UninitializedField(e) => {
207                Self::UninitializedField(e)
208            }
209            openstack_keystone_api_types::error::BuilderError::Validation(e) => Self::Validation(e),
210        }
211    }
212}
213
214impl From<derive_builder::UninitializedFieldError> for BuilderError {
215    fn from(ufe: derive_builder::UninitializedFieldError) -> Self {
216        Self::UninitializedField(ufe.to_string())
217    }
218}
219
220/// Context aware database error.
221#[derive(Debug, Error)]
222pub enum DatabaseError {
223    /// Conflict.
224    #[error("{message} while {context}")]
225    Conflict {
226        /// The error message.
227        message: String,
228        /// The error context.
229        context: String,
230    },
231
232    /// Database error.
233    #[error("Database error {source} while {context}")]
234    Database {
235        /// The source of the error.
236        source: sea_orm::DbErr,
237        /// The error context.
238        context: String,
239    },
240
241    /// SqlError.
242    #[error("{message} while {context}")]
243    Sql {
244        /// The error message.
245        message: String,
246        /// The error context.
247        context: String,
248    },
249}
250
251/// The trait wrapping the SQL error with the context information.
252pub trait DbContextExt<T> {
253    fn context(self, msg: impl Into<String>) -> Result<T, DatabaseError>;
254}
255
256impl<T> DbContextExt<T> for Result<T, sea_orm::DbErr> {
257    fn context(self, context: impl Into<String>) -> Result<T, DatabaseError> {
258        self.map_err(|err| match err.sql_err() {
259            Some(sea_orm::SqlErr::UniqueConstraintViolation(descr)) => DatabaseError::Conflict {
260                message: descr.to_string(),
261                context: context.into(),
262            },
263            Some(sea_orm::SqlErr::ForeignKeyConstraintViolation(descr)) => {
264                DatabaseError::Conflict {
265                    message: descr.to_string(),
266                    context: context.into(),
267                }
268            }
269            Some(other) => DatabaseError::Sql {
270                message: other.to_string(),
271                context: context.into(),
272            },
273            None => DatabaseError::Database {
274                source: err,
275                context: context.into(),
276            },
277        })
278    }
279}