109 lines
3.4 KiB
Python
109 lines
3.4 KiB
Python
"""Тесты аутентификации."""
|
|
from datetime import datetime, timedelta, timezone
|
|
from uuid import uuid4
|
|
|
|
from app.models.enums import MessengerType, RoleCode
|
|
from app.models.user import LoginToken, Role, User, UserRole
|
|
|
|
|
|
def _seed_admin(db) -> User:
|
|
for code, name in [(RoleCode.ADMIN, "Админ"), (RoleCode.COORDINATOR, "Координатор")]:
|
|
if not db.query(Role).filter(Role.code == code).first():
|
|
db.add(Role(code=code, name=name))
|
|
db.commit()
|
|
|
|
admin = (
|
|
db.query(User)
|
|
.filter(User.messenger_type == MessengerType.TELEGRAM, User.messenger_id == "1")
|
|
.first()
|
|
)
|
|
if not admin:
|
|
admin = User(messenger_type=MessengerType.TELEGRAM, messenger_id="1", full_name="Админ")
|
|
db.add(admin)
|
|
db.flush()
|
|
role = db.query(Role).filter(Role.code == RoleCode.ADMIN).first()
|
|
if not db.query(UserRole).filter(
|
|
UserRole.user_id == admin.id, UserRole.role_id == role.id
|
|
).first():
|
|
db.add(UserRole(user_id=admin.id, role_id=role.id))
|
|
db.commit()
|
|
return admin
|
|
|
|
|
|
def _make_login_token(db, value: str) -> None:
|
|
db.add(
|
|
LoginToken(
|
|
id=str(uuid4()),
|
|
token=value,
|
|
expires_at=datetime.now(timezone.utc) + timedelta(minutes=30),
|
|
)
|
|
)
|
|
db.commit()
|
|
|
|
|
|
def test_login_flow(client, db):
|
|
_seed_admin(db)
|
|
_make_login_token(db, "tok-1")
|
|
|
|
# вход
|
|
r = client.post(
|
|
"/api/v1/auth/login",
|
|
json={"token": "tok-1", "messenger_type": "telegram", "messenger_id": "1"},
|
|
)
|
|
assert r.status_code == 200, r.text
|
|
data = r.json()
|
|
assert data["user"]["roles"][0]["code"] == "admin"
|
|
access, refresh = data["access_token"], data["refresh_token"]
|
|
|
|
# повторное использование ссылки
|
|
r2 = client.post(
|
|
"/api/v1/auth/login",
|
|
json={"token": "tok-1", "messenger_type": "telegram", "messenger_id": "1"},
|
|
)
|
|
assert r2.status_code == 409
|
|
|
|
# профиль
|
|
r3 = client.get("/api/v1/auth/me", headers={"Authorization": f"Bearer {access}"})
|
|
assert r3.status_code == 200
|
|
|
|
# выдача новой ссылки (как админ)
|
|
r4 = client.post(
|
|
"/api/v1/auth/login-token",
|
|
json={"ttl_minutes": 15},
|
|
headers={"Authorization": f"Bearer {access}"},
|
|
)
|
|
assert r4.status_code == 201, r4.text
|
|
assert "token=" in r4.json()["url"]
|
|
|
|
# refresh
|
|
r5 = client.post("/api/v1/auth/refresh", json={"refresh_token": refresh})
|
|
assert r5.status_code == 200, r5.text
|
|
new_access = r5.json()["access_token"]
|
|
|
|
# logout
|
|
r6 = client.post("/api/v1/auth/logout", headers={"Authorization": f"Bearer {new_access}"})
|
|
assert r6.status_code == 204
|
|
|
|
# после logout
|
|
r7 = client.get("/api/v1/auth/me", headers={"Authorization": f"Bearer {new_access}"})
|
|
assert r7.status_code == 401
|
|
|
|
|
|
def test_login_token_requires_role(client, db):
|
|
_seed_admin(db)
|
|
_make_login_token(db, "tok-2")
|
|
r = client.post(
|
|
"/api/v1/auth/login",
|
|
json={"token": "tok-2", "messenger_type": "telegram", "messenger_id": "999"},
|
|
)
|
|
assert r.status_code == 200
|
|
access = r.json()["access_token"]
|
|
|
|
# обычный пользователь без роли не может выдавать ссылки
|
|
r2 = client.post(
|
|
"/api/v1/auth/login-token",
|
|
json={"ttl_minutes": 15},
|
|
headers={"Authorization": f"Bearer {access}"},
|
|
)
|
|
assert r2.status_code == 403
|