中控 Bridge Token 为空时自动生成,Origin 改为选填说明。
打开 env 配置或首次部署即可写入 Token,便于复制到中控登记。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+3
-4
@@ -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=
|
||||||
|
|||||||
Vendored
+9
-2
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user