diff --git a/build/src/src/calls/fetchDirectory.js b/build/src/src/calls/fetchDirectory.js index 5000f21b4..77832deac 100644 --- a/build/src/src/calls/fetchDirectory.js +++ b/build/src/src/calls/fetchDirectory.js @@ -42,7 +42,11 @@ function emitPkg(pkg) { */ const fetchDirectory = async () => { if (await isSyncing()) { - throw Error('Mainnet is syncing'); + return { + message: `Mainnet is still syncing`, + result: [], + logMessage: true, + }; } // Emit a cached version right away diff --git a/build/src/src/calls/fetchPackageData.js b/build/src/src/calls/fetchPackageData.js index 6214d343c..5ce6d264c 100644 --- a/build/src/src/calls/fetchPackageData.js +++ b/build/src/src/calls/fetchPackageData.js @@ -22,7 +22,11 @@ const fetchPackageData = async ({ id, }) => { if (await isSyncing()) { - throw Error('Mainnet is syncing'); + return { + message: `Mainnet is still syncing`, + result: {}, + logMessage: true, + }; } const packageReq = parse.packageReq(id); diff --git a/build/src/src/calls/fetchPackageVersions.js b/build/src/src/calls/fetchPackageVersions.js index 05948a058..bda52318d 100644 --- a/build/src/src/calls/fetchPackageVersions.js +++ b/build/src/src/calls/fetchPackageVersions.js @@ -23,7 +23,11 @@ const fetchPackageVersions = async ({ id, }) => { if (await isSyncing()) { - throw Error('Mainnet is syncing'); + return { + message: `Mainnet is still syncing`, + result: [], + logMessage: true, + }; } const packageReq = parse.packageReq(id); diff --git a/build/src/src/calls/getStats.js b/build/src/src/calls/getStats.js index 5c51d050e..288c0a190 100644 --- a/build/src/src/calls/getStats.js +++ b/build/src/src/calls/getStats.js @@ -13,7 +13,9 @@ const si = require('systeminformation'); * } */ const getStats = async () => { - const cpu = await si.currentLoad(); + /* eslint-disable max-len */ + const cpuRatioRaw = await shellExec(`grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage}'`); + const cpuRatio = isNaN(cpuRatioRaw) ? null : `${parseInt(cpuRatioRaw)}%`; const disk = await shellExec(`df / | awk 'NR>1 { print $5}'`, true); // Attempt two mem fetchs let memUsedRatio; @@ -25,11 +27,12 @@ const getStats = async () => { } else if (memUsed && memTotal) { memUsedRatio = Math.floor(100*memUsed/memTotal)+'%'; } + /* eslint-enable max-len */ return { message: `Checked stats of this DAppNode server`, result: { - cpu: cpu.currentload ? Math.floor(cpu.currentload)+'%' : null, + cpu: cpuRatio, memory: memUsedRatio, disk: disk.trim(), }, diff --git a/build/src/src/calls/installPackage.js b/build/src/src/calls/installPackage.js index b6d18a5a7..1b4ec7d67 100644 --- a/build/src/src/calls/installPackage.js +++ b/build/src/src/calls/installPackage.js @@ -85,16 +85,20 @@ const installPackage = async ({ // Prevent default values. Someone can try to spoof "isCore" in the manifest manifest.isCore = false; if (manifest.type == 'dncore') { - if ( - // Package has to come from a dappnode's APM repo. - name.endsWith('.dnp.dappnode.eth') && ver.startsWith('/ipfs/') - // Or the user can bypass this restriction - || options.BYPASS_CORE_RESTRICTION + if (options.BYPASS_CORE_RESTRICTION) { + manifest.isCore = true; + } else if ( + // The origin must be the registry controlled by the DAppNode team + name.endsWith('.dnp.dappnode.eth') + // It must NOT come from ipfs, thus APM + && !ver.startsWith('/ipfs/') ) { manifest.isCore = true; } else { // inform the user of improper usage - throw Error('Unverified CORE package request: '+name); + /* eslint-disable max-len */ + throw Error(`Unverified core package ${name}, only allowed origin is .dnp.dappnode.eth APM registy`); + /* eslint-enable max-len */ } } diff --git a/build/src/src/calls/managePorts.js b/build/src/src/calls/managePorts.js index 0a729769a..616c4aeed 100644 --- a/build/src/src/calls/managePorts.js +++ b/build/src/src/calls/managePorts.js @@ -36,7 +36,7 @@ const managePorts = async ({ } return { - message: msg+' ports '+ports.join(', '), + message: `${msg} ports ${ports.map((p) => `${p.number} ${p.type}`).join(', ')}`, logMessage: true, userAction: true, }; diff --git a/build/src/src/index.js b/build/src/src/index.js index bba5b4e5a..464d876a5 100644 --- a/build/src/src/index.js +++ b/build/src/src/index.js @@ -40,9 +40,16 @@ const wrapErrors = (handler, event) => result: res.result || {}, }); } catch (err) { + // Rename known shit-errors + // When attempting to call a contract while the chain is syncing: if (err.message && err.message.includes('decode 0x from ABI')) { - err.message = 'Chain is still syncing: '+err.message; + err.message = `Chain is still syncing: ${err.message}`; } + // When attempting an JSON RPC but the connection with the node is closed: + if (err.message && err.message.includes('connection not open')) { + err.message = `Could not connect to ethchain: ${err.message}`; + } + logUserAction.log({level: 'error', event, ...error2obj(err), kwargs}); logs.error('Call '+event+' error: '+err.message+'\nStack: '+err.stack); return JSON.stringify({ diff --git a/build/src/src/modules/docker/Docker.js b/build/src/src/modules/docker/Docker.js index 44dba5892..df1ec98ab 100644 --- a/build/src/src/modules/docker/Docker.js +++ b/build/src/src/modules/docker/Docker.js @@ -175,11 +175,29 @@ function getVpnImageCmd() { return 'docker inspect DAppNodeCore-vpn.dnp.dappnode.eth -f \'{{.Config.Image}}\''; } -function getUpnpCmd(port, type, IMAGE) { +/** + * + * @param {String} port Must be in the format port = { + * number: 30303, + * type: TCP + * } + * @param {String} type + * @param {String} IMAGE + * @return {String} + */ +function getUpnpCmd(port = {}, type, IMAGE) { + if (typeof port !== 'object') { + throw Error(`port must be an object: port = { number: 30303, type: 'UDP' }`); + } + if (!port.number) { + throw Error(`port must container a number property: port = { number: 30303, type: 'UDP' }`); + } let flag; if (type === 'open') flag = '-r'; if (type === 'close') flag = '-d'; - return 'docker run --rm --net=host '+IMAGE.trim()+' upnpc -e DAppNode '+flag+' '+port+' UDP'; + /* eslint-disable max-len */ + return `docker run --rm --net=host ${IMAGE.trim()} upnpc -e DAppNode ${flag} ${port.number} ${port.type || 'TCP'}`; + /* eslint-enable max-len */ } function parseOptions(options) { diff --git a/dappnode_package.json b/dappnode_package.json index b428f06eb..02849e99a 100644 --- a/dappnode_package.json +++ b/dappnode_package.json @@ -1,6 +1,6 @@ { "name": "dappmanager.dnp.dappnode.eth", - "version": "0.1.13", + "version": "0.1.14", "description": "Dappnode package responsible for providing the DappNode Package Manager", "avatar": "/ipfs/QmdT2GX9ybaoE25HBk7is8CDnfn2KaFTpZVkLdfkAQs1PN", "type": "dncore", @@ -21,7 +21,12 @@ "contributors": [ "DAppLion (https://github.com/dapplion)" ], - "keywords": ["DAppNodeCore", "DAPP", "Manager", "Installer"], + "keywords": [ + "DAppNodeCore", + "DAPP", + "Manager", + "Installer" + ], "homepage": { "adminui": "http://my.admin.dnp.dappnode.eth/", "homepage": "https://github.com/dappnode/DNP_DAPPMANAGER#readme" @@ -34,4 +39,4 @@ "url": "https://github.com/dappnode/DNP_DAPPMANAGER/issues" }, "license": "GPL-3.0" -} +} \ No newline at end of file diff --git a/docker-compose-dappmanager.yml b/docker-compose-dappmanager.yml index fa0b54884..2a473d9fd 100644 --- a/docker-compose-dappmanager.yml +++ b/docker-compose-dappmanager.yml @@ -13,7 +13,7 @@ volumes: services: dappmanager.dnp.dappnode.eth: build: ./build - image: dappmanager.dnp.dappnode.eth:0.1.13 + image: dappmanager.dnp.dappnode.eth:0.1.14 container_name: DAppNodeCore-dappmanager.dnp.dappnode.eth restart: always volumes: