Skip to main content

affinidi_messaging_sdk/
errors.rs

1use affinidi_did_authentication::errors::DIDAuthError;
2use affinidi_messaging_didcomm::message::Message;
3use affinidi_messaging_mediator_common::types::acls::ACLError;
4use affinidi_tdk_common::errors::TDKError;
5use thiserror::Error;
6
7use crate::messages::{known::MessageType, problem_report::ProblemReport};
8
9/// ATMError
10#[derive(Error, Debug)]
11#[non_exhaustive]
12pub enum ATMError {
13    #[error("DID error: {0}")]
14    DIDError(String),
15    #[error("Secrets error: {0}")]
16    SecretsError(String),
17    #[error("SSL error: {0}")]
18    SSLError(String),
19    #[error("Transport (HTTP(S)) error: {0}")]
20    TransportError(String),
21    #[error("Message sending error: {0}")]
22    MsgSendError(String),
23    #[error("Message receive error: {0}")]
24    MsgReceiveError(String),
25    #[error("WebSocket disconnected: {0}")]
26    Disconnected(String),
27    #[error("Config error: {0}")]
28    ConfigError(String),
29    #[error("Authentication error: {0}")]
30    AuthenticationError(String),
31    #[error("ACL Denied error: {0}")]
32    ACLDenied(String),
33    #[error("ACL config error: {0}")]
34    ACLConfigError(String),
35    #[error("DIDComm message error: {0}. Reason: {1}")]
36    DidcommError(String, String),
37    #[error("Unexpected envelope: {0}")]
38    UnexpectedEnvelope(String),
39    #[error("Addressing consistency error: {0}")]
40    AddressingMismatch(String),
41    #[error("Verification failed: {0}")]
42    VerificationFailed(String),
43    #[error("SDK Error: {0}")]
44    SDKError(String),
45    #[error("TDK Error: {0}")]
46    TDKError(String),
47    #[error("DIDComm Problem Report: code: ({0}), comment: ({1}), escalate?: ({2})")]
48    ProblemReport(String, String, String),
49    #[error("DIDComm Mediator error: code({0}), message: ({1})")]
50    MediatorError(String, String),
51    #[error("ATM DID Profile error: {0}")]
52    ProfileError(String),
53}
54
55impl ATMError {
56    /// Creates an ATM Error from a DIDComm Problem Report Error Message
57    pub fn from_problem_report(message: &Message) -> Self {
58        if let Ok(MessageType::ProblemReport) = message.typ.parse::<MessageType>() {
59            let body: ProblemReport = match serde_json::from_value(message.body.clone()) {
60                Ok(body) => body,
61                Err(err) => {
62                    return ATMError::SDKError(format!(
63                        "Internal error handling error. Could not parse Problem Report message. Reason: {err}"
64                    ));
65                }
66            };
67
68            let comment = body.interpolation();
69
70            ATMError::ProblemReport(
71                body.code,
72                comment,
73                body.escalate_to.unwrap_or("NONE".into()),
74            )
75        } else {
76            // Handling for non-Problem Report messages
77            ATMError::SDKError(format!(
78                "Internal error handling error. Expecting a DIDComm Problem Report message. Received instead ({})",
79                message.typ
80            ))
81        }
82    }
83}
84
85impl From<ATMError> for TDKError {
86    fn from(err: ATMError) -> Self {
87        TDKError::ATM(err.to_string())
88    }
89}
90
91impl From<TDKError> for ATMError {
92    fn from(err: TDKError) -> Self {
93        ATMError::TDKError(err.to_string())
94    }
95}
96
97impl From<DIDAuthError> for ATMError {
98    fn from(err: DIDAuthError) -> Self {
99        ATMError::AuthenticationError(err.to_string())
100    }
101}
102
103impl From<ACLError> for ATMError {
104    fn from(err: ACLError) -> Self {
105        match err {
106            ACLError::Config(msg) => ATMError::ACLConfigError(msg),
107            ACLError::Denied(msg) => ATMError::ACLDenied(msg),
108            // ACLError is `#[non_exhaustive]` from mediator-common 0.15;
109            // surface any future variant as a generic ACL error so the
110            // SDK keeps compiling against unmodified consumers when
111            // mediator-common lands new ACL failure modes.
112            other => ATMError::ACLConfigError(other.to_string()),
113        }
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use super::*;
120
121    #[test]
122    fn test_from_problem_report_works() {
123        let message = Message::build(
124            "example-1".to_string(),
125            "https://didcomm.org/report-problem/2.0/problem-report".to_string(),
126            serde_json::json!({
127                "code": "test-code",
128                "comment": "Test one {1} two {2} three {3}",
129                "escalate_to": "test-escalate",
130                "args": ["1", "2", "3"]
131            }),
132        )
133        .finalize();
134
135        let error = ATMError::from_problem_report(&message);
136
137        match error {
138            ATMError::ProblemReport(code, comment, escalate) => {
139                assert_eq!(code, "test-code");
140                assert_eq!(comment, "Test one 1 two 2 three 3");
141                assert_eq!(escalate, "test-escalate");
142            }
143            _ => panic!("Expected ProblemReport error"),
144        }
145    }
146
147    #[test]
148    fn test_from_problem_report_wrong_type() {
149        let message = Message::build(
150            "example-1".to_string(),
151            "https://didcomm.org/NOT-A-PROBLEM/2.0/problem-report".to_string(),
152            serde_json::json!({
153                "code": "test-code",
154                "comment": "Test one {1} two {2} three {3}",
155                "escalate_to": "test-escalate",
156                "args": ["1", "2", "3"]
157            }),
158        )
159        .finalize();
160
161        let error = ATMError::from_problem_report(&message);
162
163        match error {
164            ATMError::SDKError(_) => {}
165            _ => panic!("Expected SDKError error"),
166        }
167    }
168
169    #[test]
170    fn test_from_problem_report_wrong_body() {
171        let message = Message::build(
172            "example-1".to_string(),
173            "https://didcomm.org/NOT-A-PROBLEM/2.0/problem-report".to_string(),
174            serde_json::json!({}),
175        )
176        .finalize();
177
178        let error = ATMError::from_problem_report(&message);
179
180        match error {
181            ATMError::SDKError(_) => {}
182            _ => panic!("Expected SDKError error"),
183        }
184    }
185}