mirror of
https://github.com/Rarebuffalo/securelens-backend.git
synced 2026-06-19 07:00:30 +00:00
implement httpx client to upload scan results to backend
This commit is contained in:
61
cli/securelens/scanners/sync.py
Normal file
61
cli/securelens/scanners/sync.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import os
|
||||
import httpx
|
||||
from typing import Optional
|
||||
from securelens.scanners import LocalScanResult
|
||||
|
||||
BACKEND_URL_DEFAULT = "http://localhost:8000"
|
||||
|
||||
async def sync_scan_to_backend(result: LocalScanResult, token: Optional[str] = None) -> Optional[str]:
|
||||
"""
|
||||
Synchronizes a LocalScanResult with the SecureLens central backend.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
result : The LocalScanResult instance containing findings.
|
||||
token : Optional JWT Bearer token to associate the scan with a user account.
|
||||
|
||||
Returns
|
||||
-------
|
||||
The assigned scan_id from the database on success, or None on failure.
|
||||
"""
|
||||
backend_base = os.environ.get("SECURELENS_BACKEND_URL") or BACKEND_URL_DEFAULT
|
||||
sync_url = f"{backend_base.rstrip('/')}/code-scan/sync"
|
||||
|
||||
# Construct the payload matching the CodeScanSyncRequest schema
|
||||
payload = {
|
||||
"repo_url": result.target,
|
||||
"summary": result.ai_summary or f"Local scan completed with {len(result.vulnerabilities)} issue(s).",
|
||||
"issues": [
|
||||
{
|
||||
"file_path": v.file_path,
|
||||
"severity": v.severity,
|
||||
"issue": v.issue,
|
||||
"explanation": v.explanation,
|
||||
"suggested_fix": v.suggested_fix or "",
|
||||
"line_number": v.line_number
|
||||
}
|
||||
for v in result.vulnerabilities
|
||||
]
|
||||
}
|
||||
|
||||
headers = {}
|
||||
if token:
|
||||
headers["Authorization"] = f"Bearer {token}"
|
||||
elif os.environ.get("SECURELENS_TOKEN"):
|
||||
headers["Authorization"] = f"Bearer {os.environ.get('SECURELENS_TOKEN')}"
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=15.0) as client:
|
||||
response = await client.post(sync_url, json=payload, headers=headers)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
return data.get("scan_id")
|
||||
else:
|
||||
# Fallback check for alternative key structures
|
||||
response_data = response.json()
|
||||
if "scan_id" in response_data:
|
||||
return response_data["scan_id"]
|
||||
return None
|
||||
except Exception as e:
|
||||
# Silently fail sync, but return None so caller can notify user
|
||||
return None
|
||||
Reference in New Issue
Block a user