diff --git a/.gitignore b/.gitignore index 1d86873..8c6bcaa 100644 --- a/.gitignore +++ b/.gitignore @@ -49,5 +49,8 @@ docs/_build # Editors .vscode +# Pytest +.pytest_cache + # Project specific example/db.sqlite3 diff --git a/django_cryptolock/migrations/0001_initial.py b/django_cryptolock/migrations/0001_initial.py index 4a58877..7604568 100644 --- a/django_cryptolock/migrations/0001_initial.py +++ b/django_cryptolock/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.5 on 2019-10-15 14:37 +# Generated by Django 2.2.5 on 2019-10-15 17:25 from django.conf import settings from django.db import migrations, models @@ -23,7 +23,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('address', models.CharField(max_length=106, validators=[django_cryptolock.validators.validate_monero_address])), + ('address', models.CharField(max_length=106, unique=True, validators=[django_cryptolock.validators.validate_monero_address])), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ diff --git a/django_cryptolock/migrations/0002_auto_20191015_1141.py b/django_cryptolock/migrations/0002_auto_20191015_1141.py deleted file mode 100644 index 33eb58a..0000000 --- a/django_cryptolock/migrations/0002_auto_20191015_1141.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.5 on 2019-10-15 16:41 - -from django.conf import settings -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('django_cryptolock', '0001_initial'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='address', - unique_together={('user', 'address')}, - ), - ] diff --git a/django_cryptolock/models.py b/django_cryptolock/models.py index 982c157..9d7c806 100644 --- a/django_cryptolock/models.py +++ b/django_cryptolock/models.py @@ -13,14 +13,15 @@ class Address(TimeStampedModel): """Addresses that belong to a given user account.""" user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) - address = models.CharField(max_length=106, validators=[validate_monero_address]) + address = models.CharField( + max_length=106, validators=[validate_monero_address], unique=True + ) class Meta: """Meta definition for Address.""" verbose_name = _("Address") verbose_name_plural = _("Addresses") - unique_together = ["user", "address"] def __str__(self): """Unicode representation of Address.""" diff --git a/django_cryptolock/validators.py b/django_cryptolock/validators.py index 2f7afe6..9d5a80e 100644 --- a/django_cryptolock/validators.py +++ b/django_cryptolock/validators.py @@ -13,7 +13,7 @@ def validate_monero_address(value): _("%(value)s is not a valid address"), params={"value": value} ) - network = getattr(settings, "MONERO_NETWORK", None) + network = getattr(settings, "DJCL_MONERO_NETWORK", None) if not network: raise ValidationError( _("Please configure the monero network in the settings file") diff --git a/requirements_test.txt b/requirements_test.txt index 8c5c538..54c17ff 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -8,3 +8,4 @@ coveralls pytest pytest-django pytest-cov +model_mommy diff --git a/tests/settings.py b/tests/settings.py index e8e4bed..e32e56d 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -27,6 +27,15 @@ if django.VERSION >= (1, 10): else: MIDDLEWARE_CLASSES = () -MONERO_WALLET_RPC_HOST = "localhost:3030" -MONERO_WALLET_RPC_USER = "test" -MONERO_WALLET_RPC_PASS = "test" +AUTHENTICATION_BACKENDS = [ + "django_cryptolock.backends.MoneroAddressBackend", + "django.contrib.auth.backends.ModelBackend", +] + +# Test only default settings +DJCL_MONERO_NETWORK = "stagenet" + +DJCL_MONERO_WALLET_RPC_HOST = "localhost:3030" +DJCL_MONERO_WALLET_RPC_USER = "test" +DJCL_MONERO_WALLET_RPC_PASS = "test" +DJCL_MONERO_WALLET_RPC_PROTOCOL = "http" diff --git a/tests/test_models.py b/tests/test_models.py index 089a8fc..ae36ac5 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -7,18 +7,64 @@ test_django-cryptolock Tests for `django-cryptolock` models module. """ +from django.core.exceptions import ValidationError +from django.db import IntegrityError -from django.test import TestCase +import pytest +from model_mommy import mommy -from django_cryptolock import models +from django_cryptolock.models import Address + +VALID_MONERO_MAINNET_ADDR = "45D8b4XiUdz86FwztAJHVeLnQqGHQUqiHSwZe6rXFHSoXw522dPdixsdi7JAGsfJsfHRCP94UFhY5W3U8KCBhsRNUSLbYFk" +VALID_MONERO_STAGENET_ADDR = "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt" +VALID_MONERO_TESTNET_ADDR = "9vmn8Vyxh6JEVmPr4qTcj3ND3FywDpMXH2fVLLEARyKCJTc3jWjxeWcbRNcaa57Bj36cARBSfWnfS89oFVKBBvGTAegdRxG" + +pytestmark = pytest.mark.django_db -class TestDjango_cryptolock(TestCase): - def setUp(self): - pass +def test_valid_mainnet_address(settings): + settings.DJCL_MONERO_NETWORK = "mainnet" - def test_something(self): - pass + addr = mommy.make(Address, address=VALID_MONERO_MAINNET_ADDR) + addr.full_clean() - def tearDown(self): - pass + +def test_valid_stagenet_addr(settings): + settings.DJCL_MONERO_NETWORK = "stagenet" + + addr = mommy.make(Address, address=VALID_MONERO_STAGENET_ADDR) + addr.full_clean() + + +def test_valid_testnet_addr(settings): + settings.DJCL_MONERO_NETWORK = "testnet" + + addr = mommy.make(Address, address=VALID_MONERO_TESTNET_ADDR) + addr.full_clean() + + +def test_invalid_address(): + bad_addr = "Verywrongaddress" + addr = mommy.make(Address, address=bad_addr) + + with pytest.raises(ValidationError) as error: + addr.full_clean() + + assert f"{bad_addr} is not a valid address" in error.value.message_dict["address"] + + +def test_wrong_network_address(settings): + settings.DJCL_MONERO_NETWORK = "stagenet" + addr = mommy.make(Address, address=VALID_MONERO_MAINNET_ADDR) + + with pytest.raises(ValidationError) as error: + addr.full_clean() + + assert "Invalid address for stagenet" in error.value.message_dict["address"] + + +def test_address_is_unique(): + addr = mommy.make(Address, address=VALID_MONERO_MAINNET_ADDR) + + with pytest.raises(IntegrityError): + mommy.make(Address, address=VALID_MONERO_MAINNET_ADDR)