diff --git a/app/js/app.config.js b/app/js/app.config.js index 3080421b2e9023ac7a0b77064a91b406032deee0..cedf5665fd070b4e8f2202b46a724da523b38046 100644 --- a/app/js/app.config.js +++ b/app/js/app.config.js @@ -1,8 +1,8 @@ module.exports = () => { - require('./services/bma')(angular); + require('./services/webmin')(angular); - var duniterApp = angular.module('duniterUIApp', [ + const duniterApp = angular.module('duniterUIApp', [ 'ui.router', 'homeControllers', 'pascalprecht.translate' @@ -66,7 +66,7 @@ module.exports = () => { } }; - let homeControllers = angular.module('homeControllers', ['duniter.services', 'ngFileUpload']); + let homeControllers = angular.module('homeControllers', ['duniter.services.bma', 'duniter.services.webmin', 'ngFileUpload']); homeControllers.controller('IndexController', require('./controllers/IndexController')); homeControllers.controller('AboutController', require('./controllers/AboutController')); diff --git a/app/js/controllers/IndexController.js b/app/js/controllers/IndexController.js index 7063358b3bcf077613b2656609288c645330a159..77daba155323efc5348a8cfa6c6cda0eb611773d 100644 --- a/app/js/controllers/IndexController.js +++ b/app/js/controllers/IndexController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $http, $state, BMA, summary, UIUtils) => { +module.exports = ($scope, $http, $state, BMA, Webmin, summary, UIUtils) => { UIUtils.changeTitle(summary.version); @@ -10,7 +10,7 @@ module.exports = ($scope, $http, $state, BMA, summary, UIUtils) => { co(function *() { let connected = false; try { - let summary = yield BMA.webmin.summary(); + let summary = yield Webmin.summary(); if (summary.current) { return $state.go('main.home.overview'); } diff --git a/app/js/controllers/init/create/IdentityController.js b/app/js/controllers/init/create/IdentityController.js index 9e01dfcd413b057b0ec2b14a85a6184e6864f27f..548b7d3a6623f6e7de61948a61578ac6196d9c68 100644 --- a/app/js/controllers/init/create/IdentityController.js +++ b/app/js/controllers/init/create/IdentityController.js @@ -17,6 +17,7 @@ module.exports = ($scope, $state, PubkeyGenerator) => { PubkeyGenerator($scope); + conf.dev_autoconf = true; if (conf.dev_autoconf) { $scope.$parent.conf.idty_uid = 'dev_' + ~~(Math.random() * 2147483647); $scope.$parent.conf.idty_entropy = ~~(Math.random() * 2147483647) + ""; diff --git a/app/js/controllers/init/create/RootBlockController.js b/app/js/controllers/init/create/RootBlockController.js index 4b0222d03b08bfdb9bca7350342e21ffea786aa6..572ff33d8b9f0285d24662f6331a72aaa66ba057 100644 --- a/app/js/controllers/init/create/RootBlockController.js +++ b/app/js/controllers/init/create/RootBlockController.js @@ -3,7 +3,7 @@ var co = require('co'); var conf = require('js/lib/conf/conf'); -module.exports = ($scope, $http, $state, BMA) => { +module.exports = ($scope, $http, $state, BMA, Webmin) => { $scope.generated = ''; $scope.started = false; @@ -20,11 +20,11 @@ module.exports = ($scope, $http, $state, BMA) => { } $scope.host_listening = hosts.join('\n'); $scope.started = true; - yield BMA.webmin.server.sendConf({ + yield Webmin.server.sendConf({ conf: $scope.$parent.conf }); - yield BMA.webmin.server.http.start(); - yield BMA.webmin.server.http.openUPnP(); + yield Webmin.server.http.start(); + yield Webmin.server.http.openUPnP(); yield $scope.try(); } catch (e) { $scope.message = e.message; @@ -32,13 +32,13 @@ module.exports = ($scope, $http, $state, BMA) => { }); $scope.stop = () => co(function *() { - yield BMA.webmin.server.http.stop(); + yield Webmin.server.http.stop(); $scope.started = false; }); $scope.try = () => co(function *() { try { - $scope.block = yield BMA.webmin.server.previewNext(); + $scope.block = yield Webmin.server.previewNext(); $scope.generated = $scope.block.raw; $scope.message = ''; } catch (e) { @@ -47,7 +47,8 @@ module.exports = ($scope, $http, $state, BMA) => { }); $scope.accept = () => co(function *() { - let res = yield BMA.blockchain.block_add({ + const node_address = $scope.$parent.conf.local_ipv4 || $scope.$parent.conf.local_ipv6; + let res = yield BMA(node_address + ":" + $scope.$parent.conf.lport).blockchain.block_add({ block: $scope.generated }); if (res.number == 0) { @@ -57,14 +58,14 @@ module.exports = ($scope, $http, $state, BMA) => { }); $scope.startServices = () => co(function *() { - yield BMA.webmin.server.services.startAll(); + yield Webmin.server.services.startAll(); $state.go('index'); }); $scope.cancelAndReset = () => co(function *() { - yield BMA.webmin.server.http.stop(); - yield BMA.webmin.server.services.stopAll(); - yield BMA.webmin.server.resetData(); + yield Webmin.server.http.stop(); + yield Webmin.server.services.stopAll(); + yield Webmin.server.resetData(); $state.go('index'); }); diff --git a/app/js/controllers/init/sync/SyncController.js b/app/js/controllers/init/sync/SyncController.js index 973239221c29f8857773018b9d350bfe2c33c475..493811bad50928fe6a2eeb9d8868fd1da6b81e18 100644 --- a/app/js/controllers/init/sync/SyncController.js +++ b/app/js/controllers/init/sync/SyncController.js @@ -2,9 +2,9 @@ var co = require('co'); -module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, BMA, UIUtils) => { +module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, BMA, UIUtils, Webmin) => { - let syncWS = BMA.webmin.ws(); + let syncWS = Webmin.ws(); UIUtils.enableInputs(); $scope.sync_mode = 'simplified'; @@ -27,7 +27,7 @@ module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, BMA } $scope.checking = true; try { - const current = yield BMA.webmin.server.testSync({ + const current = yield Webmin.server.testSync({ host: $scope.host, port: $scope.port }); @@ -65,7 +65,7 @@ module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, BMA $scope.sync_failed = data.value; let errorMessage = data.msg && (data.msg.message || data.msg); errorMessage = translatedErr + ' « ' + errorMessage + ' »'; - BMA.webmin.server.republishNewSelfPeer() + Webmin.server.republishNewSelfPeer() .then(() => console.log('Peer republished')); if (data.value === true) { $state.go('index'); @@ -87,10 +87,10 @@ module.exports = ($scope, $http, $state, $timeout, $stateParams, $translate, BMA } } }); - yield BMA.webmin.server.autoConfNetwork(); + yield Webmin.server.autoConfNetwork(); localStorage.setItem("sync_host", sp[0]); localStorage.setItem("sync_port", sp[1]); - BMA.webmin.server.startSync({ + Webmin.server.startSync({ host: sp[0], port: sp[1], to: $scope.to, diff --git a/app/js/controllers/main/MainController.js b/app/js/controllers/main/MainController.js index 6f570d35a0a6da6b843a6c4c17e317cc9de7af4a..60be9e3bdbc4c4903829a07784b864d4c383c82f 100644 --- a/app/js/controllers/main/MainController.js +++ b/app/js/controllers/main/MainController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $state, $http, $timeout, $interval, BMA, summary, UIUtils, Base58) => { +module.exports = ($scope, $state, $http, $timeout, $interval, BMA, Webmin, summary, UIUtils, Base58) => { const local_host = summary.host.split(':')[0]; // We suppose IPv4 configuration const local_port = summary.host.split(':')[1]; @@ -121,9 +121,9 @@ module.exports = ($scope, $state, $http, $timeout, $interval, BMA, summary, UIUt $scope.startServer = () => { $scope.server_stopped = false; return co(function *() { - yield BMA.webmin.server.http.start(); - yield BMA.webmin.server.services.startAll(); - yield BMA.webmin.server.http.regularUPnP(); + yield Webmin.server.http.start(); + yield Webmin.server.services.startAll(); + yield Webmin.server.http.regularUPnP(); $scope.server_started = true; }); }; @@ -131,8 +131,8 @@ module.exports = ($scope, $state, $http, $timeout, $interval, BMA, summary, UIUt $scope.stopServer = () => { $scope.server_started = false; return co(function *() { - yield BMA.webmin.server.http.stop(); - yield BMA.webmin.server.services.stopAll(); + yield Webmin.server.http.stop(); + yield Webmin.server.services.stopAll(); $scope.server_stopped = true; }); }; diff --git a/app/js/controllers/main/graphs/GraphsBlockchainController.js b/app/js/controllers/main/graphs/GraphsBlockchainController.js index 87c449092e8950706437940b412423f0951c6c1d..014aecdf00c9e881e13115cba967ab50f60fcd5a 100644 --- a/app/js/controllers/main/graphs/GraphsBlockchainController.js +++ b/app/js/controllers/main/graphs/GraphsBlockchainController.js @@ -4,7 +4,7 @@ const BLOCKS_COUNT = 40; var co = require('co'); -module.exports = ($scope, $state, $timeout, BMA, UIUtils, Graph) => { +module.exports = ($scope, $state, $timeout, BMA, Webmin, UIUtils, Graph) => { let data = {}; @@ -31,9 +31,9 @@ module.exports = ($scope, $state, $timeout, BMA, UIUtils, Graph) => { $scope.updateGraphs = () => { return co(function *() { - let summary = yield BMA.webmin.summary(); - let parameters = yield BMA.currency.parameters(); - let blocks = yield BMA.blockchain.blocks({ + let summary = yield Webmin.summary(); + let parameters = yield BMA(summary.host).currency.parameters(); + let blocks = yield BMA(summary.host).blockchain.blocks({ count: $scope.blocksCount, from: Math.max(0, summary.current.number - $scope.blocksCount) }); diff --git a/app/js/controllers/main/home/tabs/HomeNetworkController.js b/app/js/controllers/main/home/tabs/HomeNetworkController.js index 92cf31e72beaa70517a3df8e2c0a48dcc1fdd923..6ea67504c11d1d7c311cdb4e1b4cff3d680941ab 100644 --- a/app/js/controllers/main/home/tabs/HomeNetworkController.js +++ b/app/js/controllers/main/home/tabs/HomeNetworkController.js @@ -1,15 +1,15 @@ "use strict"; -module.exports = ($scope, BMA, peers) => { +module.exports = ($scope, BMA, peers, summary) => { $scope.peers = peers.peers; - var co = require('co'); + const co = require('co'); $scope.update = () => co(function *() { $scope.searching = true; let delayP = Q.delay(500); - $scope.peers = (yield BMA.network.peers()).peers; + $scope.peers = (yield BMA(summary.host).network.peers()).peers; yield delayP; $scope.searching = false; $scope.$apply(); diff --git a/app/js/controllers/main/home/tabs/OverviewController.js b/app/js/controllers/main/home/tabs/OverviewController.js index ddb18c2f82308fe5a6ef535e7ba2c9577a7f1b7b..2c3df4ce1cc6cf4d97b3e1f4aa89643a16009f5b 100644 --- a/app/js/controllers/main/home/tabs/OverviewController.js +++ b/app/js/controllers/main/home/tabs/OverviewController.js @@ -1,6 +1,6 @@ "use strict"; -module.exports = ($scope, $interval, BMA, UIUtils, summary, ws) => { +module.exports = ($scope, $interval, BMA, Webmin, UIUtils, summary, ws) => { let co = require('co'); let moment = require('moment'); @@ -44,7 +44,7 @@ module.exports = ($scope, $interval, BMA, UIUtils, summary, ws) => { }, 1000); $scope.loadPowData = () => co(function*() { - let res = yield BMA.webmin.powSummary(); + let res = yield Webmin.powSummary(); $scope.pow_total = res.total; $scope.pow_mirror = res.mirror; $scope.pow_waiting = res.waiting; @@ -106,7 +106,7 @@ module.exports = ($scope, $interval, BMA, UIUtils, summary, ws) => { }); function bindBlockWS(cb) { - BMA.websocket.block().on(undefined, (block) => { + BMA(summary.host).websocket.block().on(undefined, (block) => { $scope.current = block; let M = summary.current.monetaryMass || 0; let UD = summary.parameters.ud0; @@ -124,7 +124,7 @@ module.exports = ($scope, $interval, BMA, UIUtils, summary, ws) => { $scope.reconfiguring = true; let delay = Q.delay(1000); try { - let netinferfaces = yield BMA.webmin.network.interfaces(); + let netinferfaces = yield Webmin.network.interfaces(); let conf = {}; conf.local_ipv4 = netinferfaces.auto.local.ipv4 || ''; conf.local_ipv6 = netinferfaces.auto.local.ipv6 || ''; @@ -134,7 +134,7 @@ module.exports = ($scope, $interval, BMA, UIUtils, summary, ws) => { conf.rport = netinferfaces.auto.remote.port || 9330; conf.upnp = netinferfaces.auto.remote.upnp || false; conf.dns = netinferfaces.auto.remote.dns || ''; - yield BMA.webmin.server.netConf({ + yield Webmin.server.netConf({ conf: conf }); yield delay; @@ -152,7 +152,7 @@ module.exports = ($scope, $interval, BMA, UIUtils, summary, ws) => { yield $scope.startServer(); try { yield $scope.loadPowData(); - const reachable = yield BMA.webmin.isNodePubliclyReachable(); + const reachable = yield Webmin.isNodePubliclyReachable(); if (!reachable || !reachable.success) { $scope.should_reconfigure = true; } diff --git a/app/js/controllers/main/settings/SettingsController.js b/app/js/controllers/main/settings/SettingsController.js index 41beff8aba1475187efba99d4a6769fc64ec1cac..bec568e8d794c1ca5ee5f6a2d1387cc5fb8e1015 100644 --- a/app/js/controllers/main/settings/SettingsController.js +++ b/app/js/controllers/main/settings/SettingsController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $http, $state, $location, BMA, UIUtils) => { +module.exports = ($scope, $http, $state, $location, BMA, Webmin, UIUtils) => { UIUtils.enableTabs(); @@ -12,9 +12,9 @@ module.exports = ($scope, $http, $state, $location, BMA, UIUtils) => { $(".dropdown-button").dropdown({ constrainwidth: false }); $scope.fullReset = () => co(function *() { - yield BMA.webmin.server.http.stop(); - yield BMA.webmin.server.services.stopAll(); - yield BMA.webmin.server.resetData(); + yield Webmin.server.http.stop(); + yield Webmin.server.services.stopAll(); + yield Webmin.server.resetData(); $state.go('index'); }); }; diff --git a/app/js/controllers/main/settings/tabs/BackupController.js b/app/js/controllers/main/settings/tabs/BackupController.js index 3c5e1b40f79545d32ee32de386a1a520912b1596..be81a8616ad915f31af846302ecf1eaef0a170bb 100644 --- a/app/js/controllers/main/settings/tabs/BackupController.js +++ b/app/js/controllers/main/settings/tabs/BackupController.js @@ -1,8 +1,8 @@ "use strict"; -module.exports = ($scope, Importer, BMA) => { +module.exports = ($scope, Importer, Webmin) => { - $scope.export_link = BMA.webmin.getExportURL(); + $scope.export_link = Webmin.getExportURL(); Importer($scope); }; diff --git a/app/js/controllers/main/settings/tabs/CPUController.js b/app/js/controllers/main/settings/tabs/CPUController.js index 24345f31e950835aecc8cf0df637ea4d35084544..28e9e884509aa8411136245d9bdb4e628c44f5d4 100644 --- a/app/js/controllers/main/settings/tabs/CPUController.js +++ b/app/js/controllers/main/settings/tabs/CPUController.js @@ -2,13 +2,13 @@ const co = require('co'); -module.exports = ($scope, $http, $state, $timeout, UIUtils, summary, BMA) => { +module.exports = ($scope, $http, $state, $timeout, UIUtils, summary, Webmin) => { $scope.cpuPower = parseInt(summary.conf.cpu * 100); $scope.updateCPUpower = () => co(function *() { $scope.savingCPU = true; - yield BMA.webmin.server.cpuConf({ + yield Webmin.server.cpuConf({ cpu: parseFloat(($scope.cpuPower / 100).toFixed(2)) }); UIUtils.toast('settings.cpu.saved'); diff --git a/app/js/controllers/main/settings/tabs/DataController.js b/app/js/controllers/main/settings/tabs/DataController.js index d0c3d6aa47d392f8eb2697307c30b7ac44c2f5bc..4869f8c89c782168498145fe9e214d86b1ffb48f 100644 --- a/app/js/controllers/main/settings/tabs/DataController.js +++ b/app/js/controllers/main/settings/tabs/DataController.js @@ -3,7 +3,7 @@ var co = require('co'); var Peer = require('js/lib/entity/peer'); -module.exports = ($scope, $http, $state, BMA, peers) => { +module.exports = ($scope, $http, $state, Webmin, peers) => { $scope.peers = peers.map((peer) => { let p = new Peer(peer); @@ -18,9 +18,9 @@ module.exports = ($scope, $http, $state, BMA, peers) => { }; $scope.resetNodeAndSync = () => co(function *() { - yield BMA.webmin.server.http.stop(); - yield BMA.webmin.server.services.stopAll(); - yield BMA.webmin.server.resetData(); + yield Webmin.server.http.stop(); + yield Webmin.server.services.stopAll(); + yield Webmin.server.resetData(); let sp = $scope.remote_host.split('|'); $state.go('sync', { host: sp[0], diff --git a/app/js/controllers/main/settings/tabs/KeyController.js b/app/js/controllers/main/settings/tabs/KeyController.js index 41f4f2a3950f8968dbfe869d6abf81faa557e35a..9d276eda3945082b078b0f5920e7b6e8c7ac43c0 100644 --- a/app/js/controllers/main/settings/tabs/KeyController.js +++ b/app/js/controllers/main/settings/tabs/KeyController.js @@ -2,7 +2,7 @@ var co = require('co'); -module.exports = ($scope, $state, BMA, summary, PubkeyGenerator) => { +module.exports = ($scope, $state, Webmin, summary, PubkeyGenerator) => { $scope.pubkey = summary.pubkey; @@ -11,7 +11,7 @@ module.exports = ($scope, $state, BMA, summary, PubkeyGenerator) => { }, 500); $scope.accept = () => co(function *() { - yield BMA.webmin.server.keyConf({ + yield Webmin.server.keyConf({ conf: $scope.$parent.conf }); $scope.$parent.conf.idty_entropy = ''; diff --git a/app/js/controllers/main/settings/tabs/LogsSettingsController.js b/app/js/controllers/main/settings/tabs/LogsSettingsController.js index d8b64be9e9834d49627ad55829800ca736e4d7da..87af3e3571252458611dd826a1b7486604afa088 100644 --- a/app/js/controllers/main/settings/tabs/LogsSettingsController.js +++ b/app/js/controllers/main/settings/tabs/LogsSettingsController.js @@ -2,7 +2,7 @@ const co = require('co'); -module.exports = ($scope, BMA) => { +module.exports = ($scope, Webmin) => { $scope.generating = false; $scope.error = ''; @@ -12,7 +12,7 @@ module.exports = ($scope, BMA) => { try { $scope.error = ''; $scope.generating = true; - const res = yield BMA.webmin.logsExport(2000); + const res = yield Webmin.logsExport(2000); $scope.link = res.link; } catch (e) { $scope.error = (e && e.message) || e || 'Unknown error'; diff --git a/app/js/controllers/main/settings/tabs/NetworkController.js b/app/js/controllers/main/settings/tabs/NetworkController.js index 11b8b0c351efdb91043e922f6a9f6f1a5279b184..aa03971e6781340df945106dc5592e7d462e401e 100644 --- a/app/js/controllers/main/settings/tabs/NetworkController.js +++ b/app/js/controllers/main/settings/tabs/NetworkController.js @@ -3,7 +3,7 @@ var co = require('co'); var conf = require('js/lib/conf/conf'); -module.exports = ($scope, $http, $state, BMA, UIUtils, netinterfaces, firstConf) => { +module.exports = ($scope, $http, $state, Webmin, UIUtils, netinterfaces, firstConf) => { let autoconf = netinterfaces.auto; @@ -47,7 +47,7 @@ module.exports = ($scope, $http, $state, BMA, UIUtils, netinterfaces, firstConf) $scope.saveConf = () => co(function *() { $scope.$parent.conf.lport = $scope.$parent.conf.rport; $scope.$parent.conf.remote_ipv6 = $scope.$parent.conf.local_ipv6; - yield BMA.webmin.server.netConf({ + yield Webmin.server.netConf({ conf: $scope.$parent.conf }); UIUtils.toast('settings.network.saved'); diff --git a/app/js/lib/conf/conf.js b/app/js/lib/conf/conf.js index 3629194d9392e341d9e27f5f43a4dea7f31b5ff6..b787b422ad0dd51265a67ebea9e71159b888191e 100644 --- a/app/js/lib/conf/conf.js +++ b/app/js/lib/conf/conf.js @@ -1,7 +1,7 @@ module.exports = { - "server": "", // Empty server will use the browser current host - "port": "", // Empty port will use the browser current port - "default_port": 9220, - "dev_autoconf": false, - "api_timeout": 10000 // 10 sec timeout + server: "", // Empty server will use the browser current host + port: "", // Empty port will use the browser current port + default_port: 10500, + dev_autoconf: false, + api_timeout: 10000 // 10 sec timeout }; diff --git a/app/js/lib/conf/routes.js b/app/js/lib/conf/routes.js index a1b00f30d61076c21fa40bc10c4ce6d25b9ca978..0b20964a7db1378b3dedf136d35a089166d1a485 100644 --- a/app/js/lib/conf/routes.js +++ b/app/js/lib/conf/routes.js @@ -11,8 +11,8 @@ module.exports = (app) => { url: '/', template: require('views/index'), resolve: { - ws: (BMA) => BMA.webmin.ws(), - summary: (BMA) => BMA.webmin.summary() + ws: (Webmin) => Webmin.ws(), + summary: (Webmin) => Webmin.summary() }, controller: 'IndexController' }). @@ -21,7 +21,7 @@ module.exports = (app) => { url: '/about', template: require('views/about'), resolve: { - summary: (BMA) => BMA.webmin.summary(), + summary: (Webmin) => Webmin.summary(), version: (summary) => summary && 'v' + summary.version || 'unknown version' }, controller: 'AboutController' @@ -78,7 +78,7 @@ module.exports = (app) => { url: '/create/network', template: require('views/init/create/create_network'), resolve: { - netinterfaces: (BMA) => resolveNetworkAutoConf(BMA), + netinterfaces: (Webmin) => resolveNetworkAutoConf(Webmin), firstConf: () => true }, controller: 'NetworkController' @@ -107,8 +107,8 @@ module.exports = (app) => { url: '/main', template: require('views/main/main'), resolve: { - ws: (BMA) => BMA.webmin.ws(), - summary: (BMA) => BMA.webmin.summary() + ws: (Webmin) => Webmin.ws(), + summary: (Webmin) => Webmin.summary() }, controller: 'MainController' }). @@ -124,7 +124,7 @@ module.exports = (app) => { url: '/overview', template: require('views/main/home/tabs/overview'), resolve: { - startHttp: (BMA) => BMA.webmin.server.http.start() + startHttp: (Webmin) => Webmin.server.http.start() }, controller: 'OverviewController' }). @@ -133,8 +133,9 @@ module.exports = (app) => { url: '/network', template: require('views/main/home/tabs/network'), resolve: { - peers: (BMA) => co(function *() { - return BMA.network.peers(); + peers: (Webmin, BMA) => co(function *() { + const summary = yield Webmin.summary(); + return BMA(summary.host).network.peers(); }) }, controller: 'HomeNetworkController' @@ -145,7 +146,7 @@ module.exports = (app) => { url: '/settings', template: require('views/main/settings/settings'), resolve: { - summary: (BMA) => BMA.webmin.summary() + summary: (Webmin) => Webmin.summary() }, controller: 'SettingsController' }). @@ -154,10 +155,11 @@ module.exports = (app) => { url: '/data', template: require('views/main/settings/tabs/data'), resolve: { - peers: (BMA) => co(function *() { + peers: (Webmin, BMA) => co(function *() { try { - let self = yield BMA.network.peering.self(); - let res = yield BMA.network.peers(); + const summary = yield Webmin.summary(); + let self = yield BMA(summary.host).network.peering.self(); + let res = yield BMA(summary.host).network.peers(); return _.filter(res.peers, (p) => p.pubkey != self.pubkey && p.status == 'UP'); } catch (e) { console.error(e); @@ -184,7 +186,7 @@ module.exports = (app) => { url: '/cpu', template: require('views/main/settings/tabs/cpu'), resolve: { - summary: (BMA) => BMA.webmin.summary() + summary: (Webmin) => Webmin.summary() }, controller: 'CPUController' }). @@ -198,7 +200,7 @@ module.exports = (app) => { state('main.settings.network', { url: '/network', resolve: { - netinterfaces: (BMA) => resolveNetworkAutoConf(BMA), + netinterfaces: (Webmin) => resolveNetworkAutoConf(Webmin), firstConf: () => false }, template: require('views/main/settings/tabs/network'), @@ -238,7 +240,7 @@ module.exports = (app) => { //state('graphs.network', { // url: '/network', // resolve: { - // netinterfaces: (BMA) => resolveNetworkAutoConf(BMA), + // netinterfaces: (Webmin) => resolveNetworkAutoConf(Webmin), // firstConf: () => false // }, // template: require('views/graphs/network'), @@ -260,7 +262,7 @@ module.exports = (app) => { url: '/logs', template: require('views/logs'), resolve: { - ws: (BMA) => BMA.webmin.ws() + ws: (Webmin) => Webmin.ws() }, controller: 'LogsController' }). @@ -283,9 +285,9 @@ module.exports = (app) => { }); }); - function resolveNetworkAutoConf(BMA) { + function resolveNetworkAutoConf(Webmin) { return co(function *() { - let netinterfaces = yield BMA.webmin.network.interfaces(); + let netinterfaces = yield Webmin.network.interfaces(); return netinterfaces || { local: {}, remote: {} }; }); } diff --git a/app/js/services/bma.js b/app/js/services/bma.js index 452083486c77254f418983779fea5fbd473ceb90..6f1dcea273c20fb0d47f298a95eedb2e50618530 100644 --- a/app/js/services/bma.js +++ b/app/js/services/bma.js @@ -1,232 +1,192 @@ -var co = require('co'); -var _ = require('underscore'); -var conf = require('../lib/conf/conf'); +const co = require('co'); +const _ = require('underscore'); +const conf = require('../lib/conf/conf'); module.exports = (angular) => { - angular.module('duniter.services', ['ngResource']) + angular.module('duniter.services.bma', ['ngResource']) .factory('BMA', function($http, $q) { - - function httpProtocol() { - return window.location.protocol + '//'; - } - - function wsProtocol() { - return window.location.protocol === 'https:' ? 'wss://' : 'ws://'; - } - - function BMA(server) { - - function getResource(uri, protocol) { - return function(params) { - return $q.when(httpGet(uri, params, protocol)); - } + function httpProtocol() { + return window.location.protocol + '//'; } - function httpGet(uri, params, protocol) { - return Q.Promise((resolve, reject) => { - var config = { - timeout: conf.api_timeout - }, suffix = '', pkeys = [], queryParams = null; - if (typeof params == 'object') { - pkeys = _.keys(params); - queryParams = {}; - } - pkeys.forEach(function(pkey){ - var prevURI = uri; - uri = uri.replace(new RegExp(':' + pkey), params[pkey]); - if (prevURI == uri) { - queryParams[pkey] = params[pkey]; - } - }); - config.params = queryParams; - $http.get((protocol || httpProtocol()) + server + uri + suffix, config) - .success(function(data, status, headers, config) { - resolve(data); - }) - .error(function(data, status, headers, config) { - console.log(data); - reject(data); - }); - }); + function wsProtocol() { + return window.location.protocol === 'https:' ? 'wss://' : 'ws://'; } - function postResource(uri) { - return function(data, params) { - return $q.when(Q.Promise((resolve, reject) => { - var config = { - timeout: 4000 - }, suffix = '', pkeys = [], queryParams = null; - if (typeof params == 'object') { - pkeys = _.keys(params); - queryParams = {}; - } - pkeys.forEach(function(pkey){ - var prevURI = uri; - uri = uri.replace(new RegExp(':' + pkey), params[pkey]); - if (prevURI == uri) { - queryParams[pkey] = params[pkey]; + function BMA(host) { + function getResource(uri, protocol) { + return function (params) { + return $q.when(httpGet(uri, params, protocol)); } - }); - config.params = queryParams; - $http.post(httpProtocol() + server + uri + suffix, data, config) - .success(function(data, status, headers, config) { - resolve(data); - }) - .error(function(data, status, headers, config) { - reject(data); - }); - })); - } - } - - function bmaGET(uri) { - return getResource('/bma' + uri); - } - - function bmaPOST(uri) { - return postResource('/bma' + uri); - } - - function bmaWS(server, uri) { - return ws(wsProtocol() + server + '/bma' + uri); - } + } - let wsMap = {}; + function httpGet(uri, params, protocol) { + return Q.Promise((resolve, reject) => { + var config = { + timeout: conf.api_timeout + }, suffix = '', pkeys = [], queryParams = null; + if (typeof params == 'object') { + pkeys = _.keys(params); + queryParams = {}; + } + pkeys.forEach(function (pkey) { + var prevURI = uri; + uri = uri.replace(new RegExp(':' + pkey), params[pkey]); + if (prevURI == uri) { + queryParams[pkey] = params[pkey]; + } + }); + config.params = queryParams; + const url = (protocol || httpProtocol()) + host + uri + suffix; + $http.get(url, config) + .success(function (data, status, headers, config) { + resolve(data); + }) + .error(function (data, status, headers, config) { + console.log(data); + reject(data); + }); + }); + } - function ws(uri) { - var sock = wsMap[uri] || new WebSocket(uri); - wsMap[uri] = sock; - sock.onclose = function(e) { - console.log('close'); - console.log(e); - }; - sock.onerror = function(e) { - console.log('onerror'); - console.log(e); - }; - let opened = false, openedCallback; - sock.onopen = function() { - opened = true; - openedCallback && openedCallback(); - }; - let listener, messageType; - sock.onmessage = function(e) { - let res = JSON.parse(e.data); - if (res.type == 'log') { - for (let i = 0, len = res.value.length; i < len; i++) { - let log = res.value[i]; - // console[log.level](log.msg); - } + function postResource(uri) { + return function (data, params) { + return $q.when(Q.Promise((resolve, reject) => { + var config = { + timeout: 4000 + }, suffix = '', pkeys = [], queryParams = null; + if (typeof params == 'object') { + pkeys = _.keys(params); + queryParams = {}; + } + pkeys.forEach(function (pkey) { + var prevURI = uri; + uri = uri.replace(new RegExp(':' + pkey), params[pkey]); + if (prevURI == uri) { + queryParams[pkey] = params[pkey]; + } + }); + config.params = queryParams; + const url = httpProtocol() + host + uri + suffix; + $http.post(url, data, config) + .success(function (data, status, headers, config) { + resolve(data); + }) + .error(function (data, status, headers, config) { + reject(data); + }); + })); + } } - if (listener && (messageType === undefined || (res.type === messageType))) { - listener(res); + + function bmaGET(uri) { + return getResource('' + uri); } - }; - return { - on: function(type, callback) { - messageType = type; - listener = callback; - }, - whenOpened: () => co(function *() { - if (opened) return true; - else { - yield Q.Promise((resolve) => { - openedCallback = resolve; - }); - } - }), - send: (msg) => sock.send(msg) - }; - } - return { - webmin: { - getExportURL: () => httpProtocol() + server + '/webmin/data/duniter_export', - getImportURL: () => httpProtocol() + server + '/webmin/data/duniter_import', - isNodePubliclyReachable: getResource('/webmin/server/reachable'), - ws: () => ws(wsProtocol() + server + '/webmin/ws'), - summary: getResource('/webmin/summary'), - powSummary: getResource('/webmin/summary/pow'), - logsExport: (nbLines) => getResource('/webmin/logs/export/' + nbLines)(), - server: { - http: { - start: getResource('/webmin/server/http/start'), - stop: getResource('/webmin/server/http/stop'), - openUPnP: getResource('/webmin/server/http/upnp/open'), - regularUPnP: getResource('/webmin/server/http/upnp/regular') - }, - services: { - startAll: getResource('/webmin/server/services/start_all'), - stopAll: getResource('/webmin/server/services/stop_all') - }, - sendConf: postResource('/webmin/server/send_conf'), - netConf: postResource('/webmin/server/net_conf'), - keyConf: postResource('/webmin/server/key_conf'), - cpuConf: postResource('/webmin/server/cpu_conf'), - testSync: postResource('/webmin/server/test_sync'), - startSync: postResource('/webmin/server/start_sync'), - previewNext: getResource('/webmin/server/preview_next'), - autoConfNetwork: getResource('/webmin/server/auto_conf_network'), - resetData: getResource('/webmin/server/reset/data'), - republishNewSelfPeer: getResource('/webmin/server/republish_selfpeer') - }, - key: { - preview: postResource('/webmin/key/preview') - }, - network: { - interfaces: getResource('/webmin/network/interfaces') + function bmaPOST(uri) { + return postResource('' + uri); } - }, - node: { - summary: bmaGET('/node/summary') - }, - wot: { - lookup: bmaGET('/wot/lookup/:search'), - members: bmaGET('/wot/members') - }, - network: { - peering: { - self: bmaGET('/network/peering'), - peers: bmaGET('/network/peering/peers') - }, - peers: bmaGET('/network/peers') - }, - currency: { - parameters: bmaGET('/blockchain/parameters') - }, - blockchain: { - current: bmaGET('/blockchain/current'), - block: bmaGET('/blockchain/block/:block'), - blocks: bmaGET('/blockchain/blocks/:count/:from'), - block_add: bmaPOST('/blockchain/block'), - stats: { - ud: bmaGET('/blockchain/with/ud'), - tx: bmaGET('/blockchain/with/tx') + + function bmaWS(uri) { + return ws(wsProtocol() + host + '' + uri); } - }, - websocket: { - block: function() { - return bmaWS(server, '/ws/block'); - }, - peer: function() { - return bmaWS(server, '/ws/peer'); + + let wsMap = {}; + + function ws(uri) { + var sock = wsMap[uri] || new WebSocket(uri); + wsMap[uri] = sock; + sock.onclose = function (e) { + console.log('close'); + console.log(e); + }; + sock.onerror = function (e) { + console.log('onerror'); + console.log(e); + }; + let opened = false, openedCallback; + sock.onopen = function () { + opened = true; + openedCallback && openedCallback(); + }; + let listener, messageType; + sock.onmessage = function (e) { + let res = JSON.parse(e.data); + if (res.type == 'log') { + for (let i = 0, len = res.value.length; i < len; i++) { + let log = res.value[i]; + // console[log.level](log.msg); + } + } + if (listener && (messageType === undefined || (res.type === messageType))) { + listener(res); + } + }; + return { + on: function (type, callback) { + messageType = type; + listener = callback; + }, + whenOpened: () => co(function *() { + if (opened) return true; + else { + yield Q.Promise((resolve) => { + openedCallback = resolve; + }); + } + }), + send: (msg) => sock.send(msg) + }; } - }, - origin: { - network: { - peering: { - self: getResource('/network/peering', 'http://') - } + + return { + node: { + summary: bmaGET('/node/summary') + }, + wot: { + lookup: bmaGET('/wot/lookup/:search'), + members: bmaGET('/wot/members') + }, + network: { + peering: { + self: bmaGET('/network/peering'), + peers: bmaGET('/network/peering/peers') + }, + peers: bmaGET('/network/peers') + }, + currency: { + parameters: bmaGET('/blockchain/parameters') + }, + blockchain: { + current: bmaGET('/blockchain/current'), + block: bmaGET('/blockchain/block/:block'), + blocks: bmaGET('/blockchain/blocks/:count/:from'), + block_add: bmaPOST('/blockchain/block'), + stats: { + ud: bmaGET('/blockchain/with/ud'), + tx: bmaGET('/blockchain/with/tx') + } + }, + websocket: { + block: function () { + return bmaWS('/ws/block'); + }, + peer: function () { + return bmaWS('/ws/peer'); + } + }, + origin: { + network: { + peering: { + self: getResource('/network/peering', 'http://') + } + } + } } - } } - } - let server = window.location.hostname; - let port = window.location.port; - var service = BMA([server, port].join(':')); - service.instance = BMA; - return service; + + return BMA; }); }; diff --git a/app/js/services/importer.js b/app/js/services/importer.js index e32958008bcc3deaa65899b8a5fd4a40c45473fe..2501b6e5f5cd90ad3d606d0e2eb13a7c0aea9b4d 100644 --- a/app/js/services/importer.js +++ b/app/js/services/importer.js @@ -1,6 +1,6 @@ module.exports = (app) => { - app.factory('Importer', function($http, $state, $timeout, UIUtils, Upload, BMA) { + app.factory('Importer', function($http, $state, $timeout, UIUtils, Upload, Webmin) { return ($scope) => { @@ -10,7 +10,7 @@ module.exports = (app) => { if (file) { UIUtils.toast('settings.data.backup.importing'); file.upload = Upload.upload({ - url: BMA.webmin.getImportURL(), + url: Webmin.getImportURL(), data: { importData: file } }); diff --git a/app/js/services/pubkeyGenerator.js b/app/js/services/pubkeyGenerator.js index 05b21f99a86c0d2b2dc47b412a3ef7ee4068df8f..d5bde52c8af9da53b8c7757d3f9535bdf5ba4044 100644 --- a/app/js/services/pubkeyGenerator.js +++ b/app/js/services/pubkeyGenerator.js @@ -1,6 +1,6 @@ module.exports = (app) => { - app.factory('PubkeyGenerator', function($timeout, BMA) { + app.factory('PubkeyGenerator', function($timeout, Webmin) { var co = require('co'); @@ -28,7 +28,7 @@ module.exports = (app) => { } $scope.previewPubkey = () => co(function *() { - let data = yield BMA.webmin.key.preview({ + let data = yield Webmin.key.preview({ conf: $scope.$parent.conf }); $scope.pubkey_preview = data.pubkey; diff --git a/app/js/services/webmin.js b/app/js/services/webmin.js new file mode 100644 index 0000000000000000000000000000000000000000..7c5417131ba0794a9ab1709fca2eb45593dbdcfc --- /dev/null +++ b/app/js/services/webmin.js @@ -0,0 +1,176 @@ +const co = require('co'); +const _ = require('underscore'); +const conf = require('../lib/conf/conf'); + +module.exports = (angular) => { + + angular.module('duniter.services.webmin', ['ngResource']) + + .factory('Webmin', function($http, $q) { + + function httpProtocol() { + return window.location.protocol + '//'; + } + + function wsProtocol() { + return window.location.protocol === 'https:' ? 'wss://' : 'ws://'; + } + + function Webmin(server) { + + function getResource(uri, protocol) { + return function(params) { + return $q.when(httpGet(uri, params, protocol)); + } + } + + function httpGet(uri, params, protocol) { + return Q.Promise((resolve, reject) => { + var config = { + timeout: conf.api_timeout + }, suffix = '', pkeys = [], queryParams = null; + if (typeof params == 'object') { + pkeys = _.keys(params); + queryParams = {}; + } + pkeys.forEach(function(pkey){ + var prevURI = uri; + uri = uri.replace(new RegExp(':' + pkey), params[pkey]); + if (prevURI == uri) { + queryParams[pkey] = params[pkey]; + } + }); + config.params = queryParams; + $http.get((protocol || httpProtocol()) + server + uri + suffix, config) + .success(function(data, status, headers, config) { + resolve(data); + }) + .error(function(data, status, headers, config) { + console.log(data); + reject(data); + }); + }); + } + + function postResource(uri) { + return function(data, params) { + return $q.when(Q.Promise((resolve, reject) => { + var config = { + timeout: 4000 + }, suffix = '', pkeys = [], queryParams = null; + if (typeof params == 'object') { + pkeys = _.keys(params); + queryParams = {}; + } + pkeys.forEach(function(pkey){ + var prevURI = uri; + uri = uri.replace(new RegExp(':' + pkey), params[pkey]); + if (prevURI == uri) { + queryParams[pkey] = params[pkey]; + } + }); + config.params = queryParams; + $http.post(httpProtocol() + server + uri + suffix, data, config) + .success(function(data, status, headers, config) { + resolve(data); + }) + .error(function(data, status, headers, config) { + reject(data); + }); + })); + } + } + + let wsMap = {}; + + function ws(uri) { + var sock = wsMap[uri] || new WebSocket(uri); + wsMap[uri] = sock; + sock.onclose = function(e) { + console.log('close'); + console.log(e); + }; + sock.onerror = function(e) { + console.log('onerror'); + console.log(e); + }; + let opened = false, openedCallback; + sock.onopen = function() { + opened = true; + openedCallback && openedCallback(); + }; + let listener, messageType; + sock.onmessage = function(e) { + let res = JSON.parse(e.data); + if (res.type == 'log') { + for (let i = 0, len = res.value.length; i < len; i++) { + let log = res.value[i]; + // console[log.level](log.msg); + } + } + if (listener && (messageType === undefined || (res.type === messageType))) { + listener(res); + } + }; + return { + on: function(type, callback) { + messageType = type; + listener = callback; + }, + whenOpened: () => co(function *() { + if (opened) return true; + else { + yield Q.Promise((resolve) => { + openedCallback = resolve; + }); + } + }), + send: (msg) => sock.send(msg) + }; + } + + return { + getExportURL: () => httpProtocol() + "localhost:10500" + '/webmin/data/duniter_export', + getImportURL: () => httpProtocol() + "localhost:10500" + '/webmin/data/duniter_import', + isNodePubliclyReachable: getResource('/webmin/server/reachable'), + ws: () => ws(wsProtocol() + "localhost:10500" + '/webmin/ws'), + summary: getResource('/webmin/summary'), + powSummary: getResource('/webmin/summary/pow'), + logsExport: (nbLines) => getResource('/webmin/logs/export/' + nbLines)(), + server: { + http: { + start: getResource('/webmin/server/http/start'), + stop: getResource('/webmin/server/http/stop'), + openUPnP: getResource('/webmin/server/http/upnp/open'), + regularUPnP: getResource('/webmin/server/http/upnp/regular') + }, + services: { + startAll: getResource('/webmin/server/services/start_all'), + stopAll: getResource('/webmin/server/services/stop_all') + }, + sendConf: postResource('/webmin/server/send_conf'), + netConf: postResource('/webmin/server/net_conf'), + keyConf: postResource('/webmin/server/key_conf'), + cpuConf: postResource('/webmin/server/cpu_conf'), + testSync: postResource('/webmin/server/test_sync'), + startSync: postResource('/webmin/server/start_sync'), + previewNext: getResource('/webmin/server/preview_next'), + autoConfNetwork: getResource('/webmin/server/auto_conf_network'), + resetData: getResource('/webmin/server/reset/data'), + republishNewSelfPeer: getResource('/webmin/server/republish_selfpeer') + }, + key: { + preview: postResource('/webmin/key/preview') + }, + network: { + interfaces: getResource('/webmin/network/interfaces') + } + } + } + let server = window.location.hostname; + let port = window.location.port; + let service = Webmin([server, port].join(':')); + service.instance = Webmin; + return service; + }); +}; diff --git a/app/views/init/create/create_network.jade b/app/views/init/create/create_network.jade index 592396f738c9dbae6c4ad14f9f15d58571b74944..78a71ede95837d00177c0742c16e9181058dd9be 100644 --- a/app/views/init/create/create_network.jade +++ b/app/views/init/create/create_network.jade @@ -2,34 +2,73 @@ .row form.s12.center .card - .card-content + .card-action i.fa.fa-globe.fa-5x h1.card-title(translate="configuration.create_network.title") - p(translate="configuration.create_network.message") - .row: buttn.btn-large.waves-effect.waves-light(ng-click="autoconfig()") - i.left.fa.fa-magic - span(translate="configuration.create_network.button.autoconf") + .row: buttn.btn-large.waves-effect.waves-light(ng-click="autoconfig()") + i.left.fa.fa-magic + span(translate="configuration.create_network.button.autoconf") - .card-action + .row + .col.s12.m6.common-network + + h1.card-title(translate="configuration.create_network.ipv6.title") + p(translate="configuration.create_network.ipv6.message") + + select.browser-default(ng-model="$parent.conf.local_ipv6") + option(value="" selected translate="configuration.create_network.none") + option(ng-repeat="inet in local_neti | filter : 'IPv6'" value="{{ inet.addr }}" ng-selected="{{inet.addr == $parent.conf.local_ipv6}}") {{ inet.name }} + label {{ 'configuration.create_network.local_ipv6' | translate }} + + .col.s12.m6.common-network + + h1.card-title(translate="configuration.create_network.ipv4.title") + p(translate="configuration.create_network.ipv4.message") + + .col.s12.m6 + select.browser-default(ng-model="$parent.conf.local_ipv4") + option(value="" translate="configuration.create_network.none") + option(ng-repeat="inet in local_neti | filter : 'IPv4'" value="{{ inet.addr }}" ng-selected="{{inet.addr == $parent.conf.local_ipv4}}") {{ inet.name }} + label {{ 'configuration.create_network.local_ipv4' | translate }} - h1.card-title(translate="configuration.create_network.local.title") - p(translate="configuration.create_network.local.message") + .col.s12.m6 + select.browser-default(ng-model="$parent.conf.remote_ipv4") + option(value="" selected translate="configuration.create_network.none") + option(ng-repeat="inet in remote_neti | filter : 'IPv4'" value="{{ inet.addr }}" ng-selected="{{inet.addr == $parent.conf.remote_ipv4}}") {{ inet.name }} + label {{ 'configuration.create_network.remote_ipv4' | translate }} - include ../../includes/network_local + .row - h1.card-title(translate="configuration.create_network.remote.title") - p(translate="configuration.create_network.remote.message") + .col.s12.m4.upnp + input#upnp.filled-in(type="checkbox" ng-model="$parent.conf.upnp") + label(for="upnp") {{ 'configuration.create_network.upnp' | translate }} - include ../../includes/network_remote + .row + + .col.s12.m6.common-network + h1.card-title(translate="configuration.create_network.port.title") + p(translate="configuration.create_network.port.message") + .input-field.col.s6 + i.prefix.fa.fa-plug + input#rport(type="number" ng-model="$parent.conf.rport") + label(for="rport") {{ 'configuration.create_network.port' | translate }} + + .col.s12.m6.common-network + h1.card-title(translate="configuration.create_network.dns.title") + p(translate="configuration.create_network.dns.message") + .input-field + i.prefix.material-icons language + input#dns(type="text" ng-model="$parent.conf.dns") + label(for="dns") {{ 'configuration.create_network.dns' | translate }} .row .col.s12 + button.btn-large.waves-effect.waves-light.button-next(ui-sref="configure.create.parameters") + i.left.fa.fa-check + span(translate="configuration.create_network.button.validate") + button.orange.btn-large.waves-effect.waves-light.button-cancel(ui-sref="index") i.left.fa.fa-sign-out span(translate="configuration.create_currency.cancel") - - button.btn-large.waves-effect.waves-light.button-next(ui-sref="configure.create.parameters") - i.left.fa.fa-check - span(translate="configuration.create_network.button.validate") \ No newline at end of file diff --git a/server/controller/webmin.js b/server/controller/webmin.js new file mode 100644 index 0000000000000000000000000000000000000000..ccd1d8821e6db3d92b35da090a187d22a0761bd9 --- /dev/null +++ b/server/controller/webmin.js @@ -0,0 +1,526 @@ +"use strict"; + +const path = require('path'); +const util = require('util'); +const es = require('event-stream'); +const rp = require('request-promise'); +const stream = require('stream'); +const _ = require('underscore'); +const Q = require('q'); +const co = require('co'); +const keyring = require('duniter/app/lib/crypto/keyring'); +const Identity = require('duniter/app/lib/entity/identity'); +const rawer = require('duniter/app/lib/ucp/rawer'); +const logger = require('duniter/app/lib/logger')('webmin'); +const http2raw = require('duniter/app/lib/helpers/http2raw'); +const dos2unix = require('duniter/app/lib/system/dos2unix'); +const duniter = require('duniter'); +const contacter = require('duniter/app/lib/contacter'); +const bma = require('duniter/app/lib/streams/bma'); +const network = require('duniter/app/lib/system/network'); +const constants = require('duniter/app/lib/constants'); +const ucp = require('duniter/app/lib/ucp/buid'); + +module.exports = (duniterServer) => { + return new WebAdmin(duniterServer); +}; + +function WebAdmin (duniterServer) { + + // Node instance: this is the object to be managed by the web admin + const server = duniterServer; + let bmapi; + const that = this; + + server.pipe(es.mapSync(function(data) { + if (data.pulling !== undefined || data.pow !== undefined) { + that.push(data); + } + })); + + stream.Duplex.call(this, { objectMode: true }); + + // Unused, but made mandatory by Duplex interface + this._read = () => null; + this._write = () => null; + + let startServicesP, stopServicesP; + + let pluggedConfP = plugForConf(); + + let pluggedDALP = replugDAL(); + + + this.pushEntity = (req, rawer, type) => co(function *() { + let rawDocument = rawer(req); + rawDocument = dos2unix(rawDocument); + const written = yield server.writeRaw(rawDocument, type); + try { + return written.json(); + } catch (e) { + logger.error('Written:', written); + logger.error(e); + throw e; + } + }); + + function replugDAL() { + return co(function *() { + yield pluggedConfP; + + // Routing documents + server.routing(); + + return plugForDAL(); + }); + } + + this.summary = () => co(function *() { + yield pluggedDALP; + const host = server.conf ? [server.conf.ipv4, server.conf.port].join(':') : ''; + const current = yield server.dal.getCurrentBlockOrNull(); + const rootBlock = yield server.dal.getBlock(0); + const lastUDBlock = yield server.dal.blockDAL.lastBlockWithDividend(); + const parameters = yield server.dal.getParameters(); + return { + "version": server.version, + "host": host, + "current": current, + "rootBlock": rootBlock, + "pubkey": server.keyPair.publicKey, + "seckey": server.keyPair.secretKey, + "conf": { + "cpu": server.conf.cpu + }, + "parameters": parameters, + "lastUDBlock": lastUDBlock + }; + }); + + this.powSummary = () => co(function *() { + yield pluggedDALP; + return { + "total": yield server.getCountOfSelfMadePoW(), + "mirror": !(yield server.isServerMember()), + "waiting": server.isPoWWaiting() + }; + }); + + this.previewPubkey = (req) => co(function *() { + const conf = http2raw.conf(req); + const pair = yield keyring.scryptKeyPair(conf.idty_entropy, conf.idty_password); + return { + "pubkey": pair.publicKey + }; + }); + + this.startHTTP = () => co(function *() { + return { success: true }; + }); + + this.openUPnP = () => co(function *() { + yield pluggedDALP; + return server.upnp(); + }); + + this.regularUPnP = () => co(function *() { + yield pluggedDALP; + if (server.upnpAPI) { + server.upnpAPI.stopRegular(); + } + if (server.conf.upnp) { + try { + yield server.upnp(); + server.upnpAPI.startRegular(); + } catch (e) { + logger.error(e); + } + } + return {}; + }); + + this.stopHTTP = () => co(function *() { + }); + + this.previewNext = () => co(function *() { + yield pluggedDALP; + const block = yield server.doMakeNextBlock(); + block.raw = rawer.getBlock(block); + return block; + }); + + this.sendConf = (req) => co(function *() { + yield pluggedConfP; + const conf = http2raw.conf(req); + const pair = yield keyring.scryptKeyPair(conf.idty_entropy, conf.idty_password); + yield server.dal.saveConf({ + routing: true, + createNext: true, + cpu: constants.DEFAULT_CPU, + ipv4: conf.local_ipv4, + ipv6: conf.local_ipv6, + port: conf.lport, + remoteipv4: conf.remote_ipv4, + remoteipv6: conf.remote_ipv6, + remoteport: conf.rport, + upnp: conf.upnp, + salt: conf.idty_entropy, + passwd: conf.idty_password, + pair: pair.json(), + avgGenTime: conf.avgGenTime, + blocksRot: conf.blocksRot, + c: conf.c, + currency: conf.currency, + dt: conf.dt, + dtDiffEval: conf.dtDiffEval, + medianTimeBlocks: conf.medianTimeBlocks, + msValidity: conf.msValidity, + percentRot: conf.percentRot, + sigDelay: conf.sigDelay, + sigPeriod: conf.sigPeriod, + sigQty: conf.sigQty, + sigStock: conf.sigStock, + sigValidity: conf.sigValidity, + sigWindow: conf.sigWindow, + stepMax: conf.stepMax, + ud0: conf.ud0, + xpercent: conf.xpercent, + idtyWindow: conf.idtyWindow, + msWindow: conf.msWindow + }); + pluggedConfP = co(function *() { + yield bmapi.closeConnections(); + yield server.loadConf(); + bmapi = yield bma(server, null, true); + }); + yield pluggedConfP; + const buid = '0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855'; + const entity = Identity.statics.fromJSON({ + buid: buid, + uid: conf.idty_uid, + issuer: pair.publicKey, + currency: conf.currency + }); + let found = yield server.dal.getIdentityByHashOrNull(entity.getTargetHash()); + if (!found) { + let createIdentity = rawer.getOfficialIdentity(entity); + createIdentity += pair.signSync(createIdentity) + '\n'; + found = yield that.pushEntity({ body: { identity: createIdentity }}, http2raw.identity, constants.ENTITY_IDENTITY); + } + yield server.dal.fillInMembershipsOfIdentity(Q(found)); + if (_.filter(found.memberships, { membership: 'IN'}).length == 0) { + const block = ucp.format.buid(null); + let join = rawer.getMembershipWithoutSignature({ + "version": constants.DOCUMENTS_VERSION, + "currency": conf.currency, + "issuer": pair.publicKey, + "block": block, + "membership": "IN", + "userid": conf.idty_uid, + "certts": block + }); + join += pair.signSync(join) + '\n'; + yield that.pushEntity({ body: { membership: join }}, http2raw.membership, constants.ENTITY_MEMBERSHIP); + yield server.recomputeSelfPeer(); + } + // + return found; + }); + + this.publishANewSelfPeer = (req) => co(function *() { + yield pluggedConfP; + yield server.recomputeSelfPeer(); + return {}; + }); + + this.applyNetworkConf = (req) => co(function *() { + yield pluggedConfP; + const conf = http2raw.conf(req); + yield server.dal.saveConf(_.extend(server.conf, { + ipv4: conf.local_ipv4, + ipv6: conf.local_ipv6, + port: conf.lport, + remoteipv4: conf.remote_ipv4, + remoteipv6: conf.remote_ipv6, + remoteport: conf.rport, + remotehost: conf.dns, + upnp: conf.upnp + })); + pluggedConfP = co(function *() { + yield bmapi.closeConnections(); + yield server.loadConf(); + bmapi = yield bma(server, null, true); + // yield bmapi.openConnections(); + yield server.recomputeSelfPeer(); + }); + yield pluggedConfP; + return {}; + }); + + this.applyNewKeyConf = (req) => co(function *() { + yield pluggedConfP; + const conf = http2raw.conf(req); + const keyPair = yield keyring.scryptKeyPair(conf.idty_entropy, conf.idty_password); + const publicKey = keyPair.publicKey; + const secretKey = keyPair.secretKey; + yield server.dal.saveConf(_.extend(server.conf, { + salt: conf.idty_entropy, + passwd: conf.idty_password, + pair: { + pub: publicKey, + sec: secretKey + } + })); + pluggedConfP = yield server.loadConf(); + yield pluggedConfP; + return {}; + }); + + this.applyCPUConf = (req) => co(function *() { + yield pluggedConfP; + server.conf.cpu = http2raw.cpu(req); + yield server.dal.saveConf(server.conf); + yield server.applyCPU(server.conf.cpu); + pluggedConfP = yield server.loadConf(); + yield pluggedConfP; + return {}; + }); + + this.listInterfaces = () => co(function *() { + const upnp = { + name: 'upnp', + addresses: [] + }; + const manual = { + name: 'conf', + addresses: [] + }; + const lan = { + name: 'lan', + addresses: [] + }; + yield pluggedConfP; + const conf = server.conf; + if (conf.remoteipv4) { + manual.addresses.push({ family: 'IPv4', address: conf.remoteipv4 }); + } + if (conf && conf.remoteipv6) { + manual.addresses.push({ family: 'IPv6', address: conf.remoteipv6 }); + } + let upnpConf; + try { + upnpConf = yield network.upnpConf(); + if (upnpConf.remoteipv4) { + upnp.addresses.push({ + family: 'IPv4', + address: upnpConf.remoteipv4 + }); + } + if (upnpConf.remoteipv6) { + upnp.addresses.push({ + family: 'IPv6', + address: upnpConf.remoteipv6 + }); + } + } catch (e) { + logger.error(e.stack || e); + } + const lanIPv4 = network.getLANIPv4(); + lanIPv4.forEach(function(addr) { + lan.addresses.push({ + family: 'IPv4', + address: addr.value + }); + }); + const lanIPv6 = network.getLANIPv6(); + lanIPv6.forEach(function(addr) { + lan.addresses.push({ + family: 'IPv6', + address: addr.value + }); + }); + const randomPort = network.getRandomPort(conf); + return { + local: network.listInterfaces(), + remote: [upnp, manual, lan], + auto: { + local: { + ipv4: network.getBestLocalIPv4(), + ipv6: network.getBestLocalIPv6(), + port: randomPort + }, + remote: { + ipv4: upnpConf && upnpConf.remoteipv4, + ipv6: upnpConf && upnpConf.remoteipv6, + dns: '', + port: randomPort, + upnp: upnpConf ? true : false + } + }, + conf: { + local: { + ipv4: conf && conf.ipv4, + ipv6: conf && conf.ipv6, + port: conf && conf.port + }, + remote: { + ipv4: conf && conf.remoteipv4, + ipv6: conf && conf.remoteipv6, + dns: conf && conf.remotehost, + port: conf && conf.remoteport, + upnp: conf && conf.upnp + } + } + }; + }); + + this.startAllServices = () => co(function *() { + // Allow services to be stopped + stopServicesP = null; + if (!server.conf.salt && !server.conf.passwd) { + const conf = { + idty_entropy: ~~(Math.random() * 2147483647) + "", + idty_password: ~~(Math.random() * 2147483647) + "" + }; + yield that.applyNewKeyConf({ body: { conf :conf } }); + } + yield startServicesP || (startServicesP = duniter.statics.startServices(server)); + that.push({ started: true }); + return {}; + }); + + this.stopAllServices = () => co(function *() { + // Allow services to be started + startServicesP = null; + yield stopServicesP || (stopServicesP = duniter.statics.stopServices(server)); + that.push({ stopped: true }); + return {}; + }); + + this.autoConfNetwork = () => co(function *() { + // Reconfigure the network if it has not been initialized yet + if (!server.conf.remoteipv4 && !server.conf.remoteipv6 && !server.conf.remotehost) { + const bestLocal4 = network.getBestLocalIPv4(); + const bestLocal6 = network.getBestLocalIPv6(); + let upnpConf = { + remoteipv4: bestLocal4, + remoteipv6: bestLocal6, + upnp: false + }; + try { + upnpConf = yield network.upnpConf(); + upnpConf.upnp = true; + } catch (e) { + logger.error(e.stack || e); + } + let randomPort = network.getRandomPort(server.conf); + _.extend(server.conf, { + ipv4: bestLocal4, + ipv6: bestLocal6, + port: randomPort, + remoteipv4: upnpConf.remoteipv4, + remoteipv6: upnpConf.remoteipv6, + remoteport: randomPort, + upnp: upnpConf.upnp + }); + yield server.dal.saveConf(server.conf); + pluggedConfP = co(function *() { + yield bmapi.closeConnections(); + yield server.loadConf(); + bmapi = yield bma(server, null, true); + }); + } + return {}; + }); + + this.startSync = (req) => co(function *() { + const sync = server.synchronize(req.body.host, parseInt(req.body.port), parseInt(req.body.to), parseInt(req.body.chunkLen)); + sync.flow.pipe(es.mapSync(function(data) { + // Broadcast block + that.push(data); + })); + yield sync.syncPromise; + return {}; + }); + + this.resetData = () => co(function *() { + yield pluggedDALP; + // We have to wait for a non-breaking window to process reset + yield server.BlockchainService.pushFIFO(() => co(function *() { + yield that.stopHTTP(); + yield that.stopAllServices(); + yield server.unplugFileSystem(); + yield server.cleanDBData(); + yield pluggedDALP; + pluggedConfP = plugForConf(); + pluggedDALP = replugDAL(); + })); + return {}; + }); + + this.exportData = () => co(function *() { + yield pluggedDALP; + return server.exportAllDataAsZIP(); + }); + + this.importData = (req) => co(function *() { + yield that.stopHTTP(); + yield that.stopAllServices(); + yield server.unplugFileSystem(); + yield pluggedDALP; + if (!req.files.importData) { + throw "Wrong upload file name"; + } + const importZipPath = path.join(server.home, 'import.zip'); + yield new Promise((resolve, reject) => { + req.files.importData.mv(importZipPath, (err) => { + err ? reject(err) : resolve(); + }); + }); + yield server.importAllDataFromZIP(importZipPath); + pluggedConfP = plugForConf(); + pluggedDALP = replugDAL(); + return {}; + }); + + this.isNodePubliclyReachable = (req) => co(function *() { + const peer = yield server.PeeringService.peer(); + const reachable = yield contacter.statics.isReachableFromTheInternet(peer, { timeout: 5000 }); + return { success: reachable }; + }); + + this.testPeer = (req) => co(function *() { + return server.testForSync(req.body.host, parseInt(req.body.port)); + }); + + this.logsExport = (req) => co(function *() { + yield pluggedDALP; + const logs = yield server.getLastLogLines(req.params.quantity || 1500); + const body = yield rp.post({ + url: 'http://hastebin.com/documents', + body: logs + }); + const res = JSON.parse(body); + return { + link: 'http://hastebin.com/' + res.key + }; + }); + + function plugForConf() { + return co(function *() { + yield server.plugFileSystem(); + yield server.loadConf(); + bmapi = yield bma(server, null, true); + }); + } + + function plugForDAL() { + return co(function *() { + yield pluggedConfP; + return server.initDAL(); + }); + } + +} + +util.inherits(WebAdmin, stream.Duplex); diff --git a/server/lib/network.js b/server/lib/network.js new file mode 100644 index 0000000000000000000000000000000000000000..a38bbceec255337562bfe2a6227bc24520701278 --- /dev/null +++ b/server/lib/network.js @@ -0,0 +1,24 @@ +const co = require('co'); + + +const handleRequest = (method, uri, promiseFunc) => { + method(uri, function(req, res) { + res.set('Access-Control-Allow-Origin', '*'); + res.type('application/json'); + co(function *() { + try { + let result = yield promiseFunc(req); + // HTTP answer + res.status(200).send(JSON.stringify(result, null, " ")); + } catch (e) { + // HTTP error + res.status(400).send(e); + } + }); + }); +}; + + +module.exports = { + handleRequest +}; \ No newline at end of file diff --git a/server/lib/routes.js b/server/lib/routes.js new file mode 100644 index 0000000000000000000000000000000000000000..4a923821d22dc0e6ccbc14f606adcb0689216d32 --- /dev/null +++ b/server/lib/routes.js @@ -0,0 +1,139 @@ +"use strict"; + +const co = require('co'); +const es = require('event-stream'); +const constants = require('duniter/app/lib/constants'); +const logger = require('duniter/app/lib/logger')('webmin'); +const handleRequest = require('../lib/network').handleRequest; + +const WebSocketServer = require('ws').Server; + +module.exports = { + webmin: function(webminCtrl, app) { + handleRequest(app.get.bind(app), '/webmin/summary', webminCtrl.summary); + handleRequest(app.get.bind(app), '/webmin/summary/pow', webminCtrl.powSummary); + handleRequest(app.get.bind(app), '/webmin/logs/export/:quantity', webminCtrl.logsExport); + handleRequest(app.post.bind(app), '/webmin/key/preview', webminCtrl.previewPubkey); + handleRequest(app.get.bind(app), '/webmin/server/reachable', webminCtrl.isNodePubliclyReachable); + handleRequest(app.get.bind(app), '/webmin/server/http/start', webminCtrl.startHTTP); + handleRequest(app.get.bind(app), '/webmin/server/http/stop', webminCtrl.stopHTTP); + handleRequest(app.get.bind(app), '/webmin/server/http/upnp/open', webminCtrl.openUPnP); + handleRequest(app.get.bind(app), '/webmin/server/http/upnp/regular', webminCtrl.regularUPnP); + handleRequest(app.get.bind(app), '/webmin/server/preview_next', webminCtrl.previewNext); + handleRequest(app.post.bind(app), '/webmin/server/send_conf', webminCtrl.sendConf); + handleRequest(app.post.bind(app), '/webmin/server/net_conf', webminCtrl.applyNetworkConf); + handleRequest(app.post.bind(app), '/webmin/server/key_conf', webminCtrl.applyNewKeyConf); + handleRequest(app.post.bind(app), '/webmin/server/cpu_conf', webminCtrl.applyCPUConf); + handleRequest(app.get.bind(app), '/webmin/server/republish_selfpeer', webminCtrl.publishANewSelfPeer); + handleRequest(app.post.bind(app), '/webmin/server/test_sync', webminCtrl.testPeer); + handleRequest(app.post.bind(app), '/webmin/server/start_sync', webminCtrl.startSync); + handleRequest(app.get.bind(app), '/webmin/server/auto_conf_network', webminCtrl.autoConfNetwork); + handleRequest(app.get.bind(app), '/webmin/server/services/start_all', webminCtrl.startAllServices); + handleRequest(app.get.bind(app), '/webmin/server/services/stop_all', webminCtrl.stopAllServices); + handleRequest(app.get.bind(app), '/webmin/server/reset/data', webminCtrl.resetData); + handleRequest(app.get.bind(app), '/webmin/network/interfaces', webminCtrl.listInterfaces); + //app.httpGETFile('/webmin/data/duniter_export', webminCtrl.exportData); + handleRequest(app.post.bind(app), '/webmin/data/duniter_import', webminCtrl.importData); + }, + webminWS: function(webminCtrl) { + return (httpServer) => { + + // Socket for synchronization events + let wssEvents = new WebSocketServer({ + server: httpServer, + path: '/webmin/ws' + }); + + let lastLogs = []; + wssEvents.on('connection', function connection(ws) { + + ws.on('message', () => { + wssEvents.broadcast(JSON.stringify({ + type: 'log', + value: lastLogs + })); + }); + + wssEvents.broadcast(JSON.stringify({ + type: 'log', + value: lastLogs + })); + + // The callback which write each new log message to websocket + logger.addCallbackLogs((level, msg, timestamp) => { + lastLogs.splice(0, Math.max(0, lastLogs.length - constants.WEBMIN_LOGS_CACHE + 1)); + lastLogs.push({ + timestamp: timestamp, + level: level, + msg: msg + }); + wssEvents.broadcast(JSON.stringify({ + type: 'log', + value: [{ + timestamp: timestamp, + level: level, + msg: msg + }] + })); + }); + }); + + wssEvents.broadcast = (data) => wssEvents.clients.forEach((client) => { + try { + client.send(data); + } catch (e) { + console.log(e); + } + }); + + // Forward blocks & peers + webminCtrl + .pipe(es.mapSync(function(data) { + // Broadcast block + if (data.download !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'download', + value: data.download + })); + } + if (data.applied !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'applied', + value: data.applied + })); + } + if (data.sync !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'sync', + value: data.sync, + msg: (data.msg && (data.msg.message || data.msg)) + })); + } + if (data.started !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'started', + value: data.started + })); + } + if (data.stopped !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'stopped', + value: data.stopped + })); + } + if (data.pulling !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'pulling', + value: data.pulling + })); + } + if (data.pow !== undefined) { + wssEvents.broadcast(JSON.stringify({ + type: 'pow', + value: data.pow + })); + } + })); + }; + } +}; diff --git a/server/server.js b/server/server.js new file mode 100644 index 0000000000000000000000000000000000000000..ee12f77065c2010873f0c37eb6358a613d62bf15 --- /dev/null +++ b/server/server.js @@ -0,0 +1,62 @@ +#!/usr/bin/env node +"use strict"; + +const co = require('co'); +const duniter = require('duniter'); +const bodyParser = require('body-parser'); +const http = require('http'); +const express = require('express'); +const path = require('path'); +const webminController = require('./controller/webmin.js'); + +const HOME_DUNITER_DATA_FOLDER = 'rml8'; + +// Use netobs data folder +if (!process.argv.includes('--mdb')) { + process.argv.push('--mdb'); + process.argv.push(HOME_DUNITER_DATA_FOLDER); +} + +// Default action = start +if (process.argv.length === 4) process.argv.push('start'); + +// Disable Duniter logs +//duniter.statics.logger.mute(); + +duniter.statics.cli((duniterServer) => co(function*() { + + try { + + /**************************************** + * SPECIALISATION + ***************************************/ + + const app = express(); + const HOTE = 'localhost'; + const PORT = 10500; + + /** + * Sur appel de l'URL /abc + */ + app.use(express.static(path.join('..', 'public'))); + + app.use(bodyParser.urlencoded({ + extended: true + })); + app.use(bodyParser.json()); + + const wbmin = webminController(duniterServer); + const httpServer = http.createServer(app); + httpServer.listen(PORT, HOTE); + console.log("Serveur web disponible a l'adresse http://%s:%s", HOTE, PORT); + + require('./lib/routes').webmin(wbmin, app); + require('./lib/routes').webminWS(wbmin)(httpServer); + + /****************************************/ + + } catch (e) { + console.error(e); + process.exit(1); + } +}));