120 lines
2.9 KiB
Python
120 lines
2.9 KiB
Python
from datetime import datetime
|
|
from pydantic import BaseModel, Field
|
|
from typing import Any
|
|
|
|
|
|
# ============ User Ban ============
|
|
class BanUserRequest(BaseModel):
|
|
reason: str = Field(..., min_length=1, max_length=500)
|
|
banned_until: datetime | None = None # None = permanent ban
|
|
|
|
|
|
class AdminUserResponse(BaseModel):
|
|
id: int
|
|
login: str
|
|
nickname: str
|
|
role: str
|
|
avatar_url: str | None = None
|
|
telegram_id: int | None = None
|
|
telegram_username: str | None = None
|
|
marathons_count: int = 0
|
|
created_at: str
|
|
is_banned: bool = False
|
|
banned_at: str | None = None
|
|
banned_until: str | None = None # None = permanent
|
|
ban_reason: str | None = None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# ============ Admin Logs ============
|
|
class AdminLogResponse(BaseModel):
|
|
id: int
|
|
admin_id: int | None = None # Nullable for system actions
|
|
admin_nickname: str | None = None # Nullable for system actions
|
|
action: str
|
|
target_type: str
|
|
target_id: int
|
|
details: dict | None = None
|
|
ip_address: str | None = None
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AdminLogsListResponse(BaseModel):
|
|
logs: list[AdminLogResponse]
|
|
total: int
|
|
|
|
|
|
# ============ Broadcast ============
|
|
class BroadcastRequest(BaseModel):
|
|
message: str = Field(..., min_length=1, max_length=2000)
|
|
|
|
|
|
class BroadcastResponse(BaseModel):
|
|
sent_count: int
|
|
total_count: int
|
|
|
|
|
|
# ============ Static Content ============
|
|
class StaticContentResponse(BaseModel):
|
|
id: int
|
|
key: str
|
|
title: str
|
|
content: str
|
|
updated_at: datetime
|
|
created_at: datetime
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class StaticContentUpdate(BaseModel):
|
|
title: str = Field(..., min_length=1, max_length=200)
|
|
content: str = Field(..., min_length=1)
|
|
|
|
|
|
class StaticContentCreate(BaseModel):
|
|
key: str = Field(..., min_length=1, max_length=100, pattern=r"^[a-z0-9_-]+$")
|
|
title: str = Field(..., min_length=1, max_length=200)
|
|
content: str = Field(..., min_length=1)
|
|
|
|
|
|
# ============ 2FA ============
|
|
class TwoFactorInitiateRequest(BaseModel):
|
|
pass # No additional data needed
|
|
|
|
|
|
class TwoFactorInitiateResponse(BaseModel):
|
|
session_id: int
|
|
expires_at: datetime
|
|
message: str = "Code sent to Telegram"
|
|
|
|
|
|
class TwoFactorVerifyRequest(BaseModel):
|
|
session_id: int
|
|
code: str = Field(..., min_length=6, max_length=6)
|
|
|
|
|
|
class LoginResponse(BaseModel):
|
|
"""Login response that may require 2FA"""
|
|
access_token: str | None = None
|
|
token_type: str = "bearer"
|
|
user: Any = None # UserPrivate
|
|
requires_2fa: bool = False
|
|
two_factor_session_id: int | None = None
|
|
|
|
|
|
# ============ Dashboard Stats ============
|
|
class DashboardStats(BaseModel):
|
|
users_count: int
|
|
banned_users_count: int
|
|
marathons_count: int
|
|
active_marathons_count: int
|
|
games_count: int
|
|
total_participations: int
|
|
recent_logs: list[AdminLogResponse] = []
|