network/gui: add unified reset for SSL certificates and known servers
- Network.clear_pinned_server_certs(): remove cached certs and reconnect interfaces - Network.clear_recent_servers(): clear the list of recently used servers - QML bridge: expose clearPinnedServerCertificates() and clearRecentServers() - QML: move reset actions to ServerConfig with a dropdown menu (SSL / Known servers) - Qt: add Reset SSL certificates and Reset known servers buttons in Server tab
This commit is contained in:
@@ -296,6 +296,7 @@ Pane {
|
|||||||
dialog.open()
|
dialog.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,9 +50,73 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
RowLayout {
|
||||||
text: qsTr("Server")
|
Layout.fillWidth: true
|
||||||
enabled: address_tf.enabled
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Server")
|
||||||
|
enabled: address_tf.enabled
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolButton {
|
||||||
|
icon.source: '../../../icons/delete.png'
|
||||||
|
ToolTip.text: qsTr('Reset network data')
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
onClicked: resetMenu.open()
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: resetMenu
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr('SSL certificates')
|
||||||
|
onTriggered: {
|
||||||
|
var dialog = app.messageDialog.createObject(app, {
|
||||||
|
title: qsTr('Are you sure?'),
|
||||||
|
text: qsTr('This will remove cached SSL certificates for servers and reconnect to fetch them again.'),
|
||||||
|
yesno: true
|
||||||
|
})
|
||||||
|
dialog.accepted.connect(function() {
|
||||||
|
var removed = Network.clearPinnedServerCertificates()
|
||||||
|
var msg = removed < 0
|
||||||
|
? qsTr('Failed to reset SSL certificates.')
|
||||||
|
: removed > 0
|
||||||
|
? qsTr('%1 certificate files were removed.').arg(removed)
|
||||||
|
: qsTr('No cached certificate files were found.')
|
||||||
|
app.messageDialog.createObject(app, {
|
||||||
|
title: qsTr('Reset SSL certificates'),
|
||||||
|
text: msg
|
||||||
|
}).open()
|
||||||
|
})
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr('Known servers')
|
||||||
|
onTriggered: {
|
||||||
|
var dialog = app.messageDialog.createObject(app, {
|
||||||
|
title: qsTr('Are you sure?'),
|
||||||
|
text: qsTr('This will remove the list of known servers.'),
|
||||||
|
yesno: true
|
||||||
|
})
|
||||||
|
dialog.accepted.connect(function() {
|
||||||
|
var removed = Network.clearRecentServers()
|
||||||
|
var msg = removed < 0
|
||||||
|
? qsTr('Failed to reset known servers.')
|
||||||
|
: removed > 0
|
||||||
|
? qsTr('%1 server(s) were removed.').arg(removed)
|
||||||
|
: qsTr('No known servers were found.')
|
||||||
|
app.messageDialog.createObject(app, {
|
||||||
|
title: qsTr('Reset known servers'),
|
||||||
|
text: msg
|
||||||
|
}).open()
|
||||||
|
})
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextHighlightPane {
|
TextHighlightPane {
|
||||||
|
|||||||
@@ -306,3 +306,19 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def probeTor(self):
|
def probeTor(self):
|
||||||
ProxySettings.probe_tor(self.torProbeFinished.emit) # via signal
|
ProxySettings.probe_tor(self.torProbeFinished.emit) # via signal
|
||||||
|
|
||||||
|
@pyqtSlot(result=int)
|
||||||
|
def clearPinnedServerCertificates(self):
|
||||||
|
try:
|
||||||
|
return self.network.run_from_another_thread(self.network.clear_pinned_server_certs())
|
||||||
|
except Exception:
|
||||||
|
self._logger.exception("failed to clear pinned server certificates")
|
||||||
|
return -1
|
||||||
|
|
||||||
|
@pyqtSlot(result=int)
|
||||||
|
def clearRecentServers(self):
|
||||||
|
try:
|
||||||
|
return self.network.clear_recent_servers()
|
||||||
|
except Exception:
|
||||||
|
self._logger.exception("failed to clear recent servers")
|
||||||
|
return -1
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot
|
|||||||
from PyQt6.QtWidgets import (
|
from PyQt6.QtWidgets import (
|
||||||
QTreeWidget, QTreeWidgetItem, QMenu, QGridLayout, QComboBox, QLineEdit, QDialog, QVBoxLayout, QHeaderView,
|
QTreeWidget, QTreeWidgetItem, QMenu, QGridLayout, QComboBox, QLineEdit, QDialog, QVBoxLayout, QHeaderView,
|
||||||
QCheckBox, QTabWidget, QWidget, QLabel, QPushButton, QHBoxLayout,
|
QCheckBox, QTabWidget, QWidget, QLabel, QPushButton, QHBoxLayout,
|
||||||
QListWidget, QListWidgetItem,
|
QListWidget, QListWidgetItem, QMessageBox,
|
||||||
)
|
)
|
||||||
from PyQt6.QtGui import QIntValidator
|
from PyQt6.QtGui import QIntValidator
|
||||||
|
|
||||||
@@ -444,6 +444,16 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
self.layout().addWidget(self.nodes_list_widget)
|
self.layout().addWidget(self.nodes_list_widget)
|
||||||
self.nodes_list_widget.update()
|
self.nodes_list_widget.update()
|
||||||
|
|
||||||
|
self.clear_certs_button = QPushButton(_('Reset SSL certificates'))
|
||||||
|
self.clear_certs_button.clicked.connect(self.clear_pinned_server_certs)
|
||||||
|
self.clear_servers_button = QPushButton(_('Reset known servers'))
|
||||||
|
self.clear_servers_button.clicked.connect(self.clear_recent_servers)
|
||||||
|
buttons = QHBoxLayout()
|
||||||
|
buttons.addStretch(1)
|
||||||
|
buttons.addWidget(self.clear_certs_button)
|
||||||
|
buttons.addWidget(self.clear_servers_button)
|
||||||
|
self.layout().addLayout(buttons)
|
||||||
|
|
||||||
self.register_callbacks()
|
self.register_callbacks()
|
||||||
self.destroyed.connect(lambda: self.unregister_callbacks())
|
self.destroyed.connect(lambda: self.unregister_callbacks())
|
||||||
|
|
||||||
@@ -584,6 +594,54 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
_logger.debug(f"set_server: {new_net_params=}")
|
_logger.debug(f"set_server: {new_net_params=}")
|
||||||
self.network.run_from_another_thread(self.network.set_parameters(new_net_params))
|
self.network.run_from_another_thread(self.network.set_parameters(new_net_params))
|
||||||
|
|
||||||
|
def clear_pinned_server_certs(self):
|
||||||
|
result = QMessageBox.question(
|
||||||
|
self,
|
||||||
|
_('Reset SSL certificates'),
|
||||||
|
_('This will remove cached SSL certificates for servers and reconnect to fetch them again.')
|
||||||
|
+ '\n\n'
|
||||||
|
+ _('Do you want to continue?'),
|
||||||
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||||
|
QMessageBox.StandardButton.No,
|
||||||
|
)
|
||||||
|
if result != QMessageBox.StandardButton.Yes:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
removed = self.network.run_from_another_thread(self.network.clear_pinned_server_certs())
|
||||||
|
except Exception as e:
|
||||||
|
_logger.exception("failed to clear pinned server certificates")
|
||||||
|
QMessageBox.critical(self, _('Reset SSL certificates'), str(e))
|
||||||
|
return
|
||||||
|
if removed > 0:
|
||||||
|
msg = _('{} certificate files were removed.').format(removed)
|
||||||
|
else:
|
||||||
|
msg = _('No cached certificate files were found.')
|
||||||
|
QMessageBox.information(self, _('Reset SSL certificates'), msg)
|
||||||
|
|
||||||
|
def clear_recent_servers(self):
|
||||||
|
result = QMessageBox.question(
|
||||||
|
self,
|
||||||
|
_('Reset known servers'),
|
||||||
|
_('This will remove the list of known servers.')
|
||||||
|
+ '\n\n'
|
||||||
|
+ _('Do you want to continue?'),
|
||||||
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||||
|
QMessageBox.StandardButton.No,
|
||||||
|
)
|
||||||
|
if result != QMessageBox.StandardButton.Yes:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
removed = self.network.clear_recent_servers()
|
||||||
|
except Exception as e:
|
||||||
|
_logger.exception("failed to clear recent servers")
|
||||||
|
QMessageBox.critical(self, _('Reset known servers'), str(e))
|
||||||
|
return
|
||||||
|
if removed > 0:
|
||||||
|
msg = _('{} server(s) were removed.').format(removed)
|
||||||
|
else:
|
||||||
|
msg = _('No known servers were found.')
|
||||||
|
QMessageBox.information(self, _('Reset known servers'), msg)
|
||||||
|
|
||||||
|
|
||||||
class NostrWidget(QWidget, QtEventListener):
|
class NostrWidget(QWidget, QtEventListener):
|
||||||
|
|
||||||
|
|||||||
@@ -408,6 +408,36 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
"""Our guess whether the device has Internet-connectivity."""
|
"""Our guess whether the device has Internet-connectivity."""
|
||||||
return self._has_ever_managed_to_connect_to_server
|
return self._has_ever_managed_to_connect_to_server
|
||||||
|
|
||||||
|
def clear_recent_servers(self) -> int:
|
||||||
|
"""Clear the list of recently used servers."""
|
||||||
|
with self.recent_servers_lock:
|
||||||
|
count = len(self._recent_servers)
|
||||||
|
self._recent_servers = []
|
||||||
|
self._save_recent_servers()
|
||||||
|
self.logger.info(f"cleared {count} recent server(s)")
|
||||||
|
return count
|
||||||
|
|
||||||
|
async def clear_pinned_server_certs(self) -> int:
|
||||||
|
"""Delete cached server SSL certs and reconnect interfaces."""
|
||||||
|
certs_dir = os.path.join(self.config.path, 'certs')
|
||||||
|
util.make_dir(certs_dir)
|
||||||
|
removed = 0
|
||||||
|
for entry in os.scandir(certs_dir):
|
||||||
|
if not entry.is_file():
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
os.unlink(entry.path)
|
||||||
|
removed += 1
|
||||||
|
except OSError as e:
|
||||||
|
self.logger.warning(f"failed to delete cert file {entry.path!r}: {e!r}")
|
||||||
|
self.logger.info(f"removed {removed} cached server cert(s)")
|
||||||
|
if removed:
|
||||||
|
with self.interfaces_lock:
|
||||||
|
interfaces = list(self.interfaces.values())
|
||||||
|
for iface in interfaces:
|
||||||
|
await self._close_interface(iface)
|
||||||
|
return removed
|
||||||
|
|
||||||
def has_channel_db(self):
|
def has_channel_db(self):
|
||||||
return self.channel_db is not None
|
return self.channel_db is not None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user