From caea8de0811a5df6fc898d8fbab2724831b248bf Mon Sep 17 00:00:00 2001
From: inso <insomniak.fr@gmail.com>
Date: Tue, 10 Jan 2017 08:23:08 +0100
Subject: [PATCH] Handle proxy

---
 src/sakia/app.py                              |  6 +-
 src/sakia/data/connectors/bma.py              |  7 +-
 src/sakia/data/connectors/node.py             |  8 +--
 src/sakia/data/entities/user_parameters.py    |  4 ++
 src/sakia/data/processors/blockchain.py       |  2 +-
 src/sakia/data/processors/certifications.py   |  2 +-
 src/sakia/data/processors/dividends.py        |  2 +-
 src/sakia/data/processors/identities.py       |  2 +-
 src/sakia/data/processors/sources.py          |  2 +-
 src/sakia/data/processors/transactions.py     |  2 +-
 .../gui/dialogs/connection_cfg/controller.py  |  3 +-
 src/sakia/gui/dialogs/connection_cfg/model.py |  6 +-
 src/sakia/gui/dialogs/revocation/model.py     |  2 +-
 src/sakia/gui/import_account.py               | 71 -------------------
 src/sakia/services/documents.py               |  2 +-
 .../functional/test_certification_dialog.py   |  1 -
 16 files changed, 28 insertions(+), 94 deletions(-)
 delete mode 100644 src/sakia/gui/import_account.py

diff --git a/src/sakia/app.py b/src/sakia/app.py
index eb160b03..fa83118f 100644
--- a/src/sakia/app.py
+++ b/src/sakia/app.py
@@ -97,7 +97,7 @@ class Application(QObject):
 
     def instanciate_services(self):
         nodes_processor = NodesProcessor(self.db.nodes_repo)
-        bma_connector = BmaConnector(nodes_processor)
+        bma_connector = BmaConnector(nodes_processor, self.parameters)
         connections_processor = ConnectionsProcessor(self.db.connections_repo)
         identities_processor = IdentitiesProcessor(self.db.identities_repo, self.db.blockchains_repo, bma_connector)
         certs_processor = CertificationsProcessor(self.db.certifications_repo, self.db.identities_repo, bma_connector)
@@ -165,10 +165,6 @@ class Application(QObject):
 
     @asyncify
     async def get_last_version(self):
-        if self.parameters.enable_proxy is True:
-            proxy = "http://{0}:{1}".format(self.parameters.proxy_address, self.parameters.proxy_port)
-        else:
-            proxy = None
         try:
             with aiohttp.ClientSession() as session:
                 with aiohttp.Timeout(15):
diff --git a/src/sakia/data/connectors/bma.py b/src/sakia/data/connectors/bma.py
index a0f63c8a..6058a145 100644
--- a/src/sakia/data/connectors/bma.py
+++ b/src/sakia/data/connectors/bma.py
@@ -18,6 +18,7 @@ class BmaConnector:
     This class is used to access BMA API.
     """
     _nodes_processor = attr.ib()
+    _user_parameters = attr.ib()
     _logger = attr.ib(default=attr.Factory(lambda: logging.getLogger('sakia')))
 
     def filter_endpoints(self, request, nodes):
@@ -59,7 +60,7 @@ class BmaConnector:
             try:
                 self._logger.debug("Requesting {0} on endpoint {1}".format(str(request.__name__), str(endpoint)))
                 async with aiohttp.ClientSession() as session:
-                    json_data = await request(endpoint.conn_handler(session), **req_args)
+                    json_data = await request(endpoint.conn_handler(session, proxy=self._user_parameters.proxy()), **req_args)
                     return json_data
             except (ClientError, ServerDisconnectedError, gaierror,
                     asyncio.TimeoutError, ValueError, jsonschema.ValidationError) as e:
@@ -89,7 +90,9 @@ class BmaConnector:
             with aiohttp.ClientSession() as session:
                 for endpoint in endpoints:
                     self._logger.debug("Trying to connect to : " + str(endpoint))
-                    reply = asyncio.ensure_future(request(endpoint.conn_handler(session), **req_args))
+                    reply = asyncio.ensure_future(request(endpoint.conn_handler(session,
+                                                                                proxy=self._user_parameters.proxy()),
+                                                          **req_args))
                     replies.append(reply)
 
                 result = await asyncio.gather(*replies, return_exceptions=True)
diff --git a/src/sakia/data/connectors/node.py b/src/sakia/data/connectors/node.py
index 75ec387b..e96a3793 100644
--- a/src/sakia/data/connectors/node.py
+++ b/src/sakia/data/connectors/node.py
@@ -46,7 +46,7 @@ class NodeConnector(QObject):
                 ws.cancel()
 
     @classmethod
-    async def from_address(cls, currency, secured, address, port):
+    async def from_address(cls, currency, secured, address, port, proxy):
         """
         Factory method to get a node from a given address
         :param str currency: The node currency. None if we don't know\
@@ -61,7 +61,7 @@ class NodeConnector(QObject):
         http_scheme = "https" if secured else "http"
         ws_scheme = "ws" if secured else "wss"
         session = aiohttp.ClientSession()
-        peer_data = await bma.network.peering(ConnectionHandler(http_scheme, ws_scheme, address, port, session))
+        peer_data = await bma.network.peering(ConnectionHandler(http_scheme, ws_scheme, address, port, proxy, session))
 
         peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'],
                                                       peer_data['signature']))
@@ -92,9 +92,9 @@ class NodeConnector(QObject):
 
         return cls(node, None)
 
-    async def safe_request(self, endpoint, request, req_args={}):
+    async def safe_request(self, endpoint, request, proxy, req_args={}):
         try:
-            conn_handler = endpoint.conn_handler(self.session)
+            conn_handler = endpoint.conn_handler(self.session, proxy=proxy)
             data = await request(conn_handler, **req_args)
             return data
         except (ClientError, gaierror, TimeoutError, ConnectionRefusedError, DisconnectedError, ValueError) as e:
diff --git a/src/sakia/data/entities/user_parameters.py b/src/sakia/data/entities/user_parameters.py
index 2a270bde..2154f720 100644
--- a/src/sakia/data/entities/user_parameters.py
+++ b/src/sakia/data/entities/user_parameters.py
@@ -19,3 +19,7 @@ class UserParameters:
     proxy_port = attr.ib(convert=int, default=8080)
     international_system_of_units = attr.ib(convert=int, default=False)
     forgetfulness = attr.ib(convert=bool, default=True)
+
+    def proxy(self):
+        if self.enable_proxy is True:
+            return "http://{0}:{1}".format(self.proxy_address, self.proxy_port)
diff --git a/src/sakia/data/processors/blockchain.py b/src/sakia/data/processors/blockchain.py
index b1c6bd50..58077691 100644
--- a/src/sakia/data/processors/blockchain.py
+++ b/src/sakia/data/processors/blockchain.py
@@ -22,7 +22,7 @@ class BlockchainProcessor:
         :param sakia.app.Application app: the app
         """
         return cls(app.db.blockchains_repo,
-                   BmaConnector(NodesProcessor(app.db.nodes_repo)))
+                   BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
     async def timestamp(self, currency, blockstamp):
         try:
diff --git a/src/sakia/data/processors/certifications.py b/src/sakia/data/processors/certifications.py
index e8efe90a..78979327 100644
--- a/src/sakia/data/processors/certifications.py
+++ b/src/sakia/data/processors/certifications.py
@@ -24,7 +24,7 @@ class CertificationsProcessor:
         :param sakia.app.Application app: the app
         """
         return cls(app.db.certifications_repo, app.db.identities_repo,
-                   BmaConnector(NodesProcessor(app.db.nodes_repo)))
+                   BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
     def certifications_sent(self, currency, pubkey):
         """
diff --git a/src/sakia/data/processors/dividends.py b/src/sakia/data/processors/dividends.py
index 3a820666..ed37c7b3 100644
--- a/src/sakia/data/processors/dividends.py
+++ b/src/sakia/data/processors/dividends.py
@@ -25,7 +25,7 @@ class DividendsProcessor:
         :param sakia.app.Application app: the app
         """
         return cls(app.db.dividends_repo,
-                   BmaConnector(NodesProcessor(app.db.nodes_repo)))
+                   BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
     def commit(self, dividend):
         try:
diff --git a/src/sakia/data/processors/identities.py b/src/sakia/data/processors/identities.py
index b543492b..09875783 100644
--- a/src/sakia/data/processors/identities.py
+++ b/src/sakia/data/processors/identities.py
@@ -27,7 +27,7 @@ class IdentitiesProcessor:
         :param sakia.app.Application app: the app
         """
         return cls(app.db.identities_repo, app.db.blockchains_repo,
-                   BmaConnector(NodesProcessor(app.db.nodes_repo)))
+                   BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
     async def find_from_pubkey(self, currency, pubkey):
         """
diff --git a/src/sakia/data/processors/sources.py b/src/sakia/data/processors/sources.py
index 5477ff7a..fe7cc72d 100644
--- a/src/sakia/data/processors/sources.py
+++ b/src/sakia/data/processors/sources.py
@@ -23,7 +23,7 @@ class SourcesProcessor:
         :param sakia.app.Application app: the app
         """
         return cls(app.db.sources_repo,
-                   BmaConnector(NodesProcessor(app.db.nodes_repo)))
+                   BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
     async def initialize_sources(self, currency, pubkey, log_stream):
         """
diff --git a/src/sakia/data/processors/transactions.py b/src/sakia/data/processors/transactions.py
index f3cad890..8eb6dc53 100644
--- a/src/sakia/data/processors/transactions.py
+++ b/src/sakia/data/processors/transactions.py
@@ -25,7 +25,7 @@ class TransactionsProcessor:
         :param sakia.app.Application app: the app
         """
         return cls(app.db.transactions_repo,
-                   BmaConnector(NodesProcessor(app.db.nodes_repo)))
+                   BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters))
 
     def next_txid(self, currency, block_number):
         """
diff --git a/src/sakia/gui/dialogs/connection_cfg/controller.py b/src/sakia/gui/dialogs/connection_cfg/controller.py
index 74af0601..d5d8f73f 100644
--- a/src/sakia/gui/dialogs/connection_cfg/controller.py
+++ b/src/sakia/gui/dialogs/connection_cfg/controller.py
@@ -59,7 +59,8 @@ class ConnectionConfigController(QObject):
         view = ConnectionConfigView(parent.view if parent else None)
         model = ConnectionConfigModel(None, app, None,
                                       IdentitiesProcessor(app.db.identities_repo, app.db.blockchains_repo,
-                                                          BmaConnector(NodesProcessor(app.db.nodes_repo))))
+                                                          BmaConnector(NodesProcessor(app.db.nodes_repo),
+                                                                       app.parameters)))
         account_cfg = cls(parent, view, model)
         model.setParent(account_cfg)
         return account_cfg
diff --git a/src/sakia/gui/dialogs/connection_cfg/model.py b/src/sakia/gui/dialogs/connection_cfg/model.py
index 322b1012..48420919 100644
--- a/src/sakia/gui/dialogs/connection_cfg/model.py
+++ b/src/sakia/gui/dialogs/connection_cfg/model.py
@@ -30,7 +30,8 @@ class ConnectionConfigModel(QObject):
         self.identities_processor = identities_processor
 
     async def create_connection(self, server, port, secured):
-        self.node_connector = await NodeConnector.from_address(None, secured, server, port)
+        self.node_connector = await NodeConnector.from_address(None, secured, server, port,
+                                                               proxy=self.app.parameters.proxy())
         self.connection = Connection(self.node_connector.node.currency, "", "")
         self.node_connector.node.state = Node.ONLINE
 
@@ -167,7 +168,8 @@ class ConnectionConfigModel(QObject):
                 if not registered[0] and not registered[2]:
                     try:
                         data = await self.node_connector.safe_request(endpoint, bma.wot.lookup,
-                                                                      req_args={'search': search})
+                                                                      req_args={'search': search},
+                                                                      proxy=self.app.parameters.proxy())
                         if data:
                             registered = parser(data)
                         tries += 1
diff --git a/src/sakia/gui/dialogs/revocation/model.py b/src/sakia/gui/dialogs/revocation/model.py
index 968f6f93..3d7af2f2 100644
--- a/src/sakia/gui/dialogs/revocation/model.py
+++ b/src/sakia/gui/dialogs/revocation/model.py
@@ -52,7 +52,7 @@ class RevocationModel(QObject):
     async def send_to_node(self, server, port):
         session = aiohttp.ClientSession()
         try:
-            node = await Node.from_address(None, server, port, session=session)
+            node = await Node.from_address(None, server, port, proxy=self.app.parameters.proxy(), session=session)
             conn_handler = node.endpoint.conn_handler()
             await bma.wot.Revoke(conn_handler).post(session,
                                                     revocation=self.revocation_document.signed_raw(
diff --git a/src/sakia/gui/import_account.py b/src/sakia/gui/import_account.py
deleted file mode 100644
index 3c3d6e36..00000000
--- a/src/sakia/gui/import_account.py
+++ /dev/null
@@ -1,71 +0,0 @@
-"""
-Created on 22 mai 2014
-
-@author: inso
-"""
-import re
-from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox, QFileDialog
-
-from ..tools.exceptions import Error
-from ..presentation.import_account_uic import Ui_ImportAccountDialog
-
-
-class ImportAccountDialog(QDialog, Ui_ImportAccountDialog):
-
-    """
-    classdocs
-    """
-
-    def __init__(self, app, parent=None):
-        """
-        Constructor
-        """
-        super().__init__()
-        self.setupUi(self)
-        self.app = app
-        self.main_window = parent
-        self.selected_file = ""
-        self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
-
-    def accept(self):
-        account_name = self.edit_name.text()
-        try:
-            self.app.import_account(self.selected_file, account_name)
-        except Exception as e:
-            QMessageBox.critical(self, self.tr("Error"),
-                                 "{0}".format(e),
-                                 QMessageBox.Ok)
-            return
-        QMessageBox.information(self, self.tr("Account import"),
-                                self.tr("Account imported succefully !"))
-        super().accept()
-
-    def import_account(self):
-        self.selected_file = QFileDialog.getOpenFileName(self,
-                                          self.tr("Import an account file"),
-                                          "",
-                                          self.tr("All account files (*.acc)"))
-        self.selected_file = self.selected_file[0]
-        self.edit_file.setText(self.selected_file)
-        self.check()
-
-    def name_changed(self):
-        self.check()
-
-    def check(self):
-        name = self.edit_name.text()
-        if name == "":
-            self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
-            self.label_errors.setText(self.tr("Please enter a name"))
-            return
-        for account in self.app.accounts:
-            if name == account:
-                self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
-                self.label_errors.setText(self.tr("Name already exists"))
-                return
-        if self.selected_file[-4:] != ".acc":
-            self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
-            self.label_errors.setText(self.tr("File is not an account format"))
-            return
-        self.label_errors.setText("")
-        self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
diff --git a/src/sakia/services/documents.py b/src/sakia/services/documents.py
index 4f1e4515..c6acc1bb 100644
--- a/src/sakia/services/documents.py
+++ b/src/sakia/services/documents.py
@@ -45,7 +45,7 @@ class DocumentsService:
         Instanciate a blockchain processor
         :param sakia.app.Application app: the app
         """
-        return cls(BmaConnector(NodesProcessor(app.db.nodes_repo)),
+        return cls(BmaConnector(NodesProcessor(app.db.nodes_repo), app.parameters),
                    BlockchainProcessor.instanciate(app),
                    IdentitiesProcessor.instanciate(app),
                    TransactionsProcessor.instanciate(app),
diff --git a/src/sakia/tests/functional/test_certification_dialog.py b/src/sakia/tests/functional/test_certification_dialog.py
index db32d6d3..0dbd1e0c 100644
--- a/src/sakia/tests/functional/test_certification_dialog.py
+++ b/src/sakia/tests/functional/test_certification_dialog.py
@@ -4,7 +4,6 @@ from duniterpy.documents import Certification
 from PyQt5.QtCore import QLocale, Qt, QEvent
 from PyQt5.QtTest import QTest
 from PyQt5.QtWidgets import QDialogButtonBox, QApplication, QMessageBox
-from PyQt5.QtGui import QKeyEvent
 from sakia.gui.dialogs.certification.controller import CertificationController
 
 
-- 
GitLab