Simplify: общие хелперы в роутерах
- IP клиента для аудита брался инлайном в 19 местах шести модулей; теперь security.client_ip — за привратником адрес придётся читать из X-Forwarded-For, и одна точка правки для этого обязательна. - Чтение загруженной картинки (лимит размера + sniff формата) было скопировано в четыре обработчика; вынесено в user_service.read_capped_image. - Лимит размера вложения жил двумя одинаковыми константами в игроцком и админском роутере — перенесён к самим вложениям. - update_nickname и set_active_group переиспользуют nickname_format_ok и group_service.get_membership вместо собственных копий проверки. - Убраны осиротевшие импорты и комментарий-заготовка о вложениях, которые давно реализованы (MatchAttachment). #8 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BoiJK9ux8peeyjLb8TYjFf
This commit is contained in:
@@ -6,7 +6,8 @@ from fastapi.responses import FileResponse
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.auth.deps import get_current_user
|
||||
from app.core.errors import ConflictError, NoGroupError, NotFoundError, ValidationError
|
||||
from app.core.security import client_ip
|
||||
from app.core.errors import ConflictError, NoGroupError, NotFoundError
|
||||
from app.core.timeutil import iso_utc
|
||||
from app.db.session import get_session
|
||||
from app.models import Match, MatchAttachment, User
|
||||
@@ -24,7 +25,6 @@ from app.services.match_service import FinishInput, ParticipantInput, RosterInpu
|
||||
|
||||
router = APIRouter(prefix="/matches", tags=["matches"])
|
||||
|
||||
_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024 # 10 МБ
|
||||
|
||||
|
||||
def attachment_read(att: MatchAttachment, base: str) -> s.AttachmentRead:
|
||||
@@ -119,7 +119,7 @@ def start_match(
|
||||
entity_type="match",
|
||||
entity_id=match.id,
|
||||
payload={"group_id": match.group_id, "player_count": match.player_count, "status": "in_progress"},
|
||||
ip=request.client.host if request.client else None,
|
||||
ip=client_ip(request),
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
)
|
||||
session.commit()
|
||||
@@ -165,7 +165,7 @@ def finish_match(
|
||||
entity_type="match",
|
||||
entity_id=match.id,
|
||||
payload={"event": "finish", "win_reason": match.win_reason, "duration_minutes": match.duration_minutes},
|
||||
ip=request.client.host if request.client else None,
|
||||
ip=client_ip(request),
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
)
|
||||
session.commit()
|
||||
@@ -225,7 +225,7 @@ def update_match(
|
||||
action="update",
|
||||
entity_type="match",
|
||||
entity_id=match.id,
|
||||
ip=request.client.host if request.client else None,
|
||||
ip=client_ip(request),
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
)
|
||||
session.commit()
|
||||
@@ -250,12 +250,9 @@ def add_attachment(
|
||||
) -> s.AttachmentRead:
|
||||
match = match_service.get_match(session, match_id)
|
||||
_assert_can_attach(session, match, user)
|
||||
content = file.file.read(_ATTACHMENT_MAX_BYTES + 1)
|
||||
if len(content) > _ATTACHMENT_MAX_BYTES:
|
||||
raise ValidationError("Файл слишком большой (макс. 10 МБ).")
|
||||
ext = user_service.sniff_image_ext(content)
|
||||
if ext is None:
|
||||
raise ValidationError("Поддерживаются только изображения PNG, JPEG или WebP.")
|
||||
content, ext = user_service.read_capped_image(
|
||||
file, attachment_service.MAX_ATTACHMENT_BYTES, "Файл слишком большой (макс. 10 МБ)."
|
||||
)
|
||||
att = attachment_service.add_photo(
|
||||
session, match, user, content, ext, user_service.avatar_media_type(ext)
|
||||
)
|
||||
@@ -315,7 +312,7 @@ def delete_match(
|
||||
entity_type="match",
|
||||
entity_id=match_id_val,
|
||||
payload={"group_id": group_id_val},
|
||||
ip=request.client.host if request.client else None,
|
||||
ip=client_ip(request),
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
)
|
||||
session.commit()
|
||||
|
||||
Reference in New Issue
Block a user