smart-home-engine 1.1.11 → 1.1.13

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.
@@ -1,4 +1,4 @@
1
- import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-DiZlYUuT.js";/*!-----------------------------------------------------------------------------
1
+ import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-CLoKW1Ib.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -172,10 +172,10 @@
172
172
  }
173
173
  })();
174
174
  </script>
175
- <script type="module" crossorigin src="/assets/index-DiZlYUuT.js"></script>
175
+ <script type="module" crossorigin src="/assets/index-CLoKW1Ib.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-iTrR9H4f.css">
178
+ <link rel="stylesheet" crossorigin href="/assets/index-Cek-ldk8.css">
179
179
  </head>
180
180
  <body>
181
181
  <div id="app"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-home-engine",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "Node.js based script runner for use in MQTT based Smart Home environments",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/lib/dynsec.js CHANGED
@@ -25,6 +25,7 @@ const RESPONSE_TOPIC = '$CONTROL/dynamic-security/v1/response';
25
25
  let _client = null;
26
26
  let _connected = false;
27
27
  let _configured = false;
28
+ let _dynsecReady = false;
28
29
  let _timeout = 5000;
29
30
  let _log = null;
30
31
 
@@ -134,6 +135,14 @@ function init(config, log) {
134
135
  _connected = true;
135
136
  _log.info('dynsec: ready — subscribed as', dynsecCfg.adminUsername);
136
137
  _drain(); // flush any requests queued before connection
138
+ // Probe whether the plugin is actually loaded and responding
139
+ _request('getDefaultACLAccess').then(() => {
140
+ _dynsecReady = true;
141
+ _log.info('dynsec: plugin confirmed active');
142
+ }).catch((err) => {
143
+ _dynsecReady = false;
144
+ _log.warn('dynsec: plugin probe failed — is the dynamic-security plugin loaded in mosquitto.conf?', err.message);
145
+ });
137
146
  }
138
147
  });
139
148
  });
@@ -141,6 +150,7 @@ function init(config, log) {
141
150
  _client.on('close', () => {
142
151
  if (_connected) {
143
152
  _connected = false;
153
+ _dynsecReady = false;
144
154
  _log.warn('dynsec: disconnected');
145
155
  }
146
156
  });
@@ -168,9 +178,9 @@ function init(config, log) {
168
178
  });
169
179
  }
170
180
 
171
- /** @returns {{ connected: boolean, configured: boolean }} */
181
+ /** @returns {{ connected: boolean, configured: boolean, dynsecReady: boolean }} */
172
182
  function getStatus() {
173
- return { connected: _connected, configured: _configured };
183
+ return { connected: _connected, configured: _configured, dynsecReady: _dynsecReady };
174
184
  }
175
185
 
176
186
  // ── User management ────────────────────────────────────────────────────────────
@@ -813,6 +813,18 @@ router.post('/wizard/bootstrap', async (req, res) => {
813
813
  });
814
814
  }
815
815
 
816
+ // Discover the full path to the .so on the remote host.
817
+ let soPath = 'mosquitto_dynamic_security.so'; // fallback: rely on LD_LIBRARY_PATH
818
+ try {
819
+ const found = await sshDeploy.runCommand(bc.ssh, "find /usr /lib -maxdepth 8 -name 'mosquitto_dynamic_security.so' 2>/dev/null | head -1");
820
+ if (found.stdout) {
821
+ soPath = found.stdout;
822
+ _log?.debug(`broker: discovered .so on remote at ${soPath}`);
823
+ }
824
+ } catch (e) {
825
+ _log?.debug(`broker: remote .so discovery failed (${e.message}), using bare filename`);
826
+ }
827
+
816
828
  // Read the remote mosquitto.conf, parse, and add the plugin line if missing.
817
829
  let remoteConfRaw = '';
818
830
  try {
@@ -824,7 +836,7 @@ router.post('/wizard/bootstrap', async (req, res) => {
824
836
  }
825
837
  const parsed = mosquittoConf.parseText(remoteConfRaw);
826
838
  if (!parsed.managed.plugin || !String(parsed.managed.plugin).includes('mosquitto_dynamic_security')) {
827
- parsed.managed.plugin = 'mosquitto_dynamic_security.so';
839
+ parsed.managed.plugin = soPath;
828
840
  parsed.managed.plugin_opt_dynsec_config_file = dynSecPath;
829
841
  const content = mosquittoConf.serialise(parsed);
830
842
  _log?.debug(`broker: uploading updated conf to ${bc.ssh.host}:${confFilePath}`);
@@ -847,10 +859,23 @@ router.post('/wizard/bootstrap', async (req, res) => {
847
859
  });
848
860
  }
849
861
 
862
+ // Discover the full path to the .so on this host.
863
+ let soPath = 'mosquitto_dynamic_security.so'; // fallback: rely on LD_LIBRARY_PATH
864
+ try {
865
+ const r2 = await execFileAsync('find', ['/usr', '/lib', '-maxdepth', '8', '-name', 'mosquitto_dynamic_security.so'], { timeout: 8000 });
866
+ const lines = r2.stdout.trim().split('\n').filter(Boolean);
867
+ if (lines.length > 0) {
868
+ soPath = lines[0];
869
+ _log?.debug(`broker: discovered .so at ${soPath}`);
870
+ }
871
+ } catch (e) {
872
+ _log?.debug(`broker: local .so discovery failed (${e.message}), using bare filename`);
873
+ }
874
+
850
875
  // Ensure plugin line exists in local mosquitto.conf
851
876
  const parsed = mosquittoConf.parse(confFilePath);
852
877
  if (!parsed.managed.plugin || !String(parsed.managed.plugin).includes('mosquitto_dynamic_security')) {
853
- parsed.managed.plugin = 'mosquitto_dynamic_security.so';
878
+ parsed.managed.plugin = soPath;
854
879
  parsed.managed.plugin_opt_dynsec_config_file = dynSecPath;
855
880
  const content = mosquittoConf.serialise(parsed);
856
881
  _log?.debug(`broker: writing updated local conf to ${confFilePath}`);
@@ -873,3 +898,33 @@ router.post('/wizard/bootstrap', async (req, res) => {
873
898
  handleError(res, err);
874
899
  }
875
900
  });
901
+
902
+ /**
903
+ * POST /she/broker/wizard/deactivate
904
+ * Remove dynsec plugin lines from mosquitto.conf (remote or local).
905
+ * The caller is responsible for also clearing broker.dynsec credentials from
906
+ * config.json and restarting mosquitto afterwards.
907
+ */
908
+ router.post('/wizard/deactivate', async (req, res) => {
909
+ try {
910
+ const bc = getBrokerConfig(req);
911
+ const fp = confPath(bc);
912
+ if (bc.ssh && bc.ssh.host) {
913
+ const raw = await sshDeploy.readRemoteFile(bc.ssh, fp);
914
+ const parsed = mosquittoConf.parseText(raw);
915
+ delete parsed.managed.plugin;
916
+ delete parsed.managed.plugin_opt_dynsec_config_file;
917
+ const content = mosquittoConf.serialise(parsed);
918
+ await sshDeploy.uploadContent(bc.ssh, content, fp);
919
+ } else {
920
+ const parsed = mosquittoConf.parse(fp);
921
+ delete parsed.managed.plugin;
922
+ delete parsed.managed.plugin_opt_dynsec_config_file;
923
+ const content = mosquittoConf.serialise(parsed);
924
+ mosquittoConf.write(fp, content);
925
+ }
926
+ res.json({ ok: true });
927
+ } catch (err) {
928
+ handleError(res, err);
929
+ }
930
+ });