1#[cfg(feature = "backend")]
2use actix_web::{error::ResponseError, HttpResponse};
3#[cfg(feature = "backend")]
4use diesel::result::Error as DBError;
5use failure::Fail;
6
7pub type Result<T> = std::result::Result<T, failure::Error>;
8
9#[derive(Fail, Debug)]
10pub enum ThothError {
11 #[fail(display = "{} is not a valid {} code", _0, _1)]
12 InvalidSubjectCode(String, String),
13 #[fail(display = "{} is not a valid Language Code", _0)]
14 InvalidLanguageCode(String),
15 #[fail(display = "{} is not a valid Work Type", _0)]
16 InvalidWorkType(String),
17 #[fail(display = "{} is not a valid Work Status", _0)]
18 InvalidWorkStatus(String),
19 #[fail(display = "{} is not a valid Contribution Type", _0)]
20 InvalidContributionType(String),
21 #[fail(display = "{} is not a valid Publication Type", _0)]
22 InvalidPublicationType(String),
23 #[fail(display = "{} is not a valid Series Type", _0)]
24 InvalidSeriesType(String),
25 #[fail(display = "{} is not a valid Subject Type", _0)]
26 InvalidSubjectType(String),
27 #[fail(display = "{} is not a valid Language Relation", _0)]
28 InvalidLanguageRelation(String),
29 #[fail(display = "Database error: {}", _0)]
30 DatabaseError(String),
31 #[fail(display = "Internal error: {}", _0)]
32 InternalError(String),
33 #[fail(display = "Invalid credentials.")]
34 Unauthorised,
35 #[fail(display = "Failed to validate token.")]
36 InvalidToken,
37 #[fail(display = "No cookie found.")]
38 CookieError(),
39}
40
41impl juniper::IntoFieldError for ThothError {
42 fn into_field_error(self) -> juniper::FieldError {
43 match self {
44 ThothError::InvalidSubjectCode { .. } => juniper::FieldError::new(
45 self.to_string(),
46 graphql_value!({
47 "type": "INVALID_SUBJECT_CODE"
48 }),
49 ),
50 ThothError::Unauthorised => juniper::FieldError::new(
51 "Unauthorized",
52 graphql_value!({
53 "type": "NO_ACCESS"
54 }),
55 ),
56 _ => juniper::FieldError::new(
57 self.to_string(),
58 graphql_value!({
59 "type": "INTERNAL_ERROR"
60 }),
61 ),
62 }
63 }
64}
65
66#[cfg(feature = "backend")]
67impl ResponseError for ThothError {
68 fn error_response(&self) -> HttpResponse {
69 match self {
70 ThothError::Unauthorised => HttpResponse::Unauthorized().json("Unauthorized"),
71 ThothError::DatabaseError { .. } => {
72 HttpResponse::InternalServerError().json("DB error")
73 }
74 _ => HttpResponse::InternalServerError().json("Internal error"),
75 }
76 }
77}
78
79#[cfg(feature = "backend")]
80impl From<DBError> for ThothError {
81 fn from(error: DBError) -> ThothError {
82 match error {
83 DBError::DatabaseError(_kind, info) => {
84 let message = info.details().unwrap_or_else(|| info.message()).to_string();
85 ThothError::DatabaseError(message)
86 }
87 _ => ThothError::InternalError("".into()),
88 }
89 }
90}
91
92impl From<std::io::Error> for ThothError {
93 fn from(error: std::io::Error) -> ThothError {
94 ThothError::InternalError(error.to_string())
95 }
96}
97
98impl From<reqwest::Error> for ThothError {
99 fn from(error: reqwest::Error) -> ThothError {
100 ThothError::InternalError(error.to_string())
101 }
102}
103
104impl From<xml::writer::Error> for ThothError {
105 fn from(error: xml::writer::Error) -> ThothError {
106 ThothError::InternalError(error.to_string())
107 }
108}
109
110impl From<failure::Error> for ThothError {
111 fn from(error: failure::Error) -> ThothError {
112 if error.downcast_ref::<ThothError>().is_some() {
113 return error.downcast::<ThothError>().unwrap();
114 }
115 ThothError::InternalError(error.to_string())
116 }
117}