Initial commit - frontend

This commit is contained in:
Bailey Taylor
2025-09-19 03:26:52 +00:00
commit 27e9a08ee0
234 changed files with 32097 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
'use client';
import React, { createContext, useContext, useState, useEffect } from 'react';
import api from '@/lib/axios';
import { useAuth } from '@/context/AuthContext';
import { DetailedDevice } from '@/types/devices';
import { disableConsoleInProd } from '@/lib/disableConsole';
disableConsoleInProd();
interface DriveInfo {
name: string;
driveType: string;
totalSizeGB: number;
freeSpaceGB: number;
}
interface IpAddress {
interfaceName: string;
ipAddress: string;
}
interface MacAddress {
interfaceName: string;
macAddress: string;
}
interface InstalledApp {
app_name: string;
app_version: string;
publisher: string;
}
interface DeviceVulnerability {
cveId: string;
title: string;
severity: string;
score?: number;
publishedDate: string;
lastModifiedDate: string;
}
interface CachedSoftwareEntry {
id: number;
softwareName: string;
hostname: string;
version: string;
deviceId: number;
totalCves: number;
lastUpdated: string;
}
interface DeviceContextType {
devices: DetailedDevice[];
deviceVulns: { [deviceId: string]: DeviceVulnerability[] };
cachedSoftware: CachedSoftwareEntry[];
detailedCveLookup: { [cveId: string]: DeviceVulnerability }; // 🔥 New
setDevices: React.Dispatch<React.SetStateAction<DetailedDevice[]>>;
setDeviceVulns: React.Dispatch<React.SetStateAction<{ [deviceId: string]: DeviceVulnerability[] }>>;
setCachedSoftware: React.Dispatch<React.SetStateAction<CachedSoftwareEntry[]>>;
setDetailedCveLookup: React.Dispatch<React.SetStateAction<{ [cveId: string]: DeviceVulnerability }>>;
loading: boolean;
}
const DeviceContext = createContext<DeviceContextType | undefined>(undefined);
export const useDeviceContext = () => {
const context = useContext(DeviceContext);
if (!context) {
throw new Error('useDeviceContext must be used within a DeviceProvider');
}
return context;
};
export const DeviceProvider = ({
children,
initialData,
}: {
children: React.ReactNode;
initialData?: {
devices: DetailedDevice[];
vulnerabilitiesByDevice: { [deviceId: string]: DeviceVulnerability[] };
};
}) => {
const [devices, setDevices] = useState<DetailedDevice[]>(() => {
if (initialData?.devices?.length) return initialData.devices;
return [];
});
const [deviceVulns, setDeviceVulns] = useState<{ [deviceId: string]: DeviceVulnerability[] }>(
initialData?.vulnerabilitiesByDevice ?? {}
);
const [detailedCveLookup, setDetailedCveLookup] = useState<{ [cveId: string]: DeviceVulnerability }>({});
const [cachedSoftware, setCachedSoftware] = useState<CachedSoftwareEntry[]>([]); // ⬅️ NEW
const [loading, setLoading] = useState<boolean>(!initialData);
const { username, roles, loading: authLoading } = useAuth();
useEffect(() => {
if (devices.length > 0 || initialData || authLoading || !username) return;
const fetchDevicesVulnsAndSoftware = async () => {
try {
const isAdmin = roles?.includes('ADMIN');
const devicesEndpoint = isAdmin
? '/cached/devices/with-vulns/all'
: '/cached/devices/with-vulns';
const softwareEndpoint = '/cached/software/summary';
console.group('📡 Fetching Devices, Vulnerabilities, and Software');
const [devicesRes, softwareRes] = await Promise.all([
api.get(devicesEndpoint, { withCredentials: true }),
api.get(softwareEndpoint, { withCredentials: true }),
]);
console.log('✅ Devices fetched:', devicesRes.data);
console.log('✅ Software fetched:', softwareRes.data);
console.groupEnd();
// STEP 1: Set basic data
setDevices(devicesRes.data.devices);
setDeviceVulns(devicesRes.data.vulnerabilitiesByDevice);
setCachedSoftware(softwareRes.data);
// STEP 2: Extract all unique CVE IDs
const uniqueCveIds = new Set<string>();
(Object.values(devicesRes.data.vulnerabilitiesByDevice) as DeviceVulnerability[][]).forEach((vulns) => {
vulns.forEach((vuln) => {
if (vuln.cveId) {
uniqueCveIds.add(vuln.cveId);
}
});
});
// STEP 3: Fetch detailed CVE data
if (uniqueCveIds.size > 0) {
console.log('🔎 Fetching detailed CVEs for:', Array.from(uniqueCveIds));
const params = new URLSearchParams();
Array.from(uniqueCveIds).forEach(cveId => {
params.append('cveIds', cveId);
});
const cveDetailsRes = await api.get<DeviceVulnerability[]>('/vuln/cves/lookup', {
params,
withCredentials: true,
});
const lookupMap: { [cveId: string]: DeviceVulnerability } = {};
cveDetailsRes.data.forEach((cve) => {
lookupMap[cve.cveId] = cve;
});
setDetailedCveLookup(lookupMap);
}
} catch (error: any) {
console.group('❌ Device fetch failed');
console.error('🔴 Axios Error Message:', error.message);
console.error('🧾 Axios Error Config:', error.config);
if (error.response) {
console.error('📉 Status:', error.response.status);
console.error('📄 Response Headers:', error.response.headers);
console.error('📄 Response Data:', error.response.data);
} else if (error.request) {
console.error('🛑 No response received:', error.request);
}
console.groupEnd();
} finally {
setLoading(false);
}
};
fetchDevicesVulnsAndSoftware();
}, [devices.length, initialData, username, authLoading]);
useEffect(() => {
console.log("🧠 Devices updated:", devices);
}, [devices]);
if (typeof window !== 'undefined') {
(window as any).__debug_devices = devices;
}
return (
<DeviceContext.Provider value={{
devices,
deviceVulns,
cachedSoftware,
detailedCveLookup, // ✅ provide it!
setDevices,
setDeviceVulns,
setCachedSoftware,
setDetailedCveLookup, // ✅ provide this too!
loading,
}}>
{children}
</DeviceContext.Provider>
);
};