refactor: harden registration runtime
This commit is contained in:
@@ -1,30 +0,0 @@
|
|||||||
name: Temporary remaining review fixes
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- tools/apply_remaining_review_fixes.py
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
apply:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Apply remaining review fixes
|
|
||||||
run: python tools/apply_remaining_review_fixes.py
|
|
||||||
- name: Commit fixes and remove temporary files
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git rm -f tools/apply_remaining_review_fixes.py .github/workflows/temp-remaining-review-fixes.yml
|
|
||||||
git add -A
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "No changes to commit"
|
|
||||||
else
|
|
||||||
git commit -m "refactor: harden registration runtime"
|
|
||||||
git push
|
|
||||||
fi
|
|
||||||
+4
-1
@@ -35,5 +35,8 @@
|
|||||||
"defaultDomains": "example.com",
|
"defaultDomains": "example.com",
|
||||||
"email_provider": "cloudflare",
|
"email_provider": "cloudflare",
|
||||||
"yyds_api_key": "",
|
"yyds_api_key": "",
|
||||||
"yyds_jwt": ""
|
"yyds_jwt": "",
|
||||||
|
"cpa_oidc_request_timeout_sec": 15,
|
||||||
|
"cpa_oidc_poll_timeout_sec": 15,
|
||||||
|
"grok2api_allow_legacy_full_save": false
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-5
@@ -94,6 +94,10 @@ DEFAULT_CONFIG = {
|
|||||||
"cpa_oidc_request_timeout_sec": 15,
|
"cpa_oidc_request_timeout_sec": 15,
|
||||||
"cpa_oidc_poll_timeout_sec": 15,
|
"cpa_oidc_poll_timeout_sec": 15,
|
||||||
"grok2api_allow_legacy_full_save": False,
|
"grok2api_allow_legacy_full_save": False,
|
||||||
|
"email_provider": "duckmail",
|
||||||
|
"yyds_api_key": "",
|
||||||
|
"yyds_jwt": "",
|
||||||
|
"defaultDomains": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
config = DEFAULT_CONFIG.copy()
|
config = DEFAULT_CONFIG.copy()
|
||||||
@@ -188,6 +192,34 @@ def validate_config(raw):
|
|||||||
if value not in allowed:
|
if value not in allowed:
|
||||||
raise ConfigError(f"配置项 {key} 的值无效: {value!r}; 允许值: {sorted(allowed)}")
|
raise ConfigError(f"配置项 {key} 的值无效: {value!r}; 允许值: {sorted(allowed)}")
|
||||||
cfg[key] = value
|
cfg[key] = value
|
||||||
|
|
||||||
|
api_path_keys = {
|
||||||
|
"cloudflare_path_domains", "cloudflare_path_accounts",
|
||||||
|
"cloudflare_path_token", "cloudflare_path_messages",
|
||||||
|
"cloudmail_path_messages",
|
||||||
|
}
|
||||||
|
for key in api_path_keys:
|
||||||
|
value = cfg[key]
|
||||||
|
if value and not value.startswith("/"):
|
||||||
|
value = "/" + value
|
||||||
|
cfg[key] = value
|
||||||
|
|
||||||
|
url_keys = {
|
||||||
|
"cloudflare_api_base", "cloudmail_api_base",
|
||||||
|
"grok2api_remote_base", "cpa_base_url",
|
||||||
|
}
|
||||||
|
for key in url_keys:
|
||||||
|
value = cfg[key]
|
||||||
|
if not value:
|
||||||
|
continue
|
||||||
|
parsed = urllib.parse.urlsplit(value)
|
||||||
|
if parsed.scheme not in ("http", "https") or not parsed.netloc:
|
||||||
|
raise ConfigError(f"配置项 {key} 必须是有效的 http/https URL")
|
||||||
|
|
||||||
|
for key in path_keys:
|
||||||
|
value = cfg[key]
|
||||||
|
if value.startswith("~"):
|
||||||
|
cfg[key] = os.path.expanduser(value)
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
|
|
||||||
@@ -968,11 +1000,12 @@ def add_token_to_grok2api_remote_pool(raw_token, email="", log_callback=None):
|
|||||||
if token not in existing:
|
if token not in existing:
|
||||||
pool.append({"token": token, "tags": ["auto-register"], "note": email})
|
pool.append({"token": token, "tags": ["auto-register"], "note": email})
|
||||||
current[pool_name] = pool
|
current[pool_name] = pool
|
||||||
|
if not etag:
|
||||||
|
raise RemoteTokenCompatibilityError(
|
||||||
|
"旧版远端接口未提供 ETag,无法保证并发安全,已拒绝全量保存"
|
||||||
|
)
|
||||||
save_headers = dict(headers)
|
save_headers = dict(headers)
|
||||||
if etag:
|
save_headers["If-Match"] = etag
|
||||||
save_headers["If-Match"] = etag
|
|
||||||
elif log_callback:
|
|
||||||
log_callback("[!] 旧版远端接口未提供 ETag;已由显式配置允许,但仍不建议多实例并发")
|
|
||||||
endpoint = f"{fallback_base}/tokens"
|
endpoint = f"{fallback_base}/tokens"
|
||||||
try:
|
try:
|
||||||
response = http_post(endpoint, headers=save_headers, params=query, json=current, timeout=30)
|
response = http_post(endpoint, headers=save_headers, params=query, json=current, timeout=30)
|
||||||
@@ -3523,6 +3556,8 @@ class GrokRegisterGUI:
|
|||||||
line = event[1]
|
line = event[1]
|
||||||
self.log_text.insert(tk.END, f"{line}\n")
|
self.log_text.insert(tk.END, f"{line}\n")
|
||||||
self.log_text.see(tk.END)
|
self.log_text.see(tk.END)
|
||||||
|
elif kind == "clear_log":
|
||||||
|
self.log_text.delete(1.0, tk.END)
|
||||||
elif kind == "stats":
|
elif kind == "stats":
|
||||||
self.stats_var.set(f"成功: {event[1]} | 失败: {event[2]}")
|
self.stats_var.set(f"成功: {event[1]} | 失败: {event[2]}")
|
||||||
elif kind == "running":
|
elif kind == "running":
|
||||||
@@ -3550,7 +3585,7 @@ class GrokRegisterGUI:
|
|||||||
self.ui_queue.put(("log", line))
|
self.ui_queue.put(("log", line))
|
||||||
|
|
||||||
def clear_log(self):
|
def clear_log(self):
|
||||||
self.log_text.delete(1.0, tk.END)
|
self.ui_queue.put(("clear_log",))
|
||||||
|
|
||||||
def update_stats(self):
|
def update_stats(self):
|
||||||
self.ui_queue.put(("stats", self.success_count, self.fail_count))
|
self.ui_queue.put(("stats", self.success_count, self.fail_count))
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from pathlib import Path
|
|
||||||
import ast
|
|
||||||
import json
|
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[1]
|
|
||||||
MAIN = ROOT / "grok_register_ttk.py"
|
|
||||||
CONFIG_EXAMPLE = ROOT / "config.example.json"
|
|
||||||
|
|
||||||
|
|
||||||
def read(path):
|
|
||||||
return path.read_text(encoding="utf-8-sig")
|
|
||||||
|
|
||||||
|
|
||||||
def replace_once(text, old, new, label):
|
|
||||||
count = text.count(old)
|
|
||||||
if count != 1:
|
|
||||||
raise RuntimeError(f"{label}: expected one match, got {count}")
|
|
||||||
return text.replace(old, new, 1)
|
|
||||||
|
|
||||||
|
|
||||||
main = read(MAIN)
|
|
||||||
|
|
||||||
main = replace_once(
|
|
||||||
main,
|
|
||||||
' "grok2api_allow_legacy_full_save": False,\n}',
|
|
||||||
' "grok2api_allow_legacy_full_save": False,\n'
|
|
||||||
' "email_provider": "duckmail",\n'
|
|
||||||
' "yyds_api_key": "",\n'
|
|
||||||
' "yyds_jwt": "",\n'
|
|
||||||
' "defaultDomains": "",\n'
|
|
||||||
'}',
|
|
||||||
"complete default config",
|
|
||||||
)
|
|
||||||
|
|
||||||
main = replace_once(
|
|
||||||
main,
|
|
||||||
''' for key, allowed in enums.items():
|
|
||||||
value = cfg.get(key, DEFAULT_CONFIG.get(key, ""))
|
|
||||||
if value not in allowed:
|
|
||||||
raise ConfigError(f"配置项 {key} 的值无效: {value!r}; 允许值: {sorted(allowed)}")
|
|
||||||
cfg[key] = value
|
|
||||||
return cfg
|
|
||||||
''',
|
|
||||||
''' for key, allowed in enums.items():
|
|
||||||
value = cfg.get(key, DEFAULT_CONFIG.get(key, ""))
|
|
||||||
if value not in allowed:
|
|
||||||
raise ConfigError(f"配置项 {key} 的值无效: {value!r}; 允许值: {sorted(allowed)}")
|
|
||||||
cfg[key] = value
|
|
||||||
|
|
||||||
api_path_keys = {
|
|
||||||
"cloudflare_path_domains", "cloudflare_path_accounts",
|
|
||||||
"cloudflare_path_token", "cloudflare_path_messages",
|
|
||||||
"cloudmail_path_messages",
|
|
||||||
}
|
|
||||||
for key in api_path_keys:
|
|
||||||
value = cfg[key]
|
|
||||||
if value and not value.startswith("/"):
|
|
||||||
value = "/" + value
|
|
||||||
cfg[key] = value
|
|
||||||
|
|
||||||
url_keys = {
|
|
||||||
"cloudflare_api_base", "cloudmail_api_base",
|
|
||||||
"grok2api_remote_base", "cpa_base_url",
|
|
||||||
}
|
|
||||||
for key in url_keys:
|
|
||||||
value = cfg[key]
|
|
||||||
if not value:
|
|
||||||
continue
|
|
||||||
parsed = urllib.parse.urlsplit(value)
|
|
||||||
if parsed.scheme not in ("http", "https") or not parsed.netloc:
|
|
||||||
raise ConfigError(f"配置项 {key} 必须是有效的 http/https URL")
|
|
||||||
|
|
||||||
for key in path_keys:
|
|
||||||
value = cfg[key]
|
|
||||||
if value.startswith("~"):
|
|
||||||
cfg[key] = os.path.expanduser(value)
|
|
||||||
return cfg
|
|
||||||
''',
|
|
||||||
"normalize validated config",
|
|
||||||
)
|
|
||||||
|
|
||||||
main = replace_once(
|
|
||||||
main,
|
|
||||||
''' save_headers = dict(headers)
|
|
||||||
if etag:
|
|
||||||
save_headers["If-Match"] = etag
|
|
||||||
elif log_callback:
|
|
||||||
log_callback("[!] 旧版远端接口未提供 ETag;已由显式配置允许,但仍不建议多实例并发")
|
|
||||||
''',
|
|
||||||
''' if not etag:
|
|
||||||
raise RemoteTokenCompatibilityError(
|
|
||||||
"旧版远端接口未提供 ETag,无法保证并发安全,已拒绝全量保存"
|
|
||||||
)
|
|
||||||
save_headers = dict(headers)
|
|
||||||
save_headers["If-Match"] = etag
|
|
||||||
''',
|
|
||||||
"require ETag for legacy save",
|
|
||||||
)
|
|
||||||
|
|
||||||
main = replace_once(
|
|
||||||
main,
|
|
||||||
''' if kind == "log":
|
|
||||||
line = event[1]
|
|
||||||
self.log_text.insert(tk.END, f"{line}\\n")
|
|
||||||
self.log_text.see(tk.END)
|
|
||||||
elif kind == "stats":
|
|
||||||
''',
|
|
||||||
''' if kind == "log":
|
|
||||||
line = event[1]
|
|
||||||
self.log_text.insert(tk.END, f"{line}\\n")
|
|
||||||
self.log_text.see(tk.END)
|
|
||||||
elif kind == "clear_log":
|
|
||||||
self.log_text.delete(1.0, tk.END)
|
|
||||||
elif kind == "stats":
|
|
||||||
''',
|
|
||||||
"GUI clear event",
|
|
||||||
)
|
|
||||||
|
|
||||||
main = replace_once(
|
|
||||||
main,
|
|
||||||
''' def clear_log(self):
|
|
||||||
self.log_text.delete(1.0, tk.END)
|
|
||||||
''',
|
|
||||||
''' def clear_log(self):
|
|
||||||
self.ui_queue.put(("clear_log",))
|
|
||||||
''',
|
|
||||||
"queue clear log",
|
|
||||||
)
|
|
||||||
|
|
||||||
ast.parse(main, filename=str(MAIN))
|
|
||||||
MAIN.write_text(main, encoding="utf-8")
|
|
||||||
|
|
||||||
if CONFIG_EXAMPLE.exists():
|
|
||||||
data = json.loads(read(CONFIG_EXAMPLE))
|
|
||||||
data.setdefault("email_provider", "duckmail")
|
|
||||||
data.setdefault("yyds_api_key", "")
|
|
||||||
data.setdefault("yyds_jwt", "")
|
|
||||||
data.setdefault("defaultDomains", "")
|
|
||||||
data.setdefault("cpa_oidc_request_timeout_sec", 15)
|
|
||||||
data.setdefault("cpa_oidc_poll_timeout_sec", 15)
|
|
||||||
data.setdefault("grok2api_allow_legacy_full_save", False)
|
|
||||||
CONFIG_EXAMPLE.write_text(
|
|
||||||
json.dumps(data, ensure_ascii=False, indent=2) + "\n",
|
|
||||||
encoding="utf-8",
|
|
||||||
)
|
|
||||||
|
|
||||||
print("remaining review fixes applied")
|
|
||||||
Reference in New Issue
Block a user