mirror of
https://github.com/Retropex/apolloapi-v2.git
synced 2025-05-29 21:42:30 +02:00
280 lines
8.3 KiB
JavaScript
280 lines
8.3 KiB
JavaScript
const bcrypt = require('bcryptjs');
|
|
const jwt = require('jsonwebtoken');
|
|
const { exec } = require('child_process');
|
|
const generator = require('generate-password');
|
|
const config = require('config');
|
|
const { knex } = require('./db');
|
|
const fsPromises = require('fs').promises;
|
|
const path = require('path');
|
|
const os = require('os');
|
|
|
|
const configBitcoinFilePath = path.resolve(
|
|
__dirname,
|
|
'../backend/node/bitcoin.conf'
|
|
);
|
|
|
|
const configCkpoolFilePath = path.resolve(
|
|
__dirname,
|
|
'../backend/ckpool/ckpool.conf'
|
|
);
|
|
|
|
const configCkpoolServiceFilePath = path.resolve(
|
|
__dirname,
|
|
'../backend/systemd/ckpool.service'
|
|
);
|
|
|
|
module.exports.auth = {
|
|
hashPassword(password) {
|
|
return bcrypt.hash(password, 12);
|
|
},
|
|
|
|
comparePassword(password, hash) {
|
|
if (!password || !hash) {
|
|
return false;
|
|
}
|
|
return bcrypt.compare(password, hash);
|
|
},
|
|
|
|
changeSystemPassword(password) {
|
|
exec(`echo 'futurebit:${password}' | sudo chpasswd`);
|
|
},
|
|
|
|
async changeNodeRpcPassword(settings) {
|
|
try {
|
|
console.log('Generating and saving bitcoin password');
|
|
|
|
const password = generator.generate({
|
|
length: 12,
|
|
numbers: true,
|
|
});
|
|
|
|
await knex('settings').update({
|
|
node_rpc_password: password,
|
|
});
|
|
|
|
await fsPromises.access(configBitcoinFilePath);
|
|
await fsPromises.access(configCkpoolFilePath);
|
|
|
|
exec(
|
|
`sudo sed -i 's/rpcpassword.*/rpcpassword=${password}/g' ${configBitcoinFilePath}`
|
|
);
|
|
|
|
exec(
|
|
`sudo sed -i 's#"pass":.*#"pass": "${password}",#g' ${configCkpoolFilePath}`
|
|
);
|
|
|
|
exec('sudo systemctl restart node');
|
|
|
|
if (settings?.nodeEnableSoloMining) exec('sudo systemctl restart ckpool');
|
|
} catch (err) {
|
|
console.log('ERR changeNodeRpcPassword', err);
|
|
}
|
|
},
|
|
|
|
generateAccessToken() {
|
|
const accessToken = jwt.sign({}, config.get('server.secret'), {
|
|
subject: 'apollouser',
|
|
audience: 'auth',
|
|
});
|
|
return {
|
|
accessToken,
|
|
};
|
|
},
|
|
|
|
networkAddressWithCIDR(ipAddress, netmask) {
|
|
// Converti l'indirizzo IP e la netmask in forma binaria
|
|
const ipBinary = ipAddress
|
|
.split('.')
|
|
.map((part) => parseInt(part, 10).toString(2).padStart(8, '0'))
|
|
.join('');
|
|
const netmaskBinary = netmask
|
|
.split('.')
|
|
.map((part) => parseInt(part, 10).toString(2).padStart(8, '0'))
|
|
.join('');
|
|
|
|
// Applica l'operazione bitwise AND
|
|
const networkBinary = ipBinary
|
|
.split('')
|
|
.map((bit, index) => bit & netmaskBinary[index])
|
|
.join('');
|
|
|
|
// Converti il risultato in forma di stringa
|
|
const networkAddress = networkBinary
|
|
.match(/.{1,8}/g)
|
|
.map((byte) => parseInt(byte, 2))
|
|
.join('.');
|
|
|
|
// Calcola il numero di bit della netmask
|
|
const cidrPrefix = netmask
|
|
.split('.')
|
|
.reduce(
|
|
(acc, byte) =>
|
|
acc + (parseInt(byte, 10).toString(2).match(/1/g) || '').length,
|
|
0
|
|
);
|
|
|
|
return `${networkAddress}/${cidrPrefix}`;
|
|
},
|
|
|
|
getSystemNetwork() {
|
|
// Get network interface information
|
|
const interfaces = os.networkInterfaces();
|
|
let address = null;
|
|
let netmask = null;
|
|
let network = null;
|
|
|
|
// Check if wlan0 has an associated IP address
|
|
if (
|
|
interfaces['wlan0'] &&
|
|
interfaces['wlan0'].some((info) => info.family === 'IPv4')
|
|
) {
|
|
// If wlan0 has an associated IP address, use wlan0
|
|
address = interfaces['wlan0'].find(
|
|
(info) => info.family === 'IPv4'
|
|
).address;
|
|
netmask = interfaces['wlan0'].find(
|
|
(info) => info.family === 'IPv4'
|
|
).netmask;
|
|
} else if (
|
|
interfaces['eth0'] &&
|
|
interfaces['eth0'].some((info) => info.family === 'IPv4')
|
|
) {
|
|
// If wlan0 doesn't have an associated IP address but eth0 does, use eth0
|
|
address = interfaces['eth0'].find(
|
|
(info) => info.family === 'IPv4'
|
|
).address;
|
|
netmask = interfaces['eth0'].find(
|
|
(info) => info.family === 'IPv4'
|
|
).netmask;
|
|
} else {
|
|
console.log('No IP address associated with wlan0 or eth0');
|
|
}
|
|
|
|
if (address && netmask)
|
|
network = this.networkAddressWithCIDR(address, netmask);
|
|
|
|
return network;
|
|
},
|
|
|
|
async manageCkpoolConf(settings) {
|
|
try {
|
|
const ckpoolConf = {
|
|
btcd: [
|
|
{
|
|
url: '127.0.0.1:8332',
|
|
auth: 'futurebit',
|
|
pass: settings.nodeRpcPassword,
|
|
notify: true,
|
|
},
|
|
],
|
|
logdir: '/opt/apolloapi/backend/ckpool/logs',
|
|
btcsig: '/mined by Solo FutureBit Apollo/',
|
|
zmqblock: 'tcp://127.0.0.1:28332',
|
|
};
|
|
|
|
await fsPromises.writeFile(
|
|
configCkpoolFilePath,
|
|
JSON.stringify(ckpoolConf, null, 2)
|
|
);
|
|
} catch (err) {
|
|
console.log('ERR manageCkpoolConf', err);
|
|
}
|
|
},
|
|
|
|
async manageBitcoinConf(settings) {
|
|
try {
|
|
// CHecking current conf file
|
|
const currentConf = await fsPromises.readFile(configBitcoinFilePath, 'utf8');
|
|
const currentConfBase64 = Buffer.from(currentConf).toString('base64');
|
|
|
|
const defaultConf = `server=1\nrpcuser=futurebit\nrpcpassword=${settings.nodeRpcPassword}\ndaemon=0\nupnp=1\nuacomment=FutureBit-Apollo-Node`;
|
|
let conf = defaultConf;
|
|
conf += `\n#SOLO_START\nzmqpubhashblock=tcp://127.0.0.1:28332\n#SOLO_END`;
|
|
|
|
this.manageCkpoolConf(settings);
|
|
|
|
if (settings.nodeEnableSoloMining) {
|
|
exec(
|
|
`sudo cp ${configCkpoolServiceFilePath} /etc/systemd/system/ckpool.service`
|
|
);
|
|
exec('sudo systemctl daemon-reload');
|
|
exec('sudo systemctl enable ckpool');
|
|
exec('sudo systemctl restart ckpool');
|
|
} else {
|
|
exec('sudo systemctl stop ckpool');
|
|
exec('sudo systemctl disable ckpool');
|
|
}
|
|
|
|
if (settings.nodeEnableTor) {
|
|
conf += `\n#TOR_START\nproxy=127.0.0.1:9050\nlisten=1\nbind=127.0.0.1\nonlynet=onion\ndnsseed=0\ndns=0\n#TOR_END`;
|
|
exec('sudo systemctl enable tor');
|
|
exec('sudo systemctl restart tor');
|
|
} else {
|
|
exec('sudo systemctl stop tor');
|
|
exec('sudo systemctl disable tor');
|
|
}
|
|
|
|
if (settings.nodeMaxConnections)
|
|
conf += `\nmaxconnections=${settings.nodeMaxConnections}`;
|
|
else conf += '\nmaxconnections=32';
|
|
|
|
if (settings.nodeAllowLan) {
|
|
const lanNetwork = this.getSystemNetwork();
|
|
conf += `\nrpcbind=0.0.0.0\nrpcallowip=0.0.0.0/0`;
|
|
}
|
|
|
|
if (settings.nodeUserConf) {
|
|
// Extract variable names from settings.nodeUserConf using regex
|
|
const userConfVariables = settings.nodeUserConf.match(/^[^=\r\n]+/gm);
|
|
|
|
// Extract variable names from defaultConf using regex
|
|
const defaultConfVariables = defaultConf.match(/^[^=\r\n]+/gm);
|
|
|
|
// Remove variables from settings.nodeUserConf that are also present in defaultConf
|
|
const filteredUserConfVariables = userConfVariables.filter(
|
|
(variable) => !defaultConfVariables.includes(variable)
|
|
);
|
|
|
|
if (filteredUserConfVariables.length) {
|
|
// Initialize an empty array to store formatted user configurations
|
|
const formattedUserConf = [];
|
|
|
|
// Iterate through filtered variables and format them
|
|
filteredUserConfVariables.forEach((variable) => {
|
|
// If the variable has a value, format it as "variable=value"
|
|
// Otherwise, format it as "variable"
|
|
const formattedVariable = settings.nodeUserConf.includes(
|
|
`${variable}=`
|
|
)
|
|
? `${variable}=${
|
|
settings.nodeUserConf.match(new RegExp(`${variable}=(.*)`))[1]
|
|
}`
|
|
: variable;
|
|
|
|
// Push the formatted variable to the array
|
|
formattedUserConf.push(formattedVariable);
|
|
});
|
|
|
|
// Join the formatted variables into a single string with newlines
|
|
const filteredUserConf = formattedUserConf.join('\n');
|
|
|
|
// Append the filtered user configuration to the overall configuration
|
|
conf += `\n#USER_INPUT_START\n${filteredUserConf}\n#USER_INPUT_END`;
|
|
}
|
|
}
|
|
|
|
const confBase64 = Buffer.from(conf).toString('base64');
|
|
|
|
if (currentConfBase64 === confBase64) return console.log('No changes to bitcoin.conf file');
|
|
|
|
console.log('Writing Bitcoin conf file', conf);
|
|
|
|
await fsPromises.writeFile(configBitcoinFilePath, conf);
|
|
|
|
exec('sleep 3 && sudo systemctl restart node');
|
|
} catch (err) {
|
|
console.log('ERR manageBitcoinConf', err);
|
|
}
|
|
},
|
|
};
|