The smokesignal.events web application
1//! # Web Error Types
2//!
3//! This module defines the top-level error type for the HTTP layer that aggregates
4//! all domain-specific errors in the application. This allows errors to be handled
5//! uniformly at the HTTP boundary and converted into appropriate HTTP responses.
6//!
7//! Specific error variants use their own error codes, while general errors use the
8//! format: `error-smokesignal-web-<number> <message>: <details>`
9
10use axum::http::StatusCode;
11use axum::response::IntoResponse;
12use axum::response::Response;
13use thiserror::Error;
14
15use super::acceptance_error::AcceptanceError;
16use super::blob_error::BlobError;
17use super::common_error::CommonError;
18use super::event_view_errors::EventViewError;
19use super::import_error::ImportError;
20use super::lfg_error::LfgError;
21use super::login_error::LoginError;
22use super::middleware_errors::MiddlewareAuthError;
23use super::share_bluesky_error::ShareBlueskyError;
24use super::url_error::UrlError;
25
26/// Represents all possible errors that can occur in the HTTP layer.
27///
28/// This enum serves as an aggregation point for all domain-specific errors
29/// in the application, allowing them to be handled uniformly at the HTTP boundary.
30///
31/// Most variants use transparent error forwarding to preserve the original error message
32/// and error code, while a few web-specific errors have their own error code format:
33/// `error-smokesignal-web-<number> <message>: <details>`
34#[derive(Debug, Error)]
35pub(crate) enum WebError {
36 /// Error when authentication middleware fails.
37 ///
38 /// This error occurs when there are issues with verifying a user's identity
39 /// through the authentication middleware, such as invalid credentials or
40 /// expired sessions.
41 ///
42 /// **Error Code:** `error-smokesignal-web-1`
43 #[error("error-smokesignal-web-1 Middleware Auth Error: {0:?}")]
44 MiddlewareAuthError(#[from] MiddlewareAuthError),
45
46 /// Error when an unexpected error occurs that isn't covered by other error types.
47 ///
48 /// This error is a fallback for any unhandled errors in the system. In production,
49 /// these should be rare as most errors should be properly typed.
50 ///
51 /// **Error Code:** `error-smokesignal-web-2`
52 ///
53 /// Note: This should be replaced with more specific error types as part of
54 /// the ongoing effort to use typed errors throughout the codebase.
55 #[error("error-smokesignal-web-2 Unhandled web error: {0:?}")]
56 Anyhow(#[from] anyhow::Error),
57
58 /// Common HTTP errors.
59 ///
60 /// This variant wraps errors from the common error module, which contains
61 /// frequently used error types shared across HTTP handlers.
62 #[error(transparent)]
63 Common(#[from] CommonError),
64
65 /// Login-related errors.
66 ///
67 /// This error occurs during login operations, such as invalid credentials,
68 /// account lockouts, or missing account information.
69 #[error(transparent)]
70 Login(#[from] LoginError),
71
72 /// Cache operation errors.
73 ///
74 /// This error occurs when there are issues with cache operations such as
75 /// connection failures or data invalidation problems.
76 #[error(transparent)]
77 Cache(#[from] crate::storage::errors::CacheError),
78
79 /// Configuration errors.
80 ///
81 /// This error occurs when there are issues with application configuration,
82 /// such as missing environment variables or invalid settings.
83 #[error(transparent)]
84 ConfigError(#[from] crate::config_errors::ConfigError),
85
86 /// Database storage errors.
87 ///
88 /// This error occurs when there are issues with database operations,
89 /// such as query failures or transaction issues.
90 #[error(transparent)]
91 StorageError(#[from] crate::storage::errors::StorageError),
92
93 /// Event view errors.
94 ///
95 /// This error occurs when there are issues with retrieving or
96 /// displaying events, such as invalid parameters or missing data.
97 #[error(transparent)]
98 EventViewError(#[from] EventViewError),
99
100 /// Event viewing errors.
101 ///
102 /// This error occurs when there are issues with viewing specific events,
103 /// such as permission problems or invalid event identifiers.
104 #[error(transparent)]
105 ViewEventError(#[from] super::view_event_error::ViewEventError),
106
107 /// Token refresh errors.
108 ///
109 /// This error occurs when there are issues with refreshing authentication
110 /// tokens, such as expired refresh tokens or validation failures.
111 #[error(transparent)]
112 RefreshError(#[from] crate::refresh_tokens_errors::RefreshError),
113
114 /// URL processing errors.
115 ///
116 /// This error occurs when there are issues with URL processing or validation,
117 /// such as malformed URLs or invalid parameters.
118 #[error(transparent)]
119 UrlError(#[from] UrlError),
120
121 /// Import-related errors.
122 ///
123 /// This error occurs when there are issues with importing data into the system,
124 /// such as format incompatibilities or validation failures.
125 #[error(transparent)]
126 ImportError(#[from] ImportError),
127
128 /// Email-related errors.
129 ///
130 /// This error occurs when there are issues with email operations,
131 /// such as template rendering, email sending, or token generation.
132 #[error(transparent)]
133 EmailError(#[from] crate::email_errors::EmailError),
134
135 /// Image processing errors.
136 ///
137 /// This error occurs when there are issues with image operations,
138 /// such as validation, resizing, or format conversion.
139 #[error(transparent)]
140 ImageError(#[from] crate::image_errors::ImageError),
141
142 /// RSVP acceptance errors.
143 ///
144 /// This error occurs when there are issues with the RSVP acceptance workflow,
145 /// such as ticket creation, validation, or record management.
146 #[error(transparent)]
147 AcceptanceError(#[from] AcceptanceError),
148
149 /// Blob and profile handling errors.
150 ///
151 /// This error occurs when there are issues with blob uploads or profile management,
152 /// such as avatar/banner uploads or AT Protocol record operations.
153 #[error(transparent)]
154 BlobError(#[from] BlobError),
155
156 /// Looking For Group (LFG) errors.
157 ///
158 /// This error occurs when there are issues with LFG operations,
159 /// such as creating, viewing, or deactivating LFG records.
160 #[error(transparent)]
161 LfgError(#[from] LfgError),
162
163 /// Share to Bluesky errors.
164 ///
165 /// This error occurs when there are issues with sharing RSVP to Bluesky,
166 /// such as post creation failures or event not found.
167 #[error(transparent)]
168 ShareBlueskyError(#[from] ShareBlueskyError),
169}
170
171/// Implementation of Axum's `IntoResponse` trait for WebError.
172///
173/// This implementation converts errors into appropriate HTTP responses:
174/// - Authentication errors use their specialized response handling
175/// - All other errors are converted to a generic 500 Internal Server Error
176/// and logged with the `tracing` system.
177impl IntoResponse for WebError {
178 fn into_response(self) -> Response {
179 match self {
180 WebError::MiddlewareAuthError(err) => err.into_response(),
181 _ => {
182 tracing::error!(error = ?self, "internal server error");
183 StatusCode::INTERNAL_SERVER_ERROR.into_response()
184 }
185 }
186 }
187}