use actix_web::{http::StatusCode, ResponseError}; use log::error; use thiserror::Error; #[derive(Error, Debug)] pub enum NekrochanError { #[error("Chyba při zpracovávání souboru '{}': {}", .0, .1)] FileError(String, &'static str), #[error("Uživatelské jméno musí mít 1-32 znaků.")] UsernameFormatError, #[error("Heslo musí mít alespoň 8 znaků.")] PasswordFormatError, #[error("ID musí mít 1-16 znaků.")] IdFormatError, #[error("Jméno nástěnky musí mít 1-32 znaků.")] BoardNameFormatError, #[error("Popis musí mít 1-128 znaků.")] DescriptionFormatError, #[error("Jméno nesmí mít více než 32 znaků.")] PostNameFormatError, #[error("Capcode nesmí mít více než 32 znaků.")] CapcodeFormatError, #[error("E-mail nesmí mít více než 256 znaků.")] EmailFormatError, #[error("Obsah nesmí mít více než 4000 znaků")] ContentFormatError, #[error("Nástěnka /{}/ neexistuje.", .0)] BoardNotFound(String), #[error("Účet '{}' neexistuje.", .0)] AccountNotFound(String), #[error("Příspěvek /{}/{} neexistuje.", .0, .1)] PostNotFound(String, i32), #[error("Nedostatečná oprávnění.")] InsufficientPermissionError, #[error("Nesprávné přihlašovací údaje.")] IncorrectCredentialError, #[error("Neplatná strana.")] InvalidPageError, #[error("Neplatný autentizační token. Vymaž soubory cookie.")] InvalidAuthError, #[error("Pro přístup se musíš přihlásit.")] NotLoggedInError, #[error("Účet vlastníka nemůže být vymazán.")] OwnerDeletionError, #[error("Reverzní proxy nevrátilo vyžadovanou hlavičku '{}'.", .0)] HeaderError(&'static str), #[error("Nástěnka /{}/ je uzamčená.", .0)] BoardLockError(String), #[error("Toto vlákno je uzamčené.")] ThreadLockError, #[error("Nelze vytvořit odpověď na odpověď.")] ReplyReplyError, #[error("Vlákno dosáhlo limitu odpovědí.")] ReplyLimitError, #[error("Příspěvek musí mít obsah.")] NoContentError, #[error("Příspěvek musí mít soubor.")] NoFileError, #[error("Příspěvek musí mít obsah nebo soubor.")] EmptyPostError, #[error("Na této nástěnce se musí vyplnit CAPTCHA.")] RequiredCaptchaError, #[error("Nesprávné řešení CAPTCHA.")] IncorrectCaptchaError, #[error("Tato CAPTCHA neexistuje nebo už byla vyřešena.")] SolvedCaptchaError, #[error("Nebyly vybrány žádné příspěvky.")] NoPostsError, #[error("Maximální počet souborů na této nástěnce je {}.", .0)] FileLimitError(usize), #[error("Nesprávné heslo pro příspěvek #{}.", .0)] IncorrectPasswordError(i32), // 500 #[error("Nadnástěnka nebyla inicializována.")] OverboardError, #[error("Server se připojil k 41 procentům.")] InternalError, } impl From for NekrochanError { fn from(e: askama::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: ipnetwork::IpNetworkError) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: jsonwebtoken::errors::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: pwhash::error::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: fancy_regex::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: redis::RedisError) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: serde_json::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: serde_qs::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: sqlx::Error) -> Self { let overboard_err = match e.as_database_error() { Some(e) => e.message() == "relation \"overboard\" does not exist", None => false, }; if !overboard_err { error!("{e:#?}"); Self::InternalError } else { Self::OverboardError } } } impl From for NekrochanError { fn from(e: std::io::Error) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From for NekrochanError { fn from(e: std::net::AddrParseError) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl From> for NekrochanError { fn from(_: std::sync::PoisonError) -> Self { error!("CAPTCHA RwLock got poisoned or something."); Self::InternalError } } impl From for NekrochanError { fn from(e: tokio::task::JoinError) -> Self { error!("Internal server error: {e:#?}"); Self::InternalError } } impl ResponseError for NekrochanError { fn status_code(&self) -> StatusCode { match self { NekrochanError::FileError(_, _) => StatusCode::BAD_REQUEST, NekrochanError::UsernameFormatError => StatusCode::BAD_REQUEST, NekrochanError::PasswordFormatError => StatusCode::BAD_REQUEST, NekrochanError::IdFormatError => StatusCode::BAD_REQUEST, NekrochanError::BoardNameFormatError => StatusCode::BAD_REQUEST, NekrochanError::DescriptionFormatError => StatusCode::BAD_REQUEST, NekrochanError::PostNameFormatError => StatusCode::BAD_REQUEST, NekrochanError::CapcodeFormatError => StatusCode::BAD_REQUEST, NekrochanError::EmailFormatError => StatusCode::BAD_REQUEST, NekrochanError::ContentFormatError => StatusCode::BAD_REQUEST, NekrochanError::BoardNotFound(_) => StatusCode::NOT_FOUND, NekrochanError::AccountNotFound(_) => StatusCode::NOT_FOUND, NekrochanError::PostNotFound(_, _) => StatusCode::NOT_FOUND, NekrochanError::InsufficientPermissionError => StatusCode::FORBIDDEN, NekrochanError::IncorrectCredentialError => StatusCode::UNAUTHORIZED, NekrochanError::InvalidPageError => StatusCode::NOT_FOUND, NekrochanError::InvalidAuthError => StatusCode::NOT_FOUND, NekrochanError::NotLoggedInError => StatusCode::UNAUTHORIZED, NekrochanError::OwnerDeletionError => StatusCode::FORBIDDEN, NekrochanError::HeaderError(_) => StatusCode::BAD_GATEWAY, NekrochanError::BoardLockError(_) => StatusCode::FORBIDDEN, NekrochanError::ThreadLockError => StatusCode::FORBIDDEN, NekrochanError::ReplyReplyError => StatusCode::BAD_REQUEST, NekrochanError::ReplyLimitError => StatusCode::FORBIDDEN, NekrochanError::NoContentError => StatusCode::BAD_REQUEST, NekrochanError::NoFileError => StatusCode::BAD_REQUEST, NekrochanError::EmptyPostError => StatusCode::BAD_REQUEST, NekrochanError::RequiredCaptchaError => StatusCode::BAD_REQUEST, NekrochanError::IncorrectCaptchaError => StatusCode::UNAUTHORIZED, NekrochanError::SolvedCaptchaError => StatusCode::BAD_REQUEST, NekrochanError::NoPostsError => StatusCode::BAD_REQUEST, NekrochanError::FileLimitError(_) => StatusCode::BAD_REQUEST, NekrochanError::IncorrectPasswordError(_) => StatusCode::UNAUTHORIZED, NekrochanError::OverboardError => StatusCode::INTERNAL_SERVER_ERROR, NekrochanError::InternalError => StatusCode::INTERNAL_SERVER_ERROR, } } }