82 lines
3.3 KiB
Python
82 lines
3.3 KiB
Python
"""Аутентификация: методы по окружению, 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 # (для единообразия импорта)
|