2018-12-09 16:55:36 +01:00
|
|
|
use actix_web::{error::ResponseError, HttpResponse};
|
2019-03-29 21:43:03 +01:00
|
|
|
use derive_more::Display;
|
2018-12-09 16:55:36 +01:00
|
|
|
use diesel::result::{DatabaseErrorKind, Error};
|
2019-03-10 03:03:09 +01:00
|
|
|
use std::convert::From;
|
2018-12-09 16:55:36 +01:00
|
|
|
use uuid::ParseError;
|
|
|
|
|
2019-03-29 21:43:03 +01:00
|
|
|
#[derive(Debug, Display)]
|
2018-12-09 16:55:36 +01:00
|
|
|
pub enum ServiceError {
|
2019-03-29 21:43:03 +01:00
|
|
|
#[display(fmt = "Internal Server Error")]
|
2018-12-09 16:55:36 +01:00
|
|
|
InternalServerError,
|
|
|
|
|
2019-03-29 21:43:03 +01:00
|
|
|
#[display(fmt = "BadRequest: {}", _0)]
|
2018-12-09 16:55:36 +01:00
|
|
|
BadRequest(String),
|
|
|
|
|
2019-03-29 21:43:03 +01:00
|
|
|
#[display(fmt = "Unauthorized")]
|
2018-12-09 16:55:36 +01:00
|
|
|
Unauthorized,
|
|
|
|
}
|
|
|
|
|
|
|
|
// impl ResponseError trait allows to convert our errors into http responses with appropriate data
|
|
|
|
impl ResponseError for ServiceError {
|
|
|
|
fn error_response(&self) -> HttpResponse {
|
|
|
|
match *self {
|
2019-03-10 03:03:09 +01:00
|
|
|
ServiceError::InternalServerError => HttpResponse::InternalServerError()
|
|
|
|
.json("Internal Server Error, Please try later"),
|
|
|
|
ServiceError::BadRequest(ref message) => {
|
|
|
|
HttpResponse::BadRequest().json(message)
|
|
|
|
}
|
|
|
|
ServiceError::Unauthorized => {
|
|
|
|
HttpResponse::Unauthorized().json("Unauthorized")
|
|
|
|
}
|
2018-12-09 16:55:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we can return early in our handlers if UUID provided by the user is not valid
|
|
|
|
// and provide a custom message
|
|
|
|
impl From<ParseError> for ServiceError {
|
|
|
|
fn from(_: ParseError) -> ServiceError {
|
|
|
|
ServiceError::BadRequest("Invalid UUID".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Error> for ServiceError {
|
|
|
|
fn from(error: Error) -> ServiceError {
|
|
|
|
// Right now we just care about UniqueViolation from diesel
|
|
|
|
// But this would be helpful to easily map errors as our app grows
|
|
|
|
match error {
|
|
|
|
Error::DatabaseError(kind, info) => {
|
|
|
|
if let DatabaseErrorKind::UniqueViolation = kind {
|
2019-03-10 03:03:09 +01:00
|
|
|
let message =
|
|
|
|
info.details().unwrap_or_else(|| info.message()).to_string();
|
2018-12-09 16:55:36 +01:00
|
|
|
return ServiceError::BadRequest(message);
|
|
|
|
}
|
|
|
|
ServiceError::InternalServerError
|
|
|
|
}
|
2019-03-10 03:03:09 +01:00
|
|
|
_ => ServiceError::InternalServerError,
|
2018-12-09 16:55:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|