1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug)]
9pub enum RunbeamError {
10 JwtValidation(String),
12 Api(ApiError),
14 Storage(crate::storage::StorageError),
16 Config(String),
18}
19
20impl fmt::Display for RunbeamError {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 RunbeamError::JwtValidation(msg) => write!(f, "JWT validation failed: {}", msg),
24 RunbeamError::Api(err) => write!(f, "API error: {}", err),
25 RunbeamError::Storage(err) => write!(f, "Storage error: {}", err),
26 RunbeamError::Config(msg) => write!(f, "Configuration error: {}", msg),
27 }
28 }
29}
30
31impl std::error::Error for RunbeamError {}
32
33impl From<ApiError> for RunbeamError {
34 fn from(err: ApiError) -> Self {
35 RunbeamError::Api(err)
36 }
37}
38
39impl From<crate::storage::StorageError> for RunbeamError {
40 fn from(err: crate::storage::StorageError) -> Self {
41 RunbeamError::Storage(err)
42 }
43}
44
45impl From<jsonwebtoken::errors::Error> for RunbeamError {
46 fn from(err: jsonwebtoken::errors::Error) -> Self {
47 RunbeamError::JwtValidation(err.to_string())
48 }
49}
50
51#[derive(Debug)]
53pub enum ApiError {
54 Network(String),
56 Http { status: u16, message: String },
58 Parse(String),
60 Request(String),
62}
63
64impl fmt::Display for ApiError {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 ApiError::Network(msg) => write!(f, "Network error: {}", msg),
68 ApiError::Http { status, message } => {
69 write!(f, "HTTP {} error: {}", status, message)
70 }
71 ApiError::Parse(msg) => write!(f, "Parse error: {}", msg),
72 ApiError::Request(msg) => write!(f, "Request error: {}", msg),
73 }
74 }
75}
76
77impl std::error::Error for ApiError {}
78
79impl From<reqwest::Error> for ApiError {
80 fn from(err: reqwest::Error) -> Self {
81 if err.is_timeout() {
82 ApiError::Network("Request timeout".to_string())
83 } else if err.is_connect() {
84 ApiError::Network(format!("Connection failed: {}", err))
85 } else if let Some(status) = err.status() {
86 ApiError::Http {
87 status: status.as_u16(),
88 message: err.to_string(),
89 }
90 } else {
91 ApiError::Network(err.to_string())
92 }
93 }
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct UserInfo {
99 pub id: String,
100 pub email: String,
101 pub name: String,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct UserToken {
111 pub token: String,
113 #[serde(default)]
115 pub expires_at: Option<i64>,
116 #[serde(default)]
118 pub user: Option<UserInfo>,
119}
120
121impl UserToken {
122 pub fn new(token: String, expires_at: Option<i64>, user: Option<UserInfo>) -> Self {
124 Self {
125 token,
126 expires_at,
127 user,
128 }
129 }
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct TeamInfo {
135 pub id: String,
136 pub name: String,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct GatewayInfo {
142 pub id: String,
143 pub code: String,
144 pub name: String,
145 #[serde(default)]
146 pub authorized_by: Option<AuthorizedBy>,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct AuthorizedBy {
152 pub id: String,
153 pub name: String,
154 pub email: String,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct AuthorizeResponse {
160 pub machine_token: String,
161 pub expires_in: f64,
162 pub expires_at: String,
163 pub gateway: GatewayInfo,
164 #[serde(default)]
165 pub abilities: Vec<String>,
166}
167
168#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct ConfigChange {
171 pub id: String,
172 pub timestamp: String,
173 pub summary: String,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ConfigChangeDetail {
179 pub id: String,
180 pub content: String,
181 #[serde(default)]
182 pub metadata: Option<serde_json::Value>,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct ConfigChangeAck {
188 pub success: bool,
189 #[serde(default)]
190 pub message: Option<String>,
191}