From 926945f3f99338cc2894c6c8e5991349774bc506 Mon Sep 17 00:00:00 2001 From: Mondei1 Date: Tue, 26 Jan 2021 20:11:59 +0100 Subject: [PATCH] Main does now wait till provider finished loading - Provider disable method now takes complete provider instance instead - Handle when no provider is available - Remove debug messages --- src/app.ts | 5 ++- src/controllers/user.ts | 6 ++- src/helper/invoiceManager.ts | 14 ++++++- src/helper/providerManager.ts | 66 +++++++++++++++++-------------- src/helper/providers/moneroCLI.ts | 3 -- 5 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/app.ts b/src/app.ts index 907d233..67bb150 100644 --- a/src/app.ts +++ b/src/app.ts @@ -108,7 +108,10 @@ async function run() { } providerManager = new ProviderManager(resolve('./src/helper/providers')); - providerManager.scan(); + await providerManager.scan().catch(err => { + logger.error(err); + process.exit(0); + }); invoiceManager = new InvoiceManager(); diff --git a/src/controllers/user.ts b/src/controllers/user.ts index 063abd1..797346e 100644 --- a/src/controllers/user.ts +++ b/src/controllers/user.ts @@ -80,7 +80,7 @@ export async function loginUser(req: Request, res: Response) { return; } - // Check if 2FA is turned on (the attack doesn't know yet if the password is wrong) + // Check if 2FA is turned on (the attacker doesn't know if the password is wrong yet) if (user.twoFASecret != undefined) { if (twoFA == undefined) { res.status(401).send({ message: "2FA code is required." }); @@ -135,6 +135,10 @@ export async function MW_User(req: LibrePayRequest, res: Response, next: () => v } } catch (err) { if (err) { + if (err === "jwt expired") { + res.status(401).send({ message: "Your token expired" }); + return; + } res.status(500).send({ message: "We failed validating your token for some reason." }); logger.error(err); } diff --git a/src/helper/invoiceManager.ts b/src/helper/invoiceManager.ts index c588d21..8114099 100644 --- a/src/helper/invoiceManager.ts +++ b/src/helper/invoiceManager.ts @@ -29,7 +29,12 @@ export class InvoiceManager { if (invoice.status === PaymentStatus.PENDING) { this.pendingInvoices.push(invoice); } if (invoice.status === PaymentStatus.UNCONFIRMED) { this.unconfirmedTranscations.push(invoice); } - providerManager.getProvider(invoice.paymentMethod).validateInvoice(invoice); + try { + providerManager.getProvider(invoice.paymentMethod).validateInvoice(invoice); + } catch (err) { + logger.debug(`Cannot validate invoice ${invoice.id} because there is no provider for ${invoice.paymentMethod}. Remove ...`); + this.removeInvoice(invoice); + } }); }); @@ -161,6 +166,13 @@ export class InvoiceManager { setInterval(() => { this.unconfirmedTranscations.forEach(async invoice => { const transcation = invoice.transcationHash; + + if (providerManager.getProvider(invoice.paymentMethod) === undefined) { + logger.debug(`Cannot get confirmations of invoice ${invoice.id} because there is no provider for ${invoice.paymentMethod}. Remove ...`); + this.removeInvoice(invoice); + return; + + } const provider = providerManager.getProvider(invoice.paymentMethod); const tx = await provider.getTransaction(transcation); diff --git a/src/helper/providerManager.ts b/src/helper/providerManager.ts index e2557ec..57936cc 100644 --- a/src/helper/providerManager.ts +++ b/src/helper/providerManager.ts @@ -1,4 +1,4 @@ -import { readdirSync } from 'fs'; +import { readdir } from 'fs'; import { join } from 'path'; import { config } from '../../config'; import { invoiceManager, logger, providerManager } from '../app'; @@ -22,48 +22,56 @@ export class ProviderManager { /** * Scan & load all found providers */ - scan() { - const getDirectories = () => - readdirSync(this.providerFilePath, { withFileTypes: true }) - .filter(dirent => dirent.name.endsWith('.ts')) - .map(dirent => dirent.name) + async scan() { + return new Promise(async (resolve, reject) => { + await readdir(this.providerFilePath, { withFileTypes: true }, async (err, files) => { + const directories = files.filter(dirent => dirent.name.endsWith('.ts')) + .map(dirent => dirent.name); + for (let i = 0; i < directories.length; i++) { + const file = directories[i]; + const absolutePath = join(this.providerFilePath, file); + const providerModule = require(absolutePath); + const provider = new providerModule.Provider() as BackendProvider; - getDirectories().forEach(async file => { - const absolutePath = join(this.providerFilePath, file); - const providerModule = require(absolutePath); - const provider = new providerModule.Provider() as BackendProvider; + provider.CRYPTO.forEach(crypto => { + if (this.cryptoProvider.has(crypto)) { + logger.warn(`Provider ${provider.NAME} will not be activated for ${provider.CRYPTO} since there is already another provider in place!`); + } else { + this.cryptoProvider.set(crypto, provider); + config.payment.methods.push(crypto); + } + }); - provider.CRYPTO.forEach(crypto => { - if (this.cryptoProvider.has(crypto)) { - logger.warn(`Provider ${provider.NAME} will be ignored since there is already another provider active for ${provider.CRYPTO}!`); + // Execute onEnable() function of this provider + try { + await provider.onEnable(); + logger.info(`Loaded provider "${provider.NAME}" by ${provider.AUTHOR} (${provider.VERSION}) for ${provider.CRYPTO.join(', ')}`); + } catch (err) { + logger.error(`Provider "${provider.NAME}" by ${provider.AUTHOR} (${provider.VERSION}) failed to start: ${err}`); + this.disable(provider); + } + } + + if (this.cryptoProvider.size === 0) { + reject('No providers were initialized!'); return; } - - this.cryptoProvider.set(crypto, provider); - config.payment.methods.push(crypto); + + resolve(); }); - - // Execute onEnable() function of this provider - try { - await provider.onEnable(); - logger.info(`Loaded provider "${provider.NAME}" by ${provider.AUTHOR} (${provider.VERSION}) for ${provider.CRYPTO.join(', ')}`); - } catch (err) { - logger.error(`Provider "${provider.NAME}" by ${provider.AUTHOR} (${provider.VERSION}) failed to start: ${err}`); - this.disable(provider.NAME); - } - }); } /** * This provider will be no longer be used. */ - disable(name: string) { - this.cryptoProvider.forEach(provider => { - if (provider.NAME === name) { + disable(provider: BackendProvider) { + this.cryptoProvider.forEach(cryptoProvider => { + if (provider === cryptoProvider) { // Disable all coins that are supported by this provider. provider.CRYPTO.forEach(crypto => { this.cryptoProvider.delete(crypto); + config.payment.methods.splice(config.payment.methods.indexOf(crypto), 1); }); logger.warning(`Provider "${provider.NAME}" is now disabled.`); } diff --git a/src/helper/providers/moneroCLI.ts b/src/helper/providers/moneroCLI.ts index 18016e0..c6b00cd 100644 --- a/src/helper/providers/moneroCLI.ts +++ b/src/helper/providers/moneroCLI.ts @@ -101,7 +101,6 @@ export class Provider implements BackendProvider { const paymentTransaction = message.result.transfer; if (paymentTransaction === undefined) { - console.log(message) logger.warning(`Tried to get transfer by txid but failed: ${message}`); resolve(null); return; @@ -175,8 +174,6 @@ export class Provider implements BackendProvider { return; } - console.log(payment_id, message); - // The payment has not been made yet if (message.result.payments === undefined) { resolve(null);