smart-home-engine 1.1.17 → 1.1.18

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-itohNXf2.js";/*!-----------------------------------------------------------------------------
1
+ import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-BH6XhdRK.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,7 +172,7 @@
172
172
  }
173
173
  })();
174
174
  </script>
175
- <script type="module" crossorigin src="/assets/index-itohNXf2.js"></script>
175
+ <script type="module" crossorigin src="/assets/index-BH6XhdRK.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
178
  <link rel="stylesheet" crossorigin href="/assets/index-b3gdLMp3.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-home-engine",
3
- "version": "1.1.17",
3
+ "version": "1.1.18",
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": {
@@ -191,10 +191,24 @@ function serialise(conf) {
191
191
  lines.push('');
192
192
  }
193
193
 
194
- // Passthrough (comments, blanks, unmanaged keys)
195
- for (const l of passthrough) lines.push(l);
194
+ // Passthrough (comments, blanks, unmanaged keys) — strip leading blank lines
195
+ // to avoid a double-blank at the managed/passthrough boundary.
196
+ const trimmedPassthrough = [...passthrough];
197
+ while (trimmedPassthrough.length > 0 && trimmedPassthrough[0].trim() === '') {
198
+ trimmedPassthrough.shift();
199
+ }
200
+ for (const l of trimmedPassthrough) lines.push(l);
196
201
 
197
- return lines.join('\n');
202
+ // Collapse runs of more than one consecutive blank line into a single blank line.
203
+ const result = [];
204
+ let prevBlank = false;
205
+ for (const line of lines) {
206
+ const isBlank = line.trim() === '';
207
+ if (isBlank && prevBlank) continue;
208
+ result.push(line);
209
+ prevBlank = isBlank;
210
+ }
211
+ return result.join('\n');
198
212
  }
199
213
 
200
214
  /**
@@ -831,6 +831,16 @@ router.post('/wizard/bootstrap', async (req, res) => {
831
831
  _log?.warn(`broker: could not verify dynamic-security.json after init: ${e.message}`);
832
832
  }
833
833
 
834
+ // Fix ownership and permissions: mosquitto_ctrl creates the file owned by the
835
+ // SSH user (typically mode 600). Mosquitto runs as the 'mosquitto' system user
836
+ // and must be able to read it. Chown to mosquitto:mosquitto and set 644.
837
+ try {
838
+ await sshDeploy.runCommand(bc.ssh, `sudo chown mosquitto:mosquitto "${dynSecPath}" && sudo chmod 644 "${dynSecPath}"`);
839
+ _log?.debug(`broker: fixed ownership and permissions on remote ${dynSecPath}`);
840
+ } catch (e) {
841
+ _log?.warn(`broker: could not chown/chmod remote ${dynSecPath}: ${e.message} — mosquitto may fail with 'File is not readable'`);
842
+ }
843
+
834
844
  // Discover the full path to the .so on the remote host.
835
845
  let soPath = 'mosquitto_dynamic_security.so'; // fallback: rely on LD_LIBRARY_PATH
836
846
  try {
@@ -892,6 +902,22 @@ router.post('/wizard/bootstrap', async (req, res) => {
892
902
  } catch (e) {
893
903
  _log?.warn(`broker: could not verify dynamic-security.json after init: ${e.message}`);
894
904
  }
905
+
906
+ // Fix ownership and permissions: mosquitto_ctrl creates the file owned by the
907
+ // current user. Mosquitto runs as the 'mosquitto' system user and needs read access.
908
+ try {
909
+ await execFileAsync('sudo', ['chown', 'mosquitto:mosquitto', dynSecPath], { timeout: 5000 });
910
+ _log?.debug(`broker: fixed ownership on local ${dynSecPath}`);
911
+ } catch (e) {
912
+ _log?.warn(`broker: could not chown local ${dynSecPath}: ${e.message}`);
913
+ }
914
+ try {
915
+ fs.chmodSync(dynSecPath, 0o644);
916
+ _log?.debug(`broker: fixed permissions on local ${dynSecPath}`);
917
+ } catch (e) {
918
+ _log?.warn(`broker: could not chmod local ${dynSecPath}: ${e.message}`);
919
+ }
920
+
895
921
  let soPath = 'mosquitto_dynamic_security.so'; // fallback: rely on LD_LIBRARY_PATH
896
922
  try {
897
923
  const r2 = await execFileAsync('find', ['/usr', '/lib', '-maxdepth', '8', '-name', 'mosquitto_dynamic_security.so'], { timeout: 8000 });