"""Flask 实例许可门禁与 /license 页。""" from __future__ import annotations import os from pathlib import Path from flask import Flask, jsonify, redirect, render_template_string, request from lib.license.license_lib import ( get_device_id, get_license_status, is_license_valid, redeem_code, validate_license, ) _TEMPLATE_PATH = Path(__file__).resolve().parent / "templates" / "license.html" def _allowed_path(path: str) -> bool: if path in ("/license", "/api/license/status", "/api/license/redeem", "/api/license/validate", "/health"): return True if path.startswith("/static/"): return True if path.startswith("/favicon"): return True return False def install_license_gate(app: Flask) -> None: """注册 /license 与 before_request 门禁。三所 Flask 共用。""" @app.get("/health") def _license_health(): st = get_license_status(skip_remote=True) return jsonify({"ok": True, "license_valid": bool(st.get("valid"))}) @app.get("/api/license/status") def _license_status_api(): return jsonify(get_license_status()) @app.post("/api/license/redeem") def _license_redeem_api(): data = request.get_json(silent=True) or {} code = (data.get("code") or request.form.get("code") or "").strip() ckey = (data.get("client_api_key") or request.form.get("client_api_key") or "").strip() return jsonify(redeem_code(code, client_api_key=ckey or None)) @app.post("/api/license/validate") def _license_validate_api(): return jsonify(validate_license(force=True)) @app.route("/license", methods=["GET", "POST"]) def _license_page(): msg = "" err = "" if request.method == "POST": code = (request.form.get("code") or "").strip() ckey = (request.form.get("client_api_key") or "").strip() result = redeem_code(code, client_api_key=ckey or None) if result.get("ok"): msg = result.get("message") or "激活成功" else: err = result.get("message") or "激活失败" status = get_license_status() html = _TEMPLATE_PATH.read_text(encoding="utf-8") return render_template_string( html, device_id=get_device_id(), status=status, message=msg, error=err, api_url=status.get("api_url") or "", wechat="dekun03", ) @app.before_request def _license_before_request(): if os.getenv("LICENSE_DISABLED", "").strip().lower() in ("1", "true", "yes", "on"): return None path = request.path or "/" if _allowed_path(path): return None # hub bridge 内部调用:仍要求已授权(整机许可) if is_license_valid(): return None if path.startswith("/api/"): return jsonify({"ok": False, "error": "license_required", "message": "请先激活许可"}), 403 return redirect("/license")