Skip to content

Commit

Permalink
Release 0.10.2 (#666)
Browse files Browse the repository at this point in the history
High CPU usage by browser when session inactivity dialog is showing #624
Block Altcoins #627
Remove slide right animation on route change #642
Update the initiator field for Loop APIs #643
Filter Bug fix #623
Transaction id for pending waiting channel #603
Empty cookie security risk bug fix #610
Material container repositions on Mac Firefox #268 & #619 
Mask config file passwords #636
Downloaded all channels backup fails to restore #614
CLT Routing list disappears on navigation #652
Update Bump Fee modal #628
LND Paying zero amount invoice fails #657
Open channel fails after adding peer with uri #662
Update Fee Policy Bug Fix #659
Changed default password from `changeme` to `password` (#653) (Contributed By: Andrew Leschinsky <andrew@leschinsky.com>)
  • Loading branch information
ShahanaFarooqui authored Apr 24, 2021
1 parent de0e829 commit e4d6256
Show file tree
Hide file tree
Showing 145 changed files with 1,429 additions and 1,068 deletions.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions angular/5.25446aaee9f74a416633.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion angular/5.3cc9f14aefc4012c6f28.js

This file was deleted.

1 change: 0 additions & 1 deletion angular/6.d59c34ac7722c1fea6aa.js

This file was deleted.

1 change: 1 addition & 0 deletions angular/6.eee0e0f329ec52d3bce7.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion angular/7.3f5e1768ebd105934cfb.js

This file was deleted.

1 change: 1 addition & 0 deletions angular/7.e4068d65b9329bce7749.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions angular/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
<link rel="mask-icon" href="assets/images/favicon-light/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="styles.b19cbfbd6204e537cd8b.css"></head>
<link rel="stylesheet" href="styles.34373e0f495fd5a53b6a.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.4a1371653e10aae2a656.js" defer></script><script src="polyfills.ea991b800cfaf577eb9d.js" defer></script><script src="main.bf1f3d303d9abc6dfc78.js" defer></script></body>
<script src="runtime.76e78b7c520ee74ce1af.js" defer></script><script src="polyfills.a290c5ced4c403cfee17.js" defer></script><script src="main.023be7f19d26fb1d812e.js" defer></script></body>
</html>
1 change: 1 addition & 0 deletions angular/main.023be7f19d26fb1d812e.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion angular/main.bf1f3d303d9abc6dfc78.js

This file was deleted.

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion angular/runtime.4a1371653e10aae2a656.js

This file was deleted.

1 change: 1 addition & 0 deletions angular/runtime.76e78b7c520ee74ce1af.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions angular/styles.34373e0f495fd5a53b6a.css

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions angular/styles.b19cbfbd6204e537cd8b.css

This file was deleted.

2 changes: 1 addition & 1 deletion common.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ common.sortAscByKey = (array, key) => {

common.sortDescByKey = (array, key) => {
const temp = array.sort(function (a, b) {
var x = +a[key]; var y = +b[key];
var x = +a[key] ? +a[key] : 0; var y = +b[key] ? +b[key] : 0;
return (x > y) ? -1 : ((x < y) ? 1 : 0);
});
return temp;
Expand Down
2 changes: 1 addition & 1 deletion controllers/eclair/peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ exports.connectPeer = (req, res, next) => {
peer.alias = foundPeer ? foundPeer.alias : peer.nodeId.substring(0, 20);
});
let peers = (body) ? common.sortDescByStrKey(body, 'alias') : [];
peers = common.newestOnTop(peers, 'nodeId', req.query.nodeId ? req.query.nodeId : '');
peers = common.newestOnTop(peers, 'nodeId', req.query.nodeId ? req.query.nodeId : req.query.uri ? req.query.uri.substring(0, req.query.uri.indexOf('@')) : '');
logger.info({fileName: 'Peers', msg: 'Peer with Newest On Top: ' + JSON.stringify(peers)});
logger.info({fileName: 'Peers', msg: 'Peer Added Successfully'});
res.status(201).json(peers);
Expand Down
14 changes: 3 additions & 11 deletions controllers/lnd/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,9 @@ exports.postChannel = (req, res, next) => {
exports.postTransactions = (req, res, next) => {
options = common.getOptions();
options.url = common.getSelLNServerUrl() + '/v1/channels/transactions';
if(req.body.paymentReq) {
options.form = {
payment_request: req.body.paymentReq
};
} else if(req.body.paymentDecoded) {
options.form = {
payment_hash_string: req.body.paymentDecoded.payment_hash,
final_cltv_delta: parseInt(req.body.paymentDecoded.cltv_expiry),
amt: req.body.paymentDecoded.num_satoshis,
dest_string: req.body.paymentDecoded.destination
};
options.form = { payment_request: req.body.paymentReq };
if(req.body.paymentAmount) {
options.form.amt = req.body.paymentAmount;
}
if (req.body.feeLimit) { options.form.fee_limit = req.body.feeLimit; }
if (req.body.outgoingChannel) { options.form.outgoing_chan_id = req.body.outgoingChannel; }
Expand Down
17 changes: 13 additions & 4 deletions controllers/lnd/channelsBackup.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function getFilesList(callback) {
if( files && files.length > 0) {
files.forEach(file => {
if (!file.includes('.restored')) {
if (file === 'channel-all.bak') {
if (file.toLowerCase() === 'channel-all.bak' || file.toLowerCase() === 'backup-channel-all.bak') {
all_restore_exists = true;
} else {
files_list.push({channel_point: file.substring(8, file.length - 4).replace('-', ':')});
Expand Down Expand Up @@ -159,10 +159,19 @@ exports.postRestore = (req, res, next) => {
let restore_backup = '';
if (req.params.channelPoint === 'ALL') {
message = 'All Channels Restore Successful.';
channel_restore_file = common.selectedNode.channel_backup_path + common.path_separator + 'restore' + common.path_separator + 'channel-all.bak';
let exists = fs.existsSync(channel_restore_file);
channel_restore_file = common.selectedNode.channel_backup_path + common.path_separator + 'restore' + common.path_separator;
let exists = fs.existsSync(channel_restore_file + 'channel-all.bak');
let downloaded_exists = fs.existsSync(channel_restore_file + 'backup-channel-all.bak');
if (exists) {
restore_backup = fs.readFileSync(channel_restore_file, 'utf-8');
restore_backup = fs.readFileSync(channel_restore_file + 'channel-all.bak', 'utf-8');
if (restore_backup !== '') {
restore_backup = JSON.parse(restore_backup);
options.form = JSON.stringify({multi_chan_backup: restore_backup.multi_chan_backup.multi_chan_backup});
} else {
res.status(404).json({ message: 'Channels backup to restore does not Exist!' });
}
} else if (downloaded_exists) {
restore_backup = fs.readFileSync(channel_restore_file + 'backup-channel-all.bak', 'utf-8');
if (restore_backup !== '') {
restore_backup = JSON.parse(restore_backup);
options.form = JSON.stringify({multi_chan_backup: restore_backup.multi_chan_backup.multi_chan_backup});
Expand Down
62 changes: 25 additions & 37 deletions controllers/shared/RTLConf.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ exports.getConfig = (req, res, next) => {
logger.info({fileName: 'RTLConf', msg: 'Node Type: ' + req.params.nodeType + ', File Path: ' + confFile});
fs.readFile(confFile, 'utf8', function(err, data) {
if (err) {
logger.error({fileName: 'Conf', lineNum: 171, msg: 'Reading Conf Failed!'});
logger.error({fileName: 'Conf', lineNum: 168, msg: 'Reading Conf Failed!'});
res.status(500).json({
message: "Reading Config File Failed!",
error: err
Expand All @@ -175,45 +175,14 @@ exports.getConfig = (req, res, next) => {
if (fileFormat === 'JSON') {
jsonConfig = JSON.parse(data);
} else {
fileFormat = 'INI';
jsonConfig = ini.parse(data);
switch (common.selectedNode.ln_implementation) {
case 'ECL':
if (jsonConfig['eclair.api.password']) {
if (jsonConfig['eclair.api.password']) {
jsonConfig['eclair.api.password'] = jsonConfig['eclair.api.password'].replace(/./g, '*');
}
if (jsonConfig['eclair.bitcoind.rpcpassword']) {
jsonConfig['eclair.bitcoind.rpcpassword'] = jsonConfig['eclair.bitcoind.rpcpassword'].replace(/./g, '*');
}
} else {
fileFormat = 'HOCON';
jsonConfig = parseHocon(data);
if (jsonConfig.eclair && jsonConfig.eclair.api && jsonConfig.eclair.api.password) {
jsonConfig.eclair.api.password = jsonConfig.eclair.api.password.replace(/./g, '*');
}
if (jsonConfig.eclair && jsonConfig.eclair.bitcoind && jsonConfig.eclair.bitcoind.rpcpassword) {
jsonConfig.eclair.bitcoind.rpcpassword = jsonConfig.eclair.bitcoind.rpcpassword.replace(/./g, '*');
}
}
break;

default:
fileFormat = 'INI';
break;
if (common.selectedNode.ln_implementation === 'ECL' && !jsonConfig['eclair.api.password']) {
fileFormat = 'HOCON';
jsonConfig = parseHocon(data);
}
}
if (jsonConfig.Bitcoind && jsonConfig.Bitcoind['bitcoind.rpcpass']) {
jsonConfig.Bitcoind['bitcoind.rpcpass'] = jsonConfig.Bitcoind['bitcoind.rpcpass'].replace(/./g, '*');
}
if (jsonConfig['bitcoind.rpcpass']) {
jsonConfig['bitcoind.rpcpass'] = jsonConfig['bitcoind.rpcpass'].replace(/./g, '*');
}
if (jsonConfig['rpcpassword']) {
jsonConfig['rpcpassword'] = jsonConfig['rpcpassword'].replace(/./g, '*');
}
if (jsonConfig.multiPass) {
jsonConfig.multiPass = jsonConfig.multiPass.replace(/./g, '*');
}
jsonConfig = maskPasswords(jsonConfig);
const responseJSON = (fileFormat === 'JSON') ? jsonConfig : ini.stringify(jsonConfig);
res.status(200).json({format: fileFormat, data: responseJSON});
}
Expand Down Expand Up @@ -335,3 +304,22 @@ exports.updateServiceSettings = (req, res, next) => {
});
}
};

var maskPasswords = function(obj) {
var keys = Object.keys(obj);
var length = keys.length;
if (length !== 0) {
for (var i = 0; i < length; i++) {
if (typeof obj[keys[i]] === 'object') {
keys[keys[i]] = maskPasswords(obj[keys[i]]);
}
if (typeof keys[i] === 'string'
&& (keys[i].toLowerCase().includes('password') || keys[i].toLowerCase().includes('multipass')
|| keys[i].toLowerCase().includes('rpcpass') || keys[i].toLowerCase().includes('rpcpassword'))
) {
obj[keys[i]] = obj[keys[i]].replace(/./g, '*');
}
}
}
return obj;
};
16 changes: 8 additions & 8 deletions controllers/shared/authenticate.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ exports.authenticateUser = (req, res, next) => {
if(+common.rtl_sso) {
if(req.body.authenticateWith === 'JWT' && jwt.verify(req.body.authenticationValue, common.secret_key)) {
res.status(200).json({ token: token });
} else if (req.body.authenticateWith === 'PASSWORD' && crypto.createHash('sha256').update(common.cookie).digest('hex') === req.body.authenticationValue) {
} else if (req.body.authenticateWith === 'PASSWORD' && common.cookie.trim().length >= 32 && crypto.timingSafeEqual(Buffer.from(crypto.createHash('sha256').update(common.cookie).digest('hex'), 'utf-8'), Buffer.from(req.body.authenticationValue, 'utf-8'))) {
connect.refreshCookie(common.rtl_cookie_path);
const token = jwt.sign(
{ user: 'SSO_USER', configPath: common.nodes[0].config_path, macaroonPath: common.nodes[0].macaroon_path },
common.secret_key
);
res.status(200).json({ token: token });
} else {
logger.error({fileName: 'Authenticate', lineNum: 20, msg: 'SSO Authentication Failed!'});
logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'SSO Authentication Failed! Access key too short or does not match.'});
res.status(406).json({
message: "Login Failure!",
error: "SSO Authentication Failed!"
message: "SSO Authentication Failed!",
error: "SSO failed. Access key too short or does not match."
});
}
} else {
Expand All @@ -72,7 +72,7 @@ exports.authenticateUser = (req, res, next) => {
if (common.rtl_pass === password && failed.count < ALLOWED_LOGIN_ATTEMPTS) {
if (req.body.twoFAToken && req.body.twoFAToken !== '') {
if (!this.verifyToken(req.body.twoFAToken)) {
logger.error({fileName: 'Authenticate', lineNum: 61, msg: 'Invalid Token! Failed IP ' + reqIP});
logger.error({fileName: 'Authenticate', lineNum: 75, msg: 'Invalid Token! Failed IP ' + reqIP});
failed.count = failed.count + 1;
failed.lastTried = currentTime;
return res.status(401).json(handleError(failed, currentTime, 'Invalid 2FA Token!'));
Expand All @@ -86,7 +86,7 @@ exports.authenticateUser = (req, res, next) => {
);
res.status(200).json({ token: token });
} else {
logger.error({fileName: 'Authenticate', lineNum: 85, msg: 'Invalid Password! Failed IP ' + reqIP});
logger.error({fileName: 'Authenticate', lineNum: 89, msg: 'Invalid Password! Failed IP ' + reqIP});
failed.count = common.rtl_pass !== password ? (failed.count + 1) : failed.count;
failed.lastTried = common.rtl_pass !== password ? currentTime : failed.lastTried;
return res.status(401).json(handleError(failed, currentTime, 'Invalid Password!'));
Expand All @@ -96,7 +96,7 @@ exports.authenticateUser = (req, res, next) => {

exports.resetPassword = (req, res, next) => {
if(+common.rtl_sso) {
logger.error({fileName: 'Authenticate', lineNum: 47, msg: 'Password Reset Failed!'});
logger.error({fileName: 'Authenticate', lineNum: 99, msg: 'Password Reset Failed!'});
res.status(401).json({
message: "Password Reset Failed!",
error: "Password cannot be reset for SSO authentication!"
Expand All @@ -112,7 +112,7 @@ exports.resetPassword = (req, res, next) => {
);
res.status(200).json({ token: token });
} else {
logger.error({fileName: 'Authenticate', lineNum: 63, msg: 'Password Reset Failed!'});
logger.error({fileName: 'Authenticate', lineNum: 115, msg: 'Password Reset Failed!'});
res.status(401).json({
message: "Password Reset Failed!",
error: "Old password is not correct!"
Expand Down
4 changes: 2 additions & 2 deletions controllers/shared/loop.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exports.loopOut = (req, res, next) => {
max_prepay_amt: req.body.prepayAmt,
max_swap_fee: req.body.swapFee,
swap_publication_deadline: req.body.swapPublicationDeadline,
label: 'RTL'
initiator: 'RTL'
};
if (req.body.chanId !== '') { options.body['loop_out_channel'] = req.body.chanId; }
if (req.body.destAddress !== '') { options.body['dest'] = req.body.destAddress; }
Expand Down Expand Up @@ -159,7 +159,7 @@ exports.loopIn = (req, res, next) => {
amt: req.body.amount,
max_swap_fee: req.body.swapFee,
max_miner_fee: req.body.minerFee,
label: 'RTL'
initiator: 'RTL'
};
logger.info({fileName: 'Loop', msg: 'Loop In Body: ' + JSON.stringify(options.body)});
request.post(options).then(function (body) {
Expand Down
4 changes: 2 additions & 2 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ $ docker-compose logs bitcoind lnd rtl

Once the containers are running you can access the RTL UI at http://localhost:3000

- Default password is `changeme`.
- Default host, port and password can be changed in `.env`.
- Default password is `password`.
- Default host, port and password can be changed in `.env`.

When you are done you can destroy containers with:
```
Expand Down
Loading

0 comments on commit e4d6256

Please sign in to comment.