210 lines
6.5 KiB
Python
210 lines
6.5 KiB
Python
from unittest.mock import patch
|
|
|
|
from django.urls import reverse_lazy
|
|
from django.contrib.auth import get_user_model
|
|
|
|
from rest_framework.test import APIClient
|
|
from rest_framework.status import (
|
|
HTTP_200_OK,
|
|
HTTP_201_CREATED,
|
|
HTTP_405_METHOD_NOT_ALLOWED,
|
|
HTTP_400_BAD_REQUEST,
|
|
)
|
|
from model_mommy import mommy
|
|
import pytest
|
|
|
|
from django_cryptolock.models import Address, Challenge
|
|
from .helpers import (
|
|
VALID_BITCOIN_ADDRESS,
|
|
VALID_MONERO_ADDRESS,
|
|
gen_challenge,
|
|
set_bitcoin_settings,
|
|
set_monero_settings,
|
|
)
|
|
|
|
User = get_user_model()
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
@pytest.fixture
|
|
def api_client():
|
|
return APIClient()
|
|
|
|
|
|
@pytest.mark.parametrize("method", ["put", "patch", "delete", "head", "options"])
|
|
def test_methods_not_allowed_for_token_login(api_client, method):
|
|
func = getattr(api_client, method)
|
|
response = func(reverse_lazy("api_token_login"))
|
|
assert response.status_code == HTTP_405_METHOD_NOT_ALLOWED
|
|
|
|
|
|
def test_generate_new_token_login_challenge(api_client):
|
|
response = api_client.get(reverse_lazy("api_token_login"))
|
|
assert response.status_code == HTTP_200_OK
|
|
assert "challenge" in response.json().keys()
|
|
assert "expires" in response.json().keys()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"addr,set_backend,network",
|
|
[
|
|
(VALID_MONERO_ADDRESS, set_monero_settings, "monero"),
|
|
(VALID_BITCOIN_ADDRESS, set_bitcoin_settings, "bitcoin"),
|
|
],
|
|
)
|
|
def test_token_login_fails_invalid_data(
|
|
api_client, settings, addr, set_backend, network
|
|
):
|
|
settings.DJCL_MONERO_NETWORK = "mainnet"
|
|
set_backend(settings)
|
|
|
|
net = Address.NETWORK_BITCOIN if network == "bitcoin" else Address.NETWORK_MONERO
|
|
user = mommy.make(User)
|
|
mommy.make(Address, user=user, address=addr, network=net)
|
|
challenge = gen_challenge()
|
|
|
|
with patch(f"django_cryptolock.backends.verify_{network}_signature") as sig_mock:
|
|
sig_mock.return_value = False
|
|
response = api_client.post(
|
|
reverse_lazy("api_token_login"),
|
|
{"challenge": challenge, "address": addr, "signature": "something"},
|
|
)
|
|
|
|
assert response.status_code == HTTP_400_BAD_REQUEST
|
|
errors = response.json()
|
|
assert "Please enter a correct address or signature." in errors["__all__"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"addr,set_backend,network",
|
|
[
|
|
(VALID_MONERO_ADDRESS, set_monero_settings, "monero"),
|
|
(VALID_BITCOIN_ADDRESS, set_bitcoin_settings, "bitcoin"),
|
|
],
|
|
)
|
|
def test_token_login_succeeds(api_client, settings, addr, set_backend, network):
|
|
settings.DJCL_MONERO_NETWORK = "mainnet"
|
|
set_backend(settings)
|
|
|
|
net = Address.NETWORK_BITCOIN if network == "bitcoin" else Address.NETWORK_MONERO
|
|
user = mommy.make(User)
|
|
mommy.make(Address, user=user, address=addr, network=net)
|
|
challenge = gen_challenge()
|
|
|
|
with patch(f"django_cryptolock.backends.verify_{network}_signature") as sig_mock:
|
|
sig_mock.return_value = True
|
|
response = api_client.post(
|
|
reverse_lazy("api_token_login"),
|
|
{"challenge": challenge, "address": addr, "signature": "something"},
|
|
)
|
|
|
|
assert response.status_code == HTTP_200_OK
|
|
assert "token" in response.json().keys()
|
|
|
|
|
|
@pytest.mark.parametrize("method", ["put", "patch", "delete", "head", "options"])
|
|
def test_methods_not_allowed_for_sign_up(api_client, method):
|
|
func = getattr(api_client, method)
|
|
response = func(reverse_lazy("api_signup"))
|
|
assert response.status_code == HTTP_405_METHOD_NOT_ALLOWED
|
|
|
|
|
|
def test_generate_new_sign_up_challenge(api_client):
|
|
response = api_client.get(reverse_lazy("api_signup"))
|
|
assert response.status_code == HTTP_200_OK
|
|
assert "challenge" in response.json().keys()
|
|
assert "expires" in response.json().keys()
|
|
|
|
|
|
def test_sign_up_fails_no_input(api_client):
|
|
response = api_client.post(reverse_lazy("api_signup"))
|
|
errors = response.json()
|
|
assert response.status_code == HTTP_400_BAD_REQUEST
|
|
assert "This field is required." in errors["challenge"]
|
|
assert "This field is required." in errors["address"]
|
|
assert "This field is required." in errors["signature"]
|
|
assert "This field is required." in errors["username"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"addr,set_backend",
|
|
[
|
|
(VALID_MONERO_ADDRESS, set_monero_settings),
|
|
(VALID_BITCOIN_ADDRESS, set_bitcoin_settings),
|
|
],
|
|
)
|
|
def test_sign_up_fails_duplicate_address(api_client, settings, addr, set_backend):
|
|
settings.DJCL_MONERO_NETWORK = "mainnet"
|
|
set_backend(settings)
|
|
challenge = gen_challenge()
|
|
mommy.make(Address, address=addr)
|
|
response = api_client.post(
|
|
reverse_lazy("api_signup"),
|
|
{
|
|
"challenge": challenge,
|
|
"address": addr,
|
|
"signature": "something",
|
|
"username": "user",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == HTTP_400_BAD_REQUEST
|
|
errors = response.json()
|
|
assert "This address already exists" in errors["address"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"addr,set_backend",
|
|
[
|
|
(VALID_MONERO_ADDRESS, set_monero_settings),
|
|
(VALID_BITCOIN_ADDRESS, set_bitcoin_settings),
|
|
],
|
|
)
|
|
def test_sign_up_fails_invalid_signature(api_client, settings, addr, set_backend):
|
|
settings.DJCL_MONERO_NETWORK = "mainnet"
|
|
set_backend(settings)
|
|
challenge = gen_challenge()
|
|
|
|
with patch("django_cryptolock.api_views.verify_signature") as sig_mock:
|
|
sig_mock.return_value = False
|
|
response = api_client.post(
|
|
reverse_lazy("api_signup"),
|
|
{
|
|
"challenge": challenge,
|
|
"address": addr,
|
|
"signature": "something",
|
|
"username": "user",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == HTTP_400_BAD_REQUEST
|
|
errors = response.json()
|
|
assert "Invalid signature" in errors["signature"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"addr,set_backend",
|
|
[
|
|
(VALID_MONERO_ADDRESS, set_monero_settings),
|
|
(VALID_BITCOIN_ADDRESS, set_bitcoin_settings),
|
|
],
|
|
)
|
|
def test_sign_up_succeeds(api_client, settings, addr, set_backend):
|
|
settings.DJCL_MONERO_NETWORK = "mainnet"
|
|
set_backend(settings)
|
|
challenge = gen_challenge()
|
|
|
|
with patch("django_cryptolock.api_views.verify_signature") as sig_mock:
|
|
sig_mock.return_value = True
|
|
response = api_client.post(
|
|
reverse_lazy("api_signup"),
|
|
{
|
|
"challenge": challenge,
|
|
"address": addr,
|
|
"signature": "something",
|
|
"username": "user",
|
|
},
|
|
)
|
|
|
|
assert response.status_code == HTTP_201_CREATED
|