From d329a6fec60418304538096603aa25855e9f35ec Mon Sep 17 00:00:00 2001 From: ShahanaFarooqui Date: Sun, 31 Mar 2019 11:39:41 -0400 Subject: [PATCH] incomplete incomplete --- RTL-Multi-Node-Conf.json | 22 +- common.js | 1 + connect.js | 278 ++++++++++++++++++++- controllers/RTLConf.js | 24 +- controllers/authenticate.js | 83 +++--- package.json | 2 +- rtl.js | 4 +- src/app/app.component.ts | 3 +- src/app/pages/signin/signin.component.html | 13 +- src/app/pages/signin/signin.component.ts | 6 +- src/app/shared/models/RTLconfig.ts | 8 + src/app/shared/store/rtl.actions.ts | 17 +- src/app/shared/store/rtl.effects.ts | 23 +- src/app/shared/store/rtl.reducers.ts | 9 +- 14 files changed, 408 insertions(+), 85 deletions(-) diff --git a/RTL-Multi-Node-Conf.json b/RTL-Multi-Node-Conf.json index 21fcf840..05df958f 100644 --- a/RTL-Multi-Node-Conf.json +++ b/RTL-Multi-Node-Conf.json @@ -1,8 +1,7 @@ -[ -{ - "Index": "1", - "LNNode": "LND Testnet # 1", - "LNImplementation": "LND", +[{ + "index": "1", + "lnNode": "LND Testnet # 1", + "lnImplementation": "LND", "Authentication": { "macaroonPath": "/Users/suheb/Downloads", "nodeAuthType": "CUSTOM", @@ -19,7 +18,7 @@ "bitcoindConfigPath": "", "enableLogging": "true", "port": "3000", - "lndServerUrl": "https://localhost:8080/v1" + "lndServerUrl": "https://192.168.1.8:8080/v1" }, "SSO":{ "rtlSSO": 0, @@ -28,9 +27,9 @@ } }, { - "Index": "2", - "LNNode": "LND Mainnet # 1", - "LNImplementation": "LND", + "index": "2", + "lnNode": "LND Mainnet # 1", + "lnImplementation": "LND", "Authentication": { "macaroonPath": "/Users/suheb/Downloads", "nodeAuthType": "CUSTOM", @@ -47,12 +46,11 @@ "bitcoindConfigPath": "", "enableLogging": "true", "port": "3000", - "lndServerUrl": "https://localhost:8080/v1" + "lndServerUrl": "https://192.168.1.20:8080/v1" }, "SSO":{ "rtlSSO": 0, "rtlCookiePath": "", "logoutRedirectLink": "" } -} -] \ No newline at end of file +}] diff --git a/common.js b/common.js index 74bb62b5..038cbcb5 100644 --- a/common.js +++ b/common.js @@ -4,6 +4,7 @@ var common = {}; common.port = 3000; common.rtl_conf_file_path = ''; +common.rtl_multi_node_conf_file_path = ''; common.lnd_server_url = ''; common.lnd_config_path = ''; common.node_auth_type = 'DEFAULT'; diff --git a/connect.js b/connect.js index 5df647a7..1977079e 100644 --- a/connect.js +++ b/connect.js @@ -1,4 +1,5 @@ var fs = require('fs'); +var platform = require('os').platform(); var crypto = require('crypto'); var clArgs = require('optimist').argv; var ini = require('ini'); @@ -12,6 +13,30 @@ const setDefaultConfig = () => { var macaroonPath = ''; var lndConfigPath = ''; var bitcoindConfigPath = ''; + + switch (platform) { + case 'win32': + macaroonPath = 'C:\\Users\\\\AppData\\Local\\Lnd\\data\\chain\\bitcoin\\testnet'; + lndConfigPath = 'C:\\Users\\\\AppData\\Local\\Lnd'; + bitcoindConfigPath = 'C:\\Users\\\\AppData\\Local\\bitcoin\\bitcoin_testnet'; + break; + case 'darwin': + macaroonPath = '/Users//Library/Application Support/Lnd/data/chain/bitcoin/testnet'; + lndConfigPath = '/Users//Library/Application Support/Lnd/'; + bitcoindConfigPath = '/Users//Library/Application Support/Bitcoin/'; + break; + case 'linux': + macaroonPath = '/home/admin/.lnd/data/chain/bitcoin/testnet'; + lndConfigPath = '/home/admin/.lnd/'; + bitcoindConfigPath = '/home/admin/.lnd/'; + break; + default: + macaroonPath = ''; + lndConfigPath = ''; + bitcoindConfigPath = ''; + break; + } + return { Authentication: { macaroonPath: macaroonPath, @@ -132,21 +157,21 @@ const validateConfigFile = (config) => { common.enable_logging = config.Settings.enableLogging; } else if (undefined !== config.Authentication.enableLogging) { common.enable_logging = config.Authentication.enableLogging; - } + } if (common.enable_logging) { common.log_file = common.rtl_conf_file_path + '/logs/RTL.log'; - let exists = fs.existsSync(common.log_file); + let exists = fs.existsSync(common.log_file); if (exists) { fs.writeFile(common.log_file, '', () => { }); - } else if (!exists && config.Authentication.enableLogging) { + } else if ((!exists && config.Authentication.enableLogging) || (!exists && config.Settings.enableLogging)) { try { var dirname = path.dirname(common.log_file); - createDirectory(dirname); + createDirectory(dirname); var createStream = fs.createWriteStream(common.log_file); createStream.end(); } catch (err) { - console.error('Something went wrong: \n' + err); + console.error('Something went wrong while creating log file: \n' + err); } } } @@ -214,7 +239,7 @@ const readCookie = (cookieFile) => { common.cookie = fs.readFileSync(cookieFile, 'utf-8'); } catch(err) { - console.error('Something went wrong: \n' + err); + console.error('Something went wrong while creating cookie file: \n' + err); throw new Error(err); } } @@ -247,7 +272,7 @@ const logEnvVariables = () => { } var errMsg = ''; -connect.configFileExists = () => { +connect.setSingleNodeConfiguration = () => { common.rtl_conf_file_path = (undefined !== process.env.RTL_CONFIG_PATH) ? process.env.RTL_CONFIG_PATH.substring(0, process.env.RTL_CONFIG_PATH.length - 9) : path.normalize(__dirname); RTLConfFile = common.rtl_conf_file_path + '/RTL.conf'; let exists = fs.existsSync(RTLConfFile); @@ -259,16 +284,243 @@ connect.configFileExists = () => { } else { try { fs.writeFileSync(RTLConfFile, ini.stringify(setDefaultConfig())); - var config = ini.parse(fs.readFileSync(RTLConfFile, 'utf-8')); - setMacaroonPath(clArgs, config) - validateConfigFile(config); - logEnvVariables(); + throw new Error('Please change default settings of macaroonPath, lndConfigPath and bitcoindConfigPath in RTL.conf and restart the server'); } catch(err) { - console.error('Something went wrong: \n' + err); + console.error('Something went wrong while creating config file: \n' + err); throw new Error(err); } } } -module.exports = connect.configFileExists(); +connect.setNodeConfiguration = () => { + common.rtl_conf_file_path = (undefined !== process.env.RTL_CONFIG_PATH) ? process.env.RTL_CONFIG_PATH.substring(0, process.env.RTL_CONFIG_PATH.length - 9) : path.normalize(__dirname); + RTLConfFile = common.rtl_conf_file_path + '/RTL.conf'; + + common.rtl_multi_node_conf_file_path = (undefined !== process.env.RTL_MULTI_NODE_CONFIG_PATH) ? process.env.RTL_MULTI_NODE_CONFIG_PATH.substring(0, process.env.RTL_MULTI_NODE_CONFIG_PATH.length - 25) : path.normalize(__dirname); + RTLMultiNodeConfFile = common.rtl_multi_node_conf_file_path + '/RTL-Multi-Node-Conf.json'; + + +} + +// MULTI NODE CODE +// const setMacaroonPath = (clArgs, config) => { +// if(undefined !== clArgs.lndir) { +// common.macaroon_path = clArgs.lndir; +// } else if (undefined !== process.env.MACAROON_PATH) { +// common.macaroon_path = process.env.MACAROON_PATH; +// } else { +// if(undefined !== config.Authentication.macroonPath && config.Authentication.macroonPath !== '') { +// common.macaroon_path = config.Authentication.macroonPath; +// } else if(undefined !== config.Authentication.macaroonPath && config.Authentication.macaroonPath !== '') { +// common.macaroon_path = config.Authentication.macaroonPath; +// } +// } +// } + +// const validateConfigFile = (config) => { +// if(common.macaroon_path === '' || undefined === common.macaroon_path) { +// errMsg = 'Please set macaroon path through environment or RTL.conf!'; +// } + +// if(undefined !== process.env.LND_SERVER_URL) { +// common.lnd_server_url = process.env.LND_SERVER_URL; +// } else { +// if((config.Authentication.lndServerUrl === '' || undefined === config.Authentication.lndServerUrl) && (config.Settings.lndServerUrl === '' || undefined === config.Settings.lndServerUrl)) { +// errMsg = errMsg + '\nPlease set LND Server URL through environment or RTL.conf!'; +// } else { +// if (config.Settings.lndServerUrl !== '' && undefined !== config.Settings.lndServerUrl) { +// common.lnd_server_url = config.Settings.lndServerUrl; +// } else if (config.Authentication.lndServerUrl !== '' && undefined !== config.Authentication.lndServerUrl) { +// common.lnd_server_url = config.Authentication.lndServerUrl; +// } +// } +// } + +// if(undefined !== process.env.NODE_AUTH_TYPE) { +// common.node_auth_type = process.env.NODE_AUTH_TYPE; +// } else { +// if(config.Authentication.nodeAuthType === '' || undefined === config.Authentication.nodeAuthType) { +// errMsg = errMsg + '\nPlease set Node Auth Type through environment/RTL.conf!'; +// } else { +// common.node_auth_type = config.Authentication.nodeAuthType; +// } +// } + +// if(undefined !== process.env.LND_CONFIG_PATH) { +// common.lnd_config_path = process.env.LND_CONFIG_PATH; +// } else { +// if(config.Authentication.lndConfigPath !== '' && undefined !== config.Authentication.lndConfigPath) { +// common.lnd_config_path = config.Authentication.lndConfigPath; +// } else { +// if(upperCase(common.node_auth_type) === 'DEFAULT') { +// errMsg = errMsg + '\nDefault Node Authentication can be set with LND Config Path only. Please set LND Config Path through environment or RTL.conf!'; +// } +// } +// } + +// if(undefined !== process.env.BITCOIND_CONFIG_PATH) { +// common.bitcoind_config_path = process.env.BITCOIND_CONFIG_PATH; +// } else { +// if(config.Settings.bitcoindConfigPath !== '' || undefined !== config.Settings.bitcoindConfigPath) { +// common.bitcoind_config_path = config.Settings.bitcoindConfigPath; +// } else if(config.Authentication.bitcoindConfigPath !== '' || undefined !== config.Authentication.bitcoindConfigPath) { +// common.bitcoind_config_path = config.Authentication.bitcoindConfigPath; +// } +// } + +// if (undefined !== process.env.RTL_PASS) { +// common.rtl_pass = process.env.RTL_PASS; +// } else if (config.Authentication.rtlPass !== '' || undefined !== config.Authentication.rtlPass) { +// common.rtl_pass = config.Authentication.rtlPass; + +// } + +// if (upperCase(common.node_auth_type) === 'CUSTOM' && (common.rtl_pass === '' || undefined === common.rtl_pass)) { +// errMsg = errMsg + '\nCustom Node Authentication can be set with RTL password only. Please set RTL Password through environment/RTL.conf'; +// } + +// if (undefined !== process.env.ENABLE_LOGGING) { +// common.enable_logging = process.env.ENABLE_LOGGING; +// } else if (undefined !== config.Settings.enableLogging) { +// common.enable_logging = config.Settings.enableLogging; +// } else if (undefined !== config.Authentication.enableLogging) { +// common.enable_logging = config.Authentication.enableLogging; +// } +// if (common.enable_logging) { +// common.log_file = common.rtl_conf_file_path + '/logs/RTL.log'; +// let exists = fs.existsSync(common.log_file); +// if (exists) { +// fs.writeFile(common.log_file, '', () => { }); +// } else if ((!exists && config.Authentication.enableLogging) || (!exists && config.Settings.enableLogging)) { +// try { +// var dirname = path.dirname(common.log_file); +// createDirectory(dirname); +// var createStream = fs.createWriteStream(common.log_file); +// createStream.end(); +// } +// catch (err) { +// console.error('Something went wrong while creating log file: \n' + err); +// } +// } +// } + +// if (undefined !== process.env.PORT) { +// common.port = normalizePort(process.env.PORT); +// } else if (undefined !== config.Settings.port) { +// common.port = normalizePort(config.Settings.port); +// } + +// setSSOParams(config); +// if (errMsg !== '') { +// throw new Error(errMsg); +// } +// } + +// const setSSOParams = (config) => { +// if (undefined !== process.env.RTL_SSO) { +// common.rtl_sso = process.env.RTL_SSO; +// } else if (undefined !== config.SSO && undefined !== config.SSO.rtlSSO) { +// common.rtl_sso = config.SSO.rtlSSO; +// } + +// if (+common.rtl_sso) { +// if (undefined !== process.env.LOGOUT_REDIRECT_LINK) { +// common.logout_redirect_link = process.env.LOGOUT_REDIRECT_LINK; +// } else if (undefined !== config.SSO && undefined !== config.SSO.logoutRedirectLink) { +// common.logout_redirect_link = config.SSO.logoutRedirectLink; +// } + + +// if (undefined !== process.env.RTL_COOKIE_PATH) { +// common.rtl_cookie_path = process.env.RTL_COOKIE_PATH; +// } else if (undefined !== config.SSO && undefined !== config.SSO.rtlCookiePath) { +// common.rtl_cookie_path = config.SSO.rtlCookiePath; +// } else { +// common.rtl_cookie_path = common.rtl_conf_file_path + '/cookies/auth.cookie'; +// } +// readCookie(common.rtl_cookie_path); +// } +// }; + +// const createDirectory = (dirname) => { +// try { +// fs.mkdirSync(dirname); +// } catch (err) { +// if (err.code === 'EEXIST') { +// return dirname; +// } +// if (err.code === 'ENOENT') { +// throw new Error(`EACCES: permission denied, mkdir '${dirname}'`); +// } +// } +// } + +// const readCookie = (cookieFile) => { +// let exists = fs.existsSync(cookieFile); +// if (exists) { +// common.cookie = fs.readFileSync(cookieFile, 'utf-8'); +// } else { +// try { +// var dirname = path.dirname(cookieFile); +// createDirectory(dirname); +// fs.writeFileSync(cookieFile, crypto.randomBytes(64).toString('hex')); +// common.cookie = fs.readFileSync(cookieFile, 'utf-8'); +// } +// catch(err) { +// console.error('Something went wrong while creating cookie file: \n' + err); +// throw new Error(err); +// } +// } +// } + +// String.random = function (length) { +// let radom13chars = function () { +// return Math.random().toString(16).substring(2, 15).toUpperCase(); +// } +// let loops = Math.ceil(length / 13); +// return new Array(loops).fill(radom13chars).reduce((string, func) => { +// return string + func(); +// }, '').substring(-length); +// } + +// const logEnvVariables = () => { +// if (!common.enable_logging) { +// return; +// } +// logger.info('\r\nConfig Setup Variable PORT: ' + common.port); +// logger.info('\r\nConfig Setup Variable LND_SERVER_URL: ' + common.lnd_server_url); +// logger.info('\r\nConfig Setup Variable MACAROON_PATH: ' + common.macaroon_path); +// logger.info('\r\nConfig Setup Variable NODE_AUTH_TYPE: ' + common.node_auth_type); +// logger.info('\r\nConfig Setup Variable LND_CONFIG_PATH: ' + common.lnd_config_path); +// logger.info('\r\nConfig Setup Variable RTL_CONFIG_PATH: ' + common.rtl_conf_file_path); +// logger.info('\r\nConfig Setup Variable BITCOIND_CONFIG_PATH: ' + common.bitcoind_config_path); +// logger.info('\r\nConfig Setup Variable RTL_SSO: ' + common.rtl_sso); +// logger.info('\r\nConfig Setup Variable RTL_COOKIE_PATH: ' + common.rtl_cookie_path); +// logger.info('\r\nConfig Setup Variable LOGOUT_REDIRECT_LINK: ' + common.logout_redirect_link); +// } + +// var errMsg = ''; +// connect.configFileExists = () => { +// common.rtl_conf_file_path = (undefined !== process.env.RTL_CONFIG_PATH) ? process.env.RTL_CONFIG_PATH.substring(0, process.env.RTL_CONFIG_PATH.length - 9) : path.normalize(__dirname); +// RTLConfFile = common.rtl_conf_file_path + '/RTL.conf'; +// let exists = fs.existsSync(RTLConfFile); +// if (exists) { +// var config = ini.parse(fs.readFileSync(RTLConfFile, 'utf-8')); +// setMacaroonPath(clArgs, config) +// validateConfigFile(config); +// logEnvVariables(); +// } else { +// try { +// fs.writeFileSync(RTLConfFile, ini.stringify(setDefaultConfig())); +// throw new Error('Please change default settings of macaroonPath, lndConfigPath and bitcoindConfigPath in RTL.conf and restart the server'); +// } +// catch(err) { +// console.error('Something went wrong while creating config file: \n' + err); +// throw new Error(err); +// } +// } +// } + + +module.exports = connect; diff --git a/controllers/RTLConf.js b/controllers/RTLConf.js index 4b00fa49..b15b3c41 100644 --- a/controllers/RTLConf.js +++ b/controllers/RTLConf.js @@ -89,17 +89,23 @@ exports.getMultiNodeConfig = (req, res, next) => { logger.info('\r\nRTLConf.js: 91: ' + JSON.stringify(Date.now()) + ': INFO: Getting Multi Node Config'); fs.readFile(RTLMultiNodeConfFile, 'utf8', function(err, data) { if (err) { - logger.error('\r\nRTLConf.js: 94: ' + JSON.stringify(Date.now()) + ': ERROR: Getting Multi Node Config Failed!'); - res.status(500).json({ - message: "Reading Multi Node Config Failed!", - error: err - }); + if (err.code === 'ENOENT') { + logger.error('\r\nRTLConf.js: 94: ' + JSON.stringify(Date.now()) + ': INFO: Multi Node Config does not exist!'); + res.status(200).json({ nodes: [] }); + } else { + logger.error('\r\nRTLConf.js: 94: ' + JSON.stringify(Date.now()) + ': ERROR: Getting Multi Node Config Failed!'); + res.status(500).json({ + message: "Reading Multi Node Config Failed!", + error: err + }); + } } else { const multiNodeConfig = require('../RTL-Multi-Node-Conf.json'); - var nodeinfo = []; - for(var key in multiNodeConfig) - nodeinfo.push({"Index":multiNodeConfig[key].Index, "LNNode":multiNodeConfig[key].LNNode, "LNImpl":multiNodeConfig[key].LNImplementation}); - res.status(200).json({nodes:nodeinfo}); + var nodeInfos = []; + for(var key in multiNodeConfig) { + nodeInfos.push({"index":multiNodeConfig[key].index, "lnNode":multiNodeConfig[key].lnNode, "lnImpl":multiNodeConfig[key].lnImplementation}); + } + res.status(200).json({ nodes: nodeInfos }); } }); }; \ No newline at end of file diff --git a/controllers/authenticate.js b/controllers/authenticate.js index 62e4aa4b..af7c16fb 100644 --- a/controllers/authenticate.js +++ b/controllers/authenticate.js @@ -45,52 +45,57 @@ exports.authenticateUser = (req, res, next) => { } } else { password = atob(req.body.password); - if(upperCase(common.node_auth_type) === 'CUSTOM') { - if (common.rtl_pass === password) { - var rpcUser = 'Custom_User'; - const token = jwt.sign( - { user: rpcUser, lndConfigPath: common.lnd_config_path, macaroonPath: common.macaroon_path }, - common.secret_key - ); - res.status(200).json({ token: token }); - } else { - res.status(401).json({ - message: "Authentication Failed!", - error: "Password Validation Failed!" - }); - } - } else { - fs.readFile(common.lnd_config_path, 'utf8', function (err, data) { - if (err) { - logger.error('\r\nAuthenticate: 45: ' + JSON.stringify(Date.now()) + ': ERROR: LND Config Reading Failed!'); - res.status(500).json({ - message: "LND Config Reading Failed!", - error: err - }); + selNode = req.body.node; + if(selNode === '') { + if(upperCase(common.node_auth_type) === 'CUSTOM') { + if (common.rtl_pass === password) { + var rpcUser = 'Custom_User'; + const token = jwt.sign( + { user: rpcUser, lndConfigPath: common.lnd_config_path, macaroonPath: common.macaroon_path }, + common.secret_key + ); + res.status(200).json({ token: token }); } else { - const jsonLNDConfig = ini.parse(data); - if (undefined !== jsonLNDConfig.Bitcoind && undefined !== jsonLNDConfig.Bitcoind['bitcoind.rpcpass']) { - if (jsonLNDConfig.Bitcoind['bitcoind.rpcpass'] === password) { - var rpcUser = (undefined !== jsonLNDConfig.Bitcoind['bitcoind.rpcuser']) ? jsonLNDConfig.Bitcoind['bitcoind.rpcuser'] : ''; - const token = jwt.sign( - { user: rpcUser, lndConfigPath: common.lnd_config_path, macaroonPath: common.macaroon_path }, - common.secret_key - ); - res.status(200).json({ token: token }); + res.status(401).json({ + message: "Authentication Failed!", + error: "Password Validation Failed!" + }); + } + } else { + fs.readFile(common.lnd_config_path, 'utf8', function (err, data) { + if (err) { + logger.error('\r\nAuthenticate: 45: ' + JSON.stringify(Date.now()) + ': ERROR: LND Config Reading Failed!'); + res.status(500).json({ + message: "LND Config Reading Failed!", + error: err + }); + } else { + const jsonLNDConfig = ini.parse(data); + if (undefined !== jsonLNDConfig.Bitcoind && undefined !== jsonLNDConfig.Bitcoind['bitcoind.rpcpass']) { + if (jsonLNDConfig.Bitcoind['bitcoind.rpcpass'] === password) { + var rpcUser = (undefined !== jsonLNDConfig.Bitcoind['bitcoind.rpcuser']) ? jsonLNDConfig.Bitcoind['bitcoind.rpcuser'] : ''; + const token = jwt.sign( + { user: rpcUser, lndConfigPath: common.lnd_config_path, macaroonPath: common.macaroon_path }, + common.secret_key + ); + res.status(200).json({ token: token }); + } else { + res.status(401).json({ + message: "Authentication Failed!", + error: "Password Validation Failed!" + }); + } } else { res.status(401).json({ message: "Authentication Failed!", - error: "Password Validation Failed!" + error: "Password Not Found In LND Config!" }); } - } else { - res.status(401).json({ - message: "Authentication Failed!", - error: "Password Not Found In LND Config!" - }); } - } - }); + }); + } + } else { + } } }; diff --git a/package.json b/package.json index 4d5fc74a..b0d44302 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "MIT", "scripts": { "ng": "ng", - "start": "ng serve --base-href /rtl/", + "start": "ng serve --base-href /rtl/ --open", "build": "ng build --prod --base-href /rtl/", "serve": "ng serve", "prebuild": "node ./prebuild", diff --git a/rtl.js b/rtl.js index 964c98f7..be0e503d 100644 --- a/rtl.js +++ b/rtl.js @@ -2,7 +2,7 @@ const app = require("./app"); const common = require("./common"); const debug = require("debug")("node-angular"); const http = require("http"); -var connect = require('./connect'); //Do NOT Remove +var connect = require('./connect').setSingleNodeConfiguration(); //Do NOT Remove const onError = error => { if (error.syscall !== "listen") { @@ -31,7 +31,7 @@ const onListening = () => { const addr = server.address(); const bind = typeof addr === "string" ? "pipe " + addr : "port " + common.port; debug("Listening on " + bind); - console.log('Server is up and running, please open the UI at http://localhost:' + common.port); + console.log('Server is up and running, please open the UI at http://localhost:' + common.port); }; const server = http.createServer(app); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5c65765c..b20b65c7 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -34,6 +34,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy { private userIdle: UserIdleService, private router: Router) {} ngOnInit() { + this.store.dispatch(new RTLActions.FetchMultiNodeSettings()); this.store.dispatch(new RTLActions.FetchSettings()); this.accessKey = this.readAccessKey(); this.store.select('rtlRoot') @@ -67,7 +68,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy { if (actionPayload.type === RTLActions.SET_AUTH_SETTINGS) { if (!sessionStorage.getItem('token')) { if (+actionPayload.payload.rtlSSO) { - this.store.dispatch(new RTLActions.Signin(window.btoa(this.accessKey))); + this.store.dispatch(new RTLActions.Signin({ password: window.btoa(this.accessKey), node: '' })); } else { this.router.navigate([this.authSettings.logoutRedirectLink]); } diff --git a/src/app/pages/signin/signin.component.html b/src/app/pages/signin/signin.component.html index 6a141a34..5ba8800e 100644 --- a/src/app/pages/signin/signin.component.html +++ b/src/app/pages/signin/signin.component.html @@ -8,8 +8,17 @@
- - +
+ + + + {{multiNode.lnNode}} ({{multiNode.lnImpl}}) + + + +
+ + {{hintStr}} diff --git a/src/app/pages/signin/signin.component.ts b/src/app/pages/signin/signin.component.ts index 0a166d32..06192bf3 100644 --- a/src/app/pages/signin/signin.component.ts +++ b/src/app/pages/signin/signin.component.ts @@ -3,6 +3,7 @@ import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { Store } from '@ngrx/store'; +import { MultiNode } from '../../shared/models/RTLconfig'; import { LoggerService } from '../../shared/services/logger.service'; import * as fromRTLReducer from '../../shared/store/rtl.reducers'; import * as RTLActions from '../../shared/store/rtl.actions'; @@ -13,6 +14,8 @@ import * as RTLActions from '../../shared/store/rtl.actions'; styleUrls: ['./signin.component.scss'] }) export class SigninComponent implements OnInit, OnDestroy { + multiNodes: MultiNode[] = []; + selNode = ''; password = ''; nodeAuthType = ''; rtlSSO = 0; @@ -31,6 +34,7 @@ export class SigninComponent implements OnInit, OnDestroy { rtlStore.effectErrors.forEach(effectsErr => { this.logger.error(effectsErr); }); + this.multiNodes = rtlStore.multiNodes; this.nodeAuthType = rtlStore.authSettings.nodeAuthType; this.logger.info(rtlStore); if (this.nodeAuthType.toUpperCase() === 'DEFAULT') { @@ -42,7 +46,7 @@ export class SigninComponent implements OnInit, OnDestroy { } onSignin() { - this.store.dispatch(new RTLActions.Signin(window.btoa(this.password))); + this.store.dispatch(new RTLActions.Signin({ password: window.btoa(this.password), node: this.selNode })); } resetData() { diff --git a/src/app/shared/models/RTLconfig.ts b/src/app/shared/models/RTLconfig.ts index 663c0f17..d914cc96 100644 --- a/src/app/shared/models/RTLconfig.ts +++ b/src/app/shared/models/RTLconfig.ts @@ -9,6 +9,14 @@ export class Settings { ) { } } +export class MultiNode { + constructor( + public index: string, + public lnNode: string, + public lnImplementation: string + ) { } +} + export class Authentication { constructor( public lndServerUrl?: string, diff --git a/src/app/shared/store/rtl.actions.ts b/src/app/shared/store/rtl.actions.ts index 129bfffa..ff2e1708 100644 --- a/src/app/shared/store/rtl.actions.ts +++ b/src/app/shared/store/rtl.actions.ts @@ -1,5 +1,5 @@ import { Action } from '@ngrx/store'; -import { Settings, Authentication } from '../models/RTLconfig'; +import { Settings, Authentication, MultiNode } from '../models/RTLconfig'; import { ErrorPayload } from '../models/errorPayload'; import { GetInfo, Peer, Balance, NetworkInfo, Fees, Channel, Invoice, Payment, GraphNode, AddressType, @@ -19,6 +19,8 @@ export const FETCH_STORE = 'FETCH_STORE'; export const SET_STORE = 'SET_STORE'; export const FETCH_SETTINGS = 'FETCH_SETTINGS'; export const SET_SETTINGS = 'SET_SETTINGS'; +export const FETCH_MULTI_NODE_SETTINGS = 'FETCH_MULTI_NODE_SETTINGS'; +export const SET_MULTI_NODE_SETTINGS = 'SET_MULTI_NODE_SETTINGS'; export const SET_AUTH_SETTINGS = 'SET_AUTH_SETTINGS'; export const SAVE_SETTINGS = 'SAVE_SETTINGS'; export const FETCH_INFO = 'FETCH_INFO'; @@ -121,6 +123,15 @@ export class SetSettings implements Action { constructor(public payload: Settings) {} } +export class FetchMultiNodeSettings implements Action { + readonly type = FETCH_MULTI_NODE_SETTINGS; +} + +export class SetMultiNodeSettings implements Action { + readonly type = SET_MULTI_NODE_SETTINGS; + constructor(public payload: MultiNode[]) {} +} + export class SetAuthSettings implements Action { readonly type = SET_AUTH_SETTINGS; constructor(public payload: Authentication) {} @@ -371,7 +382,7 @@ export class IsAuthorizedRes implements Action { export class Signin implements Action { readonly type = SIGNIN; - constructor(public payload: string) {} // payload = password + constructor(public payload: { password: string, node: string }) {} } export class Signout implements Action { @@ -385,7 +396,7 @@ export class InitAppData implements Action { export type RTLActions = ClearEffectError | EffectError | OpenSpinner | CloseSpinner | - FetchSettings | SetSettings | SaveSettings | SetAuthSettings | + FetchSettings | SetSettings | SaveSettings | SetAuthSettings | FetchMultiNodeSettings | SetMultiNodeSettings | OpenAlert | CloseAlert | OpenConfirmation | CloseConfirmation | FetchInfo | SetInfo | FetchPeers | SetPeers | AddPeer | DetachPeer | SaveNewPeer | RemovePeer | diff --git a/src/app/shared/store/rtl.effects.ts b/src/app/shared/store/rtl.effects.ts index a224c6bd..4bc6f02b 100644 --- a/src/app/shared/store/rtl.effects.ts +++ b/src/app/shared/store/rtl.effects.ts @@ -107,6 +107,27 @@ export class RTLEffects implements OnDestroy { }) )); + @Effect() + multiNodeFetch = this.actions$.pipe( + ofType(RTLActions.FETCH_MULTI_NODE_SETTINGS), + mergeMap((action: RTLActions.FetchMultiNodeSettings) => { + this.store.dispatch(new RTLActions.ClearEffectError('FetchMultiNodeSettings')); + return this.httpClient.get(environment.CONF_API + '/multinode'); + }), + map((multiNodes: any) => { + this.logger.info(multiNodes); + return { + type: RTLActions.SET_MULTI_NODE_SETTINGS, + payload: (undefined !== multiNodes && undefined !== multiNodes.nodes) ? multiNodes.nodes : [] + }; + }, + catchError((err) => { + this.logger.error(err); + this.store.dispatch(new RTLActions.EffectError({ action: 'FetchMultiNodeSettings', code: err.status, message: err.error.error })); + return of(); + }) + )); + @Effect({ dispatch: false }) settingSave = this.actions$.pipe( ofType(RTLActions.SAVE_SETTINGS), @@ -902,7 +923,7 @@ export class RTLEffects implements OnDestroy { withLatestFrom(this.store.select('rtlRoot')), mergeMap(([action, store]: [RTLActions.Signin, fromRTLReducer.State]) => { this.store.dispatch(new RTLActions.ClearEffectError('Signin')); - return this.httpClient.post(environment.AUTHENTICATE_API, { password: action.payload }) + return this.httpClient.post(environment.AUTHENTICATE_API, { password: action.payload.password, node: action.payload.node }) .pipe( map((postRes: any) => { this.logger.info(postRes); diff --git a/src/app/shared/store/rtl.reducers.ts b/src/app/shared/store/rtl.reducers.ts index 8491f4be..78e04669 100644 --- a/src/app/shared/store/rtl.reducers.ts +++ b/src/app/shared/store/rtl.reducers.ts @@ -1,13 +1,14 @@ import * as RTLActions from './rtl.actions'; import { ErrorPayload } from '../models/errorPayload'; -import { Settings, Authentication } from '../models/RTLconfig'; +import { Settings, Authentication, MultiNode } from '../models/RTLconfig'; import { GetInfo, GetInfoChain, Peer, AddressType, Fees, NetworkInfo, Balance, Channel, Payment, Invoice, PendingChannels, ClosedChannel, Transaction, SwitchRes } from '../models/lndModels'; export interface State { effectErrors: ErrorPayload[]; + multiNodes: MultiNode[]; settings: Settings; authSettings: Authentication; information: GetInfo; @@ -33,6 +34,7 @@ export interface State { const initialState: State = { effectErrors: [], + multiNodes: [], settings: {flgSidenavOpened: true, flgSidenavPinned: true, menu: 'Vertical', menuType: 'Regular', theme: 'dark-blue', satsToBTC: false}, authSettings: {nodeAuthType: 'CUSTOM', lndConfigPath: '', bitcoindConfigPath: '', rtlSSO: 0, logoutRedirectLink: '/login' }, information: {}, @@ -83,6 +85,11 @@ export function RTLRootReducer(state = initialState, action: RTLActions.RTLActio ...state, settings: action.payload }; + case RTLActions.SET_MULTI_NODE_SETTINGS: + return { + ...state, + multiNodes: action.payload + }; case RTLActions.SET_AUTH_SETTINGS: return { ...state,