77 lines
2.1 KiB
Rust
77 lines
2.1 KiB
Rust
use rocket::http::Status;
|
|
use rocket::request::Request;
|
|
use rocket::response::status;
|
|
use rocket::response::{self, Responder};
|
|
use rocket_contrib::templates::Template;
|
|
use std::collections::HashMap;
|
|
use thiserror::Error;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum Error {
|
|
#[error("resource not found")]
|
|
NotFound,
|
|
|
|
#[error("you must be logged in")]
|
|
NotLoggedIn,
|
|
|
|
#[error("you do not have permission to access this")]
|
|
NoPermission,
|
|
|
|
#[error("invalid input")]
|
|
InvalidInput,
|
|
|
|
#[error("validation error: {0}")]
|
|
ValidationError(#[from] crate::models::convert::ValidationError),
|
|
|
|
#[error("serialization error: {0}")]
|
|
SerializationError(#[from] prost::EncodeError),
|
|
|
|
#[error("deserialization error: {0}")]
|
|
DeserializationError(#[from] prost::DecodeError),
|
|
|
|
#[error("i/o error: {0}")]
|
|
IoError(#[from] std::io::Error),
|
|
|
|
#[error("query error: {0}")]
|
|
QueryError(#[from] sqlx::Error),
|
|
|
|
#[error("rocket error: {0}")]
|
|
RocketError(#[from] rocket::error::Error),
|
|
}
|
|
|
|
impl Error {
|
|
fn is_sensitive(&self) -> bool {
|
|
use Error::*;
|
|
match self {
|
|
QueryError(_) => true,
|
|
IoError(_) => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[rocket::async_trait]
|
|
impl<'r> Responder<'r, 'static> for Error {
|
|
fn respond_to(self, req: &Request) -> response::Result<'static> {
|
|
log::error!("error: {0}", self.to_string());
|
|
//Hide sensitive error information
|
|
let message: String = if self.is_sensitive() {
|
|
"internal error".into()
|
|
} else {
|
|
self.to_string()
|
|
};
|
|
|
|
let mut context = HashMap::new();
|
|
context.insert("message", message);
|
|
let resp = Template::render("error", context).respond_to(req)?;
|
|
|
|
use Error::*;
|
|
match self {
|
|
NotFound => status::NotFound(resp).respond_to(req),
|
|
NotLoggedIn => status::Forbidden(Some(resp)).respond_to(req),
|
|
NoPermission => status::Forbidden(Some(resp)).respond_to(req),
|
|
_ => status::Custom(Status::InternalServerError, resp).respond_to(req),
|
|
}
|
|
}
|
|
}
|