93 lines
3.5 KiB
Python
93 lines
3.5 KiB
Python
from ninja import NinjaAPI
|
|
from django.conf import settings
|
|
from django.core.cache import cache
|
|
from django.http import HttpRequest
|
|
from opus_magnum.api import router as opus_magnum_router
|
|
from opus_magnum.schemas import UserInfoOut
|
|
from animations.api import router as results_router
|
|
from noita.api import router as noita_router
|
|
from games.api import router as games_router, event_router as games_event_router
|
|
from market.api import router as market_router
|
|
from submissions.api import router as submissions_router
|
|
|
|
# Create the main API instance
|
|
api = NinjaAPI(
|
|
title="PolyLAN Submission API",
|
|
version="1.0.0",
|
|
description="""API for managing Opus Magnum puzzle submissions, and Noita runs.
|
|
|
|
The Opus Magnum Submission API allows clients to upload, manage, validate, and review puzzle solution submissions for the Opus Magnum puzzle game community.
|
|
It provides features for user authentication, puzzle listing, submission uploads, automated and manual OCR validation, and administrative workflows.
|
|
|
|
The Noita Submission API allows clients to upload the result of the log file of the PolyLAN noita mod. It parses the output, and store each objectiv made by the user.
|
|
""",
|
|
openapi_extra={
|
|
"info": {
|
|
"contact": {
|
|
"name": "Legrems",
|
|
"email": "loic.gremaud@polylan.ch",
|
|
},
|
|
}
|
|
},
|
|
)
|
|
|
|
# Add authentication for protected endpoints
|
|
# api.auth = django_auth # Uncomment if you want global auth
|
|
|
|
# Include the routers
|
|
api.add_router("/games/", games_router, tags=["games"])
|
|
|
|
# Event-scoped routers: all tournament/competition activity belongs to one event.
|
|
# Each operation's own path already starts with "/events/{event_path}/<resource>/..."
|
|
# (see the PREFIX constant in each app's api.py) - django-ninja resolves a path
|
|
# parameter's source (path vs query) from the operation's own registered path
|
|
# string at decoration time, not from whatever prefix add_router() attaches later,
|
|
# so {event_path} has to live there to show up as a real templated path parameter
|
|
# in the generated OpenAPI schema (which the frontend's generated API client needs).
|
|
# These routers are therefore mounted at the root, with no extra prefix here.
|
|
api.add_router("", opus_magnum_router, tags=["opus-magnum"])
|
|
api.add_router("", results_router, tags=["results"])
|
|
api.add_router("", noita_router, tags=["noita"])
|
|
api.add_router("", games_event_router, tags=["games"])
|
|
api.add_router("", submissions_router, tags=["submissions"])
|
|
|
|
if settings.MARKET_ENABLED:
|
|
api.add_router("", market_router, tags=["market"])
|
|
|
|
|
|
# Health check endpoint
|
|
@api.get("/health")
|
|
def health_check(request):
|
|
"""Health check endpoint"""
|
|
return {"status": "healthy", "service": "polylan-submitter-api"}
|
|
|
|
|
|
# Cache management endpoint
|
|
@api.post("/cache/clear")
|
|
def clear_cache(request: HttpRequest, event_path: str | None = None):
|
|
"""Clear API caches (admin only). Pass event_path to clear just that event's keys."""
|
|
if not request.user.is_authenticated or not request.user.is_staff:
|
|
return 403, {"detail": "Admin access required"}
|
|
|
|
pattern = f"api:{event_path}:*" if event_path else "api:*"
|
|
keys = cache.keys(pattern)
|
|
cache.delete_many(keys)
|
|
|
|
return {"detail": f"Cleared {len(keys)} cache entries"}
|
|
|
|
|
|
# User info endpoint
|
|
@api.get("/user", response=UserInfoOut)
|
|
def get_user_info(request):
|
|
"""Get current user information"""
|
|
user = request.user
|
|
|
|
if user.is_authenticated:
|
|
return user
|
|
|
|
return {
|
|
"is_authenticated": False,
|
|
"is_staff": False,
|
|
"is_superuser": False,
|
|
}
|