You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.6 KiB
Rust
126 lines
3.6 KiB
Rust
use actix_web::{
|
|
body::BoxBody,
|
|
http::{header, StatusCode},
|
|
HttpResponse, ResponseError,
|
|
};
|
|
use serde::{ser::SerializeMap, Serialize, Serializer};
|
|
use std::{fmt, io};
|
|
|
|
use crate::util::{crypto, validate};
|
|
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
BadBearcap,
|
|
BadCredentials,
|
|
BadRequest,
|
|
BadSignature,
|
|
BadToken(jsonwebtoken::errors::Error),
|
|
Crypto(crypto::Error),
|
|
Database(sqlx::Error),
|
|
Invalid(validate::Error),
|
|
Io(io::Error),
|
|
MalformedApub(String),
|
|
MalformedHeader(header::ToStrError),
|
|
NotFound,
|
|
Reqwest(reqwest::Error),
|
|
}
|
|
|
|
impl ResponseError for Error {
|
|
fn status_code(&self) -> StatusCode {
|
|
match self {
|
|
Error::BadBearcap => StatusCode::UNPROCESSABLE_ENTITY,
|
|
Error::BadCredentials => StatusCode::UNAUTHORIZED,
|
|
Error::BadRequest => StatusCode::BAD_REQUEST,
|
|
Error::BadSignature => StatusCode::UNAUTHORIZED,
|
|
Error::BadToken(_) => StatusCode::UNAUTHORIZED,
|
|
Error::Invalid(_) => StatusCode::UNPROCESSABLE_ENTITY,
|
|
Error::MalformedApub(_) => StatusCode::UNPROCESSABLE_ENTITY,
|
|
Error::MalformedHeader(_) => StatusCode::BAD_REQUEST,
|
|
Error::NotFound => StatusCode::NOT_FOUND,
|
|
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
|
}
|
|
}
|
|
|
|
fn error_response(&self) -> HttpResponse<BoxBody> {
|
|
HttpResponse::build(self.status_code()).json(self)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Error::BadBearcap => write!(f, "Invalid bearcap URL"),
|
|
Error::BadCredentials => write!(f, "Invalid user name or password"),
|
|
Error::BadRequest => write!(f, "Bad request"),
|
|
Error::BadSignature => write!(f, "Bad signature"),
|
|
Error::BadToken(jwt_error) => jwt_error.fmt(f),
|
|
Error::Crypto(crypto_error) => crypto_error.fmt(f),
|
|
Error::Database(sqlx_error) => sqlx_error.fmt(f),
|
|
Error::Invalid(validate_error) => validate_error.fmt(f),
|
|
Error::Io(io_error) => io_error.fmt(f),
|
|
Error::NotFound => write!(f, "Not found"),
|
|
Error::MalformedApub(msg) => write!(f, "Malformed ActivityPub: {msg}"),
|
|
Error::MalformedHeader(to_str_error) => to_str_error.fmt(f),
|
|
Error::Reqwest(reqwest_error) => reqwest_error.fmt(f),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<sqlx::Error> for Error {
|
|
fn from(e: sqlx::Error) -> Error {
|
|
match e {
|
|
sqlx::Error::RowNotFound => Error::NotFound,
|
|
_ => Error::Database(e),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<io::Error> for Error {
|
|
fn from(e: io::Error) -> Error {
|
|
Error::Io(e)
|
|
}
|
|
}
|
|
|
|
impl From<validate::Error> for Error {
|
|
fn from(e: validate::Error) -> Error {
|
|
Error::Invalid(e)
|
|
}
|
|
}
|
|
|
|
impl From<header::ToStrError> for Error {
|
|
fn from(e: header::ToStrError) -> Error {
|
|
Error::MalformedHeader(e)
|
|
}
|
|
}
|
|
|
|
impl From<jsonwebtoken::errors::Error> for Error {
|
|
fn from(e: jsonwebtoken::errors::Error) -> Error {
|
|
Error::BadToken(e)
|
|
}
|
|
}
|
|
|
|
impl From<reqwest::Error> for Error {
|
|
fn from(e: reqwest::Error) -> Error {
|
|
Error::Reqwest(e)
|
|
}
|
|
}
|
|
|
|
impl From<crypto::Error> for Error {
|
|
fn from(e: crypto::Error) -> Error {
|
|
Error::Crypto(e)
|
|
}
|
|
}
|
|
|
|
impl Serialize for Error {
|
|
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
let mut fields = serializer.serialize_map(Some(1))?;
|
|
fields.serialize_entry("msg", format!("{}", self).as_str())?;
|
|
fields.end()
|
|
}
|
|
}
|