diff --git a/src/sakia/gui/dialogs/connection_cfg/controller.py b/src/sakia/gui/dialogs/connection_cfg/controller.py index d17d69252e9d812796aac40095ba29bddaef4736..83e6efcfd6be499a7206688260dc02830f33c769 100644 --- a/src/sakia/gui/dialogs/connection_cfg/controller.py +++ b/src/sakia/gui/dialogs/connection_cfg/controller.py @@ -1,10 +1,11 @@ import asyncio import logging -from PyQt5.QtCore import QObject +from PyQt5.QtCore import QObject, Qt from aiohttp import ClientError from asyncio import TimeoutError +from sakia.gui.widgets.dialogs import dialog_async_exec, QAsyncFileDialog, QMessageBox from duniterpy.api.errors import DuniterError from duniterpy.documents import MalformedDocumentError from sakia.data.connectors import BmaConnector @@ -212,6 +213,8 @@ class ConnectionConfigController(QObject): if self.mode == ConnectionConfigController.REGISTER: await self.view.show_register_message(self.model.blockchain_parameters()) + await self.export_identity_document() + await self.action_save_revokation() except (NoPeerAvailable, DuniterError, StopIteration) as e: if not isinstance(e, StopIteration): self.view.show_error(self.model.notification(), str(e)) @@ -268,6 +271,42 @@ class ConnectionConfigController(QObject): self.view.label_info.setText("") return True + async def action_save_revokation(self): + raw_document = self.model.generate_revokation() + # Testable way of using a QFileDialog + selected_files = await QAsyncFileDialog.get_save_filename(self.view, self.tr("Save a revokation document"), + "", self.tr("All text files (*.txt)")) + if selected_files: + path = selected_files[0] + if not path.endswith('.txt'): + path = "{0}.txt".format(path) + with open(path, 'w') as save_file: + save_file.write(raw_document) + + dialog = QMessageBox(QMessageBox.Information, self.tr("Revokation file"), + self.tr("""<div>Your revokation document has been saved.</div> +<div><b>Please keep it in a safe place.</b></div> +The publication of this document will remove your identity from the network.</p>"""), QMessageBox.Ok) + dialog.setTextFormat(Qt.RichText) + await dialog_async_exec(dialog) + + async def export_identity_document(self): + identity, identity_doc = self.model.generate_identity() + selected_files = await QAsyncFileDialog.get_save_filename(self.view, self.tr("Save an identity document"), + "", self.tr("All text files (*.txt)")) + if selected_files: + path = selected_files[0] + if not path.endswith('.txt'): + path = "{0}.txt".format(path) + with open(path, 'w') as save_file: + save_file.write(identity_doc.signed_raw()) + + dialog = QMessageBox(QMessageBox.Information, self.tr("Identity file"), + self.tr("""<div>Your identity document has been saved.</div> +Share this document to your friends for them to certify you.</p>"""), QMessageBox.Ok) + dialog.setTextFormat(Qt.RichText) + await dialog_async_exec(dialog) + @asyncify async def check_pubkey(self, checked=False): self._logger.debug("Is valid ? ") diff --git a/src/sakia/gui/dialogs/connection_cfg/model.py b/src/sakia/gui/dialogs/connection_cfg/model.py index 28d9b1d4185a7af0f9365d1814c2ea0e6591c4b3..4f8567f443d5c678ab1db1c0923f04d4f2fbd09d 100644 --- a/src/sakia/gui/dialogs/connection_cfg/model.py +++ b/src/sakia/gui/dialogs/connection_cfg/model.py @@ -56,6 +56,14 @@ class ConnectionConfigModel(QObject): def insert_or_update_identity(self, identity): self.identities_processor.insert_or_update_identity(identity) + def generate_revokation(self): + return self.app.documents_service.generate_revokation(self.connection, + self.connection.salt, + self.connection.password) + + def generate_identity(self): + return self.app.documents_service.generate_identity(self.connection) + async def initialize_blockchain(self, log_stream): """ Download blockchain information locally diff --git a/tests/functional/test_connection_cfg_dialog.py b/tests/functional/test_connection_cfg_dialog.py index 792397f74e5654c11c3a382fa022ae33ed28ab19..d95180978130abed5f67132df681de2f768c1e1f 100644 --- a/tests/functional/test_connection_cfg_dialog.py +++ b/tests/functional/test_connection_cfg_dialog.py @@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt from PyQt5.QtTest import QTest from sakia.data.processors import ConnectionsProcessor from sakia.gui.dialogs.connection_cfg import ConnectionConfigController -from tests.helpers import click_on_top_message_box +from tests.helpers import click_on_top_message_box, select_file_dialog def assert_key_parameters_behaviour(connection_config_dialog, user): @@ -35,7 +35,10 @@ def assert_pubkey_parameters_behaviour(connection_config_dialog, user): @pytest.mark.asyncio -async def test_register_empty_blockchain(application, fake_server, bob): +async def test_register_empty_blockchain(application, fake_server, bob, tmpdir): + tmpdir.mkdir("test_register") + revocation_file = tmpdir.join("test_register").join("revocation.txt") + identity_file = tmpdir.join("test_register").join("identity.txt") connection_config_dialog = ConnectionConfigController.create_connection(None, application) def close_dialog(): @@ -56,6 +59,17 @@ async def test_register_empty_blockchain(application, fake_server, bob): assert connection_config_dialog.view.stacked_pages.currentWidget() == connection_config_dialog.view.page_services assert len(ConnectionsProcessor.instanciate(application).connections()) == 1 click_on_top_message_box() + await asyncio.sleep(1) + select_file_dialog(str(identity_file)) + await asyncio.sleep(1) + click_on_top_message_box() + identity_file.ensure() + await asyncio.sleep(1) + select_file_dialog(str(revocation_file)) + await asyncio.sleep(1) + click_on_top_message_box() + await asyncio.sleep(1) + revocation_file.ensure() application.loop.call_later(10, close_dialog) asyncio.ensure_future(exec_test()) diff --git a/tests/helpers.py b/tests/helpers.py index 74b83d37e6d0a9598bb2625bf58bc0b5690fdb7a..6e340a192f67ba608fcb3ce94536c62f7501e72d 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,4 +1,4 @@ -from PyQt5.QtWidgets import QApplication, QMessageBox, QDialog +from PyQt5.QtWidgets import QApplication, QMessageBox, QDialog, QFileDialog from PyQt5.QtCore import Qt from PyQt5.QtTest import QTest @@ -10,3 +10,12 @@ def click_on_top_message_box(): QTest.keyClick(w, Qt.Key_Enter) elif isinstance(w, QDialog) and w.windowTitle() == "Registration": QTest.keyClick(w, Qt.Key_Enter) + +def select_file_dialog(filename): + topWidgets = QApplication.topLevelWidgets() + for w in topWidgets: + if isinstance(w, QFileDialog) and w.isVisible(): + w.hide() + w.selectFile(filename) + w.show() + w.accept()