1pub mod client;
13pub mod credentials;
14pub mod encryption;
15
16#[allow(unused_imports)]
18pub use client::CloudClient;
19#[allow(unused_imports)]
20pub use credentials::{Credentials, CredentialsStore};
21#[allow(unused_imports)]
22pub use encryption::{decrypt_data, derive_key, encrypt_data};
23
24pub const DEFAULT_CLOUD_URL: &str = "https://app.lore.varalys.com";
26
27pub const KEYRING_SERVICE: &str = "lore-cloud";
29
30pub const KEYRING_API_KEY_USER: &str = "api-key";
32
33pub const KEYRING_ENCRYPTION_KEY_USER: &str = "encryption-key";
35
36#[derive(Debug, thiserror::Error)]
38pub enum CloudError {
39 #[error("Not logged in. Run 'lore login' first.")]
41 NotLoggedIn,
42
43 #[error("Authentication failed: {0}")]
45 #[allow(dead_code)]
46 AuthFailed(String),
47
48 #[error("Cloud API error: {0}")]
50 #[allow(dead_code)]
51 ApiError(String),
52
53 #[error("HTTP request failed: {0}")]
55 HttpError(#[from] reqwest::Error),
56
57 #[error("Encryption error: {0}")]
59 EncryptionError(String),
60
61 #[error("Credential storage error: {0}")]
63 KeyringError(String),
64
65 #[error("Encryption key not set. Run 'lore cloud push' to set up encryption.")]
67 #[allow(dead_code)]
68 NoEncryptionKey,
69
70 #[error("OAuth state mismatch - possible CSRF attack")]
72 #[allow(dead_code)]
73 StateMismatch,
74
75 #[error("Login timed out waiting for browser authentication")]
77 #[allow(dead_code)]
78 LoginTimeout,
79
80 #[error("Server error ({status}): {message}")]
82 ServerError { status: u16, message: String },
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_cloud_error_display_not_logged_in() {
91 let err = CloudError::NotLoggedIn;
92 assert!(err.to_string().contains("Not logged in"));
93 }
94
95 #[test]
96 fn test_cloud_error_display_auth_failed() {
97 let err = CloudError::AuthFailed("invalid token".to_string());
98 assert!(err.to_string().contains("invalid token"));
99 }
100
101 #[test]
102 fn test_cloud_error_display_server_error() {
103 let err = CloudError::ServerError {
104 status: 500,
105 message: "Internal error".to_string(),
106 };
107 assert!(err.to_string().contains("500"));
108 assert!(err.to_string().contains("Internal error"));
109 }
110
111 #[test]
112 fn test_default_cloud_url() {
113 assert_eq!(DEFAULT_CLOUD_URL, "https://app.lore.varalys.com");
114 }
115
116 #[test]
117 fn test_keyring_constants() {
118 assert_eq!(KEYRING_SERVICE, "lore-cloud");
119 assert_eq!(KEYRING_API_KEY_USER, "api-key");
120 assert_eq!(KEYRING_ENCRYPTION_KEY_USER, "encryption-key");
121 }
122}