oauth2_passkey/coordination/
errors.rs1use thiserror::Error;
4
5use crate::oauth2::OAuth2Error;
6use crate::passkey::PasskeyError;
7use crate::session::SessionError;
8use crate::userdb::UserError;
9use crate::utils::UtilError;
10
11#[derive(Error, Debug)]
13pub enum CoordinationError {
14 #[error("Coordination error: {0}")]
16 Coordination(String),
17
18 #[error("Validation error: {0}")]
20 Validation(String),
21
22 #[error("Internal error: {0}")]
24 Internal(String),
25
26 #[error("Database error: {0}")]
28 Database(String),
29
30 #[error("Authentication error: {0}")]
32 Authentication(String),
33
34 #[error("Session mismatch: {0}")]
36 SessionMismatch(String),
37
38 #[error("Context token is missing")]
40 MissingContextToken,
41
42 #[error("Unauthorized access")]
44 Unauthorized,
45
46 #[error("You are already authenticated")]
48 UnexpectedlyAuthorized,
49
50 #[error("No content")]
52 NoContent,
53
54 #[error("Invalid mode")]
56 InvalidMode,
57
58 #[error("Conflict: {0}")]
60 Conflict(String),
61
62 #[error("Invalid state: {0}")]
64 InvalidState(String),
65
66 #[error("Resource not found: {resource_type} {resource_id}")]
68 ResourceNotFound {
69 resource_type: String,
71 resource_id: String,
73 },
74
75 #[error("User error: {0}")]
77 UserError(UserError),
78
79 #[error("OAuth2 error: {0}")]
81 OAuth2Error(OAuth2Error),
82
83 #[error("Passkey error: {0}")]
85 PasskeyError(PasskeyError),
86
87 #[error("Session error: {0}")]
89 SessionError(SessionError),
90
91 #[error("Utils error: {0}")]
93 UtilsError(UtilError),
94
95 #[error("Invalid response mode: {0}")]
97 InvalidResponseMode(String),
98}
99
100impl CoordinationError {
101 pub fn log(self) -> Self {
107 match &self {
108 Self::Coordination(msg) => tracing::error!("Coordination error: {}", msg),
109 Self::Validation(msg) => tracing::error!("Validation error: {}", msg),
110 Self::Internal(msg) => tracing::error!("Internal error: {}", msg),
111 Self::Database(msg) => tracing::error!("Database error: {}", msg),
112 Self::Authentication(msg) => tracing::error!("Authentication error: {}", msg),
113 Self::SessionMismatch(msg) => tracing::error!("Session mismatch: {}", msg),
114 Self::MissingContextToken => tracing::error!("Context token is missing"),
115 Self::Unauthorized => tracing::error!("Unauthorized access"),
116 Self::UnexpectedlyAuthorized => tracing::error!("Unexpectedly authorized access"),
117 Self::NoContent => tracing::error!("No content"),
118 Self::InvalidMode => tracing::error!("Invalid mode"),
119 Self::Conflict(message) => tracing::error!("Conflict: {}", message),
120 Self::InvalidState(message) => tracing::error!("Invalid state: {}", message),
121 Self::ResourceNotFound {
122 resource_type,
123 resource_id,
124 } => tracing::error!("Resource not found: {} {}", resource_type, resource_id),
125 Self::UserError(err) => tracing::error!("User error: {}", err),
126 Self::OAuth2Error(err) => tracing::error!("OAuth2 error: {}", err),
127 Self::PasskeyError(err) => tracing::error!("Passkey error: {}", err),
128 Self::SessionError(err) => tracing::error!("Session error: {}", err),
129 Self::UtilsError(err) => tracing::error!("Utils error: {}", err),
130 Self::InvalidResponseMode(message) => {
131 tracing::error!("Invalid response mode: {}", message)
132 }
133 }
134 self
135 }
136
137 pub fn log_with_context(self) -> Self {
142 match &self {
143 Self::Coordination(msg) => {
144 tracing::error!(error = %self, message = %msg, "Coordination error with context");
145 }
146 Self::Validation(msg) => {
147 tracing::error!(error = %self, message = %msg, "Validation error with context");
148 }
149 Self::Internal(msg) => {
150 tracing::error!(error = %self, message = %msg, "Internal error with context");
151 }
152 Self::Database(msg) => {
153 tracing::error!(error = %self, message = %msg, "Database error with context");
154 }
155 Self::Authentication(msg) => {
156 tracing::error!(error = %self, message = %msg, "Authentication error with context");
157 }
158 Self::SessionMismatch(msg) => {
159 tracing::error!(error = %self, message = %msg, "Session mismatch with context");
160 }
161 Self::MissingContextToken => {
162 tracing::error!(error = %self, "Context token missing with span context");
163 }
164 Self::Unauthorized => {
165 tracing::error!(error = %self, "Unauthorized access with span context");
166 }
167 Self::UnexpectedlyAuthorized => {
168 tracing::error!(error = %self, "Unexpectedly authorized with span context");
169 }
170 Self::NoContent => {
171 tracing::error!(error = %self, "No content with span context");
172 }
173 Self::InvalidMode => {
174 tracing::error!(error = %self, "Invalid mode with span context");
175 }
176 Self::InvalidState(msg) => {
177 tracing::error!(error = %self, message = %msg, "Invalid state with context");
178 }
179 Self::Conflict(msg) => {
180 tracing::error!(error = %self, message = %msg, "Conflict with context");
181 }
182 Self::ResourceNotFound {
183 resource_type,
184 resource_id,
185 } => {
186 tracing::error!(
187 error = %self,
188 resource_type = %resource_type,
189 resource_id = %resource_id,
190 "Resource not found with context"
191 );
192 }
193 Self::UserError(err) => {
195 tracing::error!(error = %self, source_error = %err, "User error with context");
196 }
197 Self::OAuth2Error(err) => {
198 tracing::error!(error = %self, source_error = %err, "OAuth2 error with context");
199 }
200 Self::PasskeyError(err) => {
201 tracing::error!(error = %self, source_error = %err, "Passkey error with context");
202 }
203 Self::SessionError(err) => {
204 tracing::error!(error = %self, source_error = %err, "Session error with context");
205 }
206 Self::UtilsError(err) => {
207 tracing::error!(error = %self, source_error = %err, "Utils error with context");
208 }
209 Self::InvalidResponseMode(msg) => {
210 tracing::error!(error = %self, message = %msg, "Invalid response mode with context");
211 }
212 }
213 self
214 }
215
216 pub fn with_span_context(self) -> Self {
221 if tracing::log::log_enabled!(tracing::log::Level::Error) {
223 let span_name = tracing::Span::current()
224 .metadata()
225 .map(|m| m.name())
226 .unwrap_or("unknown");
227 tracing::error!(
228 error = %self,
229 span_context = span_name,
230 "Error with full span context captured"
231 );
232 } else {
233 tracing::error!(
234 error = %self,
235 "Error captured without span context"
236 );
237 }
238 self
239 }
240}
241
242impl From<OAuth2Error> for CoordinationError {
245 fn from(err: OAuth2Error) -> Self {
246 let error = Self::OAuth2Error(err);
247 tracing::error!("{}", error);
248 error
249 }
250}
251
252impl From<PasskeyError> for CoordinationError {
253 fn from(err: PasskeyError) -> Self {
254 let error = Self::PasskeyError(err);
255 tracing::error!("{}", error);
256 error
257 }
258}
259
260impl From<SessionError> for CoordinationError {
261 fn from(err: SessionError) -> Self {
262 let error = Self::SessionError(err);
263 tracing::error!("{}", error);
264 error
265 }
266}
267
268impl From<UserError> for CoordinationError {
269 fn from(err: UserError) -> Self {
270 let error = Self::UserError(err);
271 tracing::error!("{}", error);
272 error
273 }
274}
275
276impl From<UtilError> for CoordinationError {
277 fn from(err: UtilError) -> Self {
278 let error = Self::UtilsError(err);
279 tracing::error!("{}", error);
280 error
281 }
282}
283
284#[cfg(test)]
285mod tests;