2026-03-02 01:48:51 +01:00
|
|
|
"""Daily Briefing Dashboard — FastAPI Application."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
from fastapi import FastAPI
|
|
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
from fastapi.responses import FileResponse
|
2026-03-02 01:48:51 +01:00
|
|
|
from fastapi.staticfiles import StaticFiles
|
|
|
|
|
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
from server.config import get_settings, reload_settings, settings
|
2026-03-02 10:13:50 +01:00
|
|
|
from server.services.mqtt_service import mqtt_service
|
2026-03-02 01:48:51 +01:00
|
|
|
|
|
|
|
|
logger = logging.getLogger("daily-briefing")
|
|
|
|
|
logging.basicConfig(
|
|
|
|
|
level=logging.DEBUG if settings.debug else logging.INFO,
|
|
|
|
|
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-02 17:45:23 +01:00
|
|
|
# Reduce noise from third-party libraries — our services log their own summaries
|
|
|
|
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
|
|
|
logging.getLogger("httpcore").setLevel(logging.WARNING)
|
|
|
|
|
|
2026-03-02 01:48:51 +01:00
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
async def lifespan(app: FastAPI):
|
|
|
|
|
"""Startup / shutdown lifecycle."""
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
from server import db
|
|
|
|
|
from server.migrations.runner import run_migrations
|
|
|
|
|
from server.services.seed_service import seed_if_empty
|
2026-03-02 01:48:51 +01:00
|
|
|
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
logger.info("Starting Daily Briefing Dashboard v2.1...")
|
|
|
|
|
|
|
|
|
|
# 1. Initialize shared database pool (bootstrap from ENV)
|
2026-03-02 01:48:51 +01:00
|
|
|
try:
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
pool = await db.init_pool(
|
2026-03-02 01:48:51 +01:00
|
|
|
host=settings.db_host,
|
|
|
|
|
port=settings.db_port,
|
|
|
|
|
dbname=settings.db_name,
|
|
|
|
|
user=settings.db_user,
|
|
|
|
|
password=settings.db_password,
|
|
|
|
|
)
|
|
|
|
|
logger.info("Database pool initialized")
|
|
|
|
|
except Exception:
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
logger.exception("Failed to initialize database pool — admin + news will be unavailable")
|
|
|
|
|
yield
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 2. Run database migrations
|
|
|
|
|
try:
|
|
|
|
|
await run_migrations(pool)
|
|
|
|
|
except Exception:
|
|
|
|
|
logger.exception("Migration error — some features may not work")
|
|
|
|
|
|
|
|
|
|
# 3. Seed database from ENV on first run
|
|
|
|
|
try:
|
|
|
|
|
await seed_if_empty()
|
|
|
|
|
except Exception:
|
|
|
|
|
logger.exception("Seeding error — admin panel may need manual setup")
|
|
|
|
|
|
|
|
|
|
# 4. Load settings from database (overrides ENV defaults)
|
|
|
|
|
try:
|
|
|
|
|
await reload_settings()
|
|
|
|
|
cfg = get_settings()
|
2026-03-02 17:45:23 +01:00
|
|
|
|
|
|
|
|
# Structured startup summary
|
|
|
|
|
integrations = [
|
|
|
|
|
("Weather", True, f"{cfg.weather_location} + {cfg.weather_location_secondary}"),
|
|
|
|
|
("HA", cfg.ha_enabled, cfg.ha_url or "not configured"),
|
|
|
|
|
("Vikunja", cfg.vikunja_enabled, cfg.vikunja_url or "not configured"),
|
|
|
|
|
("Unraid", cfg.unraid_enabled, f"{len(cfg.unraid_servers)} server(s)"),
|
|
|
|
|
("MQTT", cfg.mqtt_enabled, f"{cfg.mqtt_host}:{cfg.mqtt_port}" if cfg.mqtt_host else "not configured"),
|
|
|
|
|
("News", cfg.news_enabled, f"max_age={cfg.news_max_age_hours}h"),
|
|
|
|
|
]
|
|
|
|
|
logger.info("--- Integration Status ---")
|
|
|
|
|
for name, enabled, detail in integrations:
|
|
|
|
|
status = "ON " if enabled else "OFF"
|
|
|
|
|
logger.info(" [%s] %-10s %s", status, name, detail)
|
|
|
|
|
logger.info("--------------------------")
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
except Exception:
|
|
|
|
|
logger.exception("Failed to load settings from DB — using ENV defaults")
|
|
|
|
|
cfg = settings
|
2026-03-02 01:48:51 +01:00
|
|
|
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
# 5. Start MQTT service if enabled
|
|
|
|
|
if cfg.mqtt_enabled and cfg.mqtt_host:
|
2026-03-02 10:13:50 +01:00
|
|
|
try:
|
|
|
|
|
await mqtt_service.start(
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
host=cfg.mqtt_host,
|
|
|
|
|
port=cfg.mqtt_port,
|
|
|
|
|
username=cfg.mqtt_username or None,
|
|
|
|
|
password=cfg.mqtt_password or None,
|
|
|
|
|
topics=cfg.mqtt_topics,
|
|
|
|
|
client_id=cfg.mqtt_client_id,
|
2026-03-02 10:13:50 +01:00
|
|
|
)
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
logger.info("MQTT service started (%s:%d)", cfg.mqtt_host, cfg.mqtt_port)
|
2026-03-02 10:13:50 +01:00
|
|
|
except Exception:
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
logger.exception("Failed to start MQTT service")
|
2026-03-02 10:13:50 +01:00
|
|
|
else:
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
logger.info("MQTT disabled — configure via Admin Panel or MQTT_HOST env")
|
2026-03-02 10:13:50 +01:00
|
|
|
|
2026-03-02 01:48:51 +01:00
|
|
|
yield
|
|
|
|
|
|
|
|
|
|
# Shutdown
|
|
|
|
|
logger.info("Shutting down...")
|
2026-03-02 10:13:50 +01:00
|
|
|
await mqtt_service.stop()
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
await db.close_pool()
|
2026-03-02 01:48:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
app = FastAPI(
|
|
|
|
|
title="Daily Briefing",
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
version="2.1.0",
|
2026-03-02 01:48:51 +01:00
|
|
|
lifespan=lifespan,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# CORS — allow frontend dev server
|
|
|
|
|
app.add_middleware(
|
|
|
|
|
CORSMiddleware,
|
|
|
|
|
allow_origins=["*"],
|
|
|
|
|
allow_credentials=True,
|
|
|
|
|
allow_methods=["*"],
|
|
|
|
|
allow_headers=["*"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# --- Register Routers ---
|
2026-03-02 16:06:10 +01:00
|
|
|
from server.routers import admin, auth, dashboard, homeassistant, mqtt, news, servers, setup, tasks, weather # noqa: E402
|
2026-03-02 01:48:51 +01:00
|
|
|
|
2026-03-02 16:06:10 +01:00
|
|
|
app.include_router(setup.router)
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
app.include_router(auth.router)
|
|
|
|
|
app.include_router(admin.router)
|
2026-03-02 01:48:51 +01:00
|
|
|
app.include_router(weather.router)
|
|
|
|
|
app.include_router(news.router)
|
|
|
|
|
app.include_router(servers.router)
|
|
|
|
|
app.include_router(homeassistant.router)
|
|
|
|
|
app.include_router(tasks.router)
|
2026-03-02 10:13:50 +01:00
|
|
|
app.include_router(mqtt.router)
|
2026-03-02 01:48:51 +01:00
|
|
|
app.include_router(dashboard.router)
|
|
|
|
|
|
|
|
|
|
# --- Serve static frontend (production) ---
|
|
|
|
|
static_dir = Path(__file__).parent.parent / "static"
|
|
|
|
|
if static_dir.is_dir():
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
# SPA fallback: serve index.html for any non-API path
|
2026-03-02 16:06:10 +01:00
|
|
|
@app.get("/setup{full_path:path}")
|
|
|
|
|
async def setup_spa_fallback(full_path: str = ""):
|
|
|
|
|
index = static_dir / "index.html"
|
|
|
|
|
if index.exists():
|
|
|
|
|
return FileResponse(str(index))
|
|
|
|
|
return {"error": "Frontend not built"}
|
|
|
|
|
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
@app.get("/admin/{full_path:path}")
|
|
|
|
|
async def admin_spa_fallback(full_path: str):
|
|
|
|
|
index = static_dir / "index.html"
|
|
|
|
|
if index.exists():
|
|
|
|
|
return FileResponse(str(index))
|
|
|
|
|
return {"error": "Frontend not built"}
|
|
|
|
|
|
2026-03-02 01:48:51 +01:00
|
|
|
app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static")
|
|
|
|
|
logger.info("Serving static frontend from %s", static_dir)
|
|
|
|
|
else:
|
|
|
|
|
@app.get("/")
|
|
|
|
|
async def root():
|
|
|
|
|
return {
|
|
|
|
|
"status": "ok",
|
feat: add Admin Panel with JWT auth, DB settings, and integration management
Complete admin backend with login, where all integrations (weather, news,
Home Assistant, Vikunja, Unraid, MQTT) can be configured via web UI instead
of ENV variables. Two-layer config: ENV seeds DB on first start, then DB
is source of truth. Auto-migration system on startup.
Backend: db.py shared pool, auth.py JWT, settings_service CRUD, seed_service,
admin router (protected), test_connections per integration, config.py rewrite.
Frontend: react-router v6, login page, admin layout with sidebar, 8 settings
pages (General, Weather, News, HA, Vikunja, Unraid, MQTT, ChangePassword),
shared IntegrationForm + TestButton components.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:37:30 +01:00
|
|
|
"message": "Daily Briefing API v2.1 — Frontend not built yet",
|
|
|
|
|
"endpoints": [
|
|
|
|
|
"/api/all", "/api/weather", "/api/news", "/api/servers",
|
|
|
|
|
"/api/ha", "/api/tasks", "/api/mqtt",
|
|
|
|
|
"/api/auth/login", "/api/admin/integrations",
|
|
|
|
|
],
|
2026-03-02 01:48:51 +01:00
|
|
|
}
|