updated the new feature

This commit is contained in:
rarebuffalo
2026-05-07 10:35:36 +05:30
parent aec30fb42f
commit 8e45532240
10 changed files with 162 additions and 32 deletions

View File

@@ -17,9 +17,10 @@ from app.schemas.scan import (
ChatResponse,
ThreatNarrativeResponse,
ScanDiffResponse,
ScheduledScanResponse,
)
from app.services.ai import chat_with_scan_context, generate_threat_narrative
from app.services.ai import chat_with_scan_context, generate_threat_narrative, generate_diff_narrative
router = APIRouter(prefix="/scans", tags=["history"])
@@ -198,7 +199,7 @@ async def diff_scans(
):
result = await db.execute(
select(ScanResult).where(
ScanResult.id.in_([old_id, new_id]),
ScanResult.id.in_([old_id, new_id]),
ScanResult.user_id == current_user.id
)
)
@@ -210,17 +211,28 @@ async def diff_scans(
s_old = scans[0] if scans[0].id == old_id else scans[1]
s_new = scans[1] if scans[1].id == new_id else scans[0]
# Convert to set-like structures using issue names
# Map issues by name for set-like comparison
old_map = {i.get("issue"): i for i in s_old.issues}
new_map = {i.get("issue"): i for i in s_new.issues}
resolved = [v for k, v in old_map.items() if k not in new_map]
new_issues = [v for k, v in new_map.items() if k not in old_map]
persisting = [v for k, v in new_map.items() if k in old_map]
score_change = s_new.security_score - s_old.security_score
# Ask the AI to narrate the changes in plain English
diff_context = {
"score_change": score_change,
"resolved_issues": resolved,
"new_issues": new_issues,
"persisting_issues": persisting,
}
narrative = await generate_diff_narrative(diff_context)
return ScanDiffResponse(
resolved_issues=resolved,
new_issues=new_issues,
persisting_issues=persisting,
score_change=s_new.security_score - s_old.security_score
score_change=score_change,
narrative=narrative,
)

View File

@@ -23,6 +23,7 @@ from app.services.scanner.ports import PortScanner
from app.services.scoring import calculate_layer_statuses, calculate_score
from app.services.ai import enhance_security_issues
from app.services.threat_intel import get_threat_intel_summary
from app.services.webhook_dispatcher import dispatch_webhooks
from app.utils.validators import validate_url
logger = logging.getLogger(__name__)
@@ -38,30 +39,6 @@ dns_scanner = DNSScanner()
port_scanner = PortScanner()
async def dispatch_webhooks(user_id: str, scan_data: dict, db_session):
import hmac, hashlib, json
from sqlalchemy import select
result = await db_session.execute(
select(Webhook).where(Webhook.user_id == user_id, Webhook.is_active == True)
)
hooks = result.scalars().all()
if not hooks:
return
async with httpx.AsyncClient() as client:
payload = json.dumps(scan_data).encode("utf-8")
for hook in hooks:
headers = {"Content-Type": "application/json"}
if hook.secret_key:
sig = hmac.new(hook.secret_key.encode(), payload, hashlib.sha256).hexdigest()
headers["X-SecureLens-Signature"] = sig
try:
await client.post(hook.target_url, content=payload, headers=headers, timeout=5.0)
except Exception as e:
logger.warning(f"Webhook {hook.target_url} failed: {e}")
@router.post("/scan", response_model=ScanResponse)
@limiter.limit(settings.rate_limit)