@coffeerunhobby/mcp-ha-connect 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,511 @@
1
+ /**
2
+ * Controller-side access control: time-range profiles, IP/MAC group profiles,
3
+ * DHCP reservations, gateway ACL rules and the SSID MAC filter. These let a
4
+ * schedule (e.g. a curfew) be enforced by the controller itself instead of a
5
+ * daily block/unblock loop.
6
+ *
7
+ * Omada's create endpoints return no id, so new objects are found again by
8
+ * their (required unique) name or description. Deletes refuse objects that are
9
+ * still in use, and the SSID MAC filter refuses to lock out connected clients
10
+ * unless told to.
11
+ */
12
+ import { formatMac, normalizeMac } from './client.js';
13
+ import { MAC_GROUP_TYPE } from './macGroups.js';
14
+ import { ALWAYS_PROFILE_NAME } from './network.js';
15
+ import { accessControlLockKey, serialize } from './serialize.js';
16
+ import { buildTimeRange, describeTimeRange } from './timeRange.js';
17
+ export const IP_GROUP_TYPE = 0;
18
+ const SWITCH_ACL_PAGE_SIZE = 50;
19
+ /** All protocols, in Omada's ACL protocol numbering. */
20
+ export const ALL_PROTOCOLS = 256;
21
+ const SOURCE_TYPES = { network: 0, ipGroup: 1, ssid: 4 };
22
+ const DESTINATION_TYPES = { network: 0, ipGroup: 1 };
23
+ export class AccessControlOperations {
24
+ request;
25
+ site;
26
+ buildPath;
27
+ network;
28
+ macGroups;
29
+ clients;
30
+ constructor(request, site, buildPath, network, macGroups, clients) {
31
+ this.request = request;
32
+ this.site = site;
33
+ this.buildPath = buildPath;
34
+ this.network = network;
35
+ this.macGroups = macGroups;
36
+ this.clients = clients;
37
+ }
38
+ // Writes are serialized per site, together with MAC group edits: Omada replaces
39
+ // whole objects, and objects reference each other (a rule its time range and
40
+ // groups, an SSID filter its MAC group), so no two changes may interleave.
41
+ createTimeRange(...a) {
42
+ return this.locked(a[2]?.siteId, () => this.createTimeRangeUnlocked(...a));
43
+ }
44
+ updateTimeRange(...a) {
45
+ return this.locked(a[2]?.siteId, () => this.updateTimeRangeUnlocked(...a));
46
+ }
47
+ deleteTimeRange(...a) {
48
+ return this.locked(a[1], () => this.deleteTimeRangeUnlocked(...a));
49
+ }
50
+ createGroup(...a) {
51
+ return this.locked(a[1], () => this.createGroupUnlocked(...a));
52
+ }
53
+ deleteGroup(...a) {
54
+ return this.locked(a[2], () => this.deleteGroupUnlocked(...a));
55
+ }
56
+ setDhcpReservation(...a) {
57
+ return this.locked(a[3], () => this.setDhcpReservationUnlocked(...a));
58
+ }
59
+ removeDhcpReservation(...a) {
60
+ return this.locked(a[1], () => this.removeDhcpReservationUnlocked(...a));
61
+ }
62
+ createGatewayAcl(...a) {
63
+ return this.locked(a[1], () => this.createGatewayAclUnlocked(...a));
64
+ }
65
+ updateGatewayAcl(...a) {
66
+ return this.locked(a[2], () => this.updateGatewayAclUnlocked(...a));
67
+ }
68
+ deleteGatewayAcl(...a) {
69
+ return this.locked(a[1], () => this.deleteGatewayAclUnlocked(...a));
70
+ }
71
+ moveGatewayAcl(...a) {
72
+ return this.locked(a[2], () => this.moveGatewayAclUnlocked(...a));
73
+ }
74
+ setSsidMacFilter(...a) {
75
+ return this.locked(a[2]?.siteId, () => this.setSsidMacFilterUnlocked(...a));
76
+ }
77
+ locked(siteId, task) {
78
+ return serialize(accessControlLockKey(this.site.resolveSiteId(siteId)), task);
79
+ }
80
+ sitePath(siteId, path) {
81
+ return this.buildPath(`/sites/${encodeURIComponent(siteId)}${path}`);
82
+ }
83
+ async send(method, url, data) {
84
+ this.request.ensureSuccess(await this.request.request({ method, url, data }));
85
+ }
86
+ // ---- time-range profiles ------------------------------------------------
87
+ async listTimeRanges(siteId) {
88
+ const resolved = this.site.resolveSiteId(siteId);
89
+ const profiles = this.request.ensureSuccess(await this.request.get(this.sitePath(resolved, '/time-range-profiles')));
90
+ return (profiles ?? []).map((p) => ({ ...p, windows: describeTimeRange(p) }));
91
+ }
92
+ async createTimeRangeUnlocked(name, windows, options = {}) {
93
+ const resolved = this.site.resolveSiteId(options.siteId);
94
+ const body = buildTimeRange(checkTimeRangeName(name), windows, options.invert);
95
+ if ((await this.listTimeRanges(resolved)).some((p) => p.name === body.name)) {
96
+ throw new Error(`A time range named '${body.name}' already exists; update it or pick another name`);
97
+ }
98
+ await this.send('POST', this.sitePath(resolved, '/time-range-profiles'), body);
99
+ const created = (await this.listTimeRanges(resolved)).find((p) => p.name === body.name);
100
+ if (!created)
101
+ throw new Error(`Created time range '${body.name}' but could not find it again`);
102
+ return { profileId: created.profileId, name: created.name, windows: created.windows };
103
+ }
104
+ async updateTimeRangeUnlocked(profile, windows, options = {}) {
105
+ const resolved = this.site.resolveSiteId(options.siteId);
106
+ const current = this.resolveTimeRange(await this.listTimeRanges(resolved), profile);
107
+ const name = options.name !== undefined ? checkTimeRangeName(options.name) : current.name;
108
+ const body = buildTimeRange(name, windows, options.invert);
109
+ await this.send('PUT', this.sitePath(resolved, `/time-range-profile/${encodeURIComponent(current.profileId)}`), body);
110
+ return { profileId: current.profileId, name, before: current.windows, after: describeTimeRange(body) };
111
+ }
112
+ async deleteTimeRangeUnlocked(profile, siteId) {
113
+ const resolved = this.site.resolveSiteId(siteId);
114
+ const current = this.resolveTimeRange(await this.listTimeRanges(resolved), profile);
115
+ const users = await this.timeRangeUsers(current.profileId, resolved);
116
+ if (users.length)
117
+ throw new Error(`Time range '${current.name}' is used by ${users.join(', ')}; change or delete those first`);
118
+ await this.send('DELETE', this.sitePath(resolved, `/time-range-profile/${encodeURIComponent(current.profileId)}`));
119
+ return { profileId: current.profileId, name: current.name, deleted: true };
120
+ }
121
+ /** What references a time range: gateway and switch ACL rules, SSID WLAN schedules. */
122
+ async timeRangeUsers(profileId, siteId) {
123
+ const users = (await this.listGatewayAcls(siteId)).filter((a) => a.timeRangeId === profileId).map((a) => `gateway ACL '${a.description}'`);
124
+ // The switch ACL list rejects page sizes above 50 or so (errorCode -1001 with 200).
125
+ const switchAcls = await this.request.fetchPaginated(this.sitePath(siteId, '/acls/osw-acls'), { pageSize: SWITCH_ACL_PAGE_SIZE });
126
+ users.push(...switchAcls.filter((a) => a.timeRangeId === profileId).map((a) => `switch ACL '${a.description}'`));
127
+ for (const wlan of await this.network.listAllSsids(siteId)) {
128
+ for (const ssid of wlan.ssidList ?? []) {
129
+ const detail = (await this.network.getSsidDetail(wlan.wlanId, ssid.ssidId, siteId));
130
+ if (detail?.wlanSchedule?.scheduleId === profileId)
131
+ users.push(`the Wi-Fi schedule of SSID ${ssid.ssidName}`);
132
+ }
133
+ }
134
+ return users;
135
+ }
136
+ resolveTimeRange(profiles, profile) {
137
+ const found = resolveByIdOrName(profiles, profile, (p) => p.profileId, (p) => p.name, 'time range');
138
+ if (found.name === ALWAYS_PROFILE_NAME) {
139
+ throw new Error(`Time range '${found.name}' belongs to omada_setSsidEnabled and cannot be changed here`);
140
+ }
141
+ return found;
142
+ }
143
+ // ---- group profiles -------------------------------------------------------
144
+ async listIpGroups(siteId) {
145
+ const resolved = this.site.resolveSiteId(siteId);
146
+ const groups = this.request.ensureSuccess(await this.request.get(this.sitePath(resolved, `/profiles/groups/${IP_GROUP_TYPE}`)));
147
+ return groups ?? [];
148
+ }
149
+ /** Create an IP group (addresses as "a.b.c.d" or "a.b.c.d/n") or a MAC group. */
150
+ async createGroupUnlocked(input, siteId) {
151
+ const resolved = this.site.resolveSiteId(siteId);
152
+ const name = input.name.trim();
153
+ if (name.length < 1 || name.length > 64)
154
+ throw new Error('Group name must be 1 to 64 characters');
155
+ const existing = input.type === 'ip' ? await this.listIpGroups(resolved) : await this.macGroups.listMacGroups(resolved);
156
+ if (existing.some((g) => g.name.toLowerCase() === name.toLowerCase())) {
157
+ throw new Error(`A ${input.type.toUpperCase()} group named '${name}' already exists`);
158
+ }
159
+ const body = input.type === 'ip'
160
+ ? { name, type: IP_GROUP_TYPE, ipList: input.ips.map(parseCidr) }
161
+ : { name, type: MAC_GROUP_TYPE, macAddressList: input.macs.map((m) => ({ name: m.name, macAddress: formatMac(m.mac) })) };
162
+ if ((input.type === 'ip' ? input.ips : input.macs).length === 0)
163
+ throw new Error('A group needs at least one entry');
164
+ await this.send('POST', this.sitePath(resolved, '/profiles/groups'), body);
165
+ const after = input.type === 'ip' ? await this.listIpGroups(resolved) : await this.macGroups.listMacGroups(resolved);
166
+ const created = after.find((g) => g.name === name);
167
+ if (!created)
168
+ throw new Error(`Created group '${name}' but could not find it again`);
169
+ return { groupId: created.groupId, name, type: input.type, entries: input.type === 'ip' ? body.ipList : body.macAddressList };
170
+ }
171
+ async deleteGroupUnlocked(group, type, siteId) {
172
+ const resolved = this.site.resolveSiteId(siteId);
173
+ const groups = type === 'ip' ? await this.listIpGroups(resolved) : await this.macGroups.listMacGroups(resolved);
174
+ const target = resolveByIdOrName(groups, group, (g) => g.groupId, (g) => g.name, `${type.toUpperCase()} group`);
175
+ if (target.buildIn || target.name === 'IPGroup_Any')
176
+ throw new Error(`Group '${target.name}' is built in and cannot be deleted`);
177
+ const users = [];
178
+ for (const acl of await this.listGatewayAcls(resolved)) {
179
+ const asSource = acl.sourceType === SOURCE_TYPES.ipGroup && acl.sourceIds.includes(target.groupId);
180
+ const asDestination = acl.destinationType === DESTINATION_TYPES.ipGroup && (acl.destinationIds ?? []).includes(target.groupId);
181
+ if (asSource || asDestination)
182
+ users.push(`gateway ACL '${acl.description}'`);
183
+ }
184
+ if (type === 'mac') {
185
+ for (const s of await this.listSsidFilters(resolved)) {
186
+ if (s.filter.macFilterId === target.groupId)
187
+ users.push(`the MAC filter of SSID ${s.ssidName}`);
188
+ }
189
+ }
190
+ if (users.length)
191
+ throw new Error(`Group '${target.name}' is used by ${users.join(', ')}; change those first`);
192
+ const groupType = type === 'ip' ? IP_GROUP_TYPE : MAC_GROUP_TYPE;
193
+ await this.send('DELETE', this.sitePath(resolved, `/profiles/groups/${groupType}/${encodeURIComponent(target.groupId)}`));
194
+ return { groupId: target.groupId, name: target.name, type, deleted: true };
195
+ }
196
+ // ---- DHCP reservations -----------------------------------------------------
197
+ async listDhcpReservations(siteId) {
198
+ const resolved = this.site.resolveSiteId(siteId);
199
+ return await this.request.fetchPaginated(this.sitePath(resolved, '/setting/service/dhcp'));
200
+ }
201
+ /** Reserve `ip` for a MAC (create or change). The LAN network is the one whose subnet holds the IP. */
202
+ async setDhcpReservationUnlocked(clientMac, ip, description, siteId) {
203
+ const resolved = this.site.resolveSiteId(siteId);
204
+ const mac = formatMac(clientMac);
205
+ const address = ipToNumber(ip);
206
+ const networks = (await this.network.getLanNetworkList(resolved));
207
+ const net = networks.find((n) => n.gatewaySubnet && inSubnet(address, n.gatewaySubnet));
208
+ if (!net) {
209
+ throw new Error(`${ip} is in no LAN network (${networks.map((n) => `${n.name} ${n.gatewaySubnet ?? '?'}`).join(', ') || 'none'})`);
210
+ }
211
+ const reservations = await this.listDhcpReservations(resolved);
212
+ const clash = reservations.find((r) => r.ip === ip && normalizeMac(r.mac) !== normalizeMac(mac));
213
+ if (clash)
214
+ throw new Error(`${ip} is already reserved for ${clash.mac}${clash.description ? ` (${clash.description})` : ''}`);
215
+ const current = reservations.find((r) => normalizeMac(r.mac) === normalizeMac(mac));
216
+ const text = description?.trim() || current?.description;
217
+ if (text !== undefined && text.length > 128)
218
+ throw new Error('Description must be at most 128 characters');
219
+ if (current && current.ip === ip && current.netId === net.id && current.status !== false && current.description === text) {
220
+ return { mac, ip, network: net.name, action: 'unchanged' };
221
+ }
222
+ const body = { netId: net.id, mac, ip, description: text || undefined, status: true, options: current?.options ?? [] };
223
+ if (current) {
224
+ await this.send('PATCH', this.sitePath(resolved, `/setting/service/dhcp/${encodeURIComponent(mac)}`), body);
225
+ }
226
+ else {
227
+ await this.send('POST', this.sitePath(resolved, '/setting/service/dhcp'), body);
228
+ }
229
+ return {
230
+ mac,
231
+ ip,
232
+ network: net.name,
233
+ action: current ? 'updated' : 'created',
234
+ ...(current ? { previousIp: current.ip } : {}),
235
+ note: 'The device gets the reserved address at its next DHCP renewal (reconnect it to apply now).',
236
+ };
237
+ }
238
+ async removeDhcpReservationUnlocked(clientMac, siteId) {
239
+ const resolved = this.site.resolveSiteId(siteId);
240
+ const mac = formatMac(clientMac);
241
+ const current = (await this.listDhcpReservations(resolved)).find((r) => normalizeMac(r.mac) === normalizeMac(mac));
242
+ if (!current)
243
+ return { mac, action: 'not-present' };
244
+ await this.send('DELETE', this.sitePath(resolved, `/setting/service/dhcp/${encodeURIComponent(formatMac(current.mac))}`));
245
+ return { mac, ip: current.ip, action: 'removed' };
246
+ }
247
+ // ---- gateway ACL -------------------------------------------------------------
248
+ async listGatewayAcls(siteId) {
249
+ const resolved = this.site.resolveSiteId(siteId);
250
+ const acls = await this.request.fetchPaginated(this.sitePath(resolved, '/acls/osg-acls'));
251
+ return [...acls].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));
252
+ }
253
+ async createGatewayAclUnlocked(input, siteId) {
254
+ const resolved = this.site.resolveSiteId(siteId);
255
+ const description = checkDescription(input.description);
256
+ const existing = await this.listGatewayAcls(resolved);
257
+ if (existing.some((a) => a.description === description)) {
258
+ throw new Error(`A gateway ACL described '${description}' already exists; descriptions must be unique`);
259
+ }
260
+ const body = {
261
+ description,
262
+ status: input.enabled ?? true,
263
+ policy: input.policy === 'allow' ? 1 : 0,
264
+ protocols: input.protocols?.length ? input.protocols : [ALL_PROTOCOLS],
265
+ ...(await this.resolveEndpoints(input.source, input.destination, resolved)),
266
+ syslog: false,
267
+ direction: { lanToWan: true, lanToLan: false, wanInIds: [], vpnInIds: [] },
268
+ stateMode: 0,
269
+ };
270
+ if (input.timeRange)
271
+ body.timeRangeId = await this.timeRangeId(input.timeRange, resolved);
272
+ await this.send('POST', this.sitePath(resolved, '/acls/osg-acls'), body);
273
+ const created = (await this.listGatewayAcls(resolved)).find((a) => a.description === description);
274
+ if (!created)
275
+ throw new Error(`Created gateway ACL '${description}' but could not find it again`);
276
+ return await this.describeAcl(created, resolved);
277
+ }
278
+ async updateGatewayAclUnlocked(acl, changes, siteId) {
279
+ const resolved = this.site.resolveSiteId(siteId);
280
+ const acls = await this.listGatewayAcls(resolved);
281
+ const current = resolveByIdOrName(acls, acl, (a) => a.id, (a) => a.description, 'gateway ACL');
282
+ const description = changes.description !== undefined ? checkDescription(changes.description) : current.description;
283
+ if (description !== current.description && acls.some((a) => a.description === description)) {
284
+ throw new Error(`A gateway ACL described '${description}' already exists`);
285
+ }
286
+ const body = {
287
+ description,
288
+ status: changes.enabled ?? current.status,
289
+ policy: changes.policy ? (changes.policy === 'allow' ? 1 : 0) : current.policy,
290
+ protocols: changes.protocols?.length ? changes.protocols : current.protocols,
291
+ sourceType: current.sourceType,
292
+ sourceIds: current.sourceIds,
293
+ destinationType: current.destinationType,
294
+ destinationIds: current.destinationIds ?? [],
295
+ syslog: current.syslog ?? false,
296
+ direction: current.direction ?? { lanToWan: true, lanToLan: false, wanInIds: [], vpnInIds: [] },
297
+ stateMode: current.stateMode ?? 0,
298
+ ...(current.states ? { states: current.states } : {}),
299
+ };
300
+ if (changes.source || changes.destination) {
301
+ const endpoints = await this.resolveEndpoints(changes.source ?? { type: typeName(SOURCE_TYPES, current.sourceType), ids: current.sourceIds }, changes.destination ?? { type: typeName(DESTINATION_TYPES, current.destinationType), ids: current.destinationIds ?? [] }, resolved);
302
+ Object.assign(body, endpoints);
303
+ }
304
+ const timeRangeId = changes.timeRange === undefined ? current.timeRangeId : changes.timeRange === null ? undefined : await this.timeRangeId(changes.timeRange, resolved);
305
+ if (timeRangeId)
306
+ body.timeRangeId = timeRangeId;
307
+ // Re-read right before writing; refuse if the rule changed in between (e.g. in the web UI).
308
+ const latest = (await this.listGatewayAcls(resolved)).find((a) => a.id === current.id);
309
+ if (!latest || JSON.stringify(latest) !== JSON.stringify(current)) {
310
+ throw new Error(`Gateway ACL '${current.description}' changed while preparing the update; nothing was written. Try again.`);
311
+ }
312
+ await this.send('PUT', this.sitePath(resolved, `/acls/osg-acls/${encodeURIComponent(current.id)}`), body);
313
+ const updated = (await this.listGatewayAcls(resolved)).find((a) => a.id === current.id) ?? { ...current, ...body };
314
+ return await this.describeAcl(updated, resolved);
315
+ }
316
+ async deleteGatewayAclUnlocked(acl, siteId) {
317
+ const resolved = this.site.resolveSiteId(siteId);
318
+ const current = resolveByIdOrName(await this.listGatewayAcls(resolved), acl, (a) => a.id, (a) => a.description, 'gateway ACL');
319
+ await this.send('DELETE', this.sitePath(resolved, `/acls/${encodeURIComponent(current.id)}`));
320
+ return { id: current.id, description: current.description, deleted: true };
321
+ }
322
+ /** Move a rule to `position` (1 = evaluated first); the others keep their order. */
323
+ async moveGatewayAclUnlocked(acl, position, siteId) {
324
+ const resolved = this.site.resolveSiteId(siteId);
325
+ const acls = await this.listGatewayAcls(resolved);
326
+ const current = resolveByIdOrName(acls, acl, (a) => a.id, (a) => a.description, 'gateway ACL');
327
+ if (!Number.isInteger(position) || position < 1 || position > acls.length) {
328
+ throw new Error(`Position must be 1 to ${acls.length}`);
329
+ }
330
+ const order = acls.filter((a) => a.id !== current.id);
331
+ order.splice(position - 1, 0, current);
332
+ const indexes = Object.fromEntries(order.map((a, i) => [a.id, i + 1]));
333
+ await this.send('POST', this.sitePath(resolved, '/acls/modifyIndex'), { type: 'gateway', indexes });
334
+ return { order: order.map((a, i) => `${i + 1}. ${a.description}`) };
335
+ }
336
+ /** A rule with names instead of ids, for responses. */
337
+ async describeAcl(acl, siteId) {
338
+ const resolved = this.site.resolveSiteId(siteId);
339
+ const names = await this.endpointNames(resolved);
340
+ // Display only: a type these tools do not edit (e.g. an IP-port group) is shown by its number.
341
+ const label = (type, ids, table) => `${Object.keys(table).find((key) => table[key] === type) ?? `type ${type}`}: ${(ids ?? []).map((id) => names.get(id) ?? id).join(', ') || '(none)'}`;
342
+ const ranges = await this.listTimeRanges(resolved);
343
+ const range = acl.timeRangeId ? ranges.find((p) => p.profileId === acl.timeRangeId) : undefined;
344
+ return {
345
+ id: acl.id,
346
+ position: acl.index,
347
+ description: acl.description,
348
+ enabled: acl.status,
349
+ policy: acl.policy === 1 ? 'allow' : 'deny',
350
+ source: label(acl.sourceType, acl.sourceIds, SOURCE_TYPES),
351
+ destination: label(acl.destinationType, acl.destinationIds, DESTINATION_TYPES),
352
+ schedule: acl.timeRangeId ? { profileId: acl.timeRangeId, name: range?.name, windows: range?.windows } : 'always',
353
+ };
354
+ }
355
+ async resolveEndpoints(source, destination, siteId) {
356
+ if (!(source.type in SOURCE_TYPES))
357
+ throw new Error(`Source type must be one of ${Object.keys(SOURCE_TYPES).join(', ')}`);
358
+ if (source.ids.length === 0)
359
+ throw new Error('The rule needs at least one source');
360
+ const dest = destination ?? { type: 'ipGroup', ids: ['IPGroup_Any'] };
361
+ if (!(dest.type in DESTINATION_TYPES))
362
+ throw new Error(`Destination type must be one of ${Object.keys(DESTINATION_TYPES).join(', ')}`);
363
+ if (dest.ids.length === 0)
364
+ throw new Error('The rule needs at least one destination');
365
+ return {
366
+ sourceType: SOURCE_TYPES[source.type],
367
+ sourceIds: await this.resolveIds(source.type, source.ids, siteId),
368
+ destinationType: DESTINATION_TYPES[dest.type],
369
+ destinationIds: await this.resolveIds(dest.type, dest.ids, siteId),
370
+ };
371
+ }
372
+ /** Ids or names of IP groups, LAN networks or SSIDs -> ids. */
373
+ async resolveIds(type, values, siteId) {
374
+ const candidates = type === 'ipGroup'
375
+ ? (await this.listIpGroups(siteId)).map((g) => ({ id: g.groupId, name: g.name }))
376
+ : type === 'network'
377
+ ? (await this.network.getLanNetworkList(siteId)).map((n) => ({ id: n.id, name: n.name }))
378
+ : (await this.network.listAllSsids(siteId)).flatMap((w) => (w.ssidList ?? []).map((s) => ({ id: s.ssidId, name: s.ssidName })));
379
+ return values.map((v) => resolveByIdOrName(candidates, v, (c) => c.id, (c) => c.name, typeLabel(type)).id);
380
+ }
381
+ async endpointNames(siteId) {
382
+ const names = new Map();
383
+ const safe = async (read) => await read().catch(() => []);
384
+ for (const g of await safe(() => this.listIpGroups(siteId)))
385
+ names.set(g.groupId, g.name);
386
+ for (const n of await safe(() => this.network.getLanNetworkList(siteId)))
387
+ names.set(n.id, n.name);
388
+ for (const w of await safe(() => this.network.listAllSsids(siteId)))
389
+ for (const s of w.ssidList ?? [])
390
+ names.set(s.ssidId, s.ssidName);
391
+ return names;
392
+ }
393
+ async timeRangeId(profile, siteId) {
394
+ return resolveByIdOrName(await this.listTimeRanges(siteId), profile, (p) => p.profileId, (p) => p.name, 'time range').profileId;
395
+ }
396
+ // ---- SSID MAC filter -----------------------------------------------------------
397
+ async listSsidFilters(siteId) {
398
+ const result = [];
399
+ for (const wlan of await this.network.listAllSsids(siteId)) {
400
+ for (const s of wlan.ssidList ?? []) {
401
+ const detail = (await this.network.getSsidDetail(wlan.wlanId, s.ssidId, siteId));
402
+ result.push({ wlanId: wlan.wlanId, ssidId: s.ssidId, ssidName: s.ssidName, filter: (detail?.macFilter ?? {}) });
403
+ }
404
+ }
405
+ return result;
406
+ }
407
+ /**
408
+ * Turn an SSID's MAC filter on (allow or deny list = a MAC group) or off.
409
+ * Reports which connected clients of that SSID the new setting would cut off,
410
+ * and refuses to apply then unless `allowLockout` is set. dryRun only reports.
411
+ */
412
+ async setSsidMacFilterUnlocked(ssid, setting, options = {}) {
413
+ const resolved = this.site.resolveSiteId(options.siteId);
414
+ const filters = await this.listSsidFilters(resolved);
415
+ const target = resolveByIdOrName(filters, ssid, (f) => f.ssidId, (f) => f.ssidName, 'SSID');
416
+ const groups = await this.macGroups.listMacGroups(resolved);
417
+ const groupName = (id) => groups.find((g) => g.groupId === id)?.name ?? id;
418
+ const policyName = (p) => (p === undefined ? undefined : p === 1 ? 'allow' : 'deny');
419
+ const before = { enabled: target.filter.macFilterEnable === true, policy: policyName(target.filter.policy), group: groupName(target.filter.macFilterId) };
420
+ let after = { enabled: false, policy: before.policy, group: before.group };
421
+ let body = { macFilterEnable: false };
422
+ let wouldLockOut = [];
423
+ if (setting.enabled) {
424
+ const policy = setting.policy ?? before.policy;
425
+ if (!policy)
426
+ throw new Error('Say whether the group is an allow list or a deny list (policy)');
427
+ const groupKey = setting.group ?? target.filter.macFilterId;
428
+ if (!groupKey)
429
+ throw new Error('Name the MAC group to filter by (group)');
430
+ const group = this.macGroups.resolveGroup(groups, groupKey);
431
+ const members = new Set((group.macAddressList ?? []).map((e) => normalizeMac(e.macAddress)));
432
+ const connected = (await this.clients.listClients(resolved)).filter((c) => c.ssid === target.ssidName);
433
+ wouldLockOut = connected
434
+ .filter((c) => (policy === 'allow' ? !members.has(normalizeMac(c.mac)) : members.has(normalizeMac(c.mac))))
435
+ .map((c) => ({ mac: formatMac(c.mac), name: c.name }));
436
+ after = { enabled: true, policy, group: group.name };
437
+ body = { macFilterEnable: true, policy: policy === 'allow' ? 1 : 0, macFilterId: group.groupId };
438
+ }
439
+ const change = { ssid: target.ssidName, ssidId: target.ssidId, before, after, wouldLockOut, applied: false };
440
+ if (options.dryRun)
441
+ return change;
442
+ if (wouldLockOut.length && !options.allowLockout) {
443
+ throw new Error(`This would disconnect ${wouldLockOut.length} connected client(s) of ${target.ssidName}: ` +
444
+ `${wouldLockOut.map((c) => `${c.name ?? '?'} (${c.mac})`).join(', ')}. ` +
445
+ 'Add them to the group first, or repeat with allowLockout if that is intended. Nothing was changed.');
446
+ }
447
+ await this.send('PATCH', this.sitePath(resolved, `/wireless-network/wlans/${encodeURIComponent(target.wlanId)}/ssids/${encodeURIComponent(target.ssidId)}/update-mac-filter`), body);
448
+ return { ...change, applied: true };
449
+ }
450
+ }
451
+ /** A user profile must not take the reserved name omada_setSsidEnabled finds its 24/7 profile by. */
452
+ function checkTimeRangeName(value) {
453
+ const name = value.trim();
454
+ if (name.length < 1 || name.length > 64)
455
+ throw new Error('Time range name must be 1 to 64 characters');
456
+ if (name === ALWAYS_PROFILE_NAME)
457
+ throw new Error(`The name '${ALWAYS_PROFILE_NAME}' is reserved for omada_setSsidEnabled`);
458
+ return name;
459
+ }
460
+ function resolveByIdOrName(items, wanted, id, name, what) {
461
+ const byId = items.find((item) => id(item) === wanted);
462
+ if (byId)
463
+ return byId;
464
+ const needle = wanted.trim().toLowerCase();
465
+ const byName = items.filter((item) => name(item).toLowerCase() === needle);
466
+ if (byName.length === 1)
467
+ return byName[0];
468
+ if (byName.length > 1)
469
+ throw new Error(`Several ${what}s are named '${wanted}'; use the id`);
470
+ const available = items.map((item) => `${name(item)} (${id(item)})`).join(', ');
471
+ throw new Error(`${what[0].toUpperCase()}${what.slice(1)} '${wanted}' not found. Available: ${available || '(none)'}`);
472
+ }
473
+ function typeName(table, value) {
474
+ const found = Object.keys(table).find((key) => table[key] === value);
475
+ if (!found)
476
+ throw new Error(`This rule uses an endpoint type (${value}) these tools do not handle; edit it in the Omada web UI`);
477
+ return found;
478
+ }
479
+ function typeLabel(type) {
480
+ return type === 'ipGroup' ? 'IP group' : type === 'network' ? 'LAN network' : 'SSID';
481
+ }
482
+ function checkDescription(value) {
483
+ const text = value.trim();
484
+ if (text.length < 1 || text.length > 512)
485
+ throw new Error('Description must be 1 to 512 characters');
486
+ return text;
487
+ }
488
+ function ipToNumber(ip) {
489
+ const parts = ip.trim().split('.');
490
+ if (parts.length !== 4 || parts.some((p) => !/^\d{1,3}$/.test(p) || Number(p) > 255)) {
491
+ throw new Error(`'${ip}' is not an IPv4 address`);
492
+ }
493
+ return parts.reduce((n, p) => n * 256 + Number(p), 0);
494
+ }
495
+ function inSubnet(address, cidr) {
496
+ const [base, bits] = cidr.split('/');
497
+ const mask = Number(bits);
498
+ if (!base || !Number.isInteger(mask) || mask < 0 || mask > 32)
499
+ return false;
500
+ const size = 2 ** (32 - mask);
501
+ return Math.floor(address / size) === Math.floor(ipToNumber(base) / size);
502
+ }
503
+ function parseCidr(value) {
504
+ const [ip, bits] = value.trim().split('/');
505
+ ipToNumber(ip);
506
+ const mask = bits === undefined ? 32 : Number(bits);
507
+ if (!Number.isInteger(mask) || mask < 1 || mask > 32)
508
+ throw new Error(`'${value}': the mask must be 1 to 32`);
509
+ return { ip, mask };
510
+ }
511
+ //# sourceMappingURL=accessControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessControl.js","sourceRoot":"","sources":["../../src/omadaClient/accessControl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAwC,MAAM,gBAAgB,CAAC;AAEzG,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,wDAAwD;AACxD,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC,MAAM,YAAY,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AAClE,MAAM,iBAAiB,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAW,CAAC;AAkF9D,MAAM,OAAO,uBAAuB;IAEX;IACA;IACA;IACA;IACA;IACA;IANrB,YACqB,OAAuB,EACvB,IAAoB,EACpB,SAAmC,EACnC,OAA0B,EAC1B,SAA6B,EAC7B,OAAyB;QALzB,YAAO,GAAP,OAAO,CAAgB;QACvB,SAAI,GAAJ,IAAI,CAAgB;QACpB,cAAS,GAAT,SAAS,CAA0B;QACnC,YAAO,GAAP,OAAO,CAAmB;QAC1B,cAAS,GAAT,SAAS,CAAoB;QAC7B,YAAO,GAAP,OAAO,CAAkB;IAC3C,CAAC;IAEJ,gFAAgF;IAChF,6EAA6E;IAC7E,2EAA2E;IAEpE,eAAe,CAAC,GAAG,CAAiE;QACvF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC;IACM,eAAe,CAAC,GAAG,CAAiE;QACvF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC;IACM,eAAe,CAAC,GAAG,CAAiE;QACvF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IACM,WAAW,CAAC,GAAG,CAA6D;QAC/E,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;IACM,WAAW,CAAC,GAAG,CAA6D;QAC/E,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC;IACM,kBAAkB,CAAC,GAAG,CAAoE;QAC7F,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;IACM,qBAAqB,CAAC,GAAG,CAAuE;QACnG,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,CAAC;IACM,gBAAgB,CAAC,GAAG,CAAkE;QACzF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IACM,gBAAgB,CAAC,GAAG,CAAkE;QACzF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IACM,gBAAgB,CAAC,GAAG,CAAkE;QACzF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IACM,cAAc,CAAC,GAAG,CAAgE;QACrF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IACM,gBAAgB,CAAC,GAAG,CAAkE;QACzF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,MAAM,CAAI,MAA0B,EAAE,IAAsB;QAChE,OAAO,SAAS,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAClF,CAAC;IAEO,QAAQ,CAAC,MAAc,EAAE,IAAY;QACzC,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,MAA2C,EAAE,GAAW,EAAE,IAAc;QACvF,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAA4B,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7G,CAAC;IAED,4EAA4E;IAErE,KAAK,CAAC,cAAc,CAAC,MAAe;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CACvC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAuC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC,CAChH,CAAC;QACF,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClF,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,IAAY,EAAE,OAAqB,EAAE,UAAiD,EAAE;QAC1H,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,cAAc,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1E,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,IAAI,kDAAkD,CAAC,CAAC;QACxG,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/E,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QACxF,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,IAAI,+BAA+B,CAAC,CAAC;QAC/F,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1F,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,OAAe,EAAE,OAAqB,EAAE,UAAgE,EAAE;QAC5I,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAC1F,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACtH,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;IAC3G,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,OAAe,EAAE,MAAe;QAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QACpF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACrE,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,OAAO,CAAC,IAAI,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC/H,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;QACnH,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC/E,CAAC;IAED,uFAAuF;IAC/E,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,MAAc;QAC1D,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC;QAC3I,oFAAoF;QACpF,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAa,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC9I,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QACjH,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;gBACrC,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAA+C,CAAC;gBAClI,IAAI,MAAM,EAAE,YAAY,EAAE,UAAU,KAAK,SAAS;oBAAE,KAAK,CAAC,IAAI,CAAC,8BAA8B,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAClH,CAAC;QACL,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,gBAAgB,CAA6B,QAAa,EAAE,OAAe;QAC/E,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACpG,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,CAAC,IAAI,8DAA8D,CAAC,CAAC;QAC7G,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,8EAA8E;IAEvE,KAAK,CAAC,YAAY,CAAC,MAAe;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CACrC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAA8B,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,aAAa,EAAE,CAAC,CAAC,CACpH,CAAC;QACF,OAAO,MAAM,IAAI,EAAE,CAAC;IACxB,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,mBAAmB,CAC7B,KAA8H,EAC9H,MAAe;QAEf,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAClG,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxH,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,IAAI,kBAAkB,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,IAAI,GACN,KAAK,CAAC,IAAI,KAAK,IAAI;YACf,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;YACjE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAClI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACrH,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACrH,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,+BAA+B,CAAC,CAAC;QACrF,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;IAClI,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,KAAa,EAAE,IAAkB,EAAE,MAAe;QAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAA8B,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3I,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAChH,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,CAAC,IAAI,qCAAqC,CAAC,CAAC;QAEjI,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,KAAK,YAAY,CAAC,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACnG,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,KAAK,iBAAiB,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC/H,IAAI,QAAQ,IAAI,aAAa;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACjB,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,CAAC,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,OAAO;oBAAE,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpG,CAAC;QACL,CAAC;QACD,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,CAAC,IAAI,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAE/G,MAAM,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;QACjE,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,SAAS,IAAI,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1H,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC/E,CAAC;IAED,+EAA+E;IAExE,KAAK,CAAC,oBAAoB,CAAC,MAAe;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAkB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAChH,CAAC;IAED,uGAAuG;IAC/F,KAAK,CAAC,0BAA0B,CAAC,SAAiB,EAAE,EAAU,EAAE,WAA+B,EAAE,MAAe;QACpH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAgE,CAAC;QACjI,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,0BAA0B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,aAAa,IAAI,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;QACvI,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACjG,IAAI,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,4BAA4B,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9H,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACpF,MAAM,IAAI,GAAG,WAAW,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,WAAW,CAAC;QACzD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAE3G,IAAI,OAAO,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,KAAK,KAAK,GAAG,CAAC,EAAE,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YACvH,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,WAAoB,EAAE,CAAC;QACxE,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;QACvH,IAAI,OAAO,EAAE,CAAC;YACV,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAChH,CAAC;aAAM,CAAC;YACJ,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC,EAAE,IAAI,CAAC,CAAC;QACpF,CAAC;QACD,OAAO;YACH,GAAG;YACH,EAAE;YACF,OAAO,EAAE,GAAG,CAAC,IAAI;YACjB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAE,SAAmB,CAAC,CAAC,CAAE,SAAmB;YAC7D,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,IAAI,EAAE,4FAA4F;SACrG,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,6BAA6B,CAAC,SAAiB,EAAE,MAAe;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QACnH,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,aAAsB,EAAE,CAAC;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1H,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC;IAC/D,CAAC;IAED,iFAAiF;IAE1E,KAAK,CAAC,eAAe,CAAC,MAAe;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAa,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACtG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAC,KAAsB,EAAE,MAAe;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACtD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,+CAA+C,CAAC,CAAC;QAC5G,CAAC;QACD,MAAM,IAAI,GAA4B;YAClC,WAAW;YACX,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;YAC7B,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACtE,GAAG,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YAC3E,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC1E,SAAS,EAAE,CAAC;SACf,CAAC;QACF,IAAI,KAAK,CAAC,SAAS;YAAE,IAAI,CAAC,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC1F,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,IAAI,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC;QAClG,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,+BAA+B,CAAC,CAAC;QAClG,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAC,GAAW,EAAE,OAA0B,EAAE,MAAe;QAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC/F,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;QACpH,IAAI,WAAW,KAAK,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,EAAE,CAAC;YACzF,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,kBAAkB,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,IAAI,GAA4B;YAClC,WAAW;YACX,MAAM,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM;YACzC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;YAC9E,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS;YAC5E,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,cAAc,EAAE,OAAO,CAAC,cAAc,IAAI,EAAE;YAC5C,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC/F,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC;YACjC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxD,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CACzC,OAAO,CAAC,MAAM,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,EAC9F,OAAO,CAAC,WAAW,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC,eAAe,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,cAAc,IAAI,EAAE,EAAE,EACxH,QAAQ,CACX,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACzK,IAAI,WAAW;YAAE,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAEhD,4FAA4F;QAC5F,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;QACvF,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,gBAAgB,OAAO,CAAC,WAAW,uEAAuE,CAAC,CAAC;QAChI,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1G,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;QACnH,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,OAAqB,EAAE,QAAQ,CAAC,CAAC;IACnE,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAC,GAAW,EAAE,MAAe;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,iBAAiB,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC/H,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9F,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC/E,CAAC;IAED,oFAAoF;IAC5E,KAAK,CAAC,sBAAsB,CAAC,GAAW,EAAE,QAAgB,EAAE,MAAe;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC/F,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACxE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;QACtD,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QACpG,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,uDAAuD;IAChD,KAAK,CAAC,WAAW,CAAC,GAAe,EAAE,MAAe;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACjD,+FAA+F;QAC/F,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,GAAyB,EAAE,KAA6B,EAAE,EAAE,CACrF,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChG,OAAO;YACH,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,QAAQ,EAAE,GAAG,CAAC,KAAK;YACnB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,OAAO,EAAE,GAAG,CAAC,MAAM;YACnB,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YAC3C,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC;YAC1D,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,cAAc,EAAE,iBAAiB,CAAC;YAC9E,QAAQ,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ;SACpH,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC1B,MAA8C,EAC9C,WAAoE,EACpE,MAAc;QAEd,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,YAAY,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1H,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACnF,MAAM,IAAI,GAAG,WAAW,IAAI,EAAE,IAAI,EAAE,SAAkB,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/E,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,iBAAiB,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvI,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACtF,OAAO;YACH,UAAU,EAAE,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;YACrC,SAAS,EAAE,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC;YACjE,eAAe,EAAE,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;YAC7C,cAAc,EAAE,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;SACrE,CAAC;IACN,CAAC;IAED,+DAA+D;IACvD,KAAK,CAAC,UAAU,CAAC,IAAmB,EAAE,MAAgB,EAAE,MAAc;QAC1E,MAAM,UAAU,GACZ,IAAI,KAAK,SAAS;YACd,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACjF,CAAC,CAAC,IAAI,KAAK,SAAS;gBAClB,CAAC,CAAE,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAyC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAClI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1I,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,MAAc;QACtC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;QACxC,MAAM,IAAI,GAAG,KAAK,EAAK,IAAwB,EAAgB,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/F,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1F,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAiD,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAClJ,KAAK,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAAE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,EAAE;gBAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QACvI,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,MAAc;QACrD,OAAO,iBAAiB,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,SAAS,CAAC;IACpI,CAAC;IAED,mFAAmF;IAE3E,KAAK,CAAC,eAAe,CAAC,MAAc;QACxC,MAAM,MAAM,GAA8I,EAAE,CAAC;QAC7J,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACzD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;gBAClC,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAA4C,CAAC;gBAC5H,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE,CAAU,EAAE,CAAC,CAAC;YAC7H,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,wBAAwB,CAClC,IAAY,EACZ,OAAwE,EACxE,UAAyE,EAAE;QAE3E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,CAAC,EAAW,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;QACpF,MAAM,UAAU,GAAG,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,OAAiB,CAAC,CAAC,CAAE,MAAgB,CAAC,CAAC;QAEpH,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,KAAK,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1J,IAAI,KAAK,GAAiC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QACzG,IAAI,IAAI,GAA4B,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;QAC/D,IAAI,YAAY,GAAwC,EAAE,CAAC;QAE3D,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC;YAC/C,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;YAC/F,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;YAC5D,IAAI,CAAC,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC7F,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAkB,EAAE,EAAE,CAAE,CAAuB,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC/I,YAAY,GAAG,SAAS;iBACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;iBAC1G,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAG,CAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAClF,KAAK,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YACrD,IAAI,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QACrG,CAAC;QAED,MAAM,MAAM,GAAwB,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAClI,IAAI,OAAO,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC;QAClC,IAAI,YAAY,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CACX,yBAAyB,YAAY,CAAC,MAAM,2BAA2B,MAAM,CAAC,QAAQ,IAAI;gBACtF,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACxE,oGAAoG,CAC3G,CAAC;QACN,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,CACX,OAAO,EACP,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,EACpJ,IAAI,CACP,CAAC;QACF,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACxC,CAAC;CACJ;AAED,qGAAqG;AACrG,SAAS,kBAAkB,CAAC,KAAa;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACvG,IAAI,IAAI,KAAK,mBAAmB;QAAE,MAAM,IAAI,KAAK,CAAC,aAAa,mBAAmB,wCAAwC,CAAC,CAAC;IAC5H,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,iBAAiB,CAAI,KAAU,EAAE,MAAc,EAAE,EAAuB,EAAE,IAAyB,EAAE,IAAY;IACtH,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;IACvD,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,gBAAgB,MAAM,eAAe,CAAC,CAAC;IAC7F,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChF,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,2BAA2B,SAAS,IAAI,QAAQ,EAAE,CAAC,CAAC;AAC3H,CAAC;AAED,SAAS,QAAQ,CAAmB,KAAwB,EAAE,KAAa;IACvE,MAAM,KAAK,GAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAS,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC;IAC9E,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,0DAA0D,CAAC,CAAC;IACjI,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,SAAS,CAAC,IAAmB;IAClC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;AACzF,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACrG,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,EAAU;IAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,QAAQ,CAAC,OAAe,EAAE,IAAY;IAC3C,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAC5E,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC5B,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,UAAU,CAAC,EAAE,CAAC,CAAC;IACf,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,6BAA6B,CAAC,CAAC;IAC9G,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { ActiveClientInfo, ClientActivity, ClientBlockStatus, ClientPastConnection, ClientRateLimitSetting, GetClientActivityOptions, GetDeviceStatsOptions, GetThreatListOptions, ListClientsPastConnectionsOptions, OmadaClientInfo, OmadaDeviceInfo, OmadaDeviceStats, OmadaSiteSummary, OswStackDetail, PaginatedResult, RateLimitProfile, ThreatInfo } from '../types/index.js';
2
+ import { AccessControlOperations } from './accessControl.js';
2
3
  import { type KnownClient } from './client.js';
3
4
  import { type SsidEnableResult } from './network.js';
4
5
  import { type RequestOptions } from './request.js';
@@ -26,6 +27,8 @@ export declare class OmadaClient {
26
27
  private readonly securityOps;
27
28
  private readonly networkOps;
28
29
  private readonly macGroupOps;
30
+ /** Time ranges, IP/MAC groups, DHCP reservations, gateway ACLs and the SSID MAC filter. */
31
+ readonly accessControl: AccessControlOperations;
29
32
  private readonly omadacId;
30
33
  constructor(options: OmadaClientOptions);
31
34
  listSites(): Promise<OmadaSiteSummary[]>;
@@ -1,3 +1,4 @@
1
+ import { AccessControlOperations } from './accessControl.js';
1
2
  import { AuthManager } from './auth.js';
2
3
  import { ClientOperations } from './client.js';
3
4
  import { DeviceOperations } from './device.js';
@@ -19,6 +20,8 @@ export class OmadaClient {
19
20
  securityOps;
20
21
  networkOps;
21
22
  macGroupOps;
23
+ /** Time ranges, IP/MAC groups, DHCP reservations, gateway ACLs and the SSID MAC filter. */
24
+ accessControl;
22
25
  omadacId;
23
26
  constructor(options) {
24
27
  this.omadacId = options.omadacId;
@@ -43,6 +46,7 @@ export class OmadaClient {
43
46
  this.securityOps = new SecurityOperations(this.request, this.buildOmadaPath.bind(this));
44
47
  this.networkOps = new NetworkOperations(this.request, this.siteOps, this.buildOmadaPath.bind(this));
45
48
  this.macGroupOps = new MacGroupOperations(this.request, this.siteOps, this.buildOmadaPath.bind(this));
49
+ this.accessControl = new AccessControlOperations(this.request, this.siteOps, this.buildOmadaPath.bind(this), this.networkOps, this.macGroupOps, this.clientOps);
46
50
  }
47
51
  // Site operations
48
52
  async listSites() {