2023-12-11 15:18:43 +00:00
|
|
|
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,
|
2023-12-12 19:37:48 +00:00
|
|
|
#[error("Obsah nesmí mít více než 10000 znaků.")]
|
2023-12-11 15:18:43 +00:00
|
|
|
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),
|
2023-12-12 19:37:48 +00:00
|
|
|
#[error("Žádný takový ban pro tuto IP adresu neexistuje.")]
|
|
|
|
BanNotFound,
|
2023-12-11 15:18:43 +00:00
|
|
|
#[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),
|
2023-12-12 19:37:48 +00:00
|
|
|
#[error("Tento ban už byl odvolán.")]
|
|
|
|
AlreadyAppealedError,
|
|
|
|
#[error("Tento ban nelze odvolat.")]
|
|
|
|
UnappealableError,
|
2023-12-11 15:18:43 +00:00
|
|
|
// 500
|
|
|
|
#[error("Nadnástěnka nebyla inicializována.")]
|
|
|
|
OverboardError,
|
|
|
|
#[error("Server se připojil k 41 procentům.")]
|
|
|
|
InternalError,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<askama::Error> for NekrochanError {
|
|
|
|
fn from(e: askama::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ipnetwork::IpNetworkError> for NekrochanError {
|
|
|
|
fn from(e: ipnetwork::IpNetworkError) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<jsonwebtoken::errors::Error> for NekrochanError {
|
|
|
|
fn from(e: jsonwebtoken::errors::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<pwhash::error::Error> for NekrochanError {
|
|
|
|
fn from(e: pwhash::error::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<fancy_regex::Error> for NekrochanError {
|
|
|
|
fn from(e: fancy_regex::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<redis::RedisError> for NekrochanError {
|
|
|
|
fn from(e: redis::RedisError) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<serde_json::Error> for NekrochanError {
|
|
|
|
fn from(e: serde_json::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<serde_qs::Error> for NekrochanError {
|
|
|
|
fn from(e: serde_qs::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<sqlx::Error> 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,
|
|
|
|
};
|
|
|
|
|
2023-12-11 15:59:32 +00:00
|
|
|
if overboard_err {
|
|
|
|
Self::OverboardError
|
|
|
|
} else {
|
2023-12-11 15:18:43 +00:00
|
|
|
error!("{e:#?}");
|
2023-12-12 17:54:48 +00:00
|
|
|
|
2023-12-11 15:18:43 +00:00
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<std::io::Error> for NekrochanError {
|
|
|
|
fn from(e: std::io::Error) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<std::net::AddrParseError> for NekrochanError {
|
|
|
|
fn from(e: std::net::AddrParseError) -> Self {
|
|
|
|
error!("Internal server error: {e:#?}");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<std::sync::PoisonError<T>> for NekrochanError {
|
|
|
|
fn from(_: std::sync::PoisonError<T>) -> Self {
|
|
|
|
error!("CAPTCHA RwLock got poisoned or something.");
|
|
|
|
|
|
|
|
Self::InternalError
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<tokio::task::JoinError> 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 {
|
2023-12-12 19:37:48 +00:00
|
|
|
NekrochanError::FileError(_, _)
|
|
|
|
| NekrochanError::UsernameFormatError
|
|
|
|
| NekrochanError::PasswordFormatError
|
|
|
|
| NekrochanError::IdFormatError
|
|
|
|
| NekrochanError::BoardNameFormatError
|
|
|
|
| NekrochanError::DescriptionFormatError
|
|
|
|
| NekrochanError::PostNameFormatError
|
|
|
|
| NekrochanError::CapcodeFormatError
|
|
|
|
| NekrochanError::EmailFormatError
|
|
|
|
| NekrochanError::ContentFormatError
|
|
|
|
| NekrochanError::ReplyReplyError
|
|
|
|
| NekrochanError::NoContentError
|
|
|
|
| NekrochanError::NoFileError
|
|
|
|
| NekrochanError::EmptyPostError
|
|
|
|
| NekrochanError::RequiredCaptchaError
|
|
|
|
| NekrochanError::SolvedCaptchaError
|
|
|
|
| NekrochanError::NoPostsError
|
|
|
|
| NekrochanError::FileLimitError(_)
|
|
|
|
| NekrochanError::AlreadyAppealedError
|
|
|
|
| NekrochanError::UnappealableError => StatusCode::BAD_REQUEST,
|
|
|
|
NekrochanError::BoardNotFound(_)
|
|
|
|
| NekrochanError::AccountNotFound(_)
|
|
|
|
| NekrochanError::PostNotFound(_, _)
|
|
|
|
| NekrochanError::BanNotFound
|
|
|
|
| NekrochanError::InvalidPageError
|
|
|
|
| NekrochanError::InvalidAuthError => StatusCode::NOT_FOUND,
|
|
|
|
NekrochanError::InsufficientPermissionError
|
|
|
|
| NekrochanError::ReplyLimitError
|
|
|
|
| NekrochanError::ThreadLockError
|
|
|
|
| NekrochanError::BoardLockError(_)
|
|
|
|
| NekrochanError::OwnerDeletionError => StatusCode::FORBIDDEN,
|
|
|
|
NekrochanError::IncorrectCredentialError
|
|
|
|
| NekrochanError::NotLoggedInError
|
|
|
|
| NekrochanError::IncorrectCaptchaError
|
|
|
|
| NekrochanError::IncorrectPasswordError(_) => StatusCode::UNAUTHORIZED,
|
2023-12-11 15:18:43 +00:00
|
|
|
NekrochanError::HeaderError(_) => StatusCode::BAD_GATEWAY,
|
2023-12-12 19:37:48 +00:00
|
|
|
NekrochanError::OverboardError | NekrochanError::InternalError => {
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR
|
|
|
|
}
|
2023-12-11 15:18:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|