mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-07-01 11:14:19 +08:00
* stash some changes * add more robust testing * mypy * point PR at V5 * introduce spec file * codespell * test fix * fix workflow environment setup * fix workflow environment setup * fix workflow environment setup * add pyyaml to dependencies * split lint jobs * fix workflow environment setup * fix workflow environment setup * workflow env setup * workflow env setup * clean up code comments * add auth hook entrypoints * codespell * add codegen feature * codespell * move _unpack into dispatchers for consistency with codegen packages * surface nested models in the response * fix missing coverage in CI * socrata updates * test fix * detect plotly output * add --include and --exclude flags from generate-extension command * cap test matrix at python 3.14 * no useless comments * platform controller command description split * merge URL overloads from path params * exclude none and unset from model dump --------- Co-authored-by: deeleeramone <> Co-authored-by: Copilot <copilot@github.com>
86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
"""Credential detection — separate user-facing params from auth secrets."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Literal
|
|
|
|
CredentialLocation = Literal["query", "header"]
|
|
|
|
_CREDENTIAL_NAMES: frozenset[str] = frozenset(
|
|
{
|
|
"api_key",
|
|
"apikey",
|
|
"x_api_key",
|
|
"x_apikey",
|
|
"key",
|
|
"subscription_key",
|
|
"ocp_apim_subscription_key",
|
|
"app_id",
|
|
"app_key",
|
|
"app_token",
|
|
"appid",
|
|
"client_id",
|
|
"client_secret",
|
|
"client_token",
|
|
"token",
|
|
"access_token",
|
|
"auth_token",
|
|
"x_auth_token",
|
|
"bearer_token",
|
|
"secret",
|
|
"secret_key",
|
|
"authorization",
|
|
"consumer_key",
|
|
"consumer_secret",
|
|
"private_key",
|
|
"session_token",
|
|
}
|
|
)
|
|
|
|
|
|
def normalize_credential_key(name: str) -> str:
|
|
"""Canonicalize a parameter name for credential lookup."""
|
|
return name.lower().replace("-", "_").strip("_")
|
|
|
|
|
|
def is_credential_name(name: str) -> bool:
|
|
"""Return ``True`` if ``name`` looks like a credential (not a request param)."""
|
|
return normalize_credential_key(name) in _CREDENTIAL_NAMES
|
|
|
|
|
|
def classify_parameter(param: dict[str, Any]) -> CredentialLocation | None:
|
|
"""Return ``"query"`` / ``"header"`` for a credential param, ``None`` otherwise."""
|
|
name = param.get("name") if isinstance(param, dict) else None
|
|
if not isinstance(name, str) or not is_credential_name(name):
|
|
return None
|
|
location = param.get("in", "query")
|
|
return "header" if location == "header" else "query"
|
|
|
|
|
|
def credentials_from_command(
|
|
cmd_spec: dict[str, Any],
|
|
) -> dict[str, dict[str, str]]:
|
|
"""Walk a command spec entry; return ``{canonical_key: {name, in}}``."""
|
|
out: dict[str, dict[str, str]] = {}
|
|
for param in cmd_spec.get("parameters") or []:
|
|
loc = classify_parameter(param)
|
|
if loc is None:
|
|
continue
|
|
canonical = normalize_credential_key(param["name"])
|
|
out[canonical] = {"name": param["name"], "in": loc}
|
|
return out
|
|
|
|
|
|
def credentials_from_spec(spec_doc: dict[str, Any]) -> dict[str, dict[str, str]]:
|
|
"""Aggregate every credential entry across an entire spec doc."""
|
|
out: dict[str, dict[str, str]] = {}
|
|
for cmd in (spec_doc.get("commands") or {}).values():
|
|
for canonical, entry in credentials_from_command(cmd).items():
|
|
out.setdefault(canonical, entry)
|
|
return out
|
|
|
|
|
|
def filter_user_params(parameters: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
"""Strip credential params from a parameter list, leaving user-facing ones."""
|
|
return [p for p in parameters or [] if classify_parameter(p) is None]
|