/
pa1ch
/
FitAssistant
Обзор
Документация
Войти
/
pa1ch
/
FitAssistant
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
tests/integration/api/test_auth.py
148 строк
5 KB
Pavel Chugaev
Рефакторинг апи
14 июл 2026, 03:42
14 июл 2026, 03:42
785d36b
Код
Авторство
О чём код?
import hashlib import hmac import json import time from unittest.mock import patch from urllib.parse import urlencode from app.config import settings def _telegram_init_data( user_id: int = 42, first_name: str = "Web", *, bad_hash: bool = False ) -> str: """Build a Telegram Mini App initData string with a valid (or deliberately invalid) HMAC for the test bot token.""" user_json = json.dumps({"id": user_id, "first_name": first_name}) params = {"user": user_json, "auth_date": str(int(time.time()))} data_check = "\n".join(f"{k}={v}" for k, v in sorted(params.items())) secret_key = hmac.new( b"WebAppData", settings.telegram_bot_token.encode(), hashlib.sha256 ).digest() computed = hmac.new(secret_key, data_check.encode(), hashlib.sha256).hexdigest() params["hash"] = "deadbeef" if bad_hash else computed return urlencode(params) async def _login_via_telegram(client, user_id: int = 42, first_name: str = "Web"): """Log in through the Mini App initData flow — still the only Telegram path that doesn't go through the browser (used to set up a session in tests that aren't themselves testing Telegram login).""" return await client.post( "/api/v1/auth/telegram-init", json={"init_data": _telegram_init_data(user_id, first_name)}, ) async def test_auth_me_success(client): resp = await client.get("/api/v1/users/me") assert resp.status_code == 200 data = resp.json() assert data["name"] == "TestUser" assert data["telegram_id"] == 123456 async def test_auth_me_no_token(unauth_client): resp = await unauth_client.get("/api/v1/users/me") assert resp.status_code == 401 async def test_auth_me_invalid_token(unauth_client): resp = await unauth_client.get( "/api/v1/users/me", headers={"Authorization": "Bearer invalid.jwt.token"}, ) assert resp.status_code == 401 async def test_auth_dev_token(unauth_client, user): with patch.object(settings, "dev_user_id", user.id): resp = await unauth_client.post("/api/v1/auth/dev-token") assert resp.status_code == 200 data = resp.json() assert "access_token" in data assert data["token_type"] == "bearer" async def test_auth_dev_token_disabled(unauth_client): with patch.object(settings, "dev_user_id", 0): resp = await unauth_client.post("/api/v1/auth/dev-token") assert resp.status_code == 403 async def test_telegram_init_sets_cookies_and_authenticates(unauth_client): resp = await _login_via_telegram(unauth_client, first_name="Web") assert resp.status_code == 200 assert "access_token" in resp.cookies assert "refresh_token" in resp.cookies # The cookie alone (no Authorization header) now authenticates the client. me = await unauth_client.get("/api/v1/users/me") assert me.status_code == 200 assert me.json()["name"] == "Web" async def test_telegram_init_bad_hash_rejected(unauth_client): resp = await unauth_client.post( "/api/v1/auth/telegram-init", json={"init_data": _telegram_init_data(bad_hash=True)} ) assert resp.status_code == 401 async def test_refresh_rotates_session(unauth_client): login = await _login_via_telegram(unauth_client) resp = await unauth_client.post("/api/v1/auth/refresh") assert resp.status_code == 200 assert "access_token" in resp.json() # A new refresh token was issued (rotation) and a fresh access cookie set. assert "access_token" in resp.cookies assert resp.cookies["refresh_token"] != login.cookies["refresh_token"] async def test_refresh_without_cookie_unauthorized(unauth_client): resp = await unauth_client.post("/api/v1/auth/refresh") assert resp.status_code == 401 async def test_refresh_with_body_token_returns_tokens_not_cookies(unauth_client): """Native clients send the refresh token in the body and get both tokens back in JSON instead of cookies — the login itself still set cookies (the test client always has a cookie jar), so clear it to simulate a cookie-less client.""" login = await _login_via_telegram(unauth_client) raw_refresh = login.cookies["refresh_token"] unauth_client.cookies.clear() resp = await unauth_client.post("/api/v1/auth/refresh", json={"refresh_token": raw_refresh}) assert resp.status_code == 200 data = resp.json() assert "access_token" in data assert "refresh_token" in data assert data["refresh_token"] != raw_refresh assert "refresh_token" not in resp.cookies async def test_refresh_with_invalid_body_token_unauthorized(unauth_client): resp = await unauth_client.post( "/api/v1/auth/refresh", json={"refresh_token": "not-a-real-token"} ) assert resp.status_code == 401 async def test_auth_identities_lists_linked(unauth_client): await _login_via_telegram(unauth_client, user_id=4242) resp = await unauth_client.get("/api/v1/auth/identities") assert resp.status_code == 200 providers = {i["provider"] for i in resp.json()} assert providers == {"telegram"} async def test_logout_clears_session(unauth_client): await _login_via_telegram(unauth_client) resp = await unauth_client.post("/api/v1/auth/logout") assert resp.status_code == 204 # Refresh token was revoked → can't refresh anymore. refresh = await unauth_client.post("/api/v1/auth/refresh") assert refresh.status_code == 401