From 8279576ccdad3c920d103b3498e3ae91f35e979b Mon Sep 17 00:00:00 2001 From: Gros Frumos Date: Sat, 21 Mar 2026 08:16:46 +0200 Subject: [PATCH] =?UTF-8?q?kin:=20BATON-SEC-003=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20=D0=B0=D1=83=D1=82=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D1=8E=20=D0=BD=D0=B0?= =?UTF-8?q?=20/api/signal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_sec_003.py | 44 +++++++++++++++++++++++++++++++++++++++++++ tests/test_sec_006.py | 18 +++++++++++++----- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/tests/test_sec_003.py b/tests/test_sec_003.py index c7d3ca5..cb04e53 100644 --- a/tests/test_sec_003.py +++ b/tests/test_sec_003.py @@ -40,6 +40,8 @@ _UUID_5 = "aa000005-0000-4000-8000-000000000005" _UUID_6 = "aa000006-0000-4000-8000-000000000006" _UUID_7 = "aa000007-0000-4000-8000-000000000007" _UUID_8 = "aa000008-0000-4000-8000-000000000008" +_UUID_9 = "aa000009-0000-4000-8000-000000000009" +_UUID_10 = "aa00000a-0000-4000-8000-00000000000a" # --------------------------------------------------------------------------- @@ -206,6 +208,48 @@ async def test_old_api_key_invalid_after_re_register(): assert new_resp.status_code == 200, "Новый ключ должен работать" +# --------------------------------------------------------------------------- +# Criterion 5 (task brief) — Token from another user → 401 +# --------------------------------------------------------------------------- + + +@pytest.mark.asyncio +async def test_signal_with_other_user_token_returns_401(): + """POST /api/signal с токеном другого пользователя должен вернуть 401. + + Невозможно отправить сигнал от чужого имени даже зная UUID. + """ + async with make_app_client() as client: + # Регистрируем двух пользователей + r_a = await client.post("/api/register", json={"uuid": _UUID_9, "name": "UserA"}) + r_b = await client.post("/api/register", json={"uuid": _UUID_10, "name": "UserB"}) + assert r_a.status_code == 200 + assert r_b.status_code == 200 + api_key_a = r_a.json()["api_key"] + api_key_b = r_b.json()["api_key"] + + # UserA пытается отправить сигнал с токеном UserB + resp_a_with_b_key = await client.post( + "/api/signal", + json={"user_id": _UUID_9, "timestamp": 1742478000000}, + headers={"Authorization": f"Bearer {api_key_b}"}, + ) + + # UserB пытается отправить сигнал с токеном UserA + resp_b_with_a_key = await client.post( + "/api/signal", + json={"user_id": _UUID_10, "timestamp": 1742478000000}, + headers={"Authorization": f"Bearer {api_key_a}"}, + ) + + assert resp_a_with_b_key.status_code == 401, ( + "Нельзя отправить сигнал от имени UserA с токеном UserB" + ) + assert resp_b_with_a_key.status_code == 401, ( + "Нельзя отправить сигнал от имени UserB с токеном UserA" + ) + + # --------------------------------------------------------------------------- # Criterion 8 — SHA-256 hash is stored, not the raw key # --------------------------------------------------------------------------- diff --git a/tests/test_sec_006.py b/tests/test_sec_006.py index 8f4221d..e0db144 100644 --- a/tests/test_sec_006.py +++ b/tests/test_sec_006.py @@ -302,26 +302,34 @@ async def test_different_x_real_ip_values_have_independent_counters(): Verifies that rate-limit keys are truly per-IP. """ async with make_app_client() as client: - await client.post( + r_a = await client.post( "/api/register", json={"uuid": _UUID_XREALIP_A, "name": "IPA"} ) - await client.post( + r_b = await client.post( "/api/register", json={"uuid": _UUID_XREALIP_B, "name": "IPB"} ) + api_key_a = r_a.json()["api_key"] + api_key_b = r_b.json()["api_key"] - # Exhaust limit for IP-A + # Exhaust limit for IP-A (with valid auth so requests reach the rate limiter) for _ in range(11): await client.post( "/api/signal", json={"user_id": _UUID_XREALIP_A, "timestamp": 1742478000000}, - headers={"X-Real-IP": "198.51.100.100"}, + headers={ + "X-Real-IP": "198.51.100.100", + "Authorization": f"Bearer {api_key_a}", + }, ) # IP-B has its own independent counter — must not be blocked r = await client.post( "/api/signal", json={"user_id": _UUID_XREALIP_B, "timestamp": 1742478000000}, - headers={"X-Real-IP": "198.51.100.200"}, + headers={ + "X-Real-IP": "198.51.100.200", + "Authorization": f"Bearer {api_key_b}", + }, ) assert r.status_code == 200, (