Группы: приглашения вместо авто-добавления (согласиться/отказаться)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,12 +5,14 @@ from fastapi import APIRouter, Depends, Query, Request
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.auth.deps import get_current_user
|
||||
from app.core.timeutil import iso_utc
|
||||
from app.db.session import get_session
|
||||
from app.models import User
|
||||
from app.schemas import api as s
|
||||
from app.services import (
|
||||
audit_service,
|
||||
group_service,
|
||||
invitation_service,
|
||||
membership_service,
|
||||
stats_service,
|
||||
)
|
||||
@@ -128,29 +130,36 @@ def list_members(
|
||||
]
|
||||
|
||||
|
||||
@router.post("/{group_id}/members", response_model=s.MemberRead)
|
||||
def add_member(
|
||||
@router.post("/{group_id}/invitations", response_model=s.InvitationRead)
|
||||
def invite_member(
|
||||
group_id: int,
|
||||
body: s.MemberAdd,
|
||||
request: Request,
|
||||
session: Session = Depends(get_session),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> s.MemberRead:
|
||||
) -> s.InvitationRead:
|
||||
# Приглашать вправе ЛЮБОЙ участник группы (не только владелец) — assert_member.
|
||||
group_service.assert_member(session, group_id, user.id) # type: ignore[arg-type]
|
||||
group = group_service.get_group(session, group_id)
|
||||
member, added = membership_service.add_member_by_nickname(session, group, body.nickname)
|
||||
inv, invited = invitation_service.create_invitation(session, group, user, body.nickname)
|
||||
audit_service.record(
|
||||
session,
|
||||
actor_id=user.id,
|
||||
action="create",
|
||||
entity_type="group_member",
|
||||
entity_type="group_invitation",
|
||||
entity_id=group_id,
|
||||
payload={"added_user_id": added.id, "nickname": added.nickname},
|
||||
payload={"invited_user_id": invited.id, "nickname": invited.nickname},
|
||||
ip=request.client.host if request.client else None,
|
||||
user_agent=request.headers.get("user-agent"),
|
||||
)
|
||||
session.commit()
|
||||
return s.MemberRead(user_id=added.id, nickname=added.nickname, role=member.role)
|
||||
return s.InvitationRead(
|
||||
id=inv.id, # type: ignore[arg-type]
|
||||
group_id=group_id,
|
||||
group_name=group.name,
|
||||
invited_by_nickname=user.nickname,
|
||||
created_at=iso_utc(inv.created_at),
|
||||
)
|
||||
|
||||
|
||||
@router.delete("/{group_id}/members/{user_id}", response_model=s.OkResponse)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Входящие приглашения игрока: список, принятие, отклонение."""
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlmodel import Session
|
||||
|
||||
from app.auth.deps import get_current_user
|
||||
from app.db.session import get_session
|
||||
from app.models import User
|
||||
from app.schemas import api as s
|
||||
from app.services import invitation_service
|
||||
|
||||
router = APIRouter(prefix="/invitations", tags=["invitations"])
|
||||
|
||||
|
||||
@router.get("", response_model=list[s.InvitationRead])
|
||||
def my_invitations(
|
||||
session: Session = Depends(get_session),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> list[dict]:
|
||||
return invitation_service.list_for_user(session, user.id) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@router.post("/{invitation_id}/accept", response_model=s.OkResponse)
|
||||
def accept_invitation(
|
||||
invitation_id: int,
|
||||
session: Session = Depends(get_session),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> s.OkResponse:
|
||||
invitation_service.accept(session, user, invitation_id)
|
||||
return s.OkResponse()
|
||||
|
||||
|
||||
@router.post("/{invitation_id}/decline", response_model=s.OkResponse)
|
||||
def decline_invitation(
|
||||
invitation_id: int,
|
||||
session: Session = Depends(get_session),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> s.OkResponse:
|
||||
invitation_service.decline(session, user, invitation_id)
|
||||
return s.OkResponse()
|
||||
Reference in New Issue
Block a user