tts-voice-creator-clone-and.../routes/admin.py
mARTin-B78 db6302f99d Add version number (v1.1.0) and rewrite CHANGELOG to full Keep-a-Changelog spec
- Add VERSION file (1.1.0) at repo root
- core/constants.py: expose __version__ read from VERSION file
- routes/admin.py: GET /api/version endpoint returns {version}
- Settings → About: display "v1.1.0" next to app name via /api/version fetch
- CHANGELOG.md: full rewrite following Keep a Changelog + Semantic Versioning
  - [Unreleased] staging section at top
  - [1.1.0] 2026-05-29 — security, perf, refactor, UX changes from this session
  - [1.0.0] 2026-05-28 — all pre-session features documented
  - Compare links at bottom pointing to GitHub

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 13:53:31 +02:00

58 lines
1.5 KiB
Python

"""Admin routes: index, favicon, browse-dirs, robots."""
from __future__ import annotations
from pathlib import Path
from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse, PlainTextResponse, Response
from core.constants import STATIC_DIR, __version__
router = APIRouter()
_BROWSE_BLOCKED: frozenset[str] = frozenset({
"/proc", "/sys", "/dev", "/run", "/boot",
})
@router.get("/")
async def index():
return FileResponse(
STATIC_DIR / "index.html",
headers={"Cache-Control": "no-store, max-age=0"},
)
@router.get("/favicon.ico")
async def favicon():
return Response(status_code=204)
@router.get("/api/browse-dirs")
async def browse_dirs(path: str = "/"):
p = Path(path).resolve()
p_str = str(p)
if any(p_str == b or p_str.startswith(b + "/") for b in _BROWSE_BLOCKED):
raise HTTPException(403, "Access to this path is not permitted")
if not p.is_dir():
raise HTTPException(404, "Not a directory")
try:
entries = sorted(
[d.name for d in p.iterdir() if d.is_dir() and not d.name.startswith(".")],
key=str.lower,
)
except PermissionError:
raise HTTPException(403, "Permission denied")
parent = str(p.parent) if p.parent != p else None
return {"path": str(p), "parent": parent, "dirs": entries}
@router.get("/api/version")
async def get_version():
return {"version": __version__}
@router.get("/robots.txt", response_class=PlainTextResponse)
async def robots_txt():
return "User-agent: *\nDisallow: /"