Added new backfill button for CVE sync.
Some checks failed
Deploy Frontend / deploy (push) Failing after 36s
Some checks failed
Deploy Frontend / deploy (push) Failing after 36s
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
// src/components/admin/AdminControlsPanel.tsx
|
||||
'use client';
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
Typography,
|
||||
Box,
|
||||
Button,
|
||||
@@ -17,13 +17,14 @@ import {
|
||||
MenuItem,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
} from '@mui/material';
|
||||
import { SwitchTextTrack } from '@/components/SwitchTextTrack';
|
||||
import CVELogStream from '@/components/CVELogStream';
|
||||
import api from '@/lib/axios';
|
||||
DialogContentText,
|
||||
} from '@mui/material';
|
||||
import { SwitchTextTrack } from '@/components/SwitchTextTrack';
|
||||
import CVELogStream from '@/components/CVELogStream';
|
||||
import api from '@/lib/axios';
|
||||
|
||||
|
||||
export default function AdminControlsPanel() {
|
||||
export default function AdminControlsPanel() {
|
||||
const [pingEnabled, setPingEnabled] = useState<boolean | null>(null);
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
@@ -34,6 +35,7 @@ export default function AdminControlsPanel() {
|
||||
const [clientList, setClientList] = useState<Array<{clientId: number;clientIdentifier: string;clientName: string;}>>([]);
|
||||
const [selectedClientId, setSelectedClientId] = useState<number | null>(null);
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [backfillDialogOpen, setBackfillDialogOpen] = useState(false);
|
||||
const [cveVisible, setCveVisible] = useState(false);
|
||||
const [kevVisible, setKevVisible] = useState(false);
|
||||
const [msrcVisible, setMsrcVisible] = useState(false);
|
||||
@@ -83,8 +85,8 @@ export default function AdminControlsPanel() {
|
||||
|
||||
const fetchClients = async () => {
|
||||
try {
|
||||
const res = await api.get('/auth/clients'); // Adjust endpoint if needed
|
||||
setClientList(res.data); // Expected: [{ clientId, name }]
|
||||
const res = await api.get('/auth/clients');
|
||||
setClientList(res.data);
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch clients', err);
|
||||
}
|
||||
@@ -94,18 +96,35 @@ export default function AdminControlsPanel() {
|
||||
try {
|
||||
setLoading(true);
|
||||
await api.post('/admin/scripts/fetch-cve');
|
||||
setCveVisible(true); // 👈 Spawn CVE console
|
||||
setCveVisible(true);
|
||||
} catch (err: any) {
|
||||
alert("❌ Failed to start CVE sync: " + (err?.response?.data || err.message));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const runCveBackfill = async () => {
|
||||
setBackfillDialogOpen(false);
|
||||
try {
|
||||
setLoading(true);
|
||||
await api.post('/admin/scripts/fetch-cve-backfill');
|
||||
setCveVisible(true);
|
||||
setToastMessage('⏳ CVE backfill started - this will take 20-30 hours to complete!');
|
||||
setToastOpen(true);
|
||||
} catch (err: any) {
|
||||
setToastMessage("❌ Failed to start CVE backfill: " + (err?.response?.data || err.message));
|
||||
setToastOpen(true);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const runKevSync = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
await api.post('/admin/scripts/fetch-kev');
|
||||
setKevVisible(true); // 👈 Spawn KEV console
|
||||
setKevVisible(true);
|
||||
setToastMessage('✅ KEV sync started.');
|
||||
setToastOpen(true);
|
||||
} catch (err: any) {
|
||||
@@ -120,7 +139,7 @@ export default function AdminControlsPanel() {
|
||||
try {
|
||||
setLoading(true);
|
||||
await api.post('/admin/scripts/fetch-msrc');
|
||||
setMsrcVisible(true); // 👈 Spawn MSRC console
|
||||
setMsrcVisible(true);
|
||||
setToastMessage('✅ MSRC sync started.');
|
||||
setToastOpen(true);
|
||||
} catch (err: any) {
|
||||
@@ -135,7 +154,7 @@ export default function AdminControlsPanel() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await api.post('/admin/vulns/refresh-cache');
|
||||
setToastMessage(res.data); // Show backend result in toast
|
||||
setToastMessage(res.data);
|
||||
setToastOpen(true);
|
||||
} catch (err: any) {
|
||||
setToastMessage("❌ Failed to refresh vulnerability cache: " + (err?.response?.data || err.message));
|
||||
@@ -177,7 +196,7 @@ export default function AdminControlsPanel() {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await api.post('/admin/software/normalize');
|
||||
setToastMessage(res.data); // ✅ show result
|
||||
setToastMessage(res.data);
|
||||
setToastOpen(true);
|
||||
} catch (err: any) {
|
||||
setToastMessage("❌ Failed to normalize software entries: " + (err?.response?.data || err.message));
|
||||
@@ -237,7 +256,17 @@ export default function AdminControlsPanel() {
|
||||
disabled={loading}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
{loading ? 'Running Sync...' : 'Run CVE Sync'}
|
||||
{loading ? 'Running Sync...' : 'Run CVE Sync (Last 30 Days)'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="warning"
|
||||
onClick={() => setBackfillDialogOpen(true)}
|
||||
disabled={loading}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
{loading ? 'Starting Backfill...' : 'Backfill All CVEs (2002-Present)'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
@@ -254,9 +283,9 @@ export default function AdminControlsPanel() {
|
||||
onClick={refreshSoftwareCache}
|
||||
disabled={loading}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
>
|
||||
{loading ? 'Refreshing Software Cache...' : 'Recheck Installed Software'}
|
||||
</Button>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
@@ -271,62 +300,62 @@ export default function AdminControlsPanel() {
|
||||
onClick={runKevSync}
|
||||
disabled={loading}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
>
|
||||
{loading ? 'Syncing KEVs...' : 'Import CISA KEVs'}
|
||||
</Button>
|
||||
<Button
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={runMsrcSync}
|
||||
disabled={loading}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
>
|
||||
{loading ? 'Syncing MSRC...' : 'Import Microsoft CVEs'}
|
||||
</Button>
|
||||
<Button
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={refreshStatistics}
|
||||
disabled={loading}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
>
|
||||
{loading ? 'Refreshing Statistics...' : 'Refresh CVE Statistics'}
|
||||
</Button>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={openDialog}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
>
|
||||
Add Demo Device
|
||||
</Button>
|
||||
</Button>
|
||||
|
||||
|
||||
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
|
||||
<CVELogStream
|
||||
<CVELogStream
|
||||
visible={cveVisible}
|
||||
title="🔍 CVE Sync Logs"
|
||||
streamUrl="/admin/scripts/fetch-cve/logs/stream"
|
||||
clearUrl="/admin/scripts/fetch-cve/clear-logs"
|
||||
/>
|
||||
/>
|
||||
|
||||
<CVELogStream
|
||||
<CVELogStream
|
||||
visible={kevVisible}
|
||||
title="🛡️ KEV Sync Logs"
|
||||
streamUrl="/admin/scripts/fetch-kev/logs/stream"
|
||||
clearUrl="/admin/scripts/fetch-kev/clear-logs"
|
||||
/>
|
||||
/>
|
||||
|
||||
<CVELogStream
|
||||
<CVELogStream
|
||||
visible={msrcVisible}
|
||||
title="🖥️ MSRC Sync Logs"
|
||||
streamUrl="/admin/scripts/fetch-msrc/logs/stream"
|
||||
clearUrl="/admin/scripts/fetch-msrc/clear-logs"
|
||||
/>
|
||||
/>
|
||||
|
||||
|
||||
<Snackbar
|
||||
@@ -334,7 +363,7 @@ export default function AdminControlsPanel() {
|
||||
autoHideDuration={6000}
|
||||
onClose={() => setToastOpen(false)}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
>
|
||||
>
|
||||
<Alert
|
||||
onClose={() => setToastOpen(false)}
|
||||
severity="info"
|
||||
@@ -342,8 +371,46 @@ export default function AdminControlsPanel() {
|
||||
>
|
||||
{toastMessage}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
<Dialog open={dialogOpen} onClose={() => setDialogOpen(false)} maxWidth="xs" fullWidth>
|
||||
</Snackbar>
|
||||
|
||||
{/* Backfill Confirmation Dialog */}
|
||||
<Dialog
|
||||
open={backfillDialogOpen}
|
||||
onClose={() => setBackfillDialogOpen(false)}
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>⚠️ Confirm CVE Backfill</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
<strong>This will download ALL CVEs from 2002 to present (~250,000 CVEs).</strong>
|
||||
<br /><br />
|
||||
Expected runtime: <strong>20-30 hours</strong>
|
||||
<br />
|
||||
API calls: <strong>~8,000-10,000 requests</strong>
|
||||
<br /><br />
|
||||
The process is resumable - if it stops, you can restart it and it will continue from where it left off.
|
||||
<br /><br />
|
||||
Are you sure you want to proceed?
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setBackfillDialogOpen(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="warning"
|
||||
onClick={runCveBackfill}
|
||||
disabled={loading}
|
||||
>
|
||||
Start Backfill
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
{/* Demo Device Dialog */}
|
||||
<Dialog open={dialogOpen} onClose={() => setDialogOpen(false)} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>Select a Client</DialogTitle>
|
||||
<DialogContent>
|
||||
<FormControl fullWidth sx={{ mt: 2 }}>
|
||||
@@ -358,7 +425,7 @@ export default function AdminControlsPanel() {
|
||||
<MenuItem key={client.clientId} value={client.clientId}>
|
||||
{client.clientName} ({client.clientIdentifier})
|
||||
</MenuItem>
|
||||
))}
|
||||
))}
|
||||
|
||||
</Select>
|
||||
</FormControl>
|
||||
@@ -388,9 +455,9 @@ export default function AdminControlsPanel() {
|
||||
Create
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Dialog>
|
||||
|
||||
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user