diff --git a/.env.example b/.env.example index 2e8aed04..9ad5cf8a 100644 --- a/.env.example +++ b/.env.example @@ -17,4 +17,6 @@ TORRENT_SEED_URL=https://webtorrent.shock.network # Admin token for your own seed server TORRENT_SEED_TOKEN=jibberish # "default" or "hosting" -DEPLOYMENT_TYPE=hosting \ No newline at end of file +DEPLOYMENT_TYPE=hosting +# allow to create a user with unlocked lnd +ALLOW_UNLOCKED_LND="true" \ No newline at end of file diff --git a/src/routes.js b/src/routes.js index b719478d..c5dd90c2 100644 --- a/src/routes.js +++ b/src/routes.js @@ -611,7 +611,7 @@ module.exports = async ( // If we're connected to lnd, unlock the wallet using the password supplied // and generate an auth token if that operation was successful. if (health.LNDStatus.success && walletInitialized) { - const { alias, password, invite } = req.body + const { alias, password, invite, accessSecret } = req.body await recreateLnServices() @@ -647,8 +647,18 @@ module.exports = async ( if (!walletUnlocked) { await unlockWallet(password) } - - if (walletUnlocked && !authorization && !isKeyTrusted) { + let secretUsed = null + if (accessSecret) { + secretUsed = await Storage.get( + `UnlockedAccessSecrets/${accessSecret}` + ) + } + if ( + walletUnlocked && + !authorization && + !isKeyTrusted && + (process.env.ALLOW_UNLOCKED_LND !== 'true' || secretUsed !== false) + ) { res.status(401).json({ field: 'alias', errorMessage: @@ -658,7 +668,11 @@ module.exports = async ( return } - if (walletUnlocked && !isKeyTrusted) { + if ( + walletUnlocked && + !isKeyTrusted && + (process.env.ALLOW_UNLOCKED_LND !== 'true' || secretUsed !== false) + ) { const validatedToken = await validateToken( authorization.replace('Bearer ', '') ) @@ -674,6 +688,10 @@ module.exports = async ( } } + if (secretUsed === false) { + await Storage.setItem(`UnlockedAccessSecrets/${accessSecret}`, true) + } + if (!isKeyTrusted) { await Storage.set('trustedPKs', [...(trustedKeys || []), publicKey]) } @@ -1003,7 +1021,7 @@ module.exports = async ( app.post('/api/lnd/wallet/existing', async (req, res) => { try { - const { password, alias, invite } = req.body + const { password, alias, invite, accessSecret } = req.body const healthResponse = await checkHealth() const exists = await walletExists() if (!exists) { @@ -1034,17 +1052,30 @@ module.exports = async ( "Please specify a password that's longer than 8 characters" }) } - - if (healthResponse.LNDStatus.service !== 'walletUnlocker') { + let secretUsed = null + if (accessSecret) { + secretUsed = await Storage.get( + `UnlockedAccessSecrets/${accessSecret}` + ) + } + if ( + healthResponse.LNDStatus.service !== 'walletUnlocker' && + (process.env.ALLOW_UNLOCKED_LND !== 'true' || secretUsed !== false) + ) { return res.status(400).json({ field: 'wallet', errorMessage: 'Wallet is already unlocked. Please restart your LND instance and try again.' }) } + if (secretUsed === false) { + await Storage.setItem(`UnlockedAccessSecrets/${accessSecret}`, true) + } try { - await unlockWallet(password) + if (healthResponse.LNDStatus.service === 'walletUnlocker') { + await unlockWallet(password) + } } catch (err) { return res.status(401).json({ field: 'wallet', diff --git a/src/server.js b/src/server.js index 5e8d16b2..b62c0d34 100644 --- a/src/server.js +++ b/src/server.js @@ -1,3 +1,5 @@ +const { generateRandomString } = require('../utils/encryptionStore') + /** * @prettier */ @@ -437,6 +439,17 @@ const server = program => { } }) } + + if(process.env.ALLOW_UNLOCKED_LND === 'true'){ + const codes = await Storage.valuesWithKeyMatch(/^UnlockedAccessSecrets\//u) + if(codes.length === 0){ + const code = generateRandomString(12) + await Storage.setItem(`UnlockedAccessSecrets/${code}`, false) + logger.info("the access code is:"+code) + } else if(codes.length === 1 || codes[0] === false){ + logger.info("the access code is:"+codes[0]) + } + } serverInstance.listen(serverPort, serverHost) logger.info('App listening on ' + serverHost + ' port ' + serverPort) module.server = serverInstance