v0.1 - макет интерфейса, аутентификация через логин, аккаунт админа, создание партии в 2 этапа, базовые настройки профиля и группы, переключение между группами, статистика

This commit is contained in:
2026-06-16 17:41:06 +03:00
parent 6ab74f01aa
commit 56b5d09a4d
123 changed files with 13572 additions and 21 deletions
+81
View File
@@ -0,0 +1,81 @@
"""Аутентификация: методы по окружению, dev-вход, Telegram (проверка подписи)."""
from __future__ import annotations
import hashlib
import hmac
import time
from fastapi.testclient import TestClient
from tests.conftest import csrf_headers
def test_auth_config_dev_has_both_methods(client: TestClient):
cfg = client.get("/api/auth/config").json()
assert "telegram" in cfg["methods"]
assert "stub" in cfg["methods"] # dev → доступен вход по нику
def test_enabled_methods_by_env(monkeypatch):
from app.auth.registry import enabled_methods
from app.core.config import settings
monkeypatch.setattr(settings, "app_env", "development")
assert set(enabled_methods()) == {"telegram", "stub"}
monkeypatch.setattr(settings, "app_env", "test")
assert enabled_methods() == ["telegram"] # test (прод-клон) → только Telegram
monkeypatch.setattr(settings, "app_env", "production")
assert enabled_methods() == ["telegram"] # prod → только Telegram
def test_env_flags_and_db_path(monkeypatch):
"""dev → файл дева; test и prod → том /data (общая ветвь is_development)."""
from app.core.config import settings
monkeypatch.setattr(settings, "dev_database_url", "sqlite:///dev.db")
monkeypatch.setattr(settings, "prod_database_url", "sqlite:////data/prod.db")
monkeypatch.setattr(settings, "app_env", "development")
assert settings.is_development and settings.database_url == "sqlite:///dev.db"
monkeypatch.setattr(settings, "app_env", "test")
assert settings.is_test and settings.database_url == "sqlite:////data/prod.db"
monkeypatch.setattr(settings, "app_env", "production")
assert settings.is_production and settings.database_url == "sqlite:////data/prod.db"
def test_dev_login_works(client: TestClient):
r = client.post("/api/auth/dev/login", json={"nickname": "Тестер"})
assert r.status_code == 200, r.text
assert r.json()["nickname"] == "Тестер"
def _telegram_payload(token: str, **fields) -> dict:
data = {"id": 777, "first_name": "Иван", "username": "ivan_tg", "auth_date": int(time.time())}
data.update(fields)
secret = hashlib.sha256(token.encode()).digest()
check = "\n".join(f"{k}={data[k]}" for k in sorted(data))
sig = hmac.new(secret, check.encode(), hashlib.sha256).hexdigest()
return {**data, "hash": sig}
def test_telegram_login_valid_signature(client: TestClient, monkeypatch):
from app.core.config import settings
monkeypatch.setattr(settings, "telegram_bot_token", "TEST_BOT_TOKEN")
payload = _telegram_payload("TEST_BOT_TOKEN")
r = client.post("/api/auth/telegram", json=payload)
assert r.status_code == 200, r.text
me = r.json()
assert me["nickname"] # пользователь создан
assert me["telegram_id"] == 777
def test_telegram_login_bad_signature_rejected(client: TestClient, monkeypatch):
from app.core.config import settings
monkeypatch.setattr(settings, "telegram_bot_token", "TEST_BOT_TOKEN")
payload = _telegram_payload("TEST_BOT_TOKEN")
payload["hash"] = "deadbeef" # подделка
r = client.post("/api/auth/telegram", json=payload)
assert r.status_code == 401
_ = csrf_headers # (для единообразия импорта)