Skip to main content

unifly_core/command/
requests.rs

1// ── Typed request structs for Command payloads ──
2//
3// Every Command variant that previously took `serde_json::Value`
4// now uses one of these strongly-typed request structs instead.
5
6use serde::{Deserialize, Serialize};
7
8use crate::model::{
9    DnsPolicyType, EntityId, FirewallAction, NetworkManagement, NetworkPurpose, WifiSecurityMode,
10};
11
12// ── Network ────────────────────────────────────────────────────────
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15#[allow(clippy::struct_excessive_bools)]
16pub struct CreateNetworkRequest {
17    pub name: String,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub vlan_id: Option<u16>,
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub subnet: Option<String>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub management: Option<NetworkManagement>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub purpose: Option<NetworkPurpose>,
26    pub dhcp_enabled: bool,
27    pub enabled: bool,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub dhcp_range_start: Option<String>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub dhcp_range_stop: Option<String>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub dhcp_lease_time: Option<u32>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub firewall_zone_id: Option<String>,
36    pub isolation_enabled: bool,
37    pub internet_access_enabled: bool,
38}
39
40#[derive(Debug, Clone, Default, Serialize, Deserialize)]
41#[allow(clippy::struct_excessive_bools)]
42pub struct UpdateNetworkRequest {
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub name: Option<String>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub vlan_id: Option<u16>,
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub subnet: Option<String>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub dhcp_enabled: Option<bool>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub enabled: Option<bool>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub isolation_enabled: Option<bool>,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub internet_access_enabled: Option<bool>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub mdns_forwarding_enabled: Option<bool>,
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub ipv6_enabled: Option<bool>,
61}
62
63// ── WiFi ───────────────────────────────────────────────────────────
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66#[allow(clippy::struct_excessive_bools)]
67pub struct CreateWifiBroadcastRequest {
68    pub name: String,
69    pub ssid: String,
70    pub security_mode: WifiSecurityMode,
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub passphrase: Option<String>,
73    pub enabled: bool,
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub network_id: Option<EntityId>,
76    pub hide_ssid: bool,
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub broadcast_type: Option<String>,
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub frequencies_ghz: Option<Vec<f32>>,
81    #[serde(default)]
82    pub band_steering: bool,
83    #[serde(default)]
84    pub fast_roaming: bool,
85}
86
87#[derive(Debug, Clone, Default, Serialize, Deserialize)]
88pub struct UpdateWifiBroadcastRequest {
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub name: Option<String>,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub ssid: Option<String>,
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub security_mode: Option<WifiSecurityMode>,
95    #[serde(skip_serializing_if = "Option::is_none")]
96    pub passphrase: Option<String>,
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub enabled: Option<bool>,
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub hide_ssid: Option<bool>,
101}
102
103// ── Firewall Policy ────────────────────────────────────────────────
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct CreateFirewallPolicyRequest {
107    pub name: String,
108    pub action: FirewallAction,
109    pub source_zone_id: EntityId,
110    pub destination_zone_id: EntityId,
111    pub enabled: bool,
112    pub logging_enabled: bool,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub description: Option<String>,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub protocol: Option<String>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub source_address: Option<String>,
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub destination_address: Option<String>,
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub destination_port: Option<String>,
123}
124
125#[derive(Debug, Clone, Default, Serialize, Deserialize)]
126pub struct UpdateFirewallPolicyRequest {
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub name: Option<String>,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub action: Option<FirewallAction>,
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub enabled: Option<bool>,
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub description: Option<String>,
135    #[serde(skip_serializing_if = "Option::is_none")]
136    pub protocol: Option<String>,
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub source_address: Option<String>,
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub destination_address: Option<String>,
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub destination_port: Option<String>,
143}
144
145// ── Firewall Zone ──────────────────────────────────────────────────
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct CreateFirewallZoneRequest {
149    pub name: String,
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub description: Option<String>,
152    pub network_ids: Vec<EntityId>,
153}
154
155#[derive(Debug, Clone, Default, Serialize, Deserialize)]
156pub struct UpdateFirewallZoneRequest {
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub name: Option<String>,
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub description: Option<String>,
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub network_ids: Option<Vec<EntityId>>,
163}
164
165// ── ACL Rule ───────────────────────────────────────────────────────
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct CreateAclRuleRequest {
169    pub name: String,
170    #[serde(default = "default_acl_rule_type")]
171    pub rule_type: String,
172    pub action: FirewallAction,
173    pub source_zone_id: EntityId,
174    pub destination_zone_id: EntityId,
175    #[serde(skip_serializing_if = "Option::is_none")]
176    pub protocol: Option<String>,
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub source_port: Option<String>,
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub destination_port: Option<String>,
181    pub enabled: bool,
182}
183
184fn default_acl_rule_type() -> String {
185    "IPV4".into()
186}
187
188#[derive(Debug, Clone, Default, Serialize, Deserialize)]
189pub struct UpdateAclRuleRequest {
190    #[serde(skip_serializing_if = "Option::is_none")]
191    pub name: Option<String>,
192    #[serde(skip_serializing_if = "Option::is_none")]
193    pub action: Option<FirewallAction>,
194    #[serde(skip_serializing_if = "Option::is_none")]
195    pub enabled: Option<bool>,
196    #[serde(skip_serializing_if = "Option::is_none")]
197    pub protocol: Option<String>,
198}
199
200// ── DNS Policy ─────────────────────────────────────────────────────
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct CreateDnsPolicyRequest {
204    pub name: String,
205    pub policy_type: DnsPolicyType,
206    pub enabled: bool,
207    #[serde(skip_serializing_if = "Option::is_none")]
208    pub domains: Option<Vec<String>>,
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub upstream: Option<String>,
211    #[serde(skip_serializing_if = "Option::is_none")]
212    pub value: Option<String>,
213    #[serde(skip_serializing_if = "Option::is_none")]
214    pub ttl_seconds: Option<u32>,
215    #[serde(skip_serializing_if = "Option::is_none")]
216    pub priority: Option<u16>,
217}
218
219#[derive(Debug, Clone, Default, Serialize, Deserialize)]
220pub struct UpdateDnsPolicyRequest {
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub name: Option<String>,
223    #[serde(skip_serializing_if = "Option::is_none")]
224    pub enabled: Option<bool>,
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub domains: Option<Vec<String>>,
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub upstream: Option<String>,
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub value: Option<String>,
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub ttl_seconds: Option<u32>,
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub priority: Option<u16>,
235}
236
237// ── Traffic Matching List ──────────────────────────────────────────
238
239#[derive(Debug, Clone, Serialize, Deserialize)]
240pub struct CreateTrafficMatchingListRequest {
241    pub name: String,
242    #[serde(default = "default_traffic_list_type")]
243    pub list_type: String,
244    pub entries: Vec<String>,
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub description: Option<String>,
247}
248
249#[derive(Debug, Clone, Default, Serialize, Deserialize)]
250pub struct UpdateTrafficMatchingListRequest {
251    #[serde(skip_serializing_if = "Option::is_none")]
252    pub name: Option<String>,
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub entries: Option<Vec<String>>,
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub description: Option<String>,
257}
258
259fn default_traffic_list_type() -> String {
260    "IPV4".into()
261}
262
263// ── Vouchers ───────────────────────────────────────────────────────
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct CreateVouchersRequest {
267    pub count: u32,
268    #[serde(skip_serializing_if = "Option::is_none")]
269    pub name: Option<String>,
270    #[serde(skip_serializing_if = "Option::is_none")]
271    pub time_limit_minutes: Option<u32>,
272    #[serde(skip_serializing_if = "Option::is_none")]
273    pub data_usage_limit_mb: Option<u64>,
274    #[serde(skip_serializing_if = "Option::is_none")]
275    pub rx_rate_limit_kbps: Option<u64>,
276    #[serde(skip_serializing_if = "Option::is_none")]
277    pub tx_rate_limit_kbps: Option<u64>,
278    #[serde(skip_serializing_if = "Option::is_none")]
279    pub authorized_guest_limit: Option<u32>,
280}