Skip to main content

claw_guard/
error.rs

1use thiserror::Error;
2
3/// Errors returned by guard operations.
4#[derive(Debug, Error)]
5pub enum GuardError {
6    /// The supplied session token could not be verified.
7    #[error("invalid token")]
8    InvalidToken,
9    /// The referenced session has expired.
10    #[error("session expired")]
11    SessionExpired,
12    /// The referenced session has been revoked.
13    #[error("session revoked")]
14    SessionRevoked,
15    /// A policy denied the attempted action.
16    #[error("policy denied: {0}")]
17    PolicyDenied(String),
18    /// SQLite or `sqlx` returned an error.
19    #[error("database error: {0}")]
20    DatabaseError(#[from] sqlx::Error),
21    /// Configuration was invalid or incomplete.
22    #[error("config error: {0}")]
23    ConfigError(String),
24    /// JSON serialization or deserialization failed.
25    #[error("serialization error: {0}")]
26    SerializationError(#[from] serde_json::Error),
27    /// File I/O failed.
28    #[error("io error: {0}")]
29    IoError(#[from] std::io::Error),
30    /// Embedded migration execution failed.
31    #[error("migration error: {0}")]
32    MigrationError(#[from] sqlx::migrate::MigrateError),
33    /// JWT encoding or decoding failed.
34    #[error("jwt error")]
35    JwtError(#[from] jsonwebtoken::errors::Error),
36    /// TOML parsing failed.
37    #[error("toml parse error: {0}")]
38    TomlError(#[from] toml::de::Error),
39    /// A UUID value could not be parsed.
40    #[error("uuid parse error: {0}")]
41    UuidError(#[from] uuid::Error),
42    /// The audit worker channel is unavailable.
43    #[error("audit channel closed")]
44    AuditChannelClosed,
45}
46
47impl From<GuardError> for tonic::Status {
48    fn from(value: GuardError) -> Self {
49        match value {
50            GuardError::InvalidToken => tonic::Status::unauthenticated("invalid token"),
51            GuardError::SessionExpired | GuardError::SessionRevoked => {
52                tonic::Status::unauthenticated(value.to_string())
53            }
54            GuardError::PolicyDenied(reason) => tonic::Status::permission_denied(reason),
55            GuardError::ConfigError(message) => tonic::Status::invalid_argument(message),
56            GuardError::DatabaseError(_)
57            | GuardError::MigrationError(_)
58            | GuardError::AuditChannelClosed => tonic::Status::unavailable(value.to_string()),
59            _ => tonic::Status::internal(value.to_string()),
60        }
61    }
62}
63
64/// Result type used by all guard operations.
65pub type GuardResult<T> = Result<T, GuardError>;