diff --git a/custom_components/bahmcloud_store/views.py b/custom_components/bahmcloud_store/views.py index 4011650..2afb852 100644 --- a/custom_components/bahmcloud_store/views.py +++ b/custom_components/bahmcloud_store/views.py @@ -9,7 +9,7 @@ from aiohttp import web from homeassistant.components.http import HomeAssistantView if TYPE_CHECKING: - from .core import BCSCore # typing only, avoids runtime circular import + from .core import BCSCore # typing only _LOGGER = logging.getLogger(__name__) @@ -18,8 +18,10 @@ class StaticAssetsView(HomeAssistantView): url = "/api/bahmcloud_store_static/{path:.*}" name = "api:bahmcloud_store_static" - # RESTORE previous behavior: require HA auth (this worked for you before) - requires_auth = True + # CRITICAL: + # Panel static files (JS/CSS/HTML) must be accessible without auth. + # Otherwise module loads can fail behind proxies/clients and trigger HA's ban middleware. + requires_auth = False async def get(self, request: web.Request, path: str) -> web.Response: base = Path(__file__).resolve().parent / "panel" @@ -39,9 +41,10 @@ class StaticAssetsView(HomeAssistantView): target = (target / "index.html").resolve() if not target.exists(): + _LOGGER.error("BCS static asset not found: %s", target) return web.Response(status=404) - # aiohttp: charset must NOT be included in content_type string + # aiohttp: do NOT include charset in content_type string content_type = "text/plain" charset = None @@ -59,7 +62,12 @@ class StaticAssetsView(HomeAssistantView): elif target.suffix == ".png": content_type = "image/png" - return web.Response(body=target.read_bytes(), content_type=content_type, charset=charset) + resp = web.Response(body=target.read_bytes(), content_type=content_type, charset=charset) + + # Development friendly (prevents stale cached panel.js) + resp.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0" + resp.headers["Pragma"] = "no-cache" + return resp class BCSApiView(HomeAssistantView): @@ -72,11 +80,7 @@ class BCSApiView(HomeAssistantView): async def get(self, request: web.Request) -> web.Response: return web.json_response( - { - "ok": True, - "version": self.core.version, - "repos": self.core.list_repos_public(), - } + {"ok": True, "version": self.core.version, "repos": self.core.list_repos_public()} ) async def post(self, request: web.Request) -> web.Response: @@ -128,22 +132,17 @@ class BCSReadmeView(HomeAssistantView): if not md: return web.json_response({"ok": False, "message": "README not found."}, status=404) + # For now keep html best-effort (we will perfect it after the store is stable again) html = None - - # Best-effort: if HA provides a markdown renderer util, we use it. try: from homeassistant.util.markdown import async_render_markdown # type: ignore - html = await async_render_markdown(self.core.hass, md) except Exception as e: _LOGGER.debug("Markdown render failed: %s", e) - html = None - # Best-effort sanitization if available if html: try: from homeassistant.util.sanitize_html import async_sanitize_html # type: ignore - html = await async_sanitize_html(self.core.hass, html) except Exception as e: _LOGGER.debug("HTML sanitize not available/failed: %s", e)