mirror of
https://github.com/mblanke/ThreatHunt.git
synced 2026-03-01 14:00:20 -05:00
CLAUDE branch
i made have screwed the pooch with this
This commit is contained in:
12
frontend/index.html
Normal file
12
frontend/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Cyber Threat Hunter</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
34
frontend/package.json
Normal file
34
frontend/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "cyber-threat-hunter",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.26.1",
|
||||
"lucide-react": "^0.515.0",
|
||||
"axios": "^1.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react": "^7.34.3",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"vite": "^5.3.4",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"postcss": "^8.4.39"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
frontend/src/App.jsx
Normal file
47
frontend/src/App.jsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import React from "react";
|
||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||
import { CssBaseline } from "@mui/material";
|
||||
import { createTheme, ThemeProvider } from "@mui/material/styles";
|
||||
|
||||
import Sidebar from "./components/Sidebar";
|
||||
import HomePage from "./pages/HomePage";
|
||||
|
||||
const theme = createTheme({
|
||||
palette: {
|
||||
mode: "dark",
|
||||
},
|
||||
});
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline />
|
||||
<Router>
|
||||
<div className="flex h-screen bg-zinc-900 text-white">
|
||||
<Sidebar />
|
||||
<main className="flex-1 p-6 overflow-auto">
|
||||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</div>
|
||||
</Router>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
<Route path="/applications" element={<Applications />} />
|
||||
<Route path="/csv-processing" element={<CSVProcessing />} />
|
||||
<Route path="/settings" element={<SettingsConfig />} />
|
||||
<Route path="/virus-total" element={<VirusTotal />} />
|
||||
<Route path="/security-tools" element={<SecurityTools />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</div>
|
||||
</Router>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
76
frontend/src/components/Sidebar.jsx
Normal file
76
frontend/src/components/Sidebar.jsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ShieldCheck } from 'lucide-react';
|
||||
|
||||
const Sidebar = () => {
|
||||
return (
|
||||
<div className="w-56 h-full bg-zinc-950 p-4 flex flex-col space-y-2 rounded-r-xl shadow-md">
|
||||
<Link to="/" className="flex items-center cursor-pointer px-4 py-2 rounded-xl hover:bg-zinc-800 transition-all">
|
||||
<ShieldCheck className="w-5 h-5 mr-3 text-cyan-400" />
|
||||
<span>Home</span>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
const location = useLocation();
|
||||
const hasChildren = !!children;
|
||||
const isActive = location.pathname === to;
|
||||
|
||||
const handleClick = () => {
|
||||
if (hasChildren) {
|
||||
setIsOpen(!isOpen);
|
||||
}
|
||||
};
|
||||
|
||||
const itemContent = (
|
||||
<div
|
||||
className={`sidebar-item ${isActive ? 'bg-zinc-800' : ''}`}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<Icon className="sidebar-icon" />
|
||||
<span className="flex-grow">{label}</span>
|
||||
{hasChildren && (isOpen ? <ChevronDown className="w-4 h-4" /> : <ChevronRight className="w-4 h-4" />)}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="text-sm">
|
||||
{to && !hasChildren ? (
|
||||
<Link to={to}>{itemContent}</Link>
|
||||
) : (
|
||||
itemContent
|
||||
)}
|
||||
{hasChildren && isOpen && (
|
||||
<div className="ml-8 mt-1 space-y-1 text-zinc-400">
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Sidebar = () => {
|
||||
return (
|
||||
<div className="w-56 h-full bg-zinc-950 p-4 flex flex-col space-y-2 rounded-r-xl shadow-md">
|
||||
<SidebarItem icon={ShieldCheck} label="HomePage" to="/" />
|
||||
<SidebarItem icon={Server} label="Baseline" to="/baseline" />
|
||||
<SidebarItem icon={Bug} label="Networking" to="/networking" />
|
||||
<SidebarItem icon={Folder} label="Applications" to="/applications" />
|
||||
<SidebarItem icon={Globe} label="CSV Processing" to="/csv-processing" />
|
||||
<SidebarItem
|
||||
icon={Settings}
|
||||
label="Tools / Configs"
|
||||
children={
|
||||
<>
|
||||
<Link to="/security-tools" className="block hover:text-white">Security Tools</Link>
|
||||
<Link to="/settings" className="block hover:text-white">Configuration</Link>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<SidebarItem icon={Globe} label="Virus Total" to="/virus-total" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
203
frontend/src/index.css
Normal file
203
frontend/src/index.css
Normal file
@@ -0,0 +1,203 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||
background-color: #18181b;
|
||||
color: white;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.sidebar-item {
|
||||
@apply flex items-center cursor-pointer px-4 py-2 rounded-xl hover:bg-zinc-800 transition-all;
|
||||
}
|
||||
|
||||
.sidebar-icon {
|
||||
@apply w-5 h-5 mr-3 text-cyan-400;
|
||||
}
|
||||
|
||||
.card {
|
||||
@apply bg-zinc-800 rounded-lg p-6 shadow-lg;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply bg-cyan-600 hover:bg-cyan-700 text-white px-4 py-2 rounded-lg transition-colors;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply bg-zinc-700 hover:bg-zinc-600 text-white px-4 py-2 rounded-lg transition-colors;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.h-screen {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.bg-zinc-900 {
|
||||
background-color: #18181b;
|
||||
}
|
||||
|
||||
.bg-zinc-950 {
|
||||
background-color: #09090b;
|
||||
}
|
||||
|
||||
.bg-zinc-800 {
|
||||
background-color: #27272a;
|
||||
}
|
||||
|
||||
.text-white {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.text-zinc-400 {
|
||||
color: #a1a1aa;
|
||||
}
|
||||
|
||||
.text-cyan-400 {
|
||||
color: #22d3ee;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.p-6 {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.p-4 {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.overflow-auto {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.w-56 {
|
||||
width: 14rem;
|
||||
}
|
||||
|
||||
.space-y-6 > * + * {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.space-y-2 > * + * {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-r-xl {
|
||||
border-top-right-radius: 0.75rem;
|
||||
border-bottom-right-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.shadow-md {
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
.text-3xl {
|
||||
font-size: 1.875rem;
|
||||
line-height: 2.25rem;
|
||||
}
|
||||
|
||||
.font-bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.mb-2 {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.text-lg {
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
.font-semibold {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.w-8 {
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
.h-8 {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.mr-4 {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.rounded-lg {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.rounded-xl {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.hover\:bg-zinc-800:hover {
|
||||
background-color: #27272a;
|
||||
}
|
||||
|
||||
.transition-all {
|
||||
transition: all 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.w-5 {
|
||||
width: 1.25rem;
|
||||
}
|
||||
|
||||
.h-5 {
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.mr-3 {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
}
|
||||
105
frontend/src/pages/HomePage.jsx
Normal file
105
frontend/src/pages/HomePage.jsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Activity, Upload, FileText, Shield } from 'lucide-react';
|
||||
|
||||
const HomePage = () => {
|
||||
const [stats, setStats] = useState({
|
||||
filesUploaded: 0,
|
||||
analysesCompleted: 0,
|
||||
threatsDetected: 0
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch dashboard stats
|
||||
fetch('/api/health')
|
||||
.then(res => res.json())
|
||||
.then(data => console.log('Backend connected:', data))
|
||||
.catch(err => console.error('Backend connection failed:', err));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold mb-2">Cyber Threat Hunter</h1>
|
||||
<p className="text-zinc-400">
|
||||
Advanced threat hunting and security analysis platform
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="card">
|
||||
<div className="flex items-center">
|
||||
<Upload className="w-8 h-8 text-cyan-400 mr-4" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Files Uploaded</h3>
|
||||
<p className="text-2xl font-bold text-cyan-400">{stats.filesUploaded}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<div className="flex items-center">
|
||||
<Activity className="w-8 h-8 text-green-400 mr-4" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Analyses Completed</h3>
|
||||
<p className="text-2xl font-bold text-green-400">{stats.analysesCompleted}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<div className="flex items-center">
|
||||
<Shield className="w-8 h-8 text-red-400 mr-4" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">Threats Detected</h3>
|
||||
<p className="text-2xl font-bold text-red-400">{stats.threatsDetected}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<h2 className="text-xl font-bold mb-4">Quick Actions</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<button className="btn-primary flex items-center justify-center">
|
||||
<Upload className="w-5 h-5 mr-2" />
|
||||
Upload File for Analysis
|
||||
</button>
|
||||
<button className="btn-secondary flex items-center justify-center">
|
||||
<FileText className="w-5 h-5 mr-2" />
|
||||
View Recent Reports
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card">
|
||||
<h2 className="text-xl font-bold mb-4">System Health</h2>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between">
|
||||
<span>Backend Status</span>
|
||||
<span className="text-green-400">✓ Healthy</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span>Database Connection</span>
|
||||
<span className="text-green-400">✓ Connected</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span>Storage Available</span>
|
||||
<span className="text-yellow-400">⚠ 75% Used</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-zinc-800 rounded-lg p-6 shadow-lg">
|
||||
<div className="flex items-center">
|
||||
<Shield className="w-8 h-8 text-cyan-400 mr-4" />
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold">System Status</h3>
|
||||
<p className="text-2xl font-bold text-cyan-400">Ready</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
20
frontend/vite.config.js
Normal file
20
frontend/vite.config.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:5000',
|
||||
changeOrigin: true,
|
||||
secure: false
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: true
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user