Files
ThreatHunt/_harden_aup_scope_ui.py
mblanke 5a2ad8ec1c feat: Add Playbook Manager, Saved Searches, and Timeline View components
- Implemented PlaybookManager for creating and managing investigation playbooks with templates.
- Added SavedSearches component for managing bookmarked queries and recurring scans.
- Introduced TimelineView for visualizing forensic event timelines with zoomable charts.
- Enhanced backend processing with auto-queued jobs for dataset uploads and improved database concurrency.
- Updated frontend components for better user experience and performance optimizations.
- Documented changes in update log for future reference.
2026-02-23 14:23:07 -05:00

72 lines
2.0 KiB
Python

from pathlib import Path
p=Path(r'd:/Projects/Dev/ThreatHunt/frontend/src/components/AUPScanner.tsx')
t=p.read_text(encoding='utf-8')
# Auto-select first hunt with datasets after load
old=''' const [tRes, hRes] = await Promise.all([
keywords.listThemes(),
hunts.list(0, 200),
]);
setThemes(tRes.themes);
setHuntList(hRes.hunts);
'''
new=''' const [tRes, hRes] = await Promise.all([
keywords.listThemes(),
hunts.list(0, 200),
]);
setThemes(tRes.themes);
setHuntList(hRes.hunts);
if (!selectedHuntId && hRes.hunts.length > 0) {
const best = hRes.hunts.find(h => h.dataset_count > 0) || hRes.hunts[0];
setSelectedHuntId(best.id);
}
'''
if old not in t:
raise SystemExit('loadData block not found')
t=t.replace(old,new)
# Guard runScan
old2=''' const runScan = useCallback(async () => {
setScanning(true);
setScanResult(null);
try {
'''
new2=''' const runScan = useCallback(async () => {
if (!selectedHuntId) {
enqueueSnackbar('Please select a hunt before running AUP scan', { variant: 'warning' });
return;
}
if (selectedDs.size === 0) {
enqueueSnackbar('No datasets selected for this hunt', { variant: 'warning' });
return;
}
setScanning(true);
setScanResult(null);
try {
'''
if old2 not in t:
raise SystemExit('runScan header not found')
t=t.replace(old2,new2)
# update loadData deps
old3=''' }, [enqueueSnackbar]);
'''
new3=''' }, [enqueueSnackbar, selectedHuntId]);
'''
if old3 not in t:
raise SystemExit('loadData deps not found')
t=t.replace(old3,new3,1)
# disable button if no hunt or no datasets
old4=''' onClick={runScan} disabled={scanning}
'''
new4=''' onClick={runScan} disabled={scanning || !selectedHuntId || selectedDs.size === 0}
'''
if old4 not in t:
raise SystemExit('scan button props not found')
t=t.replace(old4,new4)
p.write_text(t,encoding='utf-8')
print('hardened AUPScanner to require explicit hunt/dataset scope')