Skip to main content

oauth_db_cli/
error.rs

1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum CliError {
5    #[error("Authentication failed: {0}")]
6    AuthError(String),
7
8    #[error("API error: {0}")]
9    ApiError(String),
10
11    #[error("Configuration error: {0}")]
12    ConfigError(String),
13
14    #[error("Not logged in. Run 'oauth-db login' first")]
15    NotLoggedIn,
16
17    #[error("Permission denied: {0}")]
18    PermissionDenied(String),
19
20    #[error("Permission denied for operation '{operation}'.\nrequired role: {required}\nYour role: {current}\n{hint}")]
21    RoleMissing {
22        current: String,
23        required: String,
24        operation: String,
25        hint: String,
26    },
27
28    #[error("Resource not found: {0}")]
29    NotFound(String),
30
31    #[error("Invalid input: {0}")]
32    InvalidInput(String),
33
34    #[error("HTTP request failed: {0}")]
35    HttpError(#[from] reqwest::Error),
36
37    #[error("IO error: {0}")]
38    IoError(#[from] std::io::Error),
39
40    #[error("Serialization error: {0}")]
41    SerdeError(#[from] serde_json::Error),
42
43    #[error("TOML error: {0}")]
44    TomlError(#[from] toml::de::Error),
45
46    #[error("Encryption error: {0}")]
47    CryptoError(String),
48
49    #[error("Encryption error: {0}")]
50    EncryptionError(String),
51
52    #[error("Serialization error: {0}")]
53    SerializationError(String),
54
55    #[error("Network error: {0}")]
56    NetworkError(String),
57}
58
59impl From<serde_yaml::Error> for CliError {
60    fn from(err: serde_yaml::Error) -> Self {
61        CliError::SerializationError(format!("YAML error: {}", err))
62    }
63}
64
65impl From<toml::ser::Error> for CliError {
66    fn from(err: toml::ser::Error) -> Self {
67        CliError::ConfigError(format!("TOML serialization error: {}", err))
68    }
69}
70
71pub type Result<T> = std::result::Result<T, CliError>;
72
73impl CliError {
74    /// Create a RoleMissing error with a helpful hint
75    pub fn role_missing(current: impl Into<String>, required: impl Into<String>, operation: impl Into<String>) -> Self {
76        let current = current.into();
77        let required = required.into();
78        let operation = operation.into();
79
80        let hint = match required.as_str() {
81            "admin" => "Please switch to an account with admin privileges or contact your administrator.",
82            "developer" => "You need to register as a developer. Run 'oauth-db register' to create an account.",
83            _ => "Please check your account permissions.",
84        };
85
86        CliError::RoleMissing {
87            current,
88            required,
89            operation,
90            hint: hint.to_string(),
91        }
92    }
93
94    /// Create a PermissionDenied error with context
95    pub fn permission_denied(resource: impl Into<String>, action: impl Into<String>) -> Self {
96        CliError::PermissionDenied(format!(
97            "You don't have permission to {} {}. Please check your access rights.",
98            action.into(),
99            resource.into()
100        ))
101    }
102}