use actix_web::{HttpResponse, error::ResponseError, http::StatusCode}; use serde::Serialize; use service::error::AppError; pub fn ok_json(data: T) -> Result { Ok(HttpResponse::Ok().json(data)) } pub struct ApiError(pub AppError); impl From for ApiError { fn from(err: AppError) -> Self { ApiError(err) } } impl std::fmt::Display for ApiError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) } } impl std::fmt::Debug for ApiError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) } } impl ResponseError for ApiError { fn status_code(&self) -> StatusCode { match &self.0 { AppError::Unauthorized => StatusCode::UNAUTHORIZED, AppError::UserNotFound => StatusCode::NOT_FOUND, AppError::InvalidPassword => StatusCode::UNAUTHORIZED, AppError::PasswordTooWeak => StatusCode::BAD_REQUEST, AppError::CaptchaError => StatusCode::BAD_REQUEST, AppError::TwoFactorRequired => { StatusCode::from_u16(402).unwrap_or(StatusCode::BAD_REQUEST) } AppError::TwoFactorAlreadyEnabled => StatusCode::CONFLICT, AppError::TwoFactorNotSetup => StatusCode::NOT_FOUND, AppError::InvalidTwoFactorCode => StatusCode::BAD_REQUEST, AppError::TwoFactorNotEnabled => StatusCode::NOT_FOUND, AppError::RsaGenerationError => StatusCode::INTERNAL_SERVER_ERROR, AppError::RsaDecodeError => StatusCode::BAD_REQUEST, AppError::UserNameExists => StatusCode::CONFLICT, AppError::EmailExists => StatusCode::CONFLICT, AppError::AccountAlreadyExists => StatusCode::CONFLICT, AppError::TxnError => StatusCode::INTERNAL_SERVER_ERROR, AppError::PasswordHashError(_) => StatusCode::INTERNAL_SERVER_ERROR, AppError::DatabaseError(_) => StatusCode::INTERNAL_SERVER_ERROR, AppError::DoMainNotSet => StatusCode::INTERNAL_SERVER_ERROR, AppError::InternalError => StatusCode::INTERNAL_SERVER_ERROR, AppError::InternalServerError(_) => { StatusCode::INTERNAL_SERVER_ERROR } AppError::PermissionDenied => StatusCode::FORBIDDEN, AppError::ProjectNotFound => StatusCode::NOT_FOUND, AppError::NoPower => StatusCode::FORBIDDEN, AppError::RoleParseError => StatusCode::BAD_REQUEST, AppError::ProjectNameAlreadyExists => StatusCode::CONFLICT, AppError::RepoNameAlreadyExists => StatusCode::CONFLICT, AppError::AvatarUploadError(_) => StatusCode::BAD_REQUEST, AppError::RepoNotFound => StatusCode::NOT_FOUND, AppError::RepoForBidAccess => StatusCode::FORBIDDEN, AppError::SerdeError(_) => StatusCode::BAD_REQUEST, AppError::Io(_) => StatusCode::INTERNAL_SERVER_ERROR, AppError::BadRequest(_) => StatusCode::BAD_REQUEST, AppError::Forbidden(_) => StatusCode::FORBIDDEN, AppError::Conflict(_) => StatusCode::CONFLICT, AppError::NotFound(_) => StatusCode::NOT_FOUND, AppError::InvalidResetToken => StatusCode::BAD_REQUEST, AppError::ResetTokenExpired => StatusCode::BAD_REQUEST, AppError::ResetTokenUsed => StatusCode::BAD_REQUEST, AppError::IssueNotFound => StatusCode::NOT_FOUND, AppError::LabelNotFound => StatusCode::NOT_FOUND, AppError::MilestoneNotFound => StatusCode::NOT_FOUND, AppError::PullRequestNotFound => StatusCode::NOT_FOUND, AppError::CommentNotFound => StatusCode::NOT_FOUND, AppError::GitRpcError(_) => StatusCode::INTERNAL_SERVER_ERROR, AppError::AiError(_) => StatusCode::INTERNAL_SERVER_ERROR, } } fn error_response(&self) -> HttpResponse { let status = self.status_code(); let message = self.0.to_string(); HttpResponse::build(status) .json(serde_json::json!({ "error": message })) } }