trustchain_http/
errors.rs

1//! Error type and conversions.
2use axum::{response::IntoResponse, Json};
3use hyper::StatusCode;
4use josekit::JoseError;
5use serde_json::json;
6use thiserror::Error;
7use trustchain_core::{
8    attestor::AttestorError, commitment::CommitmentError, issuer::IssuerError,
9    key_manager::KeyManagerError, resolver::ResolverError, vc::CredentialError,
10    verifier::VerifierError, vp::PresentationError,
11};
12use trustchain_ion::root::TrustchainRootError;
13
14use crate::attestation_utils::TrustchainCRError;
15
16/// Trustchain HTTP error type.
17// TODO: refine and add doc comments for error variants
18#[derive(Error, Debug)]
19pub enum TrustchainHTTPError {
20    #[error("Internal error.")]
21    InternalError,
22    #[error("Trustchain Verifier error: {0}")]
23    VerifierError(VerifierError),
24    #[error("Trustchain Commitment error: {0}")]
25    CommitmentError(CommitmentError),
26    #[error("Trustchain Resolver error: {0}")]
27    ResolverError(ResolverError),
28    #[error("Trustchain issuer error: {0}")]
29    IssuerError(IssuerError),
30    #[error("Trustchain root error: {0}")]
31    RootError(TrustchainRootError),
32    #[error("Trustchain presentation error: {0}")]
33    PresentationError(PresentationError),
34    #[error("Trustchain attestor error: {0}")]
35    AttestorError(#[from] AttestorError),
36    // TODO: once needed in http propagate
37    #[error("Jose error: {0}")]
38    JoseError(#[from] JoseError),
39    #[error("Trustchain key manager error: {0}")]
40    KeyManagerError(KeyManagerError),
41    #[error("Trustchain challenge-response error: {0}")]
42    CRError(TrustchainCRError),
43    #[error("Credential does not exist.")]
44    CredentialDoesNotExist,
45    #[error("No issuer available.")]
46    NoCredentialIssuer,
47    #[error("Wrapped reqwest error: {0}")]
48    ReqwestError(reqwest::Error),
49    #[error("Failed to verify credential.")]
50    FailedToVerifyCredential,
51    #[error("Invalid signature.")]
52    InvalidSignature,
53    #[error("Request does not exist.")]
54    RequestDoesNotExist,
55    #[error("Could not deserialize data: {0}")]
56    FailedToDeserialize(#[from] serde_json::Error),
57    #[error("Root event time not configured for verification.")]
58    RootEventTimeNotSet,
59    #[error("Attestation request failed.")]
60    FailedAttestationRequest,
61}
62
63impl From<ResolverError> for TrustchainHTTPError {
64    fn from(err: ResolverError) -> Self {
65        TrustchainHTTPError::ResolverError(err)
66    }
67}
68
69impl From<CommitmentError> for TrustchainHTTPError {
70    fn from(err: CommitmentError) -> Self {
71        TrustchainHTTPError::CommitmentError(err)
72    }
73}
74
75impl From<VerifierError> for TrustchainHTTPError {
76    fn from(err: VerifierError) -> Self {
77        TrustchainHTTPError::VerifierError(err)
78    }
79}
80
81impl From<IssuerError> for TrustchainHTTPError {
82    fn from(err: IssuerError) -> Self {
83        TrustchainHTTPError::IssuerError(err)
84    }
85}
86
87impl From<TrustchainRootError> for TrustchainHTTPError {
88    fn from(err: TrustchainRootError) -> Self {
89        TrustchainHTTPError::RootError(err)
90    }
91}
92
93impl From<PresentationError> for TrustchainHTTPError {
94    fn from(err: PresentationError) -> Self {
95        TrustchainHTTPError::PresentationError(err)
96    }
97}
98
99impl From<KeyManagerError> for TrustchainHTTPError {
100    fn from(err: KeyManagerError) -> Self {
101        TrustchainHTTPError::KeyManagerError(err)
102    }
103}
104
105impl From<TrustchainCRError> for TrustchainHTTPError {
106    fn from(err: TrustchainCRError) -> Self {
107        TrustchainHTTPError::CRError(err)
108    }
109}
110
111// See axum IntoRespone example:
112// https://github.com/tokio-rs/axum/blob/main/examples/jwt/src/main.rs#L147-L160
113
114impl IntoResponse for TrustchainHTTPError {
115    fn into_response(self) -> axum::response::Response {
116        // TODO: determine correct status codes for errors
117        let (status, err_message) = match self {
118            err @ TrustchainHTTPError::InternalError => {
119                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
120            }
121            err @ TrustchainHTTPError::VerifierError(VerifierError::InvalidRoot(_))
122            | err @ TrustchainHTTPError::VerifierError(VerifierError::CommitmentFailure(_)) => {
123                (StatusCode::OK, err.to_string())
124            }
125            err @ TrustchainHTTPError::VerifierError(_) => {
126                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
127            }
128            err @ TrustchainHTTPError::IssuerError(_) => {
129                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
130            }
131            err @ TrustchainHTTPError::AttestorError(_) => {
132                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
133            }
134            err @ TrustchainHTTPError::CommitmentError(_) => {
135                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
136            }
137            err @ TrustchainHTTPError::ResolverError(_) => {
138                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
139            }
140            err @ TrustchainHTTPError::PresentationError(PresentationError::CredentialError(
141                CredentialError::VerifierError(VerifierError::CommitmentFailure(_)),
142            ))
143            | err @ TrustchainHTTPError::PresentationError(PresentationError::CredentialError(
144                CredentialError::VerifierError(VerifierError::InvalidRoot(_)),
145            )) => (StatusCode::OK, err.to_string()),
146            err @ TrustchainHTTPError::PresentationError(_) => {
147                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
148            }
149            err @ TrustchainHTTPError::KeyManagerError(_) => {
150                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
151            }
152            err @ TrustchainHTTPError::JoseError(_) => {
153                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
154            }
155            err @ TrustchainHTTPError::CRError(_) => {
156                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
157            }
158            err @ TrustchainHTTPError::CredentialDoesNotExist => {
159                (StatusCode::BAD_REQUEST, err.to_string())
160            }
161            err @ TrustchainHTTPError::NoCredentialIssuer => {
162                (StatusCode::BAD_REQUEST, err.to_string())
163            }
164            TrustchainHTTPError::ReqwestError(err) => (
165                err.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
166                err.to_string(),
167            ),
168            ref err @ TrustchainHTTPError::RootError(ref variant) => match variant {
169                TrustchainRootError::NoUniqueRootEvent(_) => {
170                    (StatusCode::BAD_REQUEST, err.to_string())
171                }
172                TrustchainRootError::InvalidDate(_, _, _) => {
173                    (StatusCode::BAD_REQUEST, err.to_string())
174                }
175                TrustchainRootError::FailedToParseBlockHeight(_) => {
176                    (StatusCode::BAD_REQUEST, err.to_string())
177                }
178                _ => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()),
179            },
180            err @ TrustchainHTTPError::FailedToVerifyCredential => {
181                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
182            }
183            err @ TrustchainHTTPError::InvalidSignature => {
184                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
185            }
186            err @ TrustchainHTTPError::RequestDoesNotExist => {
187                (StatusCode::BAD_REQUEST, err.to_string())
188            }
189            err @ TrustchainHTTPError::FailedToDeserialize(_) => {
190                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
191            }
192            err @ TrustchainHTTPError::RootEventTimeNotSet => {
193                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
194            }
195            err @ TrustchainHTTPError::FailedAttestationRequest => {
196                (StatusCode::INTERNAL_SERVER_ERROR, err.to_string())
197            }
198        };
199        let body = Json(json!({ "error": err_message }));
200        (status, body).into_response()
201    }
202}