Files
customerTicket/apps/phone_contacts_api/test_api.py
T
2026-09-30 11:09:12 +03:30

126 lines
5.3 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": "علی رضایی",
"mobile": "09123456789",
"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
@pytest.mark.parametrize("search", [
"09123456789", "+989123456789", "00989123456789",
"۰۹۱۲۳۴۵۶۷۸۹", "۰۹۱۲-۳۴۵-۶۷۸۹",
])
def test_contact_feed_finds_same_mobile_in_supported_formats(client, search):
key = PhoneContactApiKey()
key.set_key(FIRST_KEY)
key.save()
make_contact(mobile="09123456789", first_name="علی", last_name="رضایی")
make_contact(mobile="09123456780", first_name="مریم")
response = client.get(URL, {"search": search}, **authorize(client))
assert response.status_code == 200
assert response.json() == {"contacts": [{
"name": "علی رضایی",
"mobile": "09123456789",
"phones": [{"type": "همراه", "number": "09123456789"}],
}]}
assert client.get(URL, {"search": "09120000000"}, **authorize(client)).json() == {"contacts": []}
@pytest.mark.parametrize("stored,search,display", [
("+989131234567", "09131234567", "09131234567"),
("+989131234567", "00989131234567", "09131234567"),
("+982112345678", "02112345678", "02112345678"),
("02112345678", "+982112345678", "02112345678"),
("+982112345678", "0098-21-1234-5678", "02112345678"),
])
def test_contact_feed_matches_any_iranian_prefix_without_mobile_area_code_assumption(client, stored, search, display):
key = PhoneContactApiKey()
key.set_key(FIRST_KEY)
key.save()
profile = make_contact(mobile="09123456789", first_name="علی", last_name="رضایی")
get_user_model().objects.filter(pk=profile.user_id).update(mobile=stored)
response = client.get(URL, {"search": search}, **authorize(client))
assert response.status_code == 200
assert response.json() == {"contacts": [{
"name": "علی رضایی",
"mobile": display,
"phones": [{"type": "همراه" if display.startswith("09") else "تلفن", "number": display}],
}]}
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()