81 lines
3.4 KiB
Python
81 lines
3.4 KiB
Python
import pytest
|
|
from django.contrib.auth import get_user_model
|
|
from django.urls import reverse
|
|
|
|
from apps.customers.models import CustomerProfile
|
|
|
|
from .models import PhoneContactApiKey
|
|
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
URL = "/api/phone-contacts"
|
|
FIRST_KEY = "first-phone-contact-api-key-1234567890"
|
|
SECOND_KEY = "second-phone-contact-api-key-1234567890"
|
|
|
|
|
|
def make_contact(*, mobile, first_name, last_name="", active=True):
|
|
user = get_user_model().objects.create_user(
|
|
username=f"contact_{mobile}", mobile=mobile, is_active=active,
|
|
account_type="CUSTOMER",
|
|
)
|
|
return CustomerProfile.objects.create(user=user, first_name=first_name, last_name=last_name)
|
|
|
|
|
|
def authorize(client, key=FIRST_KEY):
|
|
return {"HTTP_AUTHORIZATION": f"Bearer {key}"}
|
|
|
|
|
|
def test_contact_feed_authentication_search_and_contract(client):
|
|
key = PhoneContactApiKey()
|
|
key.set_key(FIRST_KEY)
|
|
key.save()
|
|
make_contact(mobile="09123456789", first_name="علی", last_name="رضایی")
|
|
make_contact(mobile="09123456780", first_name="علی", last_name="غیرفعال", active=False)
|
|
make_contact(mobile="09123456781", first_name="مریم")
|
|
|
|
assert client.get(URL, {"search": "علی"}).status_code == 401
|
|
assert client.get(URL, {"search": "علی"}, **authorize(client, SECOND_KEY)).status_code == 401
|
|
response = client.get(URL, {"search": " علی رضایی ", "limit": "50"}, **authorize(client))
|
|
assert response.status_code == 200
|
|
assert response.json() == {"contacts": [{
|
|
"name": "علی رضایی",
|
|
"phones": [{"type": "همراه", "number": "09123456789"}],
|
|
}]}
|
|
assert response["Cache-Control"] == "no-store"
|
|
assert client.get(URL, {"search": "ع"}, **authorize(client)).json() == {"contacts": []}
|
|
assert client.get(URL, {"search": "هیچ"}, **authorize(client)).json() == {"contacts": []}
|
|
assert client.post(URL, **authorize(client)).status_code == 405
|
|
|
|
|
|
def test_key_rotation_and_disabling_take_effect_immediately(client):
|
|
key = PhoneContactApiKey()
|
|
key.set_key(FIRST_KEY)
|
|
key.save()
|
|
assert client.get(URL, {"search": "علی"}, **authorize(client)).status_code == 200
|
|
key.set_key(SECOND_KEY)
|
|
key.save()
|
|
assert client.get(URL, {"search": "علی"}, **authorize(client)).status_code == 401
|
|
assert client.get(URL, {"search": "علی"}, **authorize(client, SECOND_KEY)).status_code == 200
|
|
key.is_active = False
|
|
key.save()
|
|
assert client.get(URL, {"search": "علی"}, **authorize(client, SECOND_KEY)).status_code == 401
|
|
|
|
|
|
def test_admin_can_create_and_rotate_key_without_exposing_hash(client):
|
|
admin = get_user_model().objects.create_superuser(username="api_admin", password="secure-admin-password")
|
|
client.force_login(admin)
|
|
add_url = reverse("admin:phone_contacts_api_phonecontactapikey_add")
|
|
response = client.post(add_url, {"new_key": FIRST_KEY, "is_active": "on", "_save": "Save"})
|
|
assert response.status_code == 302
|
|
key = PhoneContactApiKey.objects.get()
|
|
assert key.key_hash != FIRST_KEY
|
|
assert key.accepts(FIRST_KEY)
|
|
|
|
change_url = reverse("admin:phone_contacts_api_phonecontactapikey_change", args=[key.pk])
|
|
response = client.post(change_url, {"new_key": SECOND_KEY, "is_active": "on", "_save": "Save"})
|
|
assert response.status_code == 302
|
|
key.refresh_from_db()
|
|
assert not key.accepts(FIRST_KEY)
|
|
assert key.accepts(SECOND_KEY)
|
|
assert SECOND_KEY not in client.get(change_url).content.decode()
|