From 1de5510680927bcec16f94296ffcb48a0b4bf209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Val=C3=A9rio?= Date: Mon, 6 Jan 2020 17:24:27 +0000 Subject: [PATCH] MoneroAddressBackend now handles extra keyword arguments that might be provided. Also added more tests --- HISTORY.rst | 2 + django_cryptolock/backends.py | 5 ++- tests/test_backends.py | 77 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 tests/test_backends.py diff --git a/HISTORY.rst b/HISTORY.rst index caaada2..43a7196 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -11,6 +11,8 @@ History * Update quickstart guide. * Update instructions to contribute to the project. * Add ``DJCL`` namespace to all related settings. +* MoneroAddressBackend is now executed when more parameters are added to the + ``authenticate`` function. 0.0.1 (2019-11-25) ++++++++++++++++++ diff --git a/django_cryptolock/backends.py b/django_cryptolock/backends.py index cc022a4..4465072 100644 --- a/django_cryptolock/backends.py +++ b/django_cryptolock/backends.py @@ -14,7 +14,9 @@ User = get_user_model() class MoneroAddressBackend(ModelBackend): """Custom Monero-Cryptolock authentication backend.""" - def authenticate(self, request, address=None, challenge=None, signature=None): + def authenticate( + self, request, address=None, challenge=None, signature=None, **kwargs + ): """Validates the provided signature for the given address and challenge. This method currently relies on Wallet RPC access to verify the signature, @@ -29,7 +31,6 @@ class MoneroAddressBackend(ModelBackend): ) if not stored_address: return None - try: is_valid = verify_signature(address, challenge, signature) except JSONRPCException: diff --git a/tests/test_backends.py b/tests/test_backends.py new file mode 100644 index 0000000..b9b1c46 --- /dev/null +++ b/tests/test_backends.py @@ -0,0 +1,77 @@ +from unittest.mock import MagicMock, patch + +from django.contrib.auth import authenticate +from django.contrib.auth import get_user_model +from django.core.exceptions import PermissionDenied + +import pytest +from model_mommy import mommy + +from django_cryptolock.models import Address + +VALID_ADDRESS = "46fYuhPAdsxMbEeMg97LhSbFPamdiCw7C6b19VEcZSmV6xboWFZuZQ9MTbj1wLszhUExHi63CMtsWjDTrRDqegZiPVebgYq" +User = get_user_model() + +pytestmark = pytest.mark.django_db + +DUMMY_CREDS = {"username": "test", "password": "insecure"} + + +@pytest.fixture +def existing_user(): + return User.objects.create_user(**DUMMY_CREDS) + + +def test_monero_backend_receives_insuficient_data(existing_user): + user = authenticate(MagicMock(), username="test") + assert user is None + + +def test_monero_backend_lets_the_next_backend_to_be_used(existing_user): + user = authenticate(MagicMock(), **DUMMY_CREDS) + assert user is not None + + +def test_monero_backend_does_not_find_address(existing_user): + user = authenticate( + MagicMock(), address=VALID_ADDRESS, challeng="1", signature="somesig" + ) + assert user is None + + +def test_monero_backend_cannot_connect_to_RPC(existing_user): + mommy.make(Address, address=VALID_ADDRESS, user=existing_user) + + user = authenticate( + MagicMock(), + address=VALID_ADDRESS, + challenge="1", + signature="invalid sig", + **DUMMY_CREDS + ) + + assert user is None + + +def test_monero_backend_invalid_signature(existing_user): + mommy.make(Address, address=VALID_ADDRESS, user=existing_user) + + with patch("django_cryptolock.backends.verify_signature") as verify_mock: + verify_mock.return_value = False + user = authenticate( + MagicMock(), address=VALID_ADDRESS, challenge="1", signature="invalid sig" + ) + + assert user is None + + +def test_monero_backed_valid_signature(existing_user): + mommy.make(Address, address=VALID_ADDRESS, user=existing_user) + + with patch("django_cryptolock.backends.verify_signature") as verify_mock: + verify_mock.return_value = True + user = authenticate( + MagicMock(), address=VALID_ADDRESS, challenge="1", signature="valid sig" + ) + + assert user == existing_user