221 lines
6.2 KiB
Python
221 lines
6.2 KiB
Python
"""Admin router endpoints."""
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, update
|
|
from typing import Optional, List
|
|
from datetime import datetime
|
|
|
|
from app.core.database import get_db
|
|
from app.core.security import get_current_user
|
|
from app.models.models import User, Ban, GameLog, AuditLog
|
|
from app.schemas.schemas import BanCreate, BanResponse
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/users", response_model=List[dict])
|
|
async def list_users(
|
|
page: int = 1,
|
|
page_size: int = 50,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(get_current_user),
|
|
):
|
|
"""List all users (admin only)."""
|
|
# Check if current user is admin
|
|
if current_user.get("privlevel") not in ["Admin", "Judge"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Admin privileges required",
|
|
)
|
|
|
|
stmt = (
|
|
select(User)
|
|
.order_by(User.id)
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
)
|
|
result = await db.execute(stmt)
|
|
users = result.scalars().all()
|
|
|
|
return [
|
|
{
|
|
"id": user.id,
|
|
"username": user.username,
|
|
"email": user.email,
|
|
"privlevel": user.privlevel,
|
|
"is_active": user.is_active,
|
|
"is_banned": user.is_banned,
|
|
"vip_status": user.vip_status,
|
|
"creation_date": user.creation_date,
|
|
}
|
|
for user in users
|
|
]
|
|
|
|
|
|
@router.get("/bans", response_model=List[BanResponse])
|
|
async def list_bans(
|
|
active_only: bool = True,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(get_current_user),
|
|
):
|
|
"""List all bans (admin only)."""
|
|
# Check if current user is admin
|
|
if current_user.get("privlevel") not in ["Admin", "Judge"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Admin privileges required",
|
|
)
|
|
|
|
stmt = select(Ban).order_by(Ban.id)
|
|
if active_only:
|
|
stmt = stmt.where(Ban.active == True)
|
|
|
|
result = await db.execute(stmt)
|
|
bans = result.scalars().all()
|
|
|
|
return [BanResponse.model_validate(ban) for ban in bans]
|
|
|
|
|
|
@router.post("/bans", response_model=BanResponse)
|
|
async def create_ban(
|
|
request: BanCreate,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(get_current_user),
|
|
):
|
|
"""Create a ban (admin only)."""
|
|
# Check if current user is admin
|
|
if current_user.get("privlevel") not in ["Admin", "Judge"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Admin privileges required",
|
|
)
|
|
|
|
new_ban = Ban(
|
|
user_id=request.user_id,
|
|
reason=request.reason,
|
|
expiration_time=request.expiration_time,
|
|
moderators=current_user.get("username"),
|
|
ip_address=None, # Would get from request
|
|
)
|
|
db.add(new_ban)
|
|
await db.flush()
|
|
|
|
return BanResponse.model_validate(new_ban)
|
|
|
|
|
|
@router.post("/bans/{ban_id}/unban")
|
|
async def unban(
|
|
ban_id: int,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(get_current_user),
|
|
):
|
|
"""Unban a user (admin only)."""
|
|
# Check if current user is admin
|
|
if current_user.get("privlevel") not in ["Admin", "Judge"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Admin privileges required",
|
|
)
|
|
|
|
stmt = select(Ban).where(Ban.id == ban_id)
|
|
result = await db.execute(stmt)
|
|
ban = result.scalar_one_or_none()
|
|
|
|
if not ban:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Ban not found",
|
|
)
|
|
|
|
# Deactivate ban
|
|
stmt = (
|
|
update(Ban)
|
|
.where(Ban.id == ban_id)
|
|
.values(active=False)
|
|
)
|
|
await db.execute(stmt)
|
|
|
|
# Also unban the user
|
|
stmt = (
|
|
update(User)
|
|
.where(User.id == ban.user_id)
|
|
.values(
|
|
is_banned=False,
|
|
ban_reason=None,
|
|
ban_ends=None,
|
|
)
|
|
)
|
|
await db.execute(stmt)
|
|
|
|
return {"message": "User unbanned successfully"}
|
|
|
|
|
|
@router.get("/logs", response_model=List[dict])
|
|
async def list_logs(
|
|
room_id: Optional[int] = None,
|
|
limit: int = 100,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(get_current_user),
|
|
):
|
|
"""List game logs (admin only)."""
|
|
# Check if current user is admin
|
|
if current_user.get("privlevel") not in ["Admin", "Judge"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Admin privileges required",
|
|
)
|
|
|
|
stmt = select(GameLog).order_by(GameLog.id.desc()).limit(limit)
|
|
if room_id:
|
|
stmt = stmt.where(GameLog.room_id == room_id)
|
|
|
|
result = await db.execute(stmt)
|
|
logs = result.scalars().all()
|
|
|
|
return [
|
|
{
|
|
"id": log.id,
|
|
"room_id": log.room_id,
|
|
"player_id": log.player_id,
|
|
"message": log.message,
|
|
"timestamp": log.timestamp,
|
|
}
|
|
for log in logs
|
|
]
|
|
|
|
|
|
@router.post("/audit", response_model=dict)
|
|
async def log_audit(
|
|
action_type: str,
|
|
target_user_id: Optional[int] = None,
|
|
details: Optional[str] = None,
|
|
db: AsyncSession = Depends(get_db),
|
|
current_user: dict = Depends(get_current_user),
|
|
):
|
|
"""Create an audit log entry (admin only)."""
|
|
# Check if current user is admin
|
|
if current_user.get("privlevel") not in ["Admin", "Judge"]:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Admin privileges required",
|
|
)
|
|
|
|
new_audit = AuditLog(
|
|
admin_id=int(current_user["user_id"]),
|
|
action_type=action_type,
|
|
target_user_id=target_user_id,
|
|
details=details,
|
|
ip_address=None, # Would get from request
|
|
)
|
|
db.add(new_audit)
|
|
await db.flush()
|
|
|
|
return {
|
|
"id": new_audit.id,
|
|
"admin_id": new_audit.admin_id,
|
|
"action_type": new_audit.action_type,
|
|
"target_user_id": new_audit.target_user_id,
|
|
"details": new_audit.details,
|
|
"timestamp": new_audit.timestamp,
|
|
}
|