canic_core/api/
error.rs

1use crate::{
2    Error,
3    access::AccessError,
4    dto::error::{Error as PublicError, ErrorCode},
5};
6
7///
8/// Error
9/// (re-exported as PublicError)
10///
11
12impl Error {
13    pub fn public(&self) -> PublicError {
14        match self {
15            // ---------------------------------------------------------
16            // Access / authorization
17            // ---------------------------------------------------------
18            Self::Access(err) => access_error(err),
19
20            // ---------------------------------------------------------
21            // Input / configuration
22            // ---------------------------------------------------------
23            Self::Config(_) => {
24                Self::public_message(ErrorCode::InvalidInput, "invalid configuration")
25            }
26
27            // ---------------------------------------------------------
28            // Policy decisions
29            // ---------------------------------------------------------
30            Self::Domain(_) => Self::public_message(ErrorCode::Conflict, "policy rejected"),
31
32            // ---------------------------------------------------------
33            // State / invariants
34            // ---------------------------------------------------------
35            Self::Storage(_) => {
36                Self::public_message(ErrorCode::InvariantViolation, "invariant violation")
37            }
38
39            // ---------------------------------------------------------
40            // Infrastructure / execution
41            // ---------------------------------------------------------
42            Self::Infra(_) | Self::Ops(_) | Self::Workflow(_) => {
43                Self::public_message(ErrorCode::Internal, "internal error")
44            }
45        }
46    }
47
48    fn public_message(code: ErrorCode, message: &'static str) -> PublicError {
49        PublicError {
50            code,
51            message: message.to_string(),
52        }
53    }
54}
55
56fn access_error(err: &AccessError) -> PublicError {
57    match err {
58        AccessError::Denied(reason) => PublicError::unauthorized(reason.clone()),
59        _ => PublicError::unauthorized("unauthorized"),
60    }
61}
62
63impl From<&Error> for PublicError {
64    fn from(err: &Error) -> Self {
65        err.public()
66    }
67}
68
69impl From<Error> for PublicError {
70    fn from(err: Error) -> Self {
71        Self::from(&err)
72    }
73}
74
75impl From<AccessError> for PublicError {
76    fn from(err: AccessError) -> Self {
77        match err {
78            AccessError::Auth(e) => Self::new(ErrorCode::Unauthorized, e.to_string()),
79            AccessError::Denied(reason) => Self::new(ErrorCode::Forbidden, reason),
80            AccessError::Env(e) => Self::new(ErrorCode::Forbidden, e.to_string()),
81            AccessError::Guard(e) => Self::new(ErrorCode::Forbidden, e.to_string()),
82            AccessError::Rule(e) => Self::new(ErrorCode::Forbidden, e.to_string()),
83        }
84    }
85}