mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-10-26 15:56:34 +01:00
182 lines
8.3 KiB
Python
182 lines
8.3 KiB
Python
import json
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.views.decorators.http import require_http_methods
|
|
from django.utils import timezone
|
|
from .status_models import ScanStatusUpdate
|
|
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as logging
|
|
|
|
|
|
@csrf_exempt
|
|
@require_http_methods(['POST'])
|
|
def receive_status_update(request):
|
|
"""
|
|
Receive real-time scan status updates from platform
|
|
|
|
POST /api/ai-scanner/status-webhook
|
|
|
|
Expected payload:
|
|
{
|
|
"scan_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"phase": "scanning_files",
|
|
"progress": 75,
|
|
"current_file": "wp-content/plugins/suspicious/malware.php",
|
|
"files_discovered": 1247,
|
|
"files_scanned": 935,
|
|
"files_remaining": 312,
|
|
"threats_found": 5,
|
|
"critical_threats": 2,
|
|
"high_threats": 3,
|
|
"activity_description": "Scanning file 935/1247: wp-content/plugins/suspicious/malware.php"
|
|
}
|
|
"""
|
|
try:
|
|
data = json.loads(request.body)
|
|
|
|
scan_id = data.get('scan_id')
|
|
if not scan_id:
|
|
logging.writeToFile('[Status API] Missing scan_id in status update')
|
|
return JsonResponse({'error': 'scan_id required'}, status=400)
|
|
|
|
# Update or create status record
|
|
status_update, created = ScanStatusUpdate.objects.update_or_create(
|
|
scan_id=scan_id,
|
|
defaults={
|
|
'phase': data.get('phase', ''),
|
|
'progress': int(data.get('progress', 0)),
|
|
'current_file': data.get('current_file', ''),
|
|
'files_discovered': int(data.get('files_discovered', 0)),
|
|
'files_scanned': int(data.get('files_scanned', 0)),
|
|
'files_remaining': int(data.get('files_remaining', 0)),
|
|
'threats_found': int(data.get('threats_found', 0)),
|
|
'critical_threats': int(data.get('critical_threats', 0)),
|
|
'high_threats': int(data.get('high_threats', 0)),
|
|
'activity_description': data.get('activity_description', ''),
|
|
'last_updated': timezone.now()
|
|
}
|
|
)
|
|
|
|
action = "Created" if created else "Updated"
|
|
|
|
# Extended logging for debugging
|
|
logging.writeToFile(f'[Status API] ✅ {action} status update for scan {scan_id}')
|
|
|
|
# Track phase transitions
|
|
old_phase = status_update.phase if not created else 'none'
|
|
new_phase = data.get("phase")
|
|
if old_phase != new_phase:
|
|
logging.writeToFile(f'[Status API] 📊 Phase transition: {old_phase} → {new_phase}')
|
|
|
|
logging.writeToFile(f'[Status API] Phase: {data.get("phase")} → Progress: {data.get("progress", 0)}%')
|
|
logging.writeToFile(f'[Status API] Files: {data.get("files_scanned", 0)}/{data.get("files_discovered", 0)} ({data.get("files_remaining", 0)} remaining)')
|
|
logging.writeToFile(f'[Status API] Threats: {data.get("threats_found", 0)} total (Critical: {data.get("critical_threats", 0)}, High: {data.get("high_threats", 0)})')
|
|
if data.get('current_file'):
|
|
logging.writeToFile(f'[Status API] Current File: {data.get("current_file")}')
|
|
if data.get('activity_description'):
|
|
logging.writeToFile(f'[Status API] Activity: {data.get("activity_description")}')
|
|
|
|
# Log specific phase milestones
|
|
phase = data.get('phase', '')
|
|
if phase == 'discovering_files' and data.get('files_discovered', 0) > 0:
|
|
logging.writeToFile(f'[Status API] ✅ File discovery complete: {data.get("files_discovered")} files found')
|
|
elif phase == 'scanning_files' and data.get('files_scanned', 0) > 0:
|
|
percentage = (data.get('files_scanned', 0) / data.get('files_discovered', 1)) * 100
|
|
logging.writeToFile(f'[Status API] 📈 Scan progress: {percentage:.1f}% of files scanned')
|
|
elif phase == 'ai_analysis':
|
|
logging.writeToFile(f'[Status API] 🤖 AI Analysis phase - suspicious files being analyzed')
|
|
|
|
return JsonResponse({'success': True})
|
|
|
|
except json.JSONDecodeError:
|
|
logging.writeToFile('[Status API] Invalid JSON in status update')
|
|
return JsonResponse({'error': 'Invalid JSON'}, status=400)
|
|
except ValueError as e:
|
|
logging.writeToFile(f'[Status API] Value error in status update: {str(e)}')
|
|
return JsonResponse({'error': 'Invalid data types'}, status=400)
|
|
except Exception as e:
|
|
logging.writeToFile(f'[Status API] Status update error: {str(e)}')
|
|
return JsonResponse({'error': 'Internal server error'}, status=500)
|
|
|
|
|
|
@require_http_methods(['GET'])
|
|
def get_live_scan_progress(request, scan_id):
|
|
"""
|
|
Get current scan progress for real-time UI updates
|
|
|
|
GET /api/ai-scanner/scan/{scan_id}/live-progress
|
|
|
|
Response:
|
|
{
|
|
"success": true,
|
|
"scan_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"phase": "scanning_files",
|
|
"progress": 75,
|
|
"current_file": "wp-content/plugins/suspicious/malware.php",
|
|
"files_discovered": 1247,
|
|
"files_scanned": 935,
|
|
"files_remaining": 312,
|
|
"threats_found": 5,
|
|
"critical_threats": 2,
|
|
"high_threats": 3,
|
|
"activity_description": "Scanning file 935/1247: wp-content/plugins/suspicious/malware.php",
|
|
"last_updated": "2024-12-25T10:34:30Z",
|
|
"is_active": true
|
|
}
|
|
"""
|
|
try:
|
|
# Log the request
|
|
logging.writeToFile(f'[Status API] Live progress request for scan: {scan_id}')
|
|
|
|
# Get latest status update
|
|
try:
|
|
status_update = ScanStatusUpdate.objects.get(scan_id=scan_id)
|
|
except ScanStatusUpdate.DoesNotExist:
|
|
logging.writeToFile(f'[Status API] Status not found for scan {scan_id} - checking if scan exists in history')
|
|
|
|
# Check if scan exists in ScanHistory
|
|
from .models import ScanHistory
|
|
try:
|
|
scan_history = ScanHistory.objects.get(scan_id=scan_id)
|
|
logging.writeToFile(f'[Status API] Scan {scan_id} exists in history with status: {scan_history.status}')
|
|
|
|
# If scan exists but no status update, it might not have started yet
|
|
return JsonResponse({
|
|
'success': False,
|
|
'error': 'No live status available yet',
|
|
'scan_exists': True,
|
|
'scan_status': scan_history.status
|
|
}, status=404)
|
|
except ScanHistory.DoesNotExist:
|
|
logging.writeToFile(f'[Status API] Scan {scan_id} not found in history either')
|
|
|
|
return JsonResponse({'success': False, 'error': 'Scan not found'}, status=404)
|
|
|
|
response_data = {
|
|
'success': True,
|
|
'scan_id': scan_id,
|
|
'phase': status_update.phase,
|
|
'progress': status_update.progress,
|
|
'current_file': status_update.current_file,
|
|
'files_discovered': status_update.files_discovered,
|
|
'files_scanned': status_update.files_scanned,
|
|
'files_remaining': status_update.files_remaining,
|
|
'threats_found': status_update.threats_found,
|
|
'critical_threats': status_update.critical_threats,
|
|
'high_threats': status_update.high_threats,
|
|
'activity_description': status_update.activity_description,
|
|
'last_updated': status_update.last_updated.isoformat(),
|
|
'is_active': status_update.is_active
|
|
}
|
|
|
|
# Extended logging for frontend polling
|
|
logging.writeToFile(f'[Status API] 📊 Frontend polling scan {scan_id}')
|
|
logging.writeToFile(f'[Status API] Status: {status_update.phase} ({status_update.progress}%) - Active: {status_update.is_active}')
|
|
logging.writeToFile(f'[Status API] Progress: {status_update.files_scanned}/{status_update.files_discovered} files, {status_update.threats_found} threats')
|
|
if status_update.current_file:
|
|
logging.writeToFile(f'[Status API] Currently scanning: {status_update.current_file}')
|
|
|
|
return JsonResponse(response_data)
|
|
|
|
except Exception as e:
|
|
logging.writeToFile(f'[Status API] Get progress error: {str(e)}')
|
|
return JsonResponse({'success': False, 'error': 'Internal server error'}, status=500) |