Skip to content
Snippets Groups Projects
Commit b83012d1 authored by inso's avatar inso
Browse files

Implementing the feature #214

parent 69922eef
No related branches found
No related tags found
No related merge requests found
...@@ -19,10 +19,11 @@ from . import money ...@@ -19,10 +19,11 @@ from . import money
from .wallet import Wallet from .wallet import Wallet
from .community import Community from .community import Community
from .registry import LocalState from .registry import LocalState
from ..tools.exceptions import ContactAlreadyExists from ..tools.exceptions import ContactAlreadyExists, NoPeerAvailable
from ..tools.decorators import asyncify from ..tools.decorators import asyncify
from ucoinpy.api import bma from ucoinpy.api import bma
from ucoinpy.api.bma import PROTOCOL_VERSION from ucoinpy.api.bma import PROTOCOL_VERSION
from aiohttp.errors import ClientError
class Account(QObject): class Account(QObject):
...@@ -270,6 +271,92 @@ class Account(QObject): ...@@ -270,6 +271,92 @@ class Account(QObject):
value += val value += val
return value return value
@asyncio.coroutine
def check_registered(self, community):
"""
Checks for the pubkey and the uid of an account in a community
:param cutecoin.core.Community community: The community we check for registration
:return: (True if found, local value, network value)
"""
def _parse_uid_certifiers(data):
return self.name == data['uid'], self.name, data['uid']
def _parse_uid_lookup(data):
timestamp = 0
found_uid = ""
for result in data['results']:
if result["pubkey"] == self.pubkey:
uids = result['uids']
for uid_data in uids:
if uid_data["meta"]["timestamp"] > timestamp:
timestamp = uid_data["meta"]["timestamp"]
found_uid = uid_data["uid"]
return self.name == found_uid, self.name, found_uid
def _parse_pubkey_certifiers(data):
return self.pubkey == data['pubkey'], self.pubkey, data['pubkey']
def _parse_pubkey_lookup(data):
timestamp = 0
found_uid = ""
found_result = ["", ""]
for result in data['results']:
uids = result['uids']
for uid_data in uids:
if uid_data["meta"]["timestamp"] > timestamp:
timestamp = uid_data["meta"]["timestamp"]
found_uid = uid_data["uid"]
if found_uid == self.name:
found_result = result['pubkey'], found_uid
if found_result[1] == self.name:
return self.pubkey == found_result[0], self.pubkey, found_result[0]
else:
return False, self.pubkey, None
@asyncio.coroutine
def execute_requests(parsers, search):
tries = 0
request = bma.wot.CertifiersOf
nonlocal registered
while tries < 3 and not registered[0] and not registered[2]:
try:
data = yield from community.bma_access.simple_request(request,
req_args={'search': search})
registered = parsers[request](data)
except ValueError as e:
if '404' in str(e) or '400' in str(e):
if request == bma.wot.CertifiersOf:
request = bma.wot.Lookup
tries = 0
else:
tries += 1
else:
tries += 1
except asyncio.TimeoutError:
tries += 1
except ClientError:
tries += 1
registered = (False, self.name, None)
# We execute search based on pubkey
# And look for account UID
uid_parsers = {
bma.wot.CertifiersOf: _parse_uid_certifiers,
bma.wot.Lookup: _parse_uid_lookup
}
yield from execute_requests(uid_parsers, self.pubkey)
# If the uid wasn't found when looking for the pubkey
# We look for the uid and check for the pubkey
if not registered[0] and not registered[2]:
pubkey_parsers = {
bma.wot.CertifiersOf: _parse_pubkey_certifiers,
bma.wot.Lookup: _parse_pubkey_lookup
}
yield from execute_requests(pubkey_parsers, self.name)
return registered
@asyncio.coroutine @asyncio.coroutine
def send_selfcert(self, password, community): def send_selfcert(self, password, community):
""" """
......
...@@ -86,7 +86,8 @@ class IdentitiesRegistry: ...@@ -86,7 +86,8 @@ class IdentitiesRegistry:
tries = 0 tries = 0
while tries < 3 and identity.local_state == LocalState.NOT_FOUND: while tries < 3 and identity.local_state == LocalState.NOT_FOUND:
try: try:
data = yield from community.bma_access.simple_request(bma.wot.CertifiersOf, req_args={'search': pubkey}) data = yield from community.bma_access.simple_request(bma.wot.CertifiersOf,
req_args={'search': pubkey})
identity.uid = data['uid'] identity.uid = data['uid']
identity.local_state = LocalState.PARTIAL identity.local_state = LocalState.PARTIAL
identity.blockchain_state = BlockchainState.VALIDATED identity.blockchain_state = BlockchainState.VALIDATED
......
...@@ -16,6 +16,7 @@ from ..models.peering import PeeringTreeModel ...@@ -16,6 +16,7 @@ from ..models.peering import PeeringTreeModel
from ..core import Community from ..core import Community
from ..core.registry.identity import BlockchainState from ..core.registry.identity import BlockchainState
from ..core.net import Node from ..core.net import Node
from ..tools.decorators import asyncify
from . import toast from . import toast
...@@ -62,9 +63,12 @@ class StepPageInit(Step): ...@@ -62,9 +63,12 @@ class StepPageInit(Step):
self.node = yield from Node.from_address(None, server, port) self.node = yield from Node.from_address(None, server, port)
if self.node: if self.node:
community = Community.create(self.node) community = Community.create(self.node)
identity = yield from self.app.identities_registry.future_find(self.account.pubkey, community) registered = yield from self.account.check_registered(community)
if identity.blockchain_state == BlockchainState.NOT_FOUND: if registered[0] is False and registered[2] is None:
self.config_dialog.label_error.setText(self.tr("Could not find your identity on the network.")) self.config_dialog.label_error.setText(self.tr("Could not find your identity on the network."))
elif registered[0] is False and registered[2]:
self.config_dialog.label_error.setText(self.tr("""Your pubkey or UID is different on the network.
Yours : {0}, the network : {1}""".format(registered[1], registered[2])))
else: else:
self.config_dialog.community = community self.config_dialog.community = community
self.config_dialog.next() self.config_dialog.next()
...@@ -84,8 +88,8 @@ class StepPageInit(Step): ...@@ -84,8 +88,8 @@ class StepPageInit(Step):
self.node = yield from Node.from_address(None, server, port) self.node = yield from Node.from_address(None, server, port)
if self.node: if self.node:
community = Community.create(self.node) community = Community.create(self.node)
identity = yield from self.app.identities_registry.future_find(self.account.pubkey, community) registered = yield from self.account.check_registered(community)
if identity.blockchain_state == BlockchainState.NOT_FOUND: if registered[0] is False and registered[2] is None:
password = yield from self.password_asker.async_exec() password = yield from self.password_asker.async_exec()
if self.password_asker.result() == QDialog.Rejected: if self.password_asker.result() == QDialog.Rejected:
return return
...@@ -102,10 +106,12 @@ class StepPageInit(Step): ...@@ -102,10 +106,12 @@ class StepPageInit(Step):
if self.app.preferences['notifications']: if self.app.preferences['notifications']:
toast.display(self.tr("Error"), self.tr("{0}".format(result[1]))) toast.display(self.tr("Error"), self.tr("{0}".format(result[1])))
QApplication.restoreOverrideCursor() QApplication.restoreOverrideCursor()
self.config_dialog.community = community self.config_dialog.community = community
elif registered[0] is False and registered[2]:
self.config_dialog.label_error.setText(self.tr("""Your pubkey or UID was already found on the network.
Yours : {0}, the network : {1}""".format(registered[1], registered[2])))
else: else:
self.config_dialog.label_error.setText(self.tr("Pubkey already exists on the network")) self.config_dialog.label_error.setText(self.tr("Your account already exists on the network"))
else: else:
self.config_dialog.label_error.setText(self.tr("Could not connect.")) self.config_dialog.label_error.setText(self.tr("Could not connect."))
......
...@@ -24,7 +24,7 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -24,7 +24,7 @@ class ProcessAddCommunity(unittest.TestCase):
QLocale.setDefault(QLocale("en_GB")) QLocale.setDefault(QLocale("en_GB"))
self.lp = quamash.QEventLoop(self.qapplication) self.lp = quamash.QEventLoop(self.qapplication)
asyncio.set_event_loop(self.lp) asyncio.set_event_loop(self.lp)
self.lp.set_exception_handler(lambda lp, ctx : unitttest_exception_handler(self, lp, ctx)) #self.lp.set_exception_handler(lambda lp, ctx : unitttest_exception_handler(self, lp, ctx))
self.identities_registry = IdentitiesRegistry({}) self.identities_registry = IdentitiesRegistry({})
self.application = Application(self.qapplication, self.lp, self.identities_registry) self.application = Application(self.qapplication, self.lp, self.identities_registry)
...@@ -32,7 +32,7 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -32,7 +32,7 @@ class ProcessAddCommunity(unittest.TestCase):
# Salt/password : "testcutecoin/testcutecoin" # Salt/password : "testcutecoin/testcutecoin"
# Pubkey : 7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ # Pubkey : 7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ
self.account = Account("testcutecoin", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ", self.account = Account("testcutecoin", "7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ",
"test", [], [], [], self.identities_registry) "john", [], [], [], self.identities_registry)
self.password_asker = PasswordAskerDialog(self.account) self.password_asker = PasswordAskerDialog(self.account)
self.password_asker.password = "testcutecoin" self.password_asker.password = "testcutecoin"
self.password_asker.remember = True self.password_asker.remember = True
...@@ -52,11 +52,6 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -52,11 +52,6 @@ class ProcessAddCommunity(unittest.TestCase):
self.account, self.account,
None, self.password_asker) None, self.password_asker)
@asyncio.coroutine
def open_dialog(process_community):
result = yield from process_community.async_exec()
self.assertEqual(result, QDialog.Accepted)
def close_dialog(): def close_dialog():
if process_community.isVisible(): if process_community.isVisible():
process_community.close() process_community.close()
...@@ -84,10 +79,17 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -84,10 +79,17 @@ class ProcessAddCommunity(unittest.TestCase):
self.assertEqual(mock.get_request(i).method, 'GET') self.assertEqual(mock.get_request(i).method, 'GET')
self.assertEqual(mock.get_request(i).url, self.assertEqual(mock.get_request(i).url,
'/wot/lookup/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ') '/wot/lookup/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ')
yield from asyncio.sleep(1) yield from asyncio.sleep(5)
self.assertEqual(mock.get_request(5).method, 'GET')
self.assertEqual(mock.get_request(5).url,
'/wot/certifiers-of/john')
for i in range(6, 9):
self.assertEqual(mock.get_request(i).method, 'GET')
self.assertEqual(mock.get_request(i).url,
'/wot/lookup/john')
self.assertEqual(mock.get_request(5).method, 'POST') self.assertEqual(mock.get_request(9).url[:8], '/wot/add')
self.assertEqual(mock.get_request(5).url[:8], '/wot/add') self.assertEqual(mock.get_request(9).method, 'POST')
self.assertEqual(process_community.label_error.text(), "Broadcasting identity...") self.assertEqual(process_community.label_error.text(), "Broadcasting identity...")
yield from asyncio.sleep(1) yield from asyncio.sleep(1)
...@@ -98,7 +100,8 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -98,7 +100,8 @@ class ProcessAddCommunity(unittest.TestCase):
self.lp.call_later(15, close_dialog) self.lp.call_later(15, close_dialog)
asyncio.async(exec_test()) asyncio.async(exec_test())
self.lp.run_until_complete(open_dialog(process_community)) self.lp.run_until_complete(process_community.async_exec())
self.assertEqual(process_community.result(), QDialog.Accepted)
mock.delete_mock() mock.delete_mock()
def test_connect_community_empty_blockchain(self): def test_connect_community_empty_blockchain(self):
...@@ -110,11 +113,6 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -110,11 +113,6 @@ class ProcessAddCommunity(unittest.TestCase):
self.account, self.account,
None, self.password_asker) None, self.password_asker)
@asyncio.coroutine
def open_dialog(process_community):
result = yield from process_community.async_exec()
self.assertEqual(result, QDialog.Rejected)
def close_dialog(): def close_dialog():
if process_community.isVisible(): if process_community.isVisible():
process_community.close() process_community.close()
...@@ -132,9 +130,11 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -132,9 +130,11 @@ class ProcessAddCommunity(unittest.TestCase):
self.assertEqual(process_community.lineedit_server.text(), "127.0.0.1") self.assertEqual(process_community.lineedit_server.text(), "127.0.0.1")
self.assertEqual(process_community.spinbox_port.value(), 50000) self.assertEqual(process_community.spinbox_port.value(), 50000)
QTest.mouseClick(process_community.button_connect, Qt.LeftButton) QTest.mouseClick(process_community.button_connect, Qt.LeftButton)
yield from asyncio.sleep(1) yield from asyncio.sleep(3)
self.assertNotEqual(mock.get_request(0), None)
self.assertEqual(mock.get_request(0).method, 'GET') self.assertEqual(mock.get_request(0).method, 'GET')
self.assertEqual(mock.get_request(0).url, '/network/peering') self.assertEqual(mock.get_request(0).url, '/network/peering')
self.assertNotEqual(mock.get_request(1), None)
self.assertEqual(mock.get_request(1).method, 'GET') self.assertEqual(mock.get_request(1).method, 'GET')
self.assertEqual(mock.get_request(1).url, self.assertEqual(mock.get_request(1).url,
'/wot/certifiers-of/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ') '/wot/certifiers-of/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ')
...@@ -150,22 +150,107 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -150,22 +150,107 @@ class ProcessAddCommunity(unittest.TestCase):
self.lp.call_later(15, close_dialog) self.lp.call_later(15, close_dialog)
asyncio.async(exec_test()) asyncio.async(exec_test())
self.lp.run_until_complete(open_dialog(process_community)) self.lp.run_until_complete(process_community.async_exec())
mock.delete_mock() mock.delete_mock()
def test_connect_community_nice_blockchain(self): def test_connect_community_wrong_pubkey(self):
mock = nice_blockchain.get_mock() mock = nice_blockchain.get_mock()
time.sleep(2) time.sleep(2)
logging.debug(mock.pretend_url) logging.debug(mock.pretend_url)
API.reverse_url = pretender_reversed(mock.pretend_url) API.reverse_url = pretender_reversed(mock.pretend_url)
self.account.pubkey = "wrong_pubkey"
process_community = ProcessConfigureCommunity(self.application, process_community = ProcessConfigureCommunity(self.application,
self.account, self.account,
None, self.password_asker) None, self.password_asker)
def close_dialog():
if process_community.isVisible():
process_community.close()
@asyncio.coroutine @asyncio.coroutine
def open_dialog(process_community): def exec_test():
result = yield from process_community.async_exec() yield from asyncio.sleep(1)
self.assertEqual(result, QDialog.Accepted) QTest.mouseClick(process_community.lineedit_server, Qt.LeftButton)
QTest.keyClicks(process_community.lineedit_server, "127.0.0.1")
QTest.mouseDClick(process_community.spinbox_port, Qt.LeftButton)
process_community.spinbox_port.setValue(50000)
self.assertEqual(process_community.stacked_pages.currentWidget(),
process_community.page_node,
msg="Current widget : {0}".format(process_community.stacked_pages.currentWidget().objectName()))
self.assertEqual(process_community.lineedit_server.text(), "127.0.0.1")
self.assertEqual(process_community.spinbox_port.value(), 50000)
QTest.mouseClick(process_community.button_connect, Qt.LeftButton)
yield from asyncio.sleep(1)
self.assertNotEqual(mock.get_request(0), None)
self.assertEqual(mock.get_request(0).method, 'GET')
self.assertEqual(mock.get_request(0).url, '/network/peering')
self.assertNotEqual(mock.get_request(1), None)
self.assertEqual(mock.get_request(1).method, 'GET')
self.assertEqual(mock.get_request(1).url,
'/wot/certifiers-of/wrong_pubkey')
self.assertEqual(process_community.label_error.text(), """Your pubkey or UID is different on the network.
Yours : wrong_pubkey, the network : 7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ""")
process_community.close()
self.lp.call_later(15, close_dialog)
asyncio.async(exec_test())
self.lp.run_until_complete(process_community.async_exec())
self.assertEqual(process_community.result(), QDialog.Rejected)
mock.delete_mock()
def test_connect_community_wrong_uid(self):
mock = nice_blockchain.get_mock()
time.sleep(2)
logging.debug(mock.pretend_url)
API.reverse_url = pretender_reversed(mock.pretend_url)
self.account.name = "wrong_uid"
process_community = ProcessConfigureCommunity(self.application,
self.account,
None, self.password_asker)
def close_dialog():
if process_community.isVisible():
process_community.close()
@asyncio.coroutine
def exec_test():
yield from asyncio.sleep(1)
QTest.mouseClick(process_community.lineedit_server, Qt.LeftButton)
QTest.keyClicks(process_community.lineedit_server, "127.0.0.1")
QTest.mouseDClick(process_community.spinbox_port, Qt.LeftButton)
process_community.spinbox_port.setValue(50000)
self.assertEqual(process_community.stacked_pages.currentWidget(),
process_community.page_node,
msg="Current widget : {0}".format(process_community.stacked_pages.currentWidget().objectName()))
self.assertEqual(process_community.lineedit_server.text(), "127.0.0.1")
self.assertEqual(process_community.spinbox_port.value(), 50000)
QTest.mouseClick(process_community.button_connect, Qt.LeftButton)
yield from asyncio.sleep(1)
self.assertNotEqual(mock.get_request(0), None)
self.assertEqual(mock.get_request(0).method, 'GET')
self.assertEqual(mock.get_request(0).url, '/network/peering')
self.assertNotEqual(mock.get_request(1), None)
self.assertEqual(mock.get_request(1).method, 'GET')
self.assertEqual(mock.get_request(1).url,
'/wot/certifiers-of/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ')
self.assertEqual(process_community.label_error.text(), """Your pubkey or UID is different on the network.
Yours : wrong_uid, the network : john""")
process_community.close()
self.lp.call_later(15, close_dialog)
asyncio.async(exec_test())
self.lp.run_until_complete(process_community.async_exec())
self.assertEqual(process_community.result(), QDialog.Rejected)
mock.delete_mock()
def test_connect_community_success(self):
mock = nice_blockchain.get_mock()
time.sleep(2)
logging.debug(mock.pretend_url)
API.reverse_url = pretender_reversed(mock.pretend_url)
process_community = ProcessConfigureCommunity(self.application,
self.account,
None, self.password_asker)
def close_dialog(): def close_dialog():
if process_community.isVisible(): if process_community.isVisible():
...@@ -185,8 +270,10 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -185,8 +270,10 @@ class ProcessAddCommunity(unittest.TestCase):
self.assertEqual(process_community.spinbox_port.value(), 50000) self.assertEqual(process_community.spinbox_port.value(), 50000)
QTest.mouseClick(process_community.button_connect, Qt.LeftButton) QTest.mouseClick(process_community.button_connect, Qt.LeftButton)
yield from asyncio.sleep(1) yield from asyncio.sleep(1)
self.assertNotEqual(mock.get_request(0), None)
self.assertEqual(mock.get_request(0).method, 'GET') self.assertEqual(mock.get_request(0).method, 'GET')
self.assertEqual(mock.get_request(0).url, '/network/peering') self.assertEqual(mock.get_request(0).url, '/network/peering')
self.assertNotEqual(mock.get_request(1), None)
self.assertEqual(mock.get_request(1).method, 'GET') self.assertEqual(mock.get_request(1).method, 'GET')
self.assertEqual(mock.get_request(1).url, self.assertEqual(mock.get_request(1).url,
'/wot/certifiers-of/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ') '/wot/certifiers-of/7Aqw6Efa9EzE7gtsc8SveLLrM7gm6NEGoywSv4FJx6pZ')
...@@ -197,7 +284,7 @@ class ProcessAddCommunity(unittest.TestCase): ...@@ -197,7 +284,7 @@ class ProcessAddCommunity(unittest.TestCase):
self.lp.call_later(15, close_dialog) self.lp.call_later(15, close_dialog)
asyncio.async(exec_test()) asyncio.async(exec_test())
self.lp.run_until_complete(open_dialog(process_community)) self.lp.run_until_complete(process_community.async_exec())
mock.delete_mock() mock.delete_mock()
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -24,7 +24,7 @@ def unitttest_exception_handler(test, loop, context): ...@@ -24,7 +24,7 @@ def unitttest_exception_handler(test, loop, context):
for key in [k for k in sorted(context) if k not in {'message', 'exception'}]: for key in [k for k in sorted(context) if k not in {'message', 'exception'}]:
log_lines.append('{}: {!r}'.format(key, context[key])) log_lines.append('{}: {!r}'.format(key, context[key]))
test.failureException('\n'.join(log_lines)) test.fail('\n'.join(log_lines))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment