smart-home-engine 1.1.19 → 1.2.0
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.
- package/dist/web/assets/index-CY1IzFyN.js +230 -0
- package/dist/web/assets/{index-b3gdLMp3.css → index-CiR8cZ_Y.css} +1 -1
- package/dist/web/assets/{tsMode-bkHRbIDU.js → tsMode-Dj2ZPBcc.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/lib/dynsec.js +32 -7
- package/src/web/broker-api.js +19 -2
- package/dist/web/assets/index-sjamTHx3.js +0 -230
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-
|
|
1
|
+
import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-CY1IzFyN.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
package/dist/web/index.html
CHANGED
|
@@ -172,10 +172,10 @@
|
|
|
172
172
|
}
|
|
173
173
|
})();
|
|
174
174
|
</script>
|
|
175
|
-
<script type="module" crossorigin src="/assets/index-
|
|
175
|
+
<script type="module" crossorigin src="/assets/index-CY1IzFyN.js"></script>
|
|
176
176
|
<link rel="modulepreload" crossorigin href="/assets/monaco-langs-BW2J83t5.js">
|
|
177
177
|
<link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
|
|
178
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
178
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CiR8cZ_Y.css">
|
|
179
179
|
</head>
|
|
180
180
|
<body>
|
|
181
181
|
<div id="app"></div>
|
package/package.json
CHANGED
package/src/lib/dynsec.js
CHANGED
|
@@ -34,6 +34,10 @@ const _queue = [];
|
|
|
34
34
|
let _inflight = false;
|
|
35
35
|
let _inflightResolve = null;
|
|
36
36
|
|
|
37
|
+
// $SYS topic cache — populated by the she-admin MQTT connection which has
|
|
38
|
+
// the admin role and therefore $SYS/# subscribe + publishClientReceive ACLs.
|
|
39
|
+
const _sysData = {};
|
|
40
|
+
|
|
37
41
|
function _drain() {
|
|
38
42
|
if (_inflight || _queue.length === 0 || !_connected) return;
|
|
39
43
|
|
|
@@ -145,6 +149,12 @@ function init(config, log) {
|
|
|
145
149
|
});
|
|
146
150
|
}
|
|
147
151
|
});
|
|
152
|
+
// The admin role has subscribePattern + publishClientReceive for $SYS/#.
|
|
153
|
+
// Subscribe here so the broker status endpoint always has fresh $SYS data
|
|
154
|
+
// even when the main MQTT client lacks the necessary ACL permissions.
|
|
155
|
+
_client.subscribe('$SYS/#', (err) => {
|
|
156
|
+
if (err) _log.debug('dynsec: $SYS/# subscription failed (not critical):', err.message);
|
|
157
|
+
});
|
|
148
158
|
});
|
|
149
159
|
|
|
150
160
|
_client.on('close', () => {
|
|
@@ -160,6 +170,13 @@ function init(config, log) {
|
|
|
160
170
|
});
|
|
161
171
|
|
|
162
172
|
_client.on('message', (topic, payload) => {
|
|
173
|
+
if (topic.startsWith('$SYS/')) {
|
|
174
|
+
const val = payload.toString();
|
|
175
|
+
const now = Date.now();
|
|
176
|
+
const prev = _sysData[topic];
|
|
177
|
+
_sysData[topic] = { val, ts: now, lc: prev && prev.val !== val ? now : (prev ? prev.lc : now) };
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
163
180
|
if (topic !== RESPONSE_TOPIC) return;
|
|
164
181
|
let msg;
|
|
165
182
|
try {
|
|
@@ -192,6 +209,8 @@ function stop() {
|
|
|
192
209
|
_configured = false;
|
|
193
210
|
_connected = false;
|
|
194
211
|
_dynsecReady = false;
|
|
212
|
+
// Clear $SYS cache
|
|
213
|
+
Object.keys(_sysData).forEach((k) => delete _sysData[k]);
|
|
195
214
|
// Reject any in-flight / queued requests
|
|
196
215
|
if (_inflight && _inflightResolve) {
|
|
197
216
|
_inflightResolve = null;
|
|
@@ -223,11 +242,11 @@ function setClientPassword(username, password) {
|
|
|
223
242
|
}
|
|
224
243
|
|
|
225
244
|
function listClients(verbose = false) {
|
|
226
|
-
return _request('listClients', { verbose }).then((r) => r.clients
|
|
245
|
+
return _request('listClients', { verbose }).then((r) => r.data?.clients ?? r.clients ?? []);
|
|
227
246
|
}
|
|
228
247
|
|
|
229
248
|
function getClient(username) {
|
|
230
|
-
return _request('getClient', { username }).then((r) => r.client);
|
|
249
|
+
return _request('getClient', { username }).then((r) => r.data?.client ?? r.client);
|
|
231
250
|
}
|
|
232
251
|
|
|
233
252
|
// ── Role management ────────────────────────────────────────────────────────────
|
|
@@ -241,11 +260,11 @@ function deleteRole(rolename) {
|
|
|
241
260
|
}
|
|
242
261
|
|
|
243
262
|
function listRoles(verbose = false) {
|
|
244
|
-
return _request('listRoles', { verbose }).then((r) => r.roles
|
|
263
|
+
return _request('listRoles', { verbose }).then((r) => r.data?.roles ?? r.roles ?? []);
|
|
245
264
|
}
|
|
246
265
|
|
|
247
266
|
function getRole(rolename) {
|
|
248
|
-
return _request('getRole', { rolename }).then((r) => r.role);
|
|
267
|
+
return _request('getRole', { rolename }).then((r) => r.data?.role ?? r.role);
|
|
249
268
|
}
|
|
250
269
|
|
|
251
270
|
/**
|
|
@@ -286,11 +305,11 @@ function deleteGroup(groupname) {
|
|
|
286
305
|
}
|
|
287
306
|
|
|
288
307
|
function listGroups(verbose = false) {
|
|
289
|
-
return _request('listGroups', { verbose }).then((r) => r.groups
|
|
308
|
+
return _request('listGroups', { verbose }).then((r) => r.data?.groups ?? r.groups ?? []);
|
|
290
309
|
}
|
|
291
310
|
|
|
292
311
|
function getGroup(groupname) {
|
|
293
|
-
return _request('getGroup', { groupname }).then((r) => r.group);
|
|
312
|
+
return _request('getGroup', { groupname }).then((r) => r.data?.group ?? r.group);
|
|
294
313
|
}
|
|
295
314
|
|
|
296
315
|
function addGroupClient(groupname, username, priority = -1) {
|
|
@@ -312,7 +331,12 @@ function removeGroupRole(groupname, rolename) {
|
|
|
312
331
|
// ── Default ACL access ─────────────────────────────────────────────────────────
|
|
313
332
|
|
|
314
333
|
function getDefaultACLAccess() {
|
|
315
|
-
return _request('getDefaultACLAccess').then((r) => r.acls
|
|
334
|
+
return _request('getDefaultACLAccess').then((r) => r.data?.acls ?? r.acls ?? []);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Returns the $SYS topic cache collected by the she-admin MQTT client. */
|
|
338
|
+
function getSysData() {
|
|
339
|
+
return { ..._sysData };
|
|
316
340
|
}
|
|
317
341
|
|
|
318
342
|
function setDefaultACLAccess(acls) {
|
|
@@ -322,6 +346,7 @@ function setDefaultACLAccess(acls) {
|
|
|
322
346
|
module.exports = {
|
|
323
347
|
init,
|
|
324
348
|
getStatus,
|
|
349
|
+
getSysData,
|
|
325
350
|
stop,
|
|
326
351
|
// Users
|
|
327
352
|
createClient,
|
package/src/web/broker-api.js
CHANGED
|
@@ -79,11 +79,16 @@ function handleError(res, err) {
|
|
|
79
79
|
router.get('/status', (req, res) => {
|
|
80
80
|
const ds = dynsec.getStatus();
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
// Prefer $SYS data from the she-admin MQTT client: it has admin role ACLs
|
|
83
|
+
// that explicitly allow $SYS/# even when the main client is denied by
|
|
84
|
+
// default-deny subscribe ACLs.
|
|
85
|
+
const sys = dynsec.getSysData();
|
|
86
|
+
// Fall back to the main MQTT client's state store for any topics not yet
|
|
87
|
+
// received by the dynsec client (e.g. when dynsec is not configured).
|
|
83
88
|
if (_store) {
|
|
84
89
|
const sysPrefixes = ['$SYS/broker/version', '$SYS/broker/uptime', '$SYS/broker/clients/', '$SYS/broker/messages/'];
|
|
85
90
|
for (const [topic, entry] of _store.mqttEntries()) {
|
|
86
|
-
if (sysPrefixes.some((p) => topic.startsWith(p))) {
|
|
91
|
+
if (!sys[topic] && sysPrefixes.some((p) => topic.startsWith(p))) {
|
|
87
92
|
sys[topic] = entry;
|
|
88
93
|
}
|
|
89
94
|
}
|
|
@@ -473,6 +478,18 @@ router.delete('/groups/:group/roles/:role', async (req, res) => {
|
|
|
473
478
|
}
|
|
474
479
|
});
|
|
475
480
|
|
|
481
|
+
// ── dynsec: Default ACL access ────────────────────────────────────────────────
|
|
482
|
+
|
|
483
|
+
/** GET /she/broker/acl-defaults */
|
|
484
|
+
router.get('/acl-defaults', async (req, res) => {
|
|
485
|
+
try {
|
|
486
|
+
const acls = await dynsec.getDefaultACLAccess();
|
|
487
|
+
res.json({ acls });
|
|
488
|
+
} catch (err) {
|
|
489
|
+
handleError(res, err);
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
|
|
476
493
|
// ── CA routes ─────────────────────────────────────────────────────────────────
|
|
477
494
|
|
|
478
495
|
/** GET /she/broker/ca — CA cert info */
|