removed authorization for browser user

This commit is contained in:
2026-08-09 17:25:45 +02:00
parent b477737bad
commit 2677c81d0f
4 changed files with 18 additions and 61 deletions
+3 -27
View File
@@ -4,7 +4,6 @@
from __future__ import annotations
import argparse
import hmac
import os
from pathlib import Path
from typing import Any
@@ -124,7 +123,7 @@ def next_scene(button: dict[str, Any], bridge: HueBridge) -> dict[str, Any]:
return {"name": selected.get("metadata", {}).get("name", "scene")}
def create_app(yaml_path: Path, verify_tls: bool, api_key: str, url_prefix: str = "") -> Flask:
def create_app(yaml_path: Path, verify_tls: bool, url_prefix: str = "") -> Flask:
app = Flask(__name__)
if url_prefix:
# Gunicorn only receives traffic over its private socket from Nginx.
@@ -132,22 +131,11 @@ def create_app(yaml_path: Path, verify_tls: bool, api_key: str, url_prefix: str
app.wsgi_app = ProxyFix(app.wsgi_app, x_prefix=1)
buttons = read_dashboard(yaml_path)
def api_key_required(view: Any) -> Any:
def protected(*args: Any, **kwargs: Any) -> Any:
authorization = request.headers.get("Authorization", "")
expected = f"Bearer {api_key}"
if not hmac.compare_digest(authorization, expected):
return jsonify({"error": "Unauthorized"}), 401
return view(*args, **kwargs)
protected.__name__ = view.__name__
return protected
@app.get("/")
def index() -> str:
return render_template("index.html", buttons=buttons)
@app.get("/api/groups")
@api_key_required
def groups() -> Any:
try:
return jsonify({"groups": dashboard_state(buttons, verify_tls)})
@@ -155,7 +143,6 @@ def create_app(yaml_path: Path, verify_tls: bool, api_key: str, url_prefix: str
return jsonify({"error": str(exc)}), 503
@app.post("/api/groups/<group_id>/next-scene")
@api_key_required
def activate_next_scene(group_id: str) -> Any:
try:
button = next(item for item in buttons if item["id"] == group_id)
@@ -168,7 +155,6 @@ def create_app(yaml_path: Path, verify_tls: bool, api_key: str, url_prefix: str
return jsonify({"error": str(exc)}), 503
@app.post("/api/groups/<group_id>/off")
@api_key_required
def turn_group_off(group_id: str) -> Any:
try:
button = next(item for item in buttons if item["id"] == group_id)
@@ -182,7 +168,6 @@ def create_app(yaml_path: Path, verify_tls: bool, api_key: str, url_prefix: str
return jsonify({"error": str(exc)}), 503
@app.post("/api/groups/<group_name>/scene")
@api_key_required
def activate_group_scene(group_name: str) -> Any:
payload = request.get_json(silent=True) or {}
scene_name = payload.get("name")
@@ -226,12 +211,8 @@ def configured_url_prefix(path: Path = APP_CONFIG) -> str:
def create_gunicorn_app() -> Flask:
"""Gunicorn application factory; configuration is read from environment/files."""
config_path = Path(os.environ.get("FASTHUE_DASHBOARD_CONFIG", ROOT / "hue.yaml"))
secrets_config = load_config(Path(os.environ.get("FASTHUE_SECRETS_FILE", DEFAULT_CONFIG)).expanduser())
api_key = os.environ.get("FASTHUE_API_KEY") or secrets_config.get("api_key")
if not api_key:
raise RuntimeError("add api_key to secrets.yaml or set FASTHUE_API_KEY")
verify_tls = os.environ.get("FASTHUE_VERIFY_TLS", "").casefold() in {"1", "true", "yes"}
return create_app(config_path, verify_tls, api_key, configured_url_prefix())
return create_app(config_path, verify_tls, configured_url_prefix())
# Older Gunicorn releases do not support --factory. Expose a WSGI callable at
@@ -244,19 +225,14 @@ def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--config", type=Path, default=ROOT / "hue.yaml", help="Dashboard YAML file")
parser.add_argument("--verify-tls", action="store_true", help="Verify the Hue bridge certificate")
parser.add_argument("--api-key", help="Required Bearer token for the dashboard API")
parser.add_argument("--url-prefix", help="Override the reverse-proxy URL prefix from config.yaml")
parser.add_argument("--host", default="0.0.0.0", help="Listen address")
parser.add_argument("--port", type=int, default=5000, help="Listen port")
args = parser.parse_args()
secrets_config = load_config(Path(os.environ.get("FASTHUE_SECRETS_FILE", DEFAULT_CONFIG)).expanduser())
api_key = args.api_key or os.environ.get("FASTHUE_API_KEY") or secrets_config.get("api_key")
if not api_key:
parser.error("add api_key to secrets.yaml, set FASTHUE_API_KEY, or supply --api-key")
url_prefix = args.url_prefix.rstrip("/") if args.url_prefix is not None else configured_url_prefix()
if url_prefix and not url_prefix.startswith("/"):
parser.error("--url-prefix must start with /, for example /hue")
create_app(args.config, args.verify_tls, api_key, url_prefix).run(host=args.host, port=args.port, debug=False)
create_app(args.config, args.verify_tls, url_prefix).run(host=args.host, port=args.port, debug=False)
if __name__ == "__main__":