custom_components/bahmcloud_store/store.py aktualisiert
This commit is contained in:
@@ -23,7 +23,7 @@ DOMAIN = "bahmcloud_store"
|
||||
|
||||
|
||||
class StoreError(Exception):
|
||||
pass
|
||||
"""Store error."""
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -114,6 +114,7 @@ class BahmcloudStore:
|
||||
|
||||
async def refresh(self) -> None:
|
||||
session = async_get_clientsession(self.hass)
|
||||
|
||||
try:
|
||||
async with session.get(self.config.store_url, timeout=20) as resp:
|
||||
if resp.status != 200:
|
||||
@@ -146,7 +147,7 @@ class BahmcloudStore:
|
||||
pkg.zip_url = self._zip_url(pkg.repo, pkg.branch)
|
||||
parsed[pkg.id] = pkg
|
||||
|
||||
# update latest versions (sequential, safe)
|
||||
# compute latest versions
|
||||
for pkg in parsed.values():
|
||||
latest, rel_url = await self._fetch_latest_version(pkg)
|
||||
pkg.latest_version = latest or "unknown"
|
||||
@@ -176,6 +177,7 @@ class BahmcloudStore:
|
||||
raise StoreError("zip_url not set")
|
||||
|
||||
session = async_get_clientsession(self.hass)
|
||||
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
zip_path = Path(td) / "repo.zip"
|
||||
extract_dir = Path(td) / "extract"
|
||||
@@ -224,27 +226,46 @@ class BahmcloudStore:
|
||||
return None
|
||||
|
||||
async def register_http_views(self) -> None:
|
||||
"""Register HTTP views for static panel assets and JSON API."""
|
||||
self.hass.http.register_view(_StaticView())
|
||||
self.hass.http.register_view(_APIListView(self))
|
||||
|
||||
|
||||
class _StaticView(HomeAssistantView):
|
||||
"""
|
||||
Serves panel assets from: custom_components/bahmcloud_store/panel/
|
||||
|
||||
URLs:
|
||||
/api/bahmcloud_store_static/index.html
|
||||
/api/bahmcloud_store_static/panel.js
|
||||
/api/bahmcloud_store_static/app.js
|
||||
/api/bahmcloud_store_static/styles.css
|
||||
"""
|
||||
requires_auth = True
|
||||
name = "bahmcloud_store_static"
|
||||
url = "/api/bahmcloud_store_static/{path:.*}"
|
||||
|
||||
async def get(self, request, path):
|
||||
base = Path(__file__).resolve().parent / "panel"
|
||||
f = (base / path).resolve()
|
||||
if not str(f).startswith(str(base)) or not f.exists():
|
||||
return web.Response(status=404)
|
||||
if not path:
|
||||
path = "index.html"
|
||||
|
||||
if f.suffix == ".js":
|
||||
f = (base / path).resolve()
|
||||
|
||||
# Prevent path traversal
|
||||
if not str(f).startswith(str(base)) or not f.exists() or not f.is_file():
|
||||
return web.Response(status=404, text="Not found")
|
||||
|
||||
suffix = f.suffix.lower()
|
||||
if suffix == ".js":
|
||||
return web.Response(body=f.read_bytes(), content_type="application/javascript")
|
||||
if f.suffix == ".css":
|
||||
if suffix == ".css":
|
||||
return web.Response(body=f.read_bytes(), content_type="text/css")
|
||||
if suffix in (".html", ".htm"):
|
||||
return web.Response(body=f.read_bytes(), content_type="text/html")
|
||||
|
||||
return web.Response(body=f.read_bytes(), content_type="application/octet-stream")
|
||||
|
||||
|
||||
class _APIListView(HomeAssistantView):
|
||||
requires_auth = True
|
||||
|
||||
Reference in New Issue
Block a user