1use thiserror::Error;
2
3#[derive(Debug, Error)]
5pub enum GuardError {
6 #[error("invalid token")]
8 InvalidToken,
9 #[error("session expired")]
11 SessionExpired,
12 #[error("session revoked")]
14 SessionRevoked,
15 #[error("policy denied: {0}")]
17 PolicyDenied(String),
18 #[error("database error: {0}")]
20 DatabaseError(#[from] sqlx::Error),
21 #[error("config error: {0}")]
23 ConfigError(String),
24 #[error("serialization error: {0}")]
26 SerializationError(#[from] serde_json::Error),
27 #[error("io error: {0}")]
29 IoError(#[from] std::io::Error),
30 #[error("migration error: {0}")]
32 MigrationError(#[from] sqlx::migrate::MigrateError),
33 #[error("jwt error")]
35 JwtError(#[from] jsonwebtoken::errors::Error),
36 #[error("toml parse error: {0}")]
38 TomlError(#[from] toml::de::Error),
39 #[error("uuid parse error: {0}")]
41 UuidError(#[from] uuid::Error),
42 #[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
64pub type GuardResult<T> = Result<T, GuardError>;