From 3bb453aaba4444fa47f338572bba9bd3d559ecb9 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Fri, 28 Oct 2022 13:52:24 +0200 Subject: [PATCH] PayServer: add settings dialog and hook for view_url --- electrum/plugins/payserver/payserver.py | 20 +++++++++++-- electrum/plugins/payserver/qt.py | 38 ++++++++++++++++++++++++- electrum/wallet.py | 12 +------- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/electrum/plugins/payserver/payserver.py b/electrum/plugins/payserver/payserver.py index 343daf565..7a9687507 100644 --- a/electrum/plugins/payserver/payserver.py +++ b/electrum/plugins/payserver/payserver.py @@ -62,6 +62,9 @@ class PayServerPlugin(BasePlugin): self.server = PayServer(self.config, wallet) asyncio.run_coroutine_threadsafe(daemon._run(jobs=[self.server.run()]), daemon.asyncio_loop) + @hook + def wallet_export_request(self, d, key): + d['view_url'] = self.server.base_url + self.server.root + '/pay?id=' + key class PayServer(Logger, EventListener): @@ -83,6 +86,18 @@ class PayServer(Logger, EventListener): index_html = os.path.join(cls.WWW_DIR, "index.html") return os.path.exists(index_html) + @property + def base_url(self): + payserver = self.config.get('payserver_address', 'localhost:8080') + payserver = NetAddress.from_string(payserver) + use_ssl = bool(self.config.get('ssl_keyfile')) + protocol = 'https' if use_ssl else 'http' + return '%s://%s:%d'%(protocol, payserver.host, payserver.port) + + @property + def root(self): + return self.config.get('payserver_root', '/r') + @event_listener async def on_event_request_status(self, wallet, key, status): if status == PR_PAID: @@ -91,7 +106,6 @@ class PayServer(Logger, EventListener): @ignore_exceptions @log_exceptions async def run(self): - self.root = root = self.config.get('payserver_root', '/r') app = web.Application() app.add_routes([web.get('/api/get_invoice', self.get_request)]) app.add_routes([web.get('/api/get_status', self.get_status)]) @@ -99,8 +113,8 @@ class PayServer(Logger, EventListener): # 'follow_symlinks=True' allows symlinks to traverse out the parent directory. # This was requested by distro packagers for vendored libs, and we restrict it to only those # to minimise attack surface. note: "add_routes" call order matters (inner path goes first) - app.add_routes([web.static(f"{root}/vendor", os.path.join(self.WWW_DIR, 'vendor'), follow_symlinks=True)]) - app.add_routes([web.static(root, self.WWW_DIR)]) + app.add_routes([web.static(f"{self.root}/vendor", os.path.join(self.WWW_DIR, 'vendor'), follow_symlinks=True)]) + app.add_routes([web.static(self.root, self.WWW_DIR)]) if self.config.get('payserver_allow_create_invoice'): app.add_routes([web.post('/api/create_invoice', self.create_request)]) runner = web.AppRunner(app) diff --git a/electrum/plugins/payserver/qt.py b/electrum/plugins/payserver/qt.py index 929f64742..7a706c191 100644 --- a/electrum/plugins/payserver/qt.py +++ b/electrum/plugins/payserver/qt.py @@ -23,7 +23,43 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from functools import partial +from PyQt5 import QtWidgets +from electrum.i18n import _ +from electrum.gui.qt.util import WindowModalDialog, OkButton, Buttons, EnterButton from .payserver import PayServerPlugin + class Plugin(PayServerPlugin): - pass + + def requires_settings(self): + return True + + def settings_widget(self, window: WindowModalDialog): + return EnterButton( + _('Settings'), + partial(self.settings_dialog, window)) + + def settings_dialog(self, window: WindowModalDialog): + d = WindowModalDialog(window, _("PayServer Settings")) + form = QtWidgets.QFormLayout(None) + addr = self.config.get('payserver_address', 'localhost:8080') + url = self.server.base_url + self.server.root + '/create_invoice.html' + self.help_label = QtWidgets.QLabel('create invoice: %s'%(url, url)) + self.help_label.setOpenExternalLinks(True) + address_e = QtWidgets.QLineEdit(addr) + keyfile_e = QtWidgets.QLineEdit(self.config.get('ssl_keyfile', '')) + certfile_e = QtWidgets.QLineEdit(self.config.get('ssl_certfile', '')) + form.addRow(QtWidgets.QLabel("Network address:"), address_e) + form.addRow(QtWidgets.QLabel("SSL key file:"), keyfile_e) + form.addRow(QtWidgets.QLabel("SSL cert file:"), certfile_e) + vbox = QtWidgets.QVBoxLayout(d) + vbox.addLayout(form) + vbox.addSpacing(20) + vbox.addWidget(self.help_label) + vbox.addSpacing(20) + vbox.addLayout(Buttons(OkButton(d))) + if d.exec_(): + self.config.set_key('payserver_address', str(address_e.text())) + self.config.set_key('ssl_keyfile', str(keyfile_e.text())) + self.config.set_key('ssl_certfile', str(certfile_e.text())) diff --git a/electrum/wallet.py b/electrum/wallet.py index 949181008..882f00e54 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -2410,17 +2410,7 @@ class Abstract_Wallet(ABC, Logger, EventListener): d['URI'] = self.get_request_URI(x) if conf is not None: d['confirmations'] = conf - # add URL if we are running a payserver - payserver = self.config.get_netaddress('payserver_address') - if payserver: - root = self.config.get('payserver_root', '/r') - use_ssl = bool(self.config.get('ssl_keyfile')) - protocol = 'https' if use_ssl else 'http' - base = '%s://%s:%d'%(protocol, payserver.host, payserver.port) - d['view_url'] = base + root + '/pay?id=' + key - if use_ssl and 'URI' in d: - request_url = base + '/bip70/' + key + '.bip70' - d['bip70_url'] = request_url + run_hook('wallet_export_request', d, key) return d def export_invoice(self, x: Invoice) -> Dict[str, Any]: