webex_message_handler/
device_manager.rs1use crate::errors::{Result, WebexError};
4use crate::types::{DeviceRegistration, FetchFn, FetchRequest};
5use serde_json::json;
6use std::collections::HashMap;
7use tracing::{debug, error, info};
8
9const WDM_API_BASE: &str = "https://wdm-a.wbx2.com/wdm/api/v1/devices";
10
11fn device_body() -> serde_json::Value {
12 json!({
13 "deviceName": "webex-message-handler",
14 "deviceType": "DESKTOP",
15 "localizedModel": "rust",
16 "model": "rust",
17 "name": "webex-message-handler",
18 "systemName": "webex-message-handler",
19 "systemVersion": "1.0.0"
20 })
21}
22
23pub struct DeviceManager {
25 device_url: Option<String>,
26 http_do: FetchFn,
27}
28
29impl DeviceManager {
30 pub fn new(http_do: FetchFn) -> Self {
31 Self {
32 device_url: None,
33 http_do,
34 }
35 }
36
37 pub async fn register(&mut self, token: &str) -> Result<DeviceRegistration> {
39 debug!("Registering device with WDM");
40
41 let mut headers = HashMap::new();
42 headers.insert("Authorization".to_string(), format!("Bearer {}", token));
43 headers.insert("Content-Type".to_string(), "application/json".to_string());
44
45 let body = serde_json::to_string(&device_body())
46 .map_err(|e| WebexError::device_registration(format!("Failed to serialize body: {e}"), None))?;
47
48 let response = (self.http_do)(FetchRequest {
49 url: WDM_API_BASE.to_string(),
50 method: "POST".to_string(),
51 headers,
52 body: Some(body),
53 })
54 .await
55 .map_err(|e| WebexError::device_registration(format!("Failed to register device: {e}"), None))?;
56
57 let status = response.status;
58
59 if status == 401 {
60 error!("Device registration failed: Unauthorized");
61 return Err(WebexError::auth("Unauthorized to register device"));
62 }
63
64 if !response.ok {
65 error!("Device registration failed with status {status}");
66 return Err(WebexError::device_registration("Failed to register device", Some(status)));
67 }
68
69 let mut reg: DeviceRegistration = serde_json::from_slice(&response.body)
70 .map_err(|e| WebexError::device_registration(format!("Failed to parse response: {e}"), None))?;
71
72 reg.encryption_service_url = reg.services.get("encryptionServiceUrl").cloned().unwrap_or_default();
73 self.device_url = Some(reg.device_url.clone());
74
75 info!("Device registered successfully");
76 Ok(reg)
77 }
78
79 pub async fn refresh(&self, token: &str) -> Result<DeviceRegistration> {
81 let device_url = self.device_url.as_deref().ok_or_else(|| {
82 WebexError::device_registration("Device not registered. Call register() first.", None)
83 })?;
84
85 debug!("Refreshing device registration");
86
87 let mut headers = HashMap::new();
88 headers.insert("Authorization".to_string(), format!("Bearer {}", token));
89 headers.insert("Content-Type".to_string(), "application/json".to_string());
90
91 let body = serde_json::to_string(&device_body())
92 .map_err(|e| WebexError::device_registration(format!("Failed to serialize body: {e}"), None))?;
93
94 let response = (self.http_do)(FetchRequest {
95 url: device_url.to_string(),
96 method: "PUT".to_string(),
97 headers,
98 body: Some(body),
99 })
100 .await
101 .map_err(|e| WebexError::device_registration(format!("Failed to refresh device: {e}"), None))?;
102
103 let status = response.status;
104
105 if status == 401 {
106 error!("Device refresh failed: Unauthorized");
107 return Err(WebexError::auth("Unauthorized to refresh device"));
108 }
109
110 if !response.ok {
111 error!("Device refresh failed with status {status}");
112 return Err(WebexError::device_registration("Failed to refresh device", Some(status)));
113 }
114
115 let mut reg: DeviceRegistration = serde_json::from_slice(&response.body)
116 .map_err(|e| WebexError::device_registration(format!("Failed to parse response: {e}"), None))?;
117
118 reg.encryption_service_url = reg.services.get("encryptionServiceUrl").cloned().unwrap_or_default();
119
120 info!("Device refreshed successfully");
121 Ok(reg)
122 }
123
124 pub async fn unregister(&mut self, token: &str) -> Result<()> {
126 let device_url = self.device_url.as_deref().ok_or_else(|| {
127 WebexError::device_registration("Device not registered. Call register() first.", None)
128 })?;
129
130 debug!("Unregistering device");
131
132 let mut headers = HashMap::new();
133 headers.insert("Authorization".to_string(), format!("Bearer {}", token));
134 headers.insert("Content-Type".to_string(), "application/json".to_string());
135
136 let response = (self.http_do)(FetchRequest {
137 url: device_url.to_string(),
138 method: "DELETE".to_string(),
139 headers,
140 body: None,
141 })
142 .await
143 .map_err(|e| WebexError::device_registration(format!("Failed to unregister device: {e}"), None))?;
144
145 let status = response.status;
146
147 if status == 401 {
148 error!("Device unregistration failed: Unauthorized");
149 return Err(WebexError::auth("Unauthorized to unregister device"));
150 }
151
152 if !response.ok && status != 404 {
153 error!("Device unregistration failed with status {status}");
154 return Err(WebexError::device_registration("Failed to unregister device", Some(status)));
155 }
156
157 self.device_url = None;
158 info!("Device unregistered successfully");
159 Ok(())
160 }
161}