refactors
This commit is contained in:
parent
139a5fbef3
commit
f46d2ae8b3
12 changed files with 734 additions and 536 deletions
|
|
@ -9,11 +9,13 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|||
|
||||
from auth import require_permission
|
||||
from database import get_db
|
||||
from exceptions import BadRequestError, NotFoundError
|
||||
from invite_utils import (
|
||||
generate_invite_identifier,
|
||||
is_valid_identifier_format,
|
||||
normalize_identifier,
|
||||
)
|
||||
from mappers import InviteMapper
|
||||
from models import Invite, InviteStatus, Permission, User
|
||||
from pagination import calculate_offset, create_paginated_response
|
||||
from schemas import (
|
||||
|
|
@ -31,22 +33,6 @@ admin_router = APIRouter(prefix="/api/admin", tags=["admin"])
|
|||
MAX_INVITE_COLLISION_RETRIES = 3
|
||||
|
||||
|
||||
def _to_invite_response(invite: Invite) -> InviteResponse:
|
||||
"""Build an InviteResponse from an Invite with loaded relationships."""
|
||||
return InviteResponse(
|
||||
id=invite.id,
|
||||
identifier=invite.identifier,
|
||||
godfather_id=invite.godfather_id,
|
||||
godfather_email=invite.godfather.email,
|
||||
status=invite.status.value,
|
||||
used_by_id=invite.used_by_id,
|
||||
used_by_email=invite.used_by.email if invite.used_by else None,
|
||||
created_at=invite.created_at,
|
||||
spent_at=invite.spent_at,
|
||||
revoked_at=invite.revoked_at,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{identifier}/check", response_model=InviteCheckResponse)
|
||||
async def check_invite(
|
||||
identifier: str,
|
||||
|
|
@ -118,10 +104,7 @@ async def create_invite(
|
|||
result = await db.execute(select(User.id).where(User.id == data.godfather_id))
|
||||
godfather_id = result.scalar_one_or_none()
|
||||
if not godfather_id:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Godfather user not found",
|
||||
)
|
||||
raise BadRequestError("Godfather user not found")
|
||||
|
||||
# Try to create invite with retry on collision
|
||||
invite: Invite | None = None
|
||||
|
|
@ -150,7 +133,7 @@ async def create_invite(
|
|||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Failed to create invite",
|
||||
)
|
||||
return _to_invite_response(invite)
|
||||
return InviteMapper.to_response(invite)
|
||||
|
||||
|
||||
@admin_router.get("/invites", response_model=PaginatedInviteRecords)
|
||||
|
|
@ -197,7 +180,7 @@ async def list_all_invites(
|
|||
invites = result.scalars().all()
|
||||
|
||||
# Build responses using preloaded relationships
|
||||
records = [_to_invite_response(invite) for invite in invites]
|
||||
records = [InviteMapper.to_response(invite) for invite in invites]
|
||||
|
||||
return create_paginated_response(records, total, page, per_page)
|
||||
|
||||
|
|
@ -213,16 +196,12 @@ async def revoke_invite(
|
|||
invite = result.scalar_one_or_none()
|
||||
|
||||
if not invite:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail="Invite not found",
|
||||
)
|
||||
raise NotFoundError("Invite")
|
||||
|
||||
if invite.status != InviteStatus.READY:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Cannot revoke invite with status '{invite.status.value}'. "
|
||||
"Only READY invites can be revoked.",
|
||||
raise BadRequestError(
|
||||
f"Cannot revoke invite with status '{invite.status.value}'. "
|
||||
"Only READY invites can be revoked."
|
||||
)
|
||||
|
||||
invite.status = InviteStatus.REVOKED
|
||||
|
|
@ -230,7 +209,7 @@ async def revoke_invite(
|
|||
await db.commit()
|
||||
await db.refresh(invite)
|
||||
|
||||
return _to_invite_response(invite)
|
||||
return InviteMapper.to_response(invite)
|
||||
|
||||
|
||||
# All routers from this module for easy registration
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue