Skip to main content

unifly_api/command/
mod.rs

1// ── Command API ──
2//
3// All write operations flow through a unified `Command` enum.
4// The controller routes each variant to the appropriate API backend
5// (Integration API preferred, Session API for session-only operations).
6
7pub mod requests;
8
9use crate::core_error::CoreError;
10use crate::model::{
11    AclRule, Client, Device, DnsPolicy, EntityId, FirewallPolicy, FirewallZone, MacAddress,
12    Network, TrafficMatchingList, Voucher, WifiBroadcast,
13};
14
15pub use requests::{
16    CreateAclRuleRequest, CreateDnsPolicyRequest, CreateFirewallPolicyRequest,
17    CreateFirewallZoneRequest, CreateNatPolicyRequest, CreateNetworkRequest,
18    CreateRemoteAccessVpnServerRequest, CreateSiteToSiteVpnRequest,
19    CreateTrafficMatchingListRequest, CreateVouchersRequest, CreateVpnClientProfileRequest,
20    CreateWifiBroadcastRequest, CreateWireGuardPeerRequest, TrafficFilterSpec,
21    UpdateAclRuleRequest, UpdateDnsPolicyRequest, UpdateFirewallPolicyRequest,
22    UpdateFirewallZoneRequest, UpdateNatPolicyRequest, UpdateNetworkRequest,
23    UpdateRemoteAccessVpnServerRequest, UpdateSiteToSiteVpnRequest,
24    UpdateTrafficMatchingListRequest, UpdateVpnClientProfileRequest, UpdateWifiBroadcastRequest,
25    UpdateWireGuardPeerRequest,
26};
27
28/// A command envelope sent through the command channel.
29/// Contains the command and a oneshot response channel.
30pub(crate) struct CommandEnvelope {
31    pub command: Command,
32    pub response_tx: tokio::sync::oneshot::Sender<Result<CommandResult, CoreError>>,
33}
34
35/// All possible write operations against a UniFi controller.
36#[derive(Debug, Clone)]
37pub enum Command {
38    // ── Device operations ────────────────────────────────────────────
39    AdoptDevice {
40        mac: MacAddress,
41        ignore_device_limit: bool,
42    },
43    RemoveDevice {
44        id: EntityId,
45    },
46    RestartDevice {
47        id: EntityId,
48    },
49    LocateDevice {
50        mac: MacAddress,
51        enable: bool,
52    },
53    UpgradeDevice {
54        mac: MacAddress,
55        firmware_url: Option<String>,
56    },
57    ProvisionDevice {
58        mac: MacAddress,
59    },
60    SpeedtestDevice,
61    PowerCyclePort {
62        device_id: EntityId,
63        port_idx: u32,
64    },
65
66    // ── Client operations ────────────────────────────────────────────
67    BlockClient {
68        mac: MacAddress,
69    },
70    UnblockClient {
71        mac: MacAddress,
72    },
73    KickClient {
74        mac: MacAddress,
75    },
76    ForgetClient {
77        mac: MacAddress,
78    },
79    AuthorizeGuest {
80        client_id: EntityId,
81        time_limit_minutes: Option<u32>,
82        data_limit_mb: Option<u64>,
83        rx_rate_kbps: Option<u64>,
84        tx_rate_kbps: Option<u64>,
85    },
86    UnauthorizeGuest {
87        client_id: EntityId,
88    },
89    SetClientFixedIp {
90        mac: MacAddress,
91        ip: std::net::Ipv4Addr,
92        network_id: EntityId,
93    },
94    RemoveClientFixedIp {
95        mac: MacAddress,
96        network_id: Option<EntityId>,
97    },
98
99    // ── Network CRUD ─────────────────────────────────────────────────
100    CreateNetwork(CreateNetworkRequest),
101    UpdateNetwork {
102        id: EntityId,
103        update: UpdateNetworkRequest,
104    },
105    DeleteNetwork {
106        id: EntityId,
107        force: bool,
108    },
109
110    // ── WiFi CRUD ────────────────────────────────────────────────────
111    CreateWifiBroadcast(CreateWifiBroadcastRequest),
112    UpdateWifiBroadcast {
113        id: EntityId,
114        update: UpdateWifiBroadcastRequest,
115    },
116    DeleteWifiBroadcast {
117        id: EntityId,
118        force: bool,
119    },
120
121    // ── Firewall ─────────────────────────────────────────────────────
122    CreateFirewallPolicy(CreateFirewallPolicyRequest),
123    UpdateFirewallPolicy {
124        id: EntityId,
125        update: UpdateFirewallPolicyRequest,
126    },
127    DeleteFirewallPolicy {
128        id: EntityId,
129    },
130    PatchFirewallPolicy {
131        id: EntityId,
132        enabled: Option<bool>,
133        logging: Option<bool>,
134    },
135    ReorderFirewallPolicies {
136        zone_pair: (EntityId, EntityId),
137        ordered_ids: Vec<EntityId>,
138        after_system: bool,
139    },
140    CreateFirewallZone(CreateFirewallZoneRequest),
141    UpdateFirewallZone {
142        id: EntityId,
143        update: UpdateFirewallZoneRequest,
144    },
145    DeleteFirewallZone {
146        id: EntityId,
147    },
148
149    // ── NAT ──────────────────────────────────────────────────────────
150    CreateNatPolicy(CreateNatPolicyRequest),
151    UpdateNatPolicy {
152        id: EntityId,
153        update: UpdateNatPolicyRequest,
154    },
155    DeleteNatPolicy {
156        id: EntityId,
157    },
158
159    // ── VPN (Legacy) ────────────────────────────────────────────────
160    CreateSiteToSiteVpn(CreateSiteToSiteVpnRequest),
161    UpdateSiteToSiteVpn {
162        id: EntityId,
163        update: UpdateSiteToSiteVpnRequest,
164    },
165    DeleteSiteToSiteVpn {
166        id: EntityId,
167    },
168    CreateRemoteAccessVpnServer(CreateRemoteAccessVpnServerRequest),
169    UpdateRemoteAccessVpnServer {
170        id: EntityId,
171        update: UpdateRemoteAccessVpnServerRequest,
172    },
173    DeleteRemoteAccessVpnServer {
174        id: EntityId,
175    },
176    CreateVpnClientProfile(CreateVpnClientProfileRequest),
177    UpdateVpnClientProfile {
178        id: EntityId,
179        update: UpdateVpnClientProfileRequest,
180    },
181    DeleteVpnClientProfile {
182        id: EntityId,
183    },
184    CreateWireGuardPeer {
185        server_id: EntityId,
186        peer: CreateWireGuardPeerRequest,
187    },
188    UpdateWireGuardPeer {
189        server_id: EntityId,
190        peer_id: EntityId,
191        update: UpdateWireGuardPeerRequest,
192    },
193    DeleteWireGuardPeer {
194        server_id: EntityId,
195        peer_id: EntityId,
196    },
197    RestartVpnClientConnection {
198        id: EntityId,
199    },
200
201    // ── ACL ──────────────────────────────────────────────────────────
202    CreateAclRule(CreateAclRuleRequest),
203    UpdateAclRule {
204        id: EntityId,
205        update: UpdateAclRuleRequest,
206    },
207    DeleteAclRule {
208        id: EntityId,
209    },
210    ReorderAclRules {
211        ordered_ids: Vec<EntityId>,
212    },
213
214    // ── DNS ──────────────────────────────────────────────────────────
215    CreateDnsPolicy(CreateDnsPolicyRequest),
216    UpdateDnsPolicy {
217        id: EntityId,
218        update: UpdateDnsPolicyRequest,
219    },
220    DeleteDnsPolicy {
221        id: EntityId,
222    },
223
224    // ── Traffic matching lists ───────────────────────────────────────
225    CreateTrafficMatchingList(CreateTrafficMatchingListRequest),
226    UpdateTrafficMatchingList {
227        id: EntityId,
228        update: UpdateTrafficMatchingListRequest,
229    },
230    DeleteTrafficMatchingList {
231        id: EntityId,
232    },
233
234    // ── Hotspot / Vouchers ───────────────────────────────────────────
235    CreateVouchers(CreateVouchersRequest),
236    DeleteVoucher {
237        id: EntityId,
238    },
239    PurgeVouchers {
240        filter: String,
241    },
242
243    // ── Site settings (Session) ─────────────────────────────────────────
244    SetDpiEnabled {
245        enabled: bool,
246    },
247
248    // ── System (Session) ──────────────────────────────────────────────
249    ArchiveAlarm {
250        id: EntityId,
251    },
252    ArchiveAllAlarms,
253    CreateSite {
254        name: String,
255        description: String,
256    },
257    DeleteSite {
258        name: String,
259    },
260    CreateBackup,
261    DeleteBackup {
262        filename: String,
263    },
264    RebootController,
265    PoweroffController,
266    InviteAdmin {
267        name: String,
268        email: String,
269        role: String,
270    },
271    RevokeAdmin {
272        id: EntityId,
273    },
274    UpdateAdmin {
275        id: EntityId,
276        role: Option<String>,
277    },
278}
279
280/// Result of a command execution.
281#[derive(Debug)]
282pub enum CommandResult {
283    Ok,
284    Device(Device),
285    Client(Client),
286    Network(Network),
287    WifiBroadcast(WifiBroadcast),
288    FirewallPolicy(FirewallPolicy),
289    FirewallZone(FirewallZone),
290    AclRule(AclRule),
291    DnsPolicy(DnsPolicy),
292    Vouchers(Vec<Voucher>),
293    TrafficMatchingList(TrafficMatchingList),
294}