Add admin management endpoints

This commit is contained in:
2026-04-27 18:31:57 +02:00
parent d62aa92590
commit 5bb864f34f

View File

@@ -1,20 +1,47 @@
# Add to api/app/main.py (after the existing imports and app definition)
import os
from fastapi import Request, Query
from fastapi import FastAPI, HTTPException, Depends, Header, Query, Request
from fastapi.responses import JSONResponse
from .influx import client, INFLUX_ORG, INFLUX_BUCKET
import sqlite3
from .auth import init_db, verify_api_key, get_db # make sure auth.py exports get_db
from .models import Event, BatchEvents
from .enrichment import enrich_event
from .influx import write_event, client, INFLUX_ORG, INFLUX_BUCKET
import logging
import os
import secrets
import datetime
ADMIN_KEY = os.getenv("ADMIN_API_KEY", "admin-secret-change-me")
logging.basicConfig(level=logging.INFO)
# ---------- simple admin auth helper ----------
# Environment variables
ADMIN_API_KEY = os.getenv("ADMIN_API_KEY", "admin-secret-change-me")
# Initialise database (creates table if missing)
init_db()
app = FastAPI(title="Signal - Roblox Telemetry")
# ---------- Original endpoints ----------
@app.get("/health")
async def health():
return {"status": "ok"}
@app.post("/api/log")
async def ingest_event(payload: Event | BatchEvents, game: str = Depends(verify_api_key)):
if isinstance(payload, BatchEvents):
for event in payload.events:
enriched = enrich_event(event, game)
write_event(enriched)
else:
enriched = enrich_event(payload, game)
write_event(enriched)
return {"success": True}
# ---------- Admin authentication helper ----------
def require_admin(x_admin_key: str = Header(None)):
if not x_admin_key or x_admin_key != ADMIN_KEY:
if not x_admin_key or x_admin_key != ADMIN_API_KEY:
raise HTTPException(status_code=403, detail="Forbidden")
return True
# ---------- API Keys Management ----------
# ---------- Admin: API Keys ----------
@app.get("/admin/keys")
async def list_keys(admin: bool = Depends(require_admin)):
conn = get_db()
@@ -25,8 +52,7 @@ async def list_keys(admin: bool = Depends(require_admin)):
@app.post("/admin/keys")
async def create_key(game: str = Query(...), key: str = Query(None), admin: bool = Depends(require_admin)):
if not key:
import secrets
key = secrets.token_hex(16) # auto-generate if not provided
key = secrets.token_hex(16)
conn = get_db()
conn.execute("INSERT OR REPLACE INTO api_keys(key, game, active) VALUES(?, ?, 1)", (key, game))
conn.commit()
@@ -49,16 +75,16 @@ async def delete_key(key: str, admin: bool = Depends(require_admin)):
conn.close()
return {"ok": True}
# ---------- InfluxDB Bucket Info ----------
# ---------- Admin: InfluxDB Buckets ----------
@app.get("/admin/buckets")
async def list_buckets(admin: bool = Depends(require_admin)):
if not client:
return JSONResponse({"error": "InfluxDB client not initialised"}, status_code=503)
buckets_api = client.buckets_api()
buckets = buckets_api.find_buckets().buckets
return [{"name": b.name, "id": b.id, "org": b.org_id} for b in buckets]
return [{"name": b.name, "id": b.id} for b in buckets]
# ---------- View recent events ----------
# ---------- Admin: Events ----------
@app.get("/admin/events")
async def list_events(hours: float = 24, limit: int = 100, admin: bool = Depends(require_admin)):
if not client:
@@ -80,11 +106,10 @@ async def list_events(hours: float = 24, limit: int = 100, admin: bool = Depends
})
return events[:limit]
# ---------- Delete events (by time range + optional measurement) ----------
@app.delete("/admin/events")
async def delete_events(
start: str = Query(..., description="ISO timestamp, e.g. 2026-04-27T00:00:00Z"),
stop: str = Query(..., description="ISO timestamp"),
start: str = Query(..., description="ISO timestamp"),
stop: str = Query(...),
measurement: str = Query(None),
admin: bool = Depends(require_admin)
):