中控 Bridge Token 为空时自动生成,Origin 改为选填说明。

打开 env 配置或首次部署即可写入 Token,便于复制到中控登记。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-01 11:16:20 +08:00
parent 5806fe2f53
commit a4a9634ba8
4 changed files with 47 additions and 7 deletions
+3 -4
View File
@@ -276,10 +276,9 @@ APP_TIMEZONE=Asia/Shanghai
# TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED # TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED
# ============================================================================= # =============================================================================
# 中控对接(crypto_okx_hub 拉取持仓 / SSO 打开;也可在「系统设置 → env 配置」改) # 中控对接(crypto_okx_hub;也可在「系统设置 → env 配置 → 中控对接」查看)
# ============================================================================= # =============================================================================
# 与中控登记的 Token 一致;留空则 /api/hub/* 拒绝访问 # 首次部署/打开 env 配置时若为空会自动生成;复制到中控「添加实例」的 Bridge Token
HUB_BRIDGE_TOKEN= HUB_BRIDGE_TOKEN=
# 允许嵌入本站的中控 Origin(空格分隔);例: http://192.168.1.10:5100 https://hub.example.com # 选填。允许嵌入本站的中控 Origin(空格分隔);一般留空即可;iframe 被挡时再填,调试可 *
# 设为 * 允许任意父页(仅内网调试)
HUB_EMBED_FRAME_ANCESTORS= HUB_EMBED_FRAME_ANCESTORS=
+9 -2
View File
@@ -64,12 +64,12 @@ _SHARED_SECTIONS: list[dict[str, Any]] = [
( (
"HUB_BRIDGE_TOKEN", "HUB_BRIDGE_TOKEN",
"中控 Bridge Token", "中控 Bridge Token",
"与 crypto_okx_hub「添加实例」里的 Bridge Token 一致;可自拟长随机串,两边填相同值;留空则中控无法拉持仓", "首次打开本页自动生成;复制到 crypto_okx_hub「添加实例」即可;也可手动改后保存",
), ),
( (
"HUB_EMBED_FRAME_ANCESTORS", "HUB_EMBED_FRAME_ANCESTORS",
"允许嵌入的中控 Origin", "允许嵌入的中控 Origin",
"空格分隔,例: http://中控IP:5100 https://hub.example.com;调试可填 *", "选填。一般可留空;仅当中控 iframe 打不开时再填中控地址(空格分隔),或调试填 *",
), ),
], ],
}, },
@@ -279,6 +279,13 @@ def build_env_ui_payload(
example_path: str, example_path: str,
env_path: str, env_path: str,
) -> list[dict[str, Any]]: ) -> list[dict[str, Any]]:
# 首次打开 env 配置时若 Token 为空则自动生成,便于复制到中控
try:
from lib.hub.hub_bridge_auth import ensure_hub_bridge_token
ensure_hub_bridge_token(env_path)
except Exception:
pass
schema = _schema_field_map(example_path) schema = _schema_field_map(example_path)
env_lines = read_env_lines(env_path) env_lines = read_env_lines(env_path)
values = env_get_all(env_lines) values = env_get_all(env_lines)
+26
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
import hashlib import hashlib
import hmac import hmac
import os import os
import secrets
import time import time
from typing import Optional from typing import Optional
from urllib.parse import urlencode from urllib.parse import urlencode
@@ -94,3 +95,28 @@ def frame_ancestors_header_value() -> Optional[str]:
return "*" return "*"
parts = [p.strip() for p in raw.split() if p.strip()] parts = [p.strip() for p in raw.split() if p.strip()]
return " ".join(parts) if parts else None return " ".join(parts) if parts else None
def ensure_hub_bridge_token(env_path: str) -> str:
"""若 .env 中 HUB_BRIDGE_TOKEN 为空则生成并写入;返回当前 token."""
from lib.env.env_file_lib import apply_env_updates, env_get, read_env_lines
path = (env_path or "").strip()
if not path or not os.path.isfile(path):
existing = hub_bridge_token()
if existing:
return existing
token = secrets.token_urlsafe(32)
os.environ["HUB_BRIDGE_TOKEN"] = token
return token
lines = read_env_lines(path)
cur = (env_get(lines, "HUB_BRIDGE_TOKEN") or "").strip()
if cur:
os.environ["HUB_BRIDGE_TOKEN"] = cur
return cur
token = secrets.token_urlsafe(32)
apply_env_updates(path, {"HUB_BRIDGE_TOKEN": token})
os.environ["HUB_BRIDGE_TOKEN"] = token
return token
+9 -1
View File
@@ -3,6 +3,7 @@
- FLASK_SECRET_KEY - FLASK_SECRET_KEY
- APP_USERNAME=admin / APP_PASSWORD=admin123(仅空时) - APP_USERNAME=admin / APP_PASSWORD=admin123(仅空时)
- HUB_BRIDGE_TOKEN(仅空时,供中控对接)
""" """
from __future__ import annotations from __future__ import annotations
@@ -47,6 +48,9 @@ def main() -> int:
if (cur_pass or "").strip() in PASSWORD_PLACEHOLDERS: if (cur_pass or "").strip() in PASSWORD_PLACEHOLDERS:
updates["APP_PASSWORD"] = "admin123" updates["APP_PASSWORD"] = "admin123"
if not (env_get(lines, "HUB_BRIDGE_TOKEN") or "").strip():
updates["HUB_BRIDGE_TOKEN"] = secrets.token_urlsafe(32)
if not updates: if not updates:
print(" 密钥已存在,无需写入") print(" 密钥已存在,无需写入")
return 0 return 0
@@ -54,7 +58,11 @@ def main() -> int:
print(f" 将更新 {env_path}: {', '.join(updates.keys())}") print(f" 将更新 {env_path}: {', '.join(updates.keys())}")
if args.dry_run: if args.dry_run:
for k, v in updates.items(): for k, v in updates.items():
shown = v if k != "APP_PASSWORD" and "SECRET" not in k else "***" shown = (
"***"
if k in ("APP_PASSWORD", "HUB_BRIDGE_TOKEN") or "SECRET" in k
else v
)
print(f" {k}={shown}") print(f" {k}={shown}")
return 0 return 0