v0.1.0:24 — Keysat licensing service end-to-end
Daemon, StartOS wrapper, admin SPA, public buy/thank-you pages, discount codes, free-license redemption, Apply-discount UX, self-licensing, and v0.1.0 release notes.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
//! Unified error type for the service. Converts into appropriate HTTP
|
||||
//! responses so handlers can just `?`-propagate.
|
||||
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response},
|
||||
Json,
|
||||
};
|
||||
use serde_json::json;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AppError {
|
||||
#[error("not found: {0}")]
|
||||
NotFound(String),
|
||||
|
||||
#[error("bad request: {0}")]
|
||||
BadRequest(String),
|
||||
|
||||
#[error("unauthorized")]
|
||||
Unauthorized,
|
||||
|
||||
#[error("forbidden")]
|
||||
Forbidden,
|
||||
|
||||
#[error("conflict: {0}")]
|
||||
Conflict(String),
|
||||
|
||||
#[error("license invalid: {0}")]
|
||||
LicenseInvalid(String),
|
||||
|
||||
#[error("upstream error: {0}")]
|
||||
Upstream(String),
|
||||
|
||||
#[error("BTCPay not configured: connect via the StartOS dashboard first")]
|
||||
BtcpayNotConfigured,
|
||||
|
||||
#[error("database error: {0}")]
|
||||
Database(#[from] sqlx::Error),
|
||||
|
||||
#[error("internal error: {0}")]
|
||||
Internal(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
let (status, code) = match &self {
|
||||
AppError::NotFound(_) => (StatusCode::NOT_FOUND, "not_found"),
|
||||
AppError::BadRequest(_) => (StatusCode::BAD_REQUEST, "bad_request"),
|
||||
AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "unauthorized"),
|
||||
AppError::Forbidden => (StatusCode::FORBIDDEN, "forbidden"),
|
||||
AppError::Conflict(_) => (StatusCode::CONFLICT, "conflict"),
|
||||
AppError::LicenseInvalid(_) => (StatusCode::OK, "invalid"),
|
||||
AppError::Upstream(_) => (StatusCode::BAD_GATEWAY, "upstream_error"),
|
||||
AppError::BtcpayNotConfigured => (StatusCode::SERVICE_UNAVAILABLE, "btcpay_not_configured"),
|
||||
AppError::Database(_) | AppError::Internal(_) => {
|
||||
tracing::error!(error = %self, "internal error");
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "internal_error")
|
||||
}
|
||||
};
|
||||
|
||||
let body = Json(json!({
|
||||
"ok": false,
|
||||
"error": code,
|
||||
"message": self.to_string(),
|
||||
}));
|
||||
|
||||
(status, body).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
pub type AppResult<T> = Result<T, AppError>;
|
||||
Reference in New Issue
Block a user