feat(backend): encrypt exchange credentials, remove IS_DEMO_MODE
- Fernet encrypt qd_exchange_credentials via SECRET_KEY (cryptography) - Remove global read-only demo middleware; drop is_demo from auth payloads - Egress whitelist: /api/credentials/egress-ip returns ipv4 + ipv6 (ipify) - Exchange factory: demo/testnet URLs and OKX simulated-trading header - Bitget spot connection test; misc route/service fixes Made-with: Cursor
This commit is contained in:
@@ -15,6 +15,7 @@ from typing import Any, Dict
|
||||
|
||||
from app.utils.db import get_db_connection
|
||||
from app.utils.logger import get_logger
|
||||
from app.utils.credential_crypto import decrypt_credential_blob
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -92,7 +93,7 @@ def load_strategy_configs(strategy_id: int) -> Dict[str, Any]:
|
||||
|
||||
|
||||
def _load_credential_config(credential_id: int, user_id: int = 1) -> Dict[str, Any]:
|
||||
"""Load credential JSON from qd_exchange_credentials (plaintext in local mode)."""
|
||||
"""Load credential JSON from qd_exchange_credentials (Fernet via SECRET_KEY)."""
|
||||
with get_db_connection() as db:
|
||||
cur = db.cursor()
|
||||
cur.execute(
|
||||
@@ -105,7 +106,13 @@ def _load_credential_config(credential_id: int, user_id: int = 1) -> Dict[str, A
|
||||
)
|
||||
row = cur.fetchone() or {}
|
||||
cur.close()
|
||||
return _safe_json_loads(row.get("encrypted_config"), {}) or {}
|
||||
raw = row.get("encrypted_config")
|
||||
try:
|
||||
plain = decrypt_credential_blob(raw)
|
||||
except ValueError as e:
|
||||
logger.warning(f"decrypt credential_id={credential_id}: {e}")
|
||||
return {}
|
||||
return _safe_json_loads(plain, {}) or {}
|
||||
|
||||
|
||||
def resolve_exchange_config(exchange_config: Dict[str, Any], user_id: int = 1) -> Dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user