shared/error/
service.rs

1use crate::error::TransientError;
2use serde::{Deserialize, Serialize};
3use strum_macros::Display;
4use thiserror::Error;
5
6#[cfg(feature = "backend")]
7use actix_web::{body::BoxBody, HttpResponse, ResponseError};
8
9#[allow(missing_docs)]
10#[derive(Debug, Error, Serialize, Deserialize)]
11pub enum ServiceError {
12    #[cfg_attr(feature = "backend", error(transparent))]
13    #[cfg_attr(not(feature = "backend"), error("Internal server error"))]
14    InternalServerError(
15        #[serde(skip)]
16        #[from]
17        TransientError<anyhow::Error>,
18    ),
19    #[error("{0}")]
20    DisabledService(ServiceKindError),
21    #[error("Forbidden")]
22    Forbidden,
23    #[error("Resource not found")]
24    ResourceNotFound,
25}
26
27#[cfg(feature = "backend")]
28impl ResponseError for ServiceError {
29    fn status_code(&self) -> http::StatusCode {
30        match self {
31            Self::InternalServerError { .. } => http::StatusCode::INTERNAL_SERVER_ERROR,
32            Self::DisabledService(_) => http::StatusCode::NOT_IMPLEMENTED,
33            Self::Forbidden => http::StatusCode::FORBIDDEN,
34            Self::ResourceNotFound => http::StatusCode::NOT_FOUND,
35        }
36    }
37
38    fn error_response(&self) -> HttpResponse<BoxBody> {
39        HttpResponse::build(self.status_code()).json(self)
40    }
41}
42
43impl From<anyhow::Error> for ServiceError {
44    fn from(e: anyhow::Error) -> Self {
45        Self::InternalServerError(e.into())
46    }
47}
48
49#[allow(missing_docs)]
50#[derive(Debug, Copy, Clone, Display, Serialize, Deserialize)]
51pub enum ServiceKindError {
52    #[strum(serialize = "Algolia")]
53    Algolia,
54    #[strum(serialize = "S3")]
55    S3,
56    #[strum(serialize = "Google Cloud Storage")]
57    GoogleCloudStorage,
58    #[strum(serialize = "Google Cloud EventArc")]
59    GoogleCloudEventArc,
60    #[strum(serialize = "Google OAuth")]
61    GoogleOAuth,
62    #[strum(serialize = "Google Cloud Access Key Store")]
63    GoogleCloudAccessKeyStore,
64    #[strum(serialize = "Sendgrid Mail")]
65    Mail,
66    #[strum(serialize = "Firebase Cloud Messaging")]
67    FirebaseCloudMessaging,
68    #[strum(serialize = "Media Upload Cleaner")]
69    UploadCleaner,
70    #[strum(serialize = "Google Translate")]
71    GoogleTranslate,
72    #[strum(serialize = "Stripe")]
73    Stripe,
74}
75
76#[cfg(feature = "backend")]
77impl ResponseError for ServiceKindError {
78    fn status_code(&self) -> http::StatusCode {
79        http::StatusCode::NOT_IMPLEMENTED
80    }
81
82    fn error_response(&self) -> HttpResponse<BoxBody> {
83        HttpResponse::build(self.status_code()).json(self)
84    }
85}