Initial commit of mtgonline project

This commit is contained in:
2026-07-18 04:57:40 +00:00
commit 86c12376f8
1870 changed files with 547994 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
"""User management router endpoints."""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update
from typing import Optional
from app.core.database import get_db
from app.core.security import get_current_user, hash_password
from app.models.models import User
from app.schemas.schemas import UserUpdate, UserResponse
router = APIRouter()
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
):
"""Get user by ID."""
stmt = select(User).where(User.id == user_id)
result = await db.execute(stmt)
user = result.scalar_one_or_none()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
return UserResponse.model_validate(user)
@router.patch("/{user_id}", response_model=UserResponse)
async def update_user(
user_id: int,
request: UserUpdate,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
):
"""Update user profile."""
# Users can only update their own profile unless admin
if int(current_user["user_id"]) != user_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Cannot update another user's profile",
)
stmt = select(User).where(User.id == user_id)
result = await db.execute(stmt)
user = result.scalar_one_or_none()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
# Update fields
update_data = request.model_dump(exclude_unset=True)
# Hash new password if provided
if "new_password" in update_data:
update_data["password_sha512"] = hash_password(update_data.pop("new_password"))
# Update user
stmt = (
update(User)
.where(User.id == user_id)
.values(**update_data)
)
await db.execute(stmt)
await db.flush()
# Fetch updated user
stmt = select(User).where(User.id == user_id)
result = await db.execute(stmt)
updated_user = result.scalar_one_or_none()
return UserResponse.model_validate(updated_user)
@router.post("/{user_id}/ban")
async def ban_user(
user_id: int,
reason: str,
expiration_time: Optional[str] = None,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user),
):
"""Ban 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(User).where(User.id == user_id)
result = await db.execute(stmt)
user = result.scalar_one_or_none()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
# Update user ban status
from datetime import datetime
ban_ends = None
if expiration_time:
ban_ends = datetime.fromisoformat(expiration_time)
stmt = (
update(User)
.where(User.id == user_id)
.values(
is_banned=True,
ban_reason=reason,
ban_ends=ban_ends,
)
)
await db.execute(stmt)
await db.flush()
return {"message": f"User {user_id} has been banned"}
@router.post("/{user_id}/unban")
async def unban_user(
user_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(User).where(User.id == user_id)
result = await db.execute(stmt)
user = result.scalar_one_or_none()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
# Update user ban status
stmt = (
update(User)
.where(User.id == user_id)
.values(
is_banned=False,
ban_reason=None,
ban_ends=None,
)
)
await db.execute(stmt)
await db.flush()
return {"message": f"User {user_id} has been unbanned"}