use git::GitError; #[derive(Debug)] pub enum AppError { UserNotFound, RsaGenerationError, RsaDecodeError, CaptchaError, TwoFactorRequired, Unauthorized, DoMainNotSet, UserNameExists, EmailExists, TxnError, PasswordHashError(String), TwoFactorAlreadyEnabled, TwoFactorNotSetup, InvalidTwoFactorCode, TwoFactorNotEnabled, DatabaseError(String), InvalidPassword, ProjectNotFound, NoPower, InternalError, NotFound(String), RoleParseError, ProjectNameAlreadyExists, RepoNameAlreadyExists, AvatarUploadError(String), InternalServerError(String), PermissionDenied, RepoNotFound, RepoForBidAccess, GitError(GitError), SerdeError(serde_json::Error), Io(std::io::Error), BadRequest(String), Forbidden(String), WorkspaceNotFound, WorkspaceSlugAlreadyExists, WorkspaceNameAlreadyExists, NotWorkspaceMember, WorkspaceInviteTokenInvalid, WorkspaceInviteExpired, WorkspaceInviteAlreadyAccepted, Conflict(String), } impl AppError { pub const fn code(&self) -> i32 { use AppError::*; match self { BadRequest(_) => 40000, CaptchaError => 40001, SerdeError(_) => 40002, RsaDecodeError => 40003, RoleParseError => 40004, TwoFactorNotSetup => 40005, TwoFactorNotEnabled => 40006, Unauthorized => 40101, InvalidTwoFactorCode => 40102, InvalidPassword => 40103, NoPower => 40301, PermissionDenied => 40302, Forbidden(_) => 40304, RepoForBidAccess => 40303, NotFound(_) => 40401, UserNotFound => 40402, ProjectNotFound => 40403, RepoNotFound => 40404, UserNameExists => 40901, EmailExists => 40902, ProjectNameAlreadyExists => 40903, RepoNameAlreadyExists => 40905, TwoFactorAlreadyEnabled => 40904, TwoFactorRequired => 42801, DoMainNotSet => 50001, TxnError => 50002, RsaGenerationError => 50003, PasswordHashError(_) => 50004, DatabaseError(_) => 50005, GitError(_) => 50006, Io(_) => 50007, InternalError => 50008, InternalServerError(_) => 50009, AvatarUploadError(_) => 50010, WorkspaceNotFound => 40405, WorkspaceSlugAlreadyExists => 40906, WorkspaceNameAlreadyExists => 40907, NotWorkspaceMember => 40305, WorkspaceInviteTokenInvalid => 40006, WorkspaceInviteExpired => 40007, WorkspaceInviteAlreadyAccepted => 40908, Conflict(_) => 40909, } } pub const fn http_status_code(&self) -> u16 { use AppError::*; match self { BadRequest(_) => 400, CaptchaError => 400, SerdeError(_) => 400, RsaDecodeError => 400, RoleParseError => 400, TwoFactorNotSetup => 400, TwoFactorNotEnabled => 400, WorkspaceInviteTokenInvalid => 400, WorkspaceInviteExpired => 400, Unauthorized => 401, InvalidTwoFactorCode => 401, InvalidPassword => 401, NoPower => 403, PermissionDenied => 403, Forbidden(_) => 403, RepoForBidAccess => 403, NotWorkspaceMember => 403, NotFound(_) => 404, UserNotFound => 404, ProjectNotFound => 404, RepoNotFound => 404, WorkspaceNotFound => 404, UserNameExists => 409, EmailExists => 409, ProjectNameAlreadyExists => 409, RepoNameAlreadyExists => 409, TwoFactorAlreadyEnabled => 409, WorkspaceSlugAlreadyExists => 409, WorkspaceNameAlreadyExists => 409, WorkspaceInviteAlreadyAccepted => 409, Conflict(_) => 409, TwoFactorRequired => 428, DoMainNotSet => 500, TxnError => 500, RsaGenerationError => 500, PasswordHashError(_) => 500, DatabaseError(_) => 500, GitError(_) => 500, Io(_) => 500, InternalError => 500, InternalServerError(_) => 500, AvatarUploadError(_) => 500, } } pub const fn slug(&self) -> &'static str { use AppError::*; match self { Unauthorized => "unauthorized", UserNotFound => "user_not_found", ProjectNotFound => "project_not_found", RepoNotFound => "repo_not_found", NotFound(_) => "not_found", TwoFactorRequired => "two_factor_required", UserNameExists => "username_exists", EmailExists => "email_exists", ProjectNameAlreadyExists => "project_name_exists", RepoNameAlreadyExists => "repo_name_exists", CaptchaError => "captcha_error", BadRequest(_) => "bad_request", SerdeError(_) => "serde_error", RsaDecodeError => "rsa_decode_error", RoleParseError => "role_parse_error", TwoFactorNotSetup => "two_factor_not_setup", TwoFactorNotEnabled => "two_factor_not_enabled", InvalidTwoFactorCode => "invalid_two_factor_code", InvalidPassword => "invalid_password", NoPower => "no_power", PermissionDenied => "permission_denied", Forbidden(_) => "forbidden", RepoForBidAccess => "repo_forbidden", TwoFactorAlreadyEnabled => "two_factor_already_enabled", WorkspaceNotFound => "workspace_not_found", WorkspaceSlugAlreadyExists => "workspace_slug_exists", WorkspaceNameAlreadyExists => "workspace_name_exists", NotWorkspaceMember => "not_workspace_member", WorkspaceInviteTokenInvalid => "workspace_invite_token_invalid", WorkspaceInviteExpired => "workspace_invite_expired", WorkspaceInviteAlreadyAccepted => "workspace_invite_already_accepted", Conflict(_) => "conflict", DoMainNotSet => "domain_not_set", TxnError => "transaction_error", RsaGenerationError => "rsa_generation_error", PasswordHashError(_) => "password_hash_error", DatabaseError(_) => "database_error", GitError(_) => "git_error", Io(_) => "io_error", InternalError => "internal_error", InternalServerError(_) => "internal_server_error", AvatarUploadError(_) => "avatar_upload_error", } } pub fn user_message(&self) -> String { match self { AppError::NotFound(s) => s.clone(), AppError::BadRequest(s) => s.clone(), AppError::Forbidden(s) => s.clone(), AppError::DatabaseError(_) => "A database error occurred".to_string(), AppError::PasswordHashError(_) => "A password processing error occurred".to_string(), AppError::GitError(_) => "A git operation failed".to_string(), AppError::SerdeError(_) => "A data parsing error occurred".to_string(), AppError::Io(_) => "A file system error occurred".to_string(), AppError::InternalServerError(_) => "An internal error occurred".to_string(), AppError::AvatarUploadError(_) => "An avatar upload error occurred".to_string(), AppError::Conflict(_) => "Resource conflict".to_string(), _ => self.slug().to_string(), } } } impl From for AppError { fn from(value: argon2::password_hash::Error) -> Self { AppError::PasswordHashError(value.to_string()) } } impl From for AppError { fn from(value: sea_orm::error::DbErr) -> Self { AppError::DatabaseError(value.to_string()) } } impl From for AppError { fn from(value: GitError) -> Self { AppError::GitError(value) } } impl From for AppError { fn from(value: serde_json::Error) -> Self { AppError::SerdeError(value) } } impl From for AppError { fn from(value: std::io::Error) -> Self { AppError::Io(value) } } impl From for AppError { fn from(value: anyhow::Error) -> Self { AppError::InternalServerError(value.to_string()) } } impl From for AppError { fn from(err: room::RoomError) -> Self { use room::RoomError; match err { RoomError::Database(e) => { println!("database error: {}", e); AppError::DatabaseError(e.to_string()) } RoomError::NotFound(s) => AppError::NotFound(s), RoomError::Unauthorized => AppError::Unauthorized, RoomError::NoPower => AppError::NoPower, RoomError::RateLimited(s) => AppError::BadRequest(s), RoomError::BadRequest(s) => AppError::BadRequest(s), RoomError::RoleParseError => AppError::RoleParseError, RoomError::Internal(s) => AppError::InternalServerError(s), } } }