""" Static Files Controller Serves static files for widgets and other frontend assets. """ from fastapi import APIRouter from fastapi.responses import FileResponse, HTMLResponse from pathlib import Path import os from src.controllers.base import BaseController from src.logging_config import get_logger logger = get_logger(__name__) class StaticController(BaseController): """ Controller for serving static files Provides endpoints for: - Organizr widgets - Other static assets """ def __init__(self): super().__init__(prefix="/static", tags=["Static"]) self.static_dir = Path(__file__).parent.parent.parent / "static" def create_router(self) -> APIRouter: """Create and configure the router""" router = APIRouter(prefix=self.prefix, tags=self.tags) @router.get( "/widgets/{filename}", response_class=HTMLResponse, summary="Get widget file" ) async def get_widget(filename: str): """ Serve widget HTML files Args: filename: Widget filename (e.g., service-control.html) Returns: HTML file content """ widget_path = self.static_dir / "widgets" / filename if not widget_path.exists(): return HTMLResponse( content=f"

404 - Widget not found

{filename}

", status_code=404 ) if not widget_path.is_file(): return HTMLResponse( content=f"

400 - Not a file

", status_code=400 ) # Security: Ensure the path is within the static directory try: widget_path.resolve().relative_to(self.static_dir.resolve()) except ValueError: return HTMLResponse( content=f"

403 - Forbidden

", status_code=403 ) logger.info(f"Serving widget: {filename}") return FileResponse( widget_path, media_type="text/html", headers={ "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0" } ) @router.get( "/widgets", summary="List available widgets" ) async def list_widgets(): """ List all available widget files Returns: List of widget filenames """ widgets_dir = self.static_dir / "widgets" if not widgets_dir.exists(): return {"widgets": [], "message": "Widgets directory not found"} widgets = [] for file in widgets_dir.glob("*.html"): widgets.append({ "name": file.name, "url": f"/static/widgets/{file.name}", "size": file.stat().st_size }) return { "widgets": widgets, "count": len(widgets) } return router # Create controller instance static_controller = StaticController()