4e2c1c932a
- Added actix-web and actix-multipart dependencies to Cargo.toml - Integrated actix-web ResponseError trait for AppError handling - Migrated session module to use actix-web request lifecycle management - Enhanced Session struct with request-local state handling capabilities - Implemented proper HTTP status code mapping for various error types - Added comprehensive session middleware integration points - Updated session state persistence and modification tracking logic - Integrated proper JSON response formatting for error messages - Added support for session renewal, purge, and unchanged state management
149 lines
3.9 KiB
Rust
149 lines
3.9 KiB
Rust
use actix_web::HttpResponse;
|
|
use thiserror::Error;
|
|
|
|
pub type AppResult<T> = Result<T, AppError>;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum AppError {
|
|
#[error("config error: {0}")]
|
|
Config(String),
|
|
|
|
#[error("database error: {0}")]
|
|
Database(#[from] sqlx::Error),
|
|
|
|
#[error("redis error: {0}")]
|
|
Redis(#[from] redis::RedisError),
|
|
|
|
#[error("r2d2 error: {0}")]
|
|
R2d2(#[from] r2d2::Error),
|
|
|
|
#[error("json error: {0}")]
|
|
Json(#[from] serde_json::Error),
|
|
|
|
#[error("io error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("storage error: {0}")]
|
|
Storage(#[from] object_store::Error),
|
|
|
|
#[error("parse error: {0}")]
|
|
Parse(String),
|
|
|
|
#[error("user not found")]
|
|
UserNotFound,
|
|
|
|
#[error("password too weak")]
|
|
PasswordTooWeak,
|
|
|
|
#[error("password hash error: {0}")]
|
|
PasswordHashError(String),
|
|
|
|
#[error("invalid password")]
|
|
InvalidPassword,
|
|
|
|
#[error("account already exists")]
|
|
AccountAlreadyExists,
|
|
|
|
#[error("captcha error")]
|
|
CaptchaError,
|
|
|
|
#[error("rsa key generation failed")]
|
|
RsaGenerationError,
|
|
|
|
#[error("rsa decode error")]
|
|
RsaDecodeError,
|
|
|
|
#[error("invalid two-factor code")]
|
|
InvalidTwoFactorCode,
|
|
|
|
#[error("two-factor authentication required")]
|
|
TwoFactorRequired,
|
|
|
|
#[error("two-factor already enabled")]
|
|
TwoFactorAlreadyEnabled,
|
|
|
|
#[error("two-factor not set up")]
|
|
TwoFactorNotSetup,
|
|
|
|
#[error("two-factor not enabled")]
|
|
TwoFactorNotEnabled,
|
|
|
|
#[error("invalid reset token")]
|
|
InvalidResetToken,
|
|
|
|
#[error("reset token expired")]
|
|
ResetTokenExpired,
|
|
|
|
#[error("email already exists")]
|
|
EmailExists,
|
|
|
|
#[error("invalid email code")]
|
|
InvalidEmailCode,
|
|
|
|
#[error("unauthorized")]
|
|
Unauthorized,
|
|
|
|
#[error("forbidden: {0}")]
|
|
Forbidden(String),
|
|
|
|
#[error("bad request: {0}")]
|
|
BadRequest(String),
|
|
|
|
#[error("conflict: {0}")]
|
|
Conflict(String),
|
|
|
|
#[error("quota exceeded: {0}")]
|
|
QuotaExceeded(String),
|
|
|
|
#[error("not found: {0}")]
|
|
NotFound(String),
|
|
|
|
#[error("internal server error: {0}")]
|
|
InternalServerError(String),
|
|
|
|
#[error("transaction error")]
|
|
TxnError,
|
|
}
|
|
|
|
impl actix_web::ResponseError for AppError {
|
|
fn status_code(&self) -> actix_web::http::StatusCode {
|
|
use actix_web::http::StatusCode;
|
|
match self {
|
|
AppError::Unauthorized => StatusCode::UNAUTHORIZED,
|
|
AppError::Forbidden(_) => StatusCode::FORBIDDEN,
|
|
AppError::NotFound(_) | AppError::UserNotFound => StatusCode::NOT_FOUND,
|
|
AppError::BadRequest(_) | AppError::Parse(_) | AppError::CaptchaError => {
|
|
StatusCode::BAD_REQUEST
|
|
}
|
|
AppError::Conflict(_) | AppError::AccountAlreadyExists | AppError::EmailExists => {
|
|
StatusCode::CONFLICT
|
|
}
|
|
AppError::QuotaExceeded(_) => StatusCode::TOO_MANY_REQUESTS,
|
|
AppError::InvalidPassword
|
|
| AppError::PasswordTooWeak
|
|
| AppError::InvalidTwoFactorCode
|
|
| AppError::TwoFactorRequired
|
|
| AppError::TwoFactorAlreadyEnabled
|
|
| AppError::TwoFactorNotSetup
|
|
| AppError::TwoFactorNotEnabled
|
|
| AppError::InvalidResetToken
|
|
| AppError::ResetTokenExpired
|
|
| AppError::InvalidEmailCode
|
|
| AppError::RsaDecodeError
|
|
| AppError::RsaGenerationError => StatusCode::BAD_REQUEST,
|
|
AppError::PasswordHashError(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
|
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
|
}
|
|
}
|
|
|
|
fn error_response(&self) -> HttpResponse {
|
|
let status = self.status_code();
|
|
let message = if status == actix_web::http::StatusCode::INTERNAL_SERVER_ERROR {
|
|
"internal server error".to_string()
|
|
} else {
|
|
self.to_string()
|
|
};
|
|
HttpResponse::build(status).json(serde_json::json!({ "error": message }))
|
|
}
|
|
}
|