from __future__ import annotations from datetime import datetime, timezone import os import platform from flask import Blueprint, jsonify, request, session from app.core_settings import get_settings from app.services.capabilities import build_capabilities from app.services.catalog import get_catalog from app.services.kiosk_settings import get_kiosk_settings_service from app.services.auth import get_auth_service from app.services.influx_http import InfluxHTTPService from app.utils.serialization import to_plain dashboard_blueprint = Blueprint("dashboard", __name__) _APP_STARTED_AT = datetime.now(timezone.utc) def _resolve_kiosk_mode(requested_mode: str, require_write_access: bool = False) -> tuple[str, str]: normalized_mode = (requested_mode or "private").strip().lower() auth_service = get_auth_service() if normalized_mode == "public": if require_write_access and auth_service.enabled and session.get("auth_role") != "admin": raise PermissionError("Brak uprawnien do edycji publicznego kiosku") return "public", "public" if normalized_mode != "private": raise ValueError("Mode musi byc jednym z: public, private") if not auth_service.enabled: return "private", "private" username = session.get("auth_user") if not username: raise PermissionError("Authentication required") return f"user:{username}", "private" @dashboard_blueprint.get("/dashboard/config") def dashboard_config(): settings = get_settings() catalog = get_catalog() capabilities = build_capabilities(catalog) payload = { "app": { "name": settings.app_name, "version": settings.version, "site_name": settings.site_name, "timezone": settings.timezone, "installed_power_kwp": settings.installed_power_kwp, }, "defaults": { "realtime_range": settings.realtime["history_default_range"], "analytics_range": settings.analytics["default_range"], "analytics_bucket": settings.analytics["default_bucket"], "tab": settings.frontend_defaults["tab"], "theme": settings.frontend_defaults["theme"], "language": settings.frontend_defaults["language"], }, "auth": { "enabled": settings.auth["enabled"], }, "i18n": settings.i18n, "capabilities": capabilities, "visible_entities": [ { "metric_id": metric.id, "label": metric.label, "entity_id": metric.entity_id, "measurement": metric.measurement, "unit": metric.unit, "kind": metric.kind, } for metric in catalog.visible_entities() ], } return jsonify(to_plain(payload)) @dashboard_blueprint.get("/dashboard/kiosk-settings") def dashboard_kiosk_settings(): requested_mode = request.args.get("mode") or ("public" if request.args.get("publicKiosk") == "1" else "private") try: storage_mode, response_mode = _resolve_kiosk_mode(requested_mode) payload = get_kiosk_settings_service().get(storage_mode) payload["mode"] = response_mode return jsonify(to_plain(payload)) except PermissionError as exc: return jsonify({"detail": str(exc)}), 403 except ValueError as exc: return jsonify({"detail": str(exc)}), 400 @dashboard_blueprint.put("/dashboard/kiosk-settings") def update_dashboard_kiosk_settings(): payload = request.get_json(silent=True) or {} requested_mode = payload.get("mode", "private") try: storage_mode, response_mode = _resolve_kiosk_mode(requested_mode, require_write_access=True) updated = get_kiosk_settings_service().update_from_session(storage_mode, payload) updated["mode"] = response_mode return jsonify(to_plain(updated)) except PermissionError as exc: return jsonify({"detail": str(exc)}), 403 except ValueError as exc: return jsonify({"detail": str(exc)}), 400 @dashboard_blueprint.get("/dashboard/diagnostics") def dashboard_diagnostics(): auth_service = get_auth_service() try: auth_service.require_admin() except PermissionError as exc: return jsonify({"detail": str(exc)}), 403 settings = get_settings() influx_diagnostics = InfluxHTTPService(settings).diagnose() now = datetime.now(timezone.utc) payload = { "app": { "name": settings.app_name, "version": settings.version, "debug": settings.debug, "timezone": settings.timezone, "site_name": settings.site_name, "installed_power_kwp": settings.installed_power_kwp, "auth_enabled": settings.auth["enabled"], "started_at": _APP_STARTED_AT.isoformat(), "uptime_seconds": max(int((now - _APP_STARTED_AT).total_seconds()), 0), "python_version": platform.python_version(), "pid": os.getpid(), }, "api": { "status": "ok", "prefix": settings.api_prefix, "cors_origins_count": len(settings.cors_origins), }, "influx": influx_diagnostics, "storage": { "sqlite_path": settings.storage["sqlite_path"], "historical_import_enabled": settings.history["enabled"], "auto_sync_enabled": settings.history["auto_sync_enabled"], "default_chunk_days": settings.history["default_chunk_days"], }, } return jsonify(to_plain(payload))