feat: support real browser auth import
This commit is contained in:
@@ -221,25 +221,45 @@ class RefreshAuthResponse(BaseModel):
|
||||
warning: Optional[str] = None
|
||||
|
||||
|
||||
def _pick_best_candidate(candidates: list[dict], preferred_auth_type: str) -> Optional[dict]:
|
||||
def _norm_path(value: Any) -> str:
|
||||
return str(value or "").strip().rstrip("/")
|
||||
|
||||
|
||||
def _detect_upstream_platform(upstream: Upstream, auth_config: dict) -> str:
|
||||
api_prefix = _norm_path(upstream.api_prefix)
|
||||
groups_endpoint = _norm_path(upstream.groups_endpoint)
|
||||
rate_endpoint = _norm_path(upstream.rate_endpoint)
|
||||
login_path = _norm_path(auth_config.get("login_path"))
|
||||
|
||||
if groups_endpoint == "/api/user/self/groups" or login_path == "/api/user/login":
|
||||
return "new-api-user"
|
||||
if api_prefix == "/api/v1" or groups_endpoint in {"/groups/available", "/groups/rates"} or login_path == "/auth/login":
|
||||
return "sub2api"
|
||||
return "unknown"
|
||||
|
||||
|
||||
def _first_candidate(candidates: list[dict], *types: str) -> Optional[dict]:
|
||||
for c in candidates:
|
||||
if c.get("type") in types:
|
||||
return c
|
||||
return None
|
||||
|
||||
|
||||
def _pick_best_candidate(candidates: list[dict], preferred_auth_type: str, platform: str = "unknown") -> Optional[dict]:
|
||||
if not candidates:
|
||||
return None
|
||||
# cookie_bundle > cookie > bearer_token > api_key
|
||||
# preferred_auth_type="cookie" 时优先匹配 bundle,其次单 cookie
|
||||
|
||||
if platform == "sub2api":
|
||||
return _first_candidate(candidates, "bearer_token", "api_key")
|
||||
if platform == "new-api-user":
|
||||
return _first_candidate(candidates, "cookie_bundle", "cookie", "bearer_token", "api_key")
|
||||
if preferred_auth_type == "cookie":
|
||||
for c in candidates:
|
||||
if c["type"] == "cookie_bundle":
|
||||
return c
|
||||
for c in candidates:
|
||||
if c["type"] == "cookie":
|
||||
return c
|
||||
return _first_candidate(candidates, "cookie_bundle", "cookie")
|
||||
elif preferred_auth_type in ("bearer", "api_key"):
|
||||
type_map = {"bearer": "bearer_token", "api_key": "api_key"}
|
||||
preferred = type_map.get(preferred_auth_type)
|
||||
if preferred:
|
||||
for c in candidates:
|
||||
if c["type"] == preferred:
|
||||
return c
|
||||
return _first_candidate(candidates, preferred)
|
||||
# fallback:排序后取第一个
|
||||
return candidates[0]
|
||||
|
||||
@@ -268,11 +288,17 @@ async def refresh_auth(pid: int, db: Session = Depends(get_db), _=Depends(get_cu
|
||||
return RefreshAuthResponse(success=False, message=f"提取失败: {exc}")
|
||||
|
||||
candidates = result.get("candidates", [])
|
||||
candidate = _pick_best_candidate(candidates, upstream.auth_type)
|
||||
existing_config = _json.loads(upstream.auth_config_json or "{}")
|
||||
platform = _detect_upstream_platform(upstream, existing_config)
|
||||
candidate = _pick_best_candidate(candidates, upstream.auth_type, platform)
|
||||
if not candidate:
|
||||
if platform == "sub2api" and _first_candidate(candidates, "cookie_bundle", "cookie"):
|
||||
return RefreshAuthResponse(
|
||||
success=False,
|
||||
message="Sub2API 需要 Bearer Token;当前只提取到 Cookie。请在远程浏览器完成登录后刷新页面或触发一次接口请求,再重新提取。",
|
||||
)
|
||||
return RefreshAuthResponse(success=False, message="未提取到有效凭证,请确认已在远程浏览器中登录")
|
||||
|
||||
existing_config = _json.loads(upstream.auth_config_json or "{}")
|
||||
ctype = candidate["type"]
|
||||
|
||||
if ctype in ("cookie_bundle", "cookie"):
|
||||
@@ -281,6 +307,10 @@ async def refresh_auth(pid: int, db: Session = Depends(get_db), _=Depends(get_cu
|
||||
existing_config["cookie_string"] = candidate.get("value", "")
|
||||
if candidate.get("new_api_user"):
|
||||
existing_config["new_api_user"] = candidate["new_api_user"]
|
||||
if platform == "new-api-user":
|
||||
upstream.api_prefix = ""
|
||||
upstream.groups_endpoint = "/api/user/self/groups"
|
||||
upstream.rate_endpoint = "/api/user/self/groups"
|
||||
elif ctype == "bearer_token":
|
||||
upstream.auth_type = "bearer"
|
||||
raw = candidate.get("value", "")
|
||||
|
||||
Reference in New Issue
Block a user