@iobroker/js-controller-common 4.0.4 → 4.0.6

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.
@@ -61,23 +61,23 @@ const IoSeq =
61
61
  Seq &&
62
62
  class extends Seq {
63
63
  log(info, callback) {
64
- const ioInfo = info;
64
+ const ioInfo = deepClone(info);
65
65
  ioInfo.props = ioInfo.props || {};
66
66
 
67
67
  // map our log levels to Seq levels
68
- const level = (info.level || '').toLowerCase();
68
+ const level = (ioInfo.level || '').toLowerCase();
69
69
  if (level.includes('error')) {
70
- info.level = 'Error';
70
+ ioInfo.level = 'Error';
71
71
  } else if (level.includes('warn')) {
72
- info.level = 'Warning';
72
+ ioInfo.level = 'Warning';
73
73
  } else if (level.includes('info')) {
74
- info.level = 'Information';
74
+ ioInfo.level = 'Information';
75
75
  } else if (level.includes('debug')) {
76
- info.level = 'Debug';
76
+ ioInfo.level = 'Debug';
77
77
  } else if (level.includes('silly')) {
78
- info.level = 'Verbose';
78
+ ioInfo.level = 'Verbose';
79
79
  } else {
80
- info.level = 'Information';
80
+ ioInfo.level = 'Information';
81
81
  }
82
82
 
83
83
  // we add own properties
@@ -10,7 +10,7 @@ const cpPromise = require('promisify-child-process');
10
10
  const jwt = require('jsonwebtoken');
11
11
  const { createInterface } = require('readline');
12
12
  const { PassThrough } = require('stream');
13
- const { detectPackageManager } = require('@alcalzone/pak');
13
+ const { detectPackageManager, packageManagers } = require('@alcalzone/pak');
14
14
  const EXIT_CODES = require('./exitCodes');
15
15
  const zlib = require('zlib');
16
16
 
@@ -1258,34 +1258,32 @@ function getRepositoryFile(urlOrPath, additionalInfo, callback) {
1258
1258
  */
1259
1259
  async function getRepositoryFileAsync(url, hash, force, _actualRepo) {
1260
1260
  let _hash;
1261
- if (_actualRepo && !force && hash && (url.startsWith('http://') || url.startsWith('https://'))) {
1262
- axios = axios || require('axios');
1263
- _hash = await axios({ url: url.replace(/\.json$/, '-hash.json'), timeout: 10000 });
1264
- if (_hash && _hash.data && hash === _hash.data.hash) {
1265
- return _actualRepo;
1266
- }
1267
- }
1268
-
1269
1261
  let data;
1270
1262
 
1271
1263
  if (url.startsWith('http://') || url.startsWith('https://')) {
1272
1264
  axios = axios || require('axios');
1273
- if (!_hash) {
1265
+ try {
1274
1266
  _hash = await axios({ url: url.replace(/\.json$/, '-hash.json'), timeout: 10000 });
1267
+ } catch {
1268
+ // ignore missing hash file
1275
1269
  }
1276
1270
 
1277
- if (_actualRepo && hash && _hash && _hash.data && _hash.data.hash === hash) {
1271
+ if (_actualRepo && !force && hash && _hash && _hash.data && _hash.data.hash === hash) {
1278
1272
  data = _actualRepo;
1279
1273
  } else {
1280
1274
  const agent = `${module.exports.appName}, RND: ${randomID}, Node:${process.version}, V:${
1281
1275
  require('../../package.json').version
1282
1276
  }`;
1283
- data = await axios({
1284
- url,
1285
- timeout: 10000,
1286
- headers: { 'User-Agent': agent }
1287
- });
1288
- data = data.data;
1277
+ try {
1278
+ data = await axios({
1279
+ url,
1280
+ timeout: 10000,
1281
+ headers: { 'User-Agent': agent }
1282
+ });
1283
+ data = data.data;
1284
+ } catch (e) {
1285
+ throw new Error(`Cannot download repository file from "${url}": ${e.message}`);
1286
+ }
1289
1287
  }
1290
1288
  } else {
1291
1289
  if (fs.existsSync(url)) {
@@ -1456,6 +1454,43 @@ function getSystemNpmVersion(callback) {
1456
1454
 
1457
1455
  const getSystemNpmVersionAsync = promisify(getSystemNpmVersion);
1458
1456
 
1457
+ /**
1458
+ * @private
1459
+ * Figure out which package manager is in charge, but with a fallback to npm.
1460
+ * @param {string} [cwd] Which directory to work in. If none is given, this defaults to ioBroker's root directory.
1461
+ * @returns {Promise<PackageManager>}
1462
+ */
1463
+ async function detectPackageManagerWithFallback(cwd) {
1464
+ try {
1465
+ // For the first attempt, use pak's default of requiring a lockfile. This makes sure we find ioBroker's root dir
1466
+ return await detectPackageManager(
1467
+ typeof cwd === 'string'
1468
+ ? // If a cwd was provided, use it
1469
+ { cwd }
1470
+ : // Otherwise try to find the ioBroker root dir
1471
+ {
1472
+ cwd: __dirname,
1473
+ setCwdToPackageRoot: true
1474
+ }
1475
+ );
1476
+ } catch {
1477
+ // Lockfile not found, try again without requiring a lockfile
1478
+ }
1479
+
1480
+ // Since we have no lockfile to rely on, assume the root dir is 2 levels above js-controller
1481
+ const ioBrokerRootDir = path.join(getControllerDir(), '../..');
1482
+ try {
1483
+ return await detectPackageManager({ cwd: ioBrokerRootDir, requireLockfile: false });
1484
+ } catch {
1485
+ // Lockfile not found, use default
1486
+ }
1487
+
1488
+ // Fallback to npm
1489
+ const pak = new packageManagers.npm();
1490
+ pak.cwd = ioBrokerRootDir;
1491
+ return pak;
1492
+ }
1493
+
1459
1494
  /**
1460
1495
  * @typedef {object} InstallNodeModuleOptions
1461
1496
  * @property {boolean} [unsafePerm] Whether the `--unsafe-perm` flag should be used
@@ -1471,16 +1506,7 @@ const getSystemNpmVersionAsync = promisify(getSystemNpmVersion);
1471
1506
  */
1472
1507
  async function installNodeModule(npmUrl, options = {}) {
1473
1508
  // Figure out which package manager is in charge (probably npm at this point)
1474
- const pak = await detectPackageManager(
1475
- typeof options.cwd === 'string'
1476
- ? // If a cwd was provided, use it
1477
- { cwd: options.cwd }
1478
- : // Otherwise find the ioBroker root dir
1479
- {
1480
- cwd: __dirname,
1481
- setCwdToPackageRoot: true
1482
- }
1483
- );
1509
+ const pak = await detectPackageManagerWithFallback(options.cwd);
1484
1510
  // By default, don't print all the stuff the package manager spits out
1485
1511
  if (!options.debug) {
1486
1512
  pak.loglevel = 'error';
@@ -1520,16 +1546,7 @@ async function installNodeModule(npmUrl, options = {}) {
1520
1546
  */
1521
1547
  async function uninstallNodeModule(packageName, options = {}) {
1522
1548
  // Figure out which package manager is in charge (probably npm at this point)
1523
- const pak = await detectPackageManager(
1524
- typeof options.cwd === 'string'
1525
- ? // If a cwd was provided, use it
1526
- { cwd: options.cwd }
1527
- : // Otherwise find the ioBroker root dir
1528
- {
1529
- cwd: __dirname,
1530
- setCwdToPackageRoot: true
1531
- }
1532
- );
1549
+ const pak = await detectPackageManagerWithFallback(options.cwd);
1533
1550
  // By default, don't print all the stuff the package manager spits out
1534
1551
  if (!options.debug) {
1535
1552
  pak.loglevel = 'error';
@@ -1563,16 +1580,7 @@ async function uninstallNodeModule(packageName, options = {}) {
1563
1580
  */
1564
1581
  async function rebuildNodeModules(options = {}) {
1565
1582
  // Figure out which package manager is in charge (probably npm at this point)
1566
- const pak = await detectPackageManager(
1567
- typeof options.cwd === 'string'
1568
- ? // If a cwd was provided, use it
1569
- { cwd: options.cwd }
1570
- : // Otherwise find the ioBroker root dir
1571
- {
1572
- cwd: __dirname,
1573
- setCwdToPackageRoot: true
1574
- }
1575
- );
1583
+ const pak = await detectPackageManagerWithFallback(options.cwd);
1576
1584
  // By default, don't print all the stuff the package manager spits out
1577
1585
  if (!options.debug) {
1578
1586
  pak.loglevel = 'error';
@@ -2995,6 +3003,7 @@ function pipeLinewise(input, output) {
2995
3003
  crlfDelay: Infinity
2996
3004
  });
2997
3005
  rl.on('line', line => output.write(line + os.EOL));
3006
+ rl.on('error', () => {}); // Ignore errors
2998
3007
  }
2999
3008
 
3000
3009
  /**
@@ -3439,33 +3448,60 @@ async function getInstancesOrderedByStartPrio(objects, logger, logPrefix = '') {
3439
3448
  * @returns {Promise<void>}
3440
3449
  */
3441
3450
  async function setExecutableCapabilities(execPath, capabilities, modeEffective, modePermitted, modeInherited) {
3451
+ if (!Array.isArray(capabilities) || !capabilities.length) {
3452
+ throw new Error('No capabilities array provided');
3453
+ }
3454
+
3442
3455
  // if not linux do nothing and silently exit
3443
- if (os.platform() === 'linux') {
3444
- if (Array.isArray(capabilities) && capabilities.length) {
3445
- let modes = '';
3446
- const capabilitiesStr = capabilities.join(',');
3456
+ if (os.platform() !== 'linux') {
3457
+ return;
3458
+ }
3447
3459
 
3448
- if (modeEffective) {
3449
- modes += 'e';
3460
+ // if Docker and Admin Capabilities should be set check if we are allowed to do that
3461
+ if (isDocker() && capabilities.includes('cap_net_admin')) {
3462
+ try {
3463
+ const systemCaps = fs.readFileSync(`/proc/${process.pid}/status`, 'utf-8');
3464
+ const capBnd = systemCaps.match(/^CapBnd:\s(.+)$/m);
3465
+ // We found a value in CapBnd line
3466
+ if (capBnd && capBnd[1]) {
3467
+ const { stdout } = await execAsync(`capsh --decode=${capBnd[1]}`);
3468
+ // Stdout looks like "0x00000000a80425fb=cap_chown,cap_dac_override,..."
3469
+ if (stdout && stdout.startsWith(`0x${capBnd[1]}=`)) {
3470
+ const capBndArr = stdout.substring(capBnd[1].length + 3).split(',');
3471
+ // if Admin Capability is not included in System Capabilities we remove it from array
3472
+ if (!capBndArr.includes('cap_net_admin')) {
3473
+ capabilities = capabilities.filter(c => c !== 'cap_net_admin');
3474
+ }
3475
+ }
3450
3476
  }
3477
+ } catch {
3478
+ // Ok we could not find it out, so update Caps but better without Admin Capability
3479
+ capabilities = capabilities.filter(c => c !== 'cap_net_admin');
3480
+ }
3481
+ }
3451
3482
 
3452
- if (modePermitted) {
3453
- modes += 'p';
3454
- }
3483
+ if (capabilities.length) {
3484
+ let modes = '';
3485
+ const capabilitiesStr = capabilities.join(',');
3455
3486
 
3456
- if (modeInherited) {
3457
- modes += 'i';
3458
- }
3487
+ if (modeEffective) {
3488
+ modes += 'e';
3489
+ }
3459
3490
 
3460
- if (modes.length) {
3461
- modes = `+${modes}`;
3462
- }
3491
+ if (modePermitted) {
3492
+ modes += 'p';
3493
+ }
3463
3494
 
3464
- // if this throws it needs to be caught outside
3465
- await cpPromise.exec(`sudo setcap ${capabilitiesStr}${modes} ${execPath}`);
3466
- } else {
3467
- throw new Error('No capabilities array provided');
3495
+ if (modeInherited) {
3496
+ modes += 'i';
3468
3497
  }
3498
+
3499
+ if (modes.length) {
3500
+ modes = `+${modes}`;
3501
+ }
3502
+
3503
+ // if this throws it needs to be caught outside
3504
+ await cpPromise.exec(`sudo setcap ${capabilitiesStr}${modes} ${execPath}`);
3469
3505
  }
3470
3506
  }
3471
3507
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iobroker/js-controller-common",
3
- "version": "4.0.4",
3
+ "version": "4.0.6",
4
4
  "engines": {
5
5
  "node": ">=12.0.0"
6
6
  },
@@ -47,5 +47,5 @@
47
47
  "lib/",
48
48
  "index.js"
49
49
  ],
50
- "gitHead": "184f8340136fe668fb4d64d572ebeecb7b06b6e7"
50
+ "gitHead": "3581cca2a0661a5fc346e5cb99bf664898b3d652"
51
51
  }