"""Тесты входа в админку через Telegram: подпись, сессия и CSRF.""" from __future__ import annotations import time from fastapi.testclient import TestClient from admin.security import verify_telegram_auth def test_healthz_is_public(client_factory) -> None: assert client_factory(authenticated=False).get("/healthz").status_code == 200 def test_protected_page_redirects_to_login(client_factory) -> None: response = client_factory(authenticated=False, follow_redirects=False).get("/") assert response.status_code == 303 assert response.headers["location"].startswith("/login") def test_login_page_has_widget(client_factory) -> None: response = client_factory(authenticated=False).get("/login") assert response.status_code == 200 assert "telegram-widget.js" in response.text assert "debot_test_bot" in response.text assert "https://debot-test.mpakosrv.ru/auth/telegram" in response.text def test_login_page_without_config(client_factory, settings_factory) -> None: client = client_factory( authenticated=False, settings=settings_factory(bot_token="", bot_username=""), ) response = client.get("/login") assert response.status_code == 200 assert "Вход не настроен" in response.text def test_login_with_valid_signature(client_factory, telegram_query) -> None: client: TestClient = client_factory(authenticated=False, follow_redirects=False) response = client.get("/auth/telegram", params=telegram_query()) assert response.status_code == 303 assert response.headers["location"] == "/" assert client.get("/").status_code == 200 def test_login_rejects_bad_hash(client_factory, telegram_query) -> None: params = telegram_query() params["hash"] = "0" * 64 response = client_factory(authenticated=False).get("/auth/telegram", params=params) assert response.status_code == 403 assert "Не удалось проверить вход" in response.text def test_login_rejects_stale_auth_date(client_factory, telegram_query) -> None: params = telegram_query(auth_date=int(time.time()) - 90_000) response = client_factory(authenticated=False).get("/auth/telegram", params=params) assert response.status_code == 403 def test_login_rejects_non_admin(client_factory, telegram_query) -> None: response = client_factory(authenticated=False).get("/auth/telegram", params=telegram_query(telegram_id=2)) assert response.status_code == 403 assert "нет доступа" in response.text def test_logout_requires_csrf(client_factory) -> None: response = client_factory().post("/logout") assert response.status_code == 400 def test_logout_clears_session(client_factory, csrf_token) -> None: client: TestClient = client_factory() token = csrf_token(client.get("/").text) response = client.post("/logout", data={"csrf_token": token}) assert response.status_code == 200 assert client.get("/", follow_redirects=False).status_code == 303 def test_verify_signature(bot_token: str) -> None: """Юнит-проверка подписи без HTTP (данные собираем тем же алгоритмом).""" import hashlib import hmac data = {"id": "1", "first_name": "Admin", "auth_date": str(int(time.time()))} check = "\n".join(f"{key}={value}" for key, value in sorted(data.items())) secret = hashlib.sha256(bot_token.encode()).digest() data["hash"] = hmac.new(secret, check.encode(), hashlib.sha256).hexdigest() assert verify_telegram_auth(data, bot_token) assert not verify_telegram_auth({**data, "id": "2"}, bot_token) assert not verify_telegram_auth(data, "999:OTHER") assert not verify_telegram_auth(data, bot_token, now=time.time() + 90_000)