From b3a3a042d419f255978812f277ee483b0a4ff30f Mon Sep 17 00:00:00 2001
From: inso <insomniak.fr@gmaiL.com>
Date: Sat, 1 Oct 2016 01:39:56 +0200
Subject: [PATCH] Add key entity

---
 src/sakia/data/entities/__init__.py           |  1 +
 src/sakia/data/entities/connection.py         | 13 ++++
 src/sakia/data/repositories/__init__.py       |  1 +
 src/sakia/data/repositories/connections.py    | 76 +++++++++++++++++++
 src/sakia/data/repositories/meta.sql          |  8 ++
 .../tests/unit/data/test_connections_repo.py  | 32 ++++++++
 6 files changed, 131 insertions(+)
 create mode 100644 src/sakia/data/entities/connection.py
 create mode 100644 src/sakia/data/repositories/connections.py
 create mode 100644 src/sakia/tests/unit/data/test_connections_repo.py

diff --git a/src/sakia/data/entities/__init__.py b/src/sakia/data/entities/__init__.py
index 40b3174b..35265ddc 100644
--- a/src/sakia/data/entities/__init__.py
+++ b/src/sakia/data/entities/__init__.py
@@ -3,3 +3,4 @@ from .blockchain import Blockchain, BlockchainParameters
 from .certification import Certification
 from .transaction import Transaction
 from .node import Node
+from .connection import Connection
diff --git a/src/sakia/data/entities/connection.py b/src/sakia/data/entities/connection.py
new file mode 100644
index 00000000..b6042dcb
--- /dev/null
+++ b/src/sakia/data/entities/connection.py
@@ -0,0 +1,13 @@
+import attr
+
+
+@attr.s()
+class Connection:
+    """
+    A connection represents a connection to a currency's network
+    It is defined by the currency name, and the key informations
+    used to connect to it
+    """
+    currency = attr.ib(convert=str)
+    pubkey = attr.ib(convert=str)
+    salt = attr.ib(convert=str)
diff --git a/src/sakia/data/repositories/__init__.py b/src/sakia/data/repositories/__init__.py
index a7e8f366..cf14e2a6 100644
--- a/src/sakia/data/repositories/__init__.py
+++ b/src/sakia/data/repositories/__init__.py
@@ -4,3 +4,4 @@ from .meta import MetaDatabase
 from .certifications import CertificationsRepo
 from .transactions import TransactionsRepo
 from .nodes import NodesRepo
+from .connections import ConnectionsRepo
diff --git a/src/sakia/data/repositories/connections.py b/src/sakia/data/repositories/connections.py
new file mode 100644
index 00000000..11a53cde
--- /dev/null
+++ b/src/sakia/data/repositories/connections.py
@@ -0,0 +1,76 @@
+import attr
+
+from ..entities import Connection
+
+
+@attr.s(frozen=True)
+class ConnectionsRepo:
+    """
+    The repository for Connections entities.
+    """
+    _conn = attr.ib()  # :type sqlite3.Connection
+    _primary_connections = (Connection.currency, Connection.pubkey)
+
+    def insert(self, connection):
+        """
+        Commit a connection to the database
+        :param sakia.data.entities.Connection connection: the connection to commit
+        """
+        with self._conn:
+            connection_tuple = attr.astuple(connection)
+            values = ",".join(['?'] * len(connection_tuple))
+            self._conn.execute("INSERT INTO connections VALUES ({0})".format(values), connection_tuple)
+
+    def get_one(self, **search):
+        """
+        Get an existing connection in the database
+        :param dict search: the criterions of the lookup
+        :rtype: sakia.data.entities.Connection
+        """
+        with self._conn:
+            filters = []
+            values = []
+            for k, v in search.items():
+                filters.append("{k}=?".format(k=k))
+                values.append(v)
+
+            request = "SELECT * FROM connections WHERE {filters}".format(filters=" AND ".join(filters))
+
+            c = self._conn.execute(request, tuple(values))
+            data = c.fetchone()
+            if data:
+                return Connection(*data)
+
+    def get_all(self, **search):
+        """
+        Get all existing connection in the database corresponding to the search
+        :param dict search: the criterions of the lookup
+        :rtype: sakia.data.entities.Connection
+        """
+        with self._conn:
+            filters = []
+            values = []
+            for k, v in search.items():
+                value = v
+                filters.append("{connection} = ?".format(connection=k))
+                values.append(value)
+
+            request = "SELECT * FROM connections WHERE {filters}".format(filters=" AND ".join(filters))
+
+            c = self._conn.execute(request, tuple(values))
+            datas = c.fetchall()
+            if datas:
+                return [Connection(*data) for data in datas]
+        return []
+
+    def drop(self, connection):
+        """
+        Drop an existing connection from the database
+        :param sakia.data.entities.Connection connection: the connection to update
+        """
+        with self._conn:
+            where_fields = attr.astuple(connection, filter=attr.filters.include(*ConnectionsRepo._primary_connections))
+            self._conn.execute("""DELETE FROM connections
+                                  WHERE
+                                  currency=? AND
+                                  pubkey=?""", where_fields)
diff --git a/src/sakia/data/repositories/meta.sql b/src/sakia/data/repositories/meta.sql
index 4c9f3e1b..693aeea8 100644
--- a/src/sakia/data/repositories/meta.sql
+++ b/src/sakia/data/repositories/meta.sql
@@ -92,3 +92,11 @@ CREATE TABLE IF NOT EXISTS nodes(
                                root                 BOOLEAN,
                                PRIMARY KEY (currency, pubkey)
                                );
+
+-- Keys TABLE
+CREATE TABLE IF NOT EXISTS connections(
+                               currency           VARCHAR(30),
+                               pubkey             VARCHAR(50),
+                               salt               VARCHAR(50),
+                               PRIMARY KEY (currency, pubkey)
+                               );
diff --git a/src/sakia/tests/unit/data/test_connections_repo.py b/src/sakia/tests/unit/data/test_connections_repo.py
new file mode 100644
index 00000000..b70d4164
--- /dev/null
+++ b/src/sakia/tests/unit/data/test_connections_repo.py
@@ -0,0 +1,32 @@
+from sakia.data.repositories import ConnectionsRepo, MetaDatabase
+from sakia.data.entities import Connection
+from duniterpy.documents import BlockUID
+import unittest
+import sqlite3
+
+
+class TestConnectionsRepo(unittest.TestCase):
+    def setUp(self):
+        self.meta_repo = MetaDatabase.create(":memory:")
+        self.meta_repo.prepare()
+        self.meta_repo.upgrade_database()
+
+    def tearDown(self):
+        pass
+
+    def test_add_get_drop_connection(self):
+        connections_repo = ConnectionsRepo(self.meta_repo.conn)
+        connections_repo.insert(Connection("testcurrency",
+                                                 "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
+                                                 "somesalt"))
+        connection = connections_repo.get_one(currency="testcurrency",
+                                           pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
+                                           salt="somesalt")
+        self.assertEqual(connection.currency, "testcurrency")
+        self.assertEqual(connection.pubkey, "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ")
+        self.assertEqual(connection.salt, "somesalt")
+        connections_repo.drop(connection)
+        connection = connections_repo.get_one(currency="testcurrency",
+                                           pubkey="7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
+                                           salt="somesalt")
+        self.assertIsNone(connection)
-- 
GitLab