validate the address first on signup
This commit is contained in:
parent
c2fa8309fd
commit
dd2e1a769a
|
@ -1,12 +1,14 @@
|
|||
from django import forms
|
||||
from django.contrib.auth import authenticate
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext, gettext_lazy as _
|
||||
from django.conf import settings
|
||||
|
||||
from pybitid import bitid
|
||||
|
||||
from .models import Address
|
||||
from .validators import validate_monero_address
|
||||
from .validators import validate_monero_address, validate_bitcoin_address
|
||||
from .utils import generate_challenge
|
||||
|
||||
|
||||
|
@ -98,12 +100,34 @@ class SimpleSignUpForm(ChallengeMixin, forms.Form):
|
|||
super().__init__(*args, **kwargs)
|
||||
self.request = request
|
||||
self.include_challange()
|
||||
self.network = None
|
||||
|
||||
def clean_address(self):
|
||||
self.network = None
|
||||
value = self.cleaned_data["address"]
|
||||
bitcoin_backend = "django_cryptolock.backends.BitcoinAddressBackend"
|
||||
monero_backend = "django_cryptolock.backends.MoneroAddressBackend"
|
||||
|
||||
if bitcoin_backend in settings.AUTHENTICATION_BACKENDS:
|
||||
try:
|
||||
validate_bitcoin_address(value)
|
||||
self.network = Address.NETWORK_BITCOIN
|
||||
except ValidationError:
|
||||
pass
|
||||
|
||||
if monero_backend in settings.AUTHENTICATION_BACKENDS:
|
||||
try:
|
||||
validate_monero_address(value)
|
||||
self.network = Address.NETWORK_MONERO
|
||||
except ValidationError:
|
||||
pass
|
||||
|
||||
if not self.network:
|
||||
raise forms.ValidationError(_("Invalid address"))
|
||||
|
||||
if Address.objects.filter(address=value).exists():
|
||||
raise forms.ValidationError(_("This address already exists"))
|
||||
|
||||
return value
|
||||
|
||||
def clean_username(self):
|
||||
|
|
|
@ -29,9 +29,11 @@ class CryptoLockSignUpView(FormView):
|
|||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
valid_sig, network = self.verify_signature(form)
|
||||
valid_sig = self.verify_signature(form)
|
||||
except JSONRPCException:
|
||||
form._errors["__all__"] = ErrorList([_("Error connecting to daemon")])
|
||||
form._errors["__all__"] = ErrorList(
|
||||
[_("Error connecting to Monero daemon")]
|
||||
)
|
||||
return self.form_invalid(form)
|
||||
|
||||
username = form.cleaned_data["username"]
|
||||
|
@ -39,7 +41,7 @@ class CryptoLockSignUpView(FormView):
|
|||
|
||||
if valid_sig:
|
||||
user = get_user_model().objects.create(username=username)
|
||||
user.address_set.create(address=address, network=network)
|
||||
user.address_set.create(address=address, network=form.network)
|
||||
return super().form_valid(form)
|
||||
else:
|
||||
form._errors["signature"] = ErrorList([_("Invalid signature")])
|
||||
|
@ -52,19 +54,15 @@ class CryptoLockSignUpView(FormView):
|
|||
address = form.cleaned_data["address"]
|
||||
challenge = form.cleaned_data["challenge"]
|
||||
signature = form.cleaned_data["signature"]
|
||||
bitcoin_backend = "django_cryptolock.backends.BitcoinAddressBackend"
|
||||
monero_backend = "django_cryptolock.backends.MoneroAddressBackend"
|
||||
bitcoin = form.network == Address.NETWORK_BITCOIN
|
||||
monero = form.network == Address.NETWORK_MONERO
|
||||
valid_sig = False
|
||||
network = None
|
||||
|
||||
if bitcoin_backend in settings.AUTHENTICATION_BACKENDS:
|
||||
if bitcoin:
|
||||
valid_sig = verify_bitcoin_signature(
|
||||
address, challenge, signature, request=self.request
|
||||
)
|
||||
network = Address.NETWORK_BITCOIN
|
||||
|
||||
if monero_backend in settings.AUTHENTICATION_BACKENDS and not valid_sig:
|
||||
elif monero:
|
||||
valid_sig = verify_monero_signature(address, challenge, signature)
|
||||
network = Address.NETWORK_MONERO
|
||||
|
||||
return valid_sig, network
|
||||
return valid_sig
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
def set_monero_settings(settings):
|
||||
settings.AUTHENTICATION_BACKENDS = [
|
||||
"django_cryptolock.backends.MoneroAddressBackend",
|
||||
"django.contrib.auth.backends.ModelBackend",
|
||||
]
|
||||
|
||||
|
||||
def set_bitcoin_settings(settings):
|
||||
settings.AUTHENTICATION_BACKENDS = [
|
||||
"django_cryptolock.backends.BitcoinAddressBackend",
|
||||
"django.contrib.auth.backends.ModelBackend",
|
||||
]
|
|
@ -9,6 +9,8 @@ from model_mommy import mommy
|
|||
|
||||
from django_cryptolock.models import Address
|
||||
|
||||
from .helpers import set_monero_settings, set_bitcoin_settings
|
||||
|
||||
User = get_user_model()
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
@ -20,20 +22,6 @@ VALID_BITID_URI = "bitid://www.django-cryptolock.test/?x=44d91949c7b2eb20"
|
|||
EXAMPLE_LOGIN_URL = "https://www.django-cryptolock.test/"
|
||||
|
||||
|
||||
def set_monero_settings(settings):
|
||||
settings.AUTHENTICATION_BACKENDS = [
|
||||
"django_cryptolock.backends.MoneroAddressBackend",
|
||||
"django.contrib.auth.backends.ModelBackend",
|
||||
]
|
||||
|
||||
|
||||
def set_bitcoin_settings(settings):
|
||||
settings.AUTHENTICATION_BACKENDS = [
|
||||
"django_cryptolock.backends.BitcoinAddressBackend",
|
||||
"django.contrib.auth.backends.ModelBackend",
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def existing_user():
|
||||
return User.objects.create_user(**DUMMY_CREDS)
|
||||
|
|
|
@ -8,9 +8,12 @@ from model_mommy import mommy
|
|||
from django_cryptolock.forms import SimpleLoginForm, SimpleSignUpForm
|
||||
from django_cryptolock.models import Address
|
||||
|
||||
from .helpers import set_monero_settings, set_bitcoin_settings
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
VALID_ADDRESS = "46fYuhPAdsxMbEeMg97LhSbFPamdiCw7C6b19VEcZSmV6xboWFZuZQ9MTbj1wLszhUExHi63CMtsWjDTrRDqegZiPVebgYq"
|
||||
VALID_MONERO_ADDRESS = "46fYuhPAdsxMbEeMg97LhSbFPamdiCw7C6b19VEcZSmV6xboWFZuZQ9MTbj1wLszhUExHi63CMtsWjDTrRDqegZiPVebgYq"
|
||||
VALID_BITCOIN_ADDRESS = "1N5attoW1FviYGnLmRu9xjaPMKTkWxtUCW"
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
|
@ -45,7 +48,7 @@ def test_simpleloginform_valid_data(settings):
|
|||
form = SimpleLoginForm(
|
||||
request=request,
|
||||
data={
|
||||
"address": VALID_ADDRESS,
|
||||
"address": VALID_MONERO_ADDRESS,
|
||||
"challenge": "12345678",
|
||||
"signature": "some valid signature",
|
||||
},
|
||||
|
@ -56,7 +59,7 @@ def test_simpleloginform_valid_data(settings):
|
|||
assert form.is_valid()
|
||||
|
||||
|
||||
def test_simplesignupform_generaes_new_challenge():
|
||||
def test_simplesignupform_generates_new_challenge():
|
||||
request = MagicMock()
|
||||
initial = {}
|
||||
request.session.__setitem__.side_effect = initial.__setitem__
|
||||
|
@ -68,7 +71,7 @@ def test_simplesignupform_generaes_new_challenge():
|
|||
assert form.initial.get("challenge").startswith("bitid://something")
|
||||
|
||||
|
||||
def test_simplesignupform_generaes_no_new_challenge():
|
||||
def test_simplesignupform_generates_no_new_challenge():
|
||||
request = MagicMock()
|
||||
initial = {}
|
||||
request.session.__setitem__.side_effect = initial.__setitem__
|
||||
|
@ -81,17 +84,68 @@ def test_simplesignupform_generaes_no_new_challenge():
|
|||
|
||||
def test_validate_address_unique(settings):
|
||||
settings.DJCL_MONERO_NETWORK = "mainnet"
|
||||
mommy.make(Address, address=VALID_ADDRESS)
|
||||
mommy.make(Address, address=VALID_MONERO_ADDRESS)
|
||||
request = MagicMock()
|
||||
request.build_absolute_uri.return_value = "http://something/"
|
||||
form = SimpleSignUpForm(
|
||||
request=request,
|
||||
data={
|
||||
"username": "foo",
|
||||
"address": VALID_ADDRESS,
|
||||
"address": VALID_MONERO_ADDRESS,
|
||||
"challenge": "12345678",
|
||||
"signature": "some valid signature",
|
||||
},
|
||||
)
|
||||
assert not form.is_valid()
|
||||
assert "This address already exists" in form.errors["address"]
|
||||
|
||||
|
||||
def test_simplesignupform_validate_bitcoin_addr(settings):
|
||||
set_bitcoin_settings(settings)
|
||||
request = MagicMock()
|
||||
request.build_absolute_uri.return_value = "http://something/"
|
||||
request.session.get.return_value = "12345678"
|
||||
form = SimpleSignUpForm(
|
||||
request=request,
|
||||
data={
|
||||
"username": "foo",
|
||||
"address": VALID_BITCOIN_ADDRESS,
|
||||
"challenge": "12345678",
|
||||
"signature": "some valid signature",
|
||||
},
|
||||
)
|
||||
assert form.is_valid()
|
||||
|
||||
|
||||
def test_simplesignupform_valid_monero_addr(settings):
|
||||
set_monero_settings(settings)
|
||||
settings.DJCL_MONERO_NETWORK = "mainnet"
|
||||
request = MagicMock()
|
||||
request.build_absolute_uri.return_value = "http://something/"
|
||||
request.session.get.return_value = "12345678"
|
||||
form = SimpleSignUpForm(
|
||||
request=request,
|
||||
data={
|
||||
"username": "foo",
|
||||
"address": VALID_MONERO_ADDRESS,
|
||||
"challenge": "12345678",
|
||||
"signature": "some valid signature",
|
||||
},
|
||||
)
|
||||
assert form.is_valid()
|
||||
|
||||
|
||||
def test_simplesignupform_validate_invalid_addr():
|
||||
request = MagicMock()
|
||||
request.build_absolute_uri.return_value = "http://something/"
|
||||
form = SimpleSignUpForm(
|
||||
request=request,
|
||||
data={
|
||||
"username": "foo",
|
||||
"address": "bad addr",
|
||||
"challenge": "12345678",
|
||||
"signature": "some valid signature",
|
||||
},
|
||||
)
|
||||
assert not form.is_valid()
|
||||
assert "Invalid address" in form.errors["address"]
|
||||
|
|
Loading…
Reference in New Issue