auth_protect: pass authMessage in the auth_protect decorator,
instead of relying on side-effects This is probably safer, and also more self-contained.
This commit is contained in:
@@ -4,32 +4,28 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty
|
|||||||
|
|
||||||
from electrum.logging import get_logger
|
from electrum.logging import get_logger
|
||||||
|
|
||||||
def auth_protect(func=None, reject=None, method='pin'):
|
def auth_protect(message='', method='pin', reject=None):
|
||||||
if func is None:
|
|
||||||
return partial(auth_protect, reject=reject, method=method)
|
|
||||||
|
|
||||||
@wraps(func)
|
def decorator(func=None):
|
||||||
def wrapper(self, *args, **kwargs):
|
if func is None:
|
||||||
_logger = get_logger(__name__)
|
return partial(auth_protect, reject=reject, method=method)
|
||||||
_logger.debug(f'{str(self)}.{func.__name__}')
|
|
||||||
if hasattr(self, '__auth_fcall'):
|
|
||||||
_logger.debug('object already has a pending authed function call')
|
|
||||||
raise Exception('object already has a pending authed function call')
|
|
||||||
setattr(self, '__auth_fcall', (func,args,kwargs,reject))
|
|
||||||
getattr(self, 'authRequired').emit(method)
|
|
||||||
|
|
||||||
return wrapper
|
@wraps(func)
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
_logger = get_logger(__name__)
|
||||||
|
_logger.debug(f'{str(self)}.{func.__name__}')
|
||||||
|
if hasattr(self, '__auth_fcall'):
|
||||||
|
_logger.debug('object already has a pending authed function call')
|
||||||
|
raise Exception('object already has a pending authed function call')
|
||||||
|
setattr(self, '__auth_fcall', (func,args,kwargs,reject))
|
||||||
|
getattr(self, 'authRequired').emit(method, message)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
|
|
||||||
class AuthMixin:
|
class AuthMixin:
|
||||||
_auth_logger = get_logger(__name__)
|
_auth_logger = get_logger(__name__)
|
||||||
|
authRequired = pyqtSignal([str, str], arguments=['method', 'authMessage'])
|
||||||
authRequired = pyqtSignal([str],arguments=['method'])
|
|
||||||
|
|
||||||
auth_message = ''
|
|
||||||
_authMixinMessageChanged = pyqtSignal()
|
|
||||||
@pyqtProperty(str, notify=_authMixinMessageChanged)
|
|
||||||
def authMessage(self):
|
|
||||||
return self.auth_message
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def authProceed(self):
|
def authProceed(self):
|
||||||
@@ -44,7 +40,6 @@ class AuthMixin:
|
|||||||
raise e
|
raise e
|
||||||
finally:
|
finally:
|
||||||
delattr(self,'__auth_fcall')
|
delattr(self,'__auth_fcall')
|
||||||
self.auth_message = ''
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def authCancel(self):
|
def authCancel(self):
|
||||||
@@ -64,4 +59,3 @@ class AuthMixin:
|
|||||||
raise e
|
raise e
|
||||||
finally:
|
finally:
|
||||||
delattr(self, '__auth_fcall')
|
delattr(self, '__auth_fcall')
|
||||||
self.auth_message = ''
|
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ ApplicationWindow
|
|||||||
id: _swaphelper
|
id: _swaphelper
|
||||||
wallet: Daemon.currentWallet
|
wallet: Daemon.currentWallet
|
||||||
onAuthRequired: {
|
onAuthRequired: {
|
||||||
app.handleAuthRequired(_swaphelper, method)
|
app.handleAuthRequired(_swaphelper, method, authMessage)
|
||||||
}
|
}
|
||||||
onError: {
|
onError: {
|
||||||
var dialog = app.messageDialog.createObject(app, { text: message })
|
var dialog = app.messageDialog.createObject(app, { text: message })
|
||||||
@@ -477,8 +477,8 @@ ApplicationWindow
|
|||||||
var dialog = app.messageDialog.createObject(app, {'text': error})
|
var dialog = app.messageDialog.createObject(app, {'text': error})
|
||||||
dialog.open()
|
dialog.open()
|
||||||
}
|
}
|
||||||
function onAuthRequired(method) {
|
function onAuthRequired(method, authMessage) {
|
||||||
handleAuthRequired(Daemon, method)
|
handleAuthRequired(Daemon, method, authMessage)
|
||||||
}
|
}
|
||||||
function onLoadingChanged() {
|
function onLoadingChanged() {
|
||||||
if (!Daemon.loading)
|
if (!Daemon.loading)
|
||||||
@@ -509,8 +509,8 @@ ApplicationWindow
|
|||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Daemon.currentWallet
|
target: Daemon.currentWallet
|
||||||
function onAuthRequired(method) {
|
function onAuthRequired(method, authMessage) {
|
||||||
handleAuthRequired(Daemon.currentWallet, method)
|
handleAuthRequired(Daemon.currentWallet, method, authMessage)
|
||||||
}
|
}
|
||||||
// TODO: add to notification queue instead of barging through
|
// TODO: add to notification queue instead of barging through
|
||||||
function onPaymentSucceeded(key) {
|
function onPaymentSucceeded(key) {
|
||||||
@@ -523,12 +523,12 @@ ApplicationWindow
|
|||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: Config
|
target: Config
|
||||||
function onAuthRequired(method) {
|
function onAuthRequired(method, authMessage) {
|
||||||
handleAuthRequired(Config, method)
|
handleAuthRequired(Config, method, authMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAuthRequired(qtobject, method) {
|
function handleAuthRequired(qtobject, method, authMessage) {
|
||||||
console.log('auth using method ' + method)
|
console.log('auth using method ' + method)
|
||||||
if (method == 'wallet') {
|
if (method == 'wallet') {
|
||||||
if (Daemon.currentWallet.verify_password('')) {
|
if (Daemon.currentWallet.verify_password('')) {
|
||||||
@@ -551,12 +551,12 @@ ApplicationWindow
|
|||||||
} else if (method == 'pin') {
|
} else if (method == 'pin') {
|
||||||
if (Config.pinCode == '') {
|
if (Config.pinCode == '') {
|
||||||
// no PIN configured
|
// no PIN configured
|
||||||
handleAuthConfirmationOnly(qtobject)
|
handleAuthConfirmationOnly(qtobject, authMessage)
|
||||||
} else {
|
} else {
|
||||||
var dialog = app.pinDialog.createObject(app, {
|
var dialog = app.pinDialog.createObject(app, {
|
||||||
mode: 'check',
|
mode: 'check',
|
||||||
pincode: Config.pinCode,
|
pincode: Config.pinCode,
|
||||||
authMessage: qtobject.authMessage
|
authMessage: authMessage
|
||||||
})
|
})
|
||||||
dialog.accepted.connect(function() {
|
dialog.accepted.connect(function() {
|
||||||
qtobject.authProceed()
|
qtobject.authProceed()
|
||||||
@@ -573,12 +573,12 @@ ApplicationWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAuthConfirmationOnly(qtobject) {
|
function handleAuthConfirmationOnly(qtobject, authMessage) {
|
||||||
if (!qtobject.authMessage) {
|
if (!authMessage) {
|
||||||
qtobject.authProceed()
|
qtobject.authProceed()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var dialog = app.messageDialog.createObject(app, {text: qtobject.authMessage, yesno: true})
|
var dialog = app.messageDialog.createObject(app, {text: authMessage, yesno: true})
|
||||||
dialog.accepted.connect(function() {
|
dialog.accepted.connect(function() {
|
||||||
qtobject.authProceed()
|
qtobject.authProceed()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
node_id=self._node_pubkey,
|
node_id=self._node_pubkey,
|
||||||
fee_est=None)
|
fee_est=None)
|
||||||
|
|
||||||
self.auth_message = _('Open Lightning channel?')
|
|
||||||
acpt = lambda tx: self.do_open_channel(tx, self._connect_str_resolved, self._wallet.password)
|
acpt = lambda tx: self.do_open_channel(tx, self._connect_str_resolved, self._wallet.password)
|
||||||
|
|
||||||
self._finalizer = QETxFinalizer(self, make_tx=mktx, accept=acpt)
|
self._finalizer = QETxFinalizer(self, make_tx=mktx, accept=acpt)
|
||||||
@@ -174,7 +173,7 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
self._finalizer.wallet = self._wallet
|
self._finalizer.wallet = self._wallet
|
||||||
self.finalizerChanged.emit()
|
self.finalizerChanged.emit()
|
||||||
|
|
||||||
@auth_protect
|
@auth_protect(message=_('Open Lichtning channel?'))
|
||||||
def do_open_channel(self, funding_tx, conn_str, password):
|
def do_open_channel(self, funding_tx, conn_str, password):
|
||||||
"""
|
"""
|
||||||
conn_str: a connection string that extract_nodeid can parse, i.e. cannot be a trampoline name
|
conn_str: a connection string that extract_nodeid can parse, i.e. cannot be a trampoline name
|
||||||
|
|||||||
@@ -261,10 +261,9 @@ class QEDaemon(AuthMixin, QObject):
|
|||||||
self.walletDeleteError.emit('balance', _('There are still coins present in this wallet. Really delete?'))
|
self.walletDeleteError.emit('balance', _('There are still coins present in this wallet. Really delete?'))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.auth_message = _('Really delete this wallet?')
|
|
||||||
self.delete_wallet(wallet)
|
self.delete_wallet(wallet)
|
||||||
|
|
||||||
@auth_protect
|
@auth_protect(message=_('Really delete this wallet?'))
|
||||||
def delete_wallet(self, wallet):
|
def delete_wallet(self, wallet):
|
||||||
path = standardize_path(wallet.wallet.storage.path)
|
path = standardize_path(wallet.wallet.storage.path)
|
||||||
self._logger.debug('deleting wallet with path %s' % path)
|
self._logger.debug('deleting wallet with path %s' % path)
|
||||||
|
|||||||
@@ -383,7 +383,6 @@ class QEInvoice(QObject, QtEventListener):
|
|||||||
# TODO: is update amount_msat for overrideAmount sufficient?
|
# TODO: is update amount_msat for overrideAmount sufficient?
|
||||||
self._effectiveInvoice.amount_msat = self.amountOverride.satsInt * 1000
|
self._effectiveInvoice.amount_msat = self.amountOverride.satsInt * 1000
|
||||||
|
|
||||||
self._wallet.auth_message = _('Pay Lightning Invoice?')
|
|
||||||
self._wallet.pay_lightning_invoice(self._effectiveInvoice)
|
self._wallet.pay_lightning_invoice(self._effectiveInvoice)
|
||||||
|
|
||||||
def get_max_spendable_onchain(self):
|
def get_max_spendable_onchain(self):
|
||||||
|
|||||||
@@ -423,17 +423,9 @@ class QESwapHelper(AuthMixin, QObject, QtEventListener):
|
|||||||
if not self._wallet.wallet.network:
|
if not self._wallet.wallet.network:
|
||||||
self.error.emit(_("You are offline."))
|
self.error.emit(_("You are offline."))
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.isReverse:
|
|
||||||
self.auth_message = _('Do you want to do a reverse submarine swap?')
|
|
||||||
else:
|
|
||||||
self.auth_message = _('Do you want to do a submarine swap? '
|
|
||||||
'You will need to wait for the swap transaction to confirm.'
|
|
||||||
)
|
|
||||||
|
|
||||||
self._do_execute_swap()
|
self._do_execute_swap()
|
||||||
|
|
||||||
@auth_protect
|
@auth_protect(message=_('Confirm Lightning swap?'))
|
||||||
def _do_execute_swap(self):
|
def _do_execute_swap(self):
|
||||||
if self.isReverse:
|
if self.isReverse:
|
||||||
lightning_amount = self._send_amount
|
lightning_amount = self._send_amount
|
||||||
|
|||||||
@@ -584,7 +584,7 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
|||||||
def ln_auth_rejected(self):
|
def ln_auth_rejected(self):
|
||||||
self.paymentAuthRejected.emit()
|
self.paymentAuthRejected.emit()
|
||||||
|
|
||||||
@auth_protect(reject='ln_auth_rejected')
|
@auth_protect(message=_('Pay lightning invoice?'), reject='ln_auth_rejected')
|
||||||
def pay_lightning_invoice(self, invoice: 'QEInvoice'):
|
def pay_lightning_invoice(self, invoice: 'QEInvoice'):
|
||||||
amount_msat = invoice.get_amount_msat()
|
amount_msat = invoice.get_amount_msat()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user