фикс бага с дублем аккаунтов при логине по нику

This commit is contained in:
2026-06-26 15:33:27 +03:00
parent f4286ffa6c
commit 8f4a58d33d
2 changed files with 55 additions and 2 deletions
+14 -2
View File
@@ -10,7 +10,7 @@ from fastapi import APIRouter, Depends, Request, Response
from sqlmodel import Session, select from sqlmodel import Session, select
from app.auth.dev_stub import DevStubProvider from app.auth.dev_stub import DevStubProvider
from app.auth.login import login_with_identity from app.auth.login import establish_session, login_with_identity
from app.auth.provider import ExternalIdentity from app.auth.provider import ExternalIdentity
from app.db.session import get_session from app.db.session import get_session
from app.models import User from app.models import User
@@ -28,7 +28,19 @@ def dev_login(
response: Response, response: Response,
session: Session = Depends(get_session), session: Session = Depends(get_session),
) -> s.MeRead: ) -> s.MeRead:
identity = DevStubProvider().authenticate({"nickname": body.nickname}) # Dev-вход «стать игроком с этим ником». Если такой игрок уже есть (любого провайдера —
# Telegram, или stub с изменённым позже ником), входим именно в него, а не плодим дубли.
# Только если игрока с таким ником нет — создаём нового stub-пользователя.
nickname = (body.nickname or "").strip()
existing = (
session.exec(select(User).where(User.nickname == nickname)).first()
if nickname
else None
)
if existing is not None:
user = establish_session(session, response, request, existing, existing.auth_provider)
return build_me(session, user)
identity = DevStubProvider().authenticate({"nickname": nickname})
user = login_with_identity(session, response, request, identity) user = login_with_identity(session, response, request, identity)
return build_me(session, user) return build_me(session, user)
+41
View File
@@ -58,6 +58,47 @@ def _telegram_payload(token: str, **fields) -> dict:
return {**data, "hash": sig} return {**data, "hash": sig}
def test_dev_login_into_telegram_user_no_duplicate(client: TestClient, engine, monkeypatch):
"""Dev-вход по нику Telegram-аккаунта входит в него, а не создаёт дубль «ник 2»."""
from sqlmodel import Session, select
from app.core.config import settings
from app.models import User
monkeypatch.setattr(settings, "telegram_bot_token", "TEST_BOT_TOKEN")
r = client.post("/api/auth/telegram", json=_telegram_payload("TEST_BOT_TOKEN"))
assert r.status_code == 200, r.text
tg_id, nick = r.json()["id"], r.json()["nickname"]
client.cookies.clear() # «другой вход» — без сессии
r2 = client.post("/api/auth/dev/login", json={"nickname": nick})
assert r2.status_code == 200, r2.text
assert r2.json()["id"] == tg_id # тот же аккаунт, не новый
with Session(engine) as s:
users = s.exec(select(User).where(User.nickname == nick)).all()
assert len(users) == 1 # дубликат не создан
def test_dev_login_after_rename_no_duplicate(client: TestClient, engine):
"""После смены ника dev-вход по новому нику входит в того же игрока (без дубля)."""
from sqlmodel import Session, select
from app.models import User
uid = client.post("/api/auth/dev/login", json={"nickname": "Старый"}).json()["id"]
pr = client.patch("/api/users/me", json={"nickname": "Новый"}, headers=csrf_headers(client))
assert pr.status_code == 200, pr.text
client.cookies.clear()
r2 = client.post("/api/auth/dev/login", json={"nickname": "Новый"})
assert r2.status_code == 200, r2.text
assert r2.json()["id"] == uid
with Session(engine) as s:
assert len(s.exec(select(User).where(User.nickname == "Новый")).all()) == 1
def test_telegram_login_valid_signature(client: TestClient, monkeypatch): def test_telegram_login_valid_signature(client: TestClient, monkeypatch):
from app.core.config import settings from app.core.config import settings