use std::fmt; #[derive(Debug)] pub enum AppError { UserNotFound, RsaGenerationError, RsaDecodeError, CaptchaError, TwoFactorRequired, Unauthorized, DoMainNotSet, UserNameExists, EmailExists, AccountAlreadyExists, TxnError, PasswordHashError(String), TwoFactorAlreadyEnabled, TwoFactorNotSetup, InvalidTwoFactorCode, TwoFactorNotEnabled, DatabaseError(String), InvalidPassword, PasswordTooWeak, ProjectNotFound, NoPower, InternalError, NotFound(String), RoleParseError, ProjectNameAlreadyExists, RepoNameAlreadyExists, AvatarUploadError(String), InternalServerError(String), PermissionDenied, RepoNotFound, RepoForBidAccess, SerdeError(serde_json::Error), Io(std::io::Error), BadRequest(String), Forbidden(String), Conflict(String), InvalidResetToken, ResetTokenExpired, ResetTokenUsed, IssueNotFound, LabelNotFound, MilestoneNotFound, PullRequestNotFound, CommentNotFound, GitRpcError(String), AiError(ai::error::AiError), } impl fmt::Display for AppError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { AppError::UserNotFound => write!(f, "user not found"), AppError::RsaGenerationError => { write!(f, "RSA key generation failed") } AppError::RsaDecodeError => write!(f, "RSA decode failed"), AppError::CaptchaError => write!(f, "captcha verification failed"), AppError::TwoFactorRequired => { write!(f, "two-factor authentication required") } AppError::Unauthorized => write!(f, "unauthorized"), AppError::DoMainNotSet => write!(f, "domain not configured"), AppError::UserNameExists => write!(f, "username already exists"), AppError::EmailExists => write!(f, "email already exists"), AppError::AccountAlreadyExists => { write!(f, "account already exists") } AppError::TxnError => write!(f, "transaction error"), AppError::PasswordHashError(e) => { write!(f, "password hash error: {}", e) } AppError::TwoFactorAlreadyEnabled => { write!(f, "two-factor already enabled") } AppError::TwoFactorNotSetup => write!(f, "two-factor not setup"), AppError::InvalidTwoFactorCode => { write!(f, "invalid two-factor code") } AppError::TwoFactorNotEnabled => { write!(f, "two-factor not enabled") } AppError::DatabaseError(e) => write!(f, "database error: {}", e), AppError::InvalidPassword => write!(f, "invalid password"), AppError::PasswordTooWeak => write!(f, "password too weak"), AppError::ProjectNotFound => write!(f, "project not found"), AppError::NoPower => write!(f, "permission denied"), AppError::InternalError => write!(f, "internal error"), AppError::NotFound(msg) => write!(f, "not found: {}", msg), AppError::RoleParseError => write!(f, "role parse error"), AppError::ProjectNameAlreadyExists => { write!(f, "project name already exists") } AppError::RepoNameAlreadyExists => { write!(f, "repo name already exists") } AppError::AvatarUploadError(e) => { write!(f, "avatar upload error: {}", e) } AppError::InternalServerError(e) => { write!(f, "internal server error: {}", e) } AppError::PermissionDenied => write!(f, "permission denied"), AppError::RepoNotFound => write!(f, "repo not found"), AppError::RepoForBidAccess => write!(f, "repo access forbidden"), AppError::SerdeError(e) => write!(f, "serde error: {}", e), AppError::Io(e) => write!(f, "IO error: {}", e), AppError::BadRequest(msg) => write!(f, "bad request: {}", msg), AppError::Forbidden(msg) => write!(f, "forbidden: {}", msg), AppError::Conflict(msg) => write!(f, "conflict: {}", msg), AppError::InvalidResetToken => write!(f, "invalid reset token"), AppError::ResetTokenExpired => write!(f, "reset token expired"), AppError::ResetTokenUsed => write!(f, "reset token already used"), AppError::IssueNotFound => write!(f, "issue not found"), AppError::LabelNotFound => write!(f, "label not found"), AppError::MilestoneNotFound => write!(f, "milestone not found"), AppError::PullRequestNotFound => { write!(f, "pull request not found") } AppError::CommentNotFound => write!(f, "comment not found"), AppError::GitRpcError(e) => write!(f, "git rpc error: {}", e), AppError::AiError(e) => write!(f, "ai error: {}", e), } } } impl std::error::Error for AppError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { AppError::SerdeError(e) => Some(e), AppError::Io(e) => Some(e), AppError::AiError(e) => Some(e), _ => None, } } } impl From for AppError { fn from(e: ai::error::AiError) -> Self { AppError::AiError(e) } }