Files
Deep-Package-Inspection/diff.patch
T

519 lines
47 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
diff --git a/src/app/(dashboard)/agents/page.tsx b/src/app/(dashboard)/agents/page.tsx
index 29b337e..7fc94d9 100644
--- a/src/app/(dashboard)/agents/page.tsx
+++ b/src/app/(dashboard)/agents/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
@@ -66,7 +66,7 @@ export default function AgentsPage() {
router.refresh();
window.location.reload();
} catch (err: any) {
- alert('Gagal masuk mode View As: ' + err.message);
+ alert('Failed to enter View As mode: ' + err.message);
} finally {
setViewAsLoading(null);
}
@@ -210,7 +210,7 @@ export default function AgentsPage() {
>
{isViewAsLoading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Eye className="w-4 h-4" />}
</button>
- <button onClick={(e) => { e.stopPropagation(); openDelete(row); }} className="p-1.5 text-red-400 hover:text-red-300 hover:bg-red-950/30 rounded transition-colors" title="Hapus">
+ <button onClick={(e) => { e.stopPropagation(); openDelete(row); }} className="p-1.5 text-red-400 hover:text-red-300 hover:bg-red-950/30 rounded transition-colors" title="Delete">
<Trash2 className="w-4 h-4" />
</button>
</>
@@ -224,11 +224,7 @@ export default function AgentsPage() {
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- <Server className="w-6 h-6 text-primary" />
- Agents Inventory
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
+
<button
onClick={openCreate}
className="flex items-center gap-2 bg-primary hover:bg-primary/90 text-primary-foreground px-4 py-2 rounded-md text-sm font-medium transition-colors"
@@ -253,7 +249,7 @@ export default function AgentsPage() {
API Key yang Anda gunakan saat ini (<code className="bg-red-950/40 text-red-300 px-1.5 py-0.5 rounded font-mono text-xs">sk_db_live_...</code>) adalah <strong>Site-scoped API Key</strong>. BackOne membatasi kunci ini agar hanya dapat membaca data statistik jaringan (Informatics), sehingga tidak memiliki izin untuk mengelola inventaris Agents global.
</p>
<div className="bg-slate-900/60 rounded-lg p-4 border border-border/40 text-xs space-y-2 leading-relaxed">
- <p className="font-semibold text-white">💡 Cara Mengatasinya:</p>
+ <p className="font-semibold text-white">💡 Cara Mengatasinya:</p>
<ol className="list-decimal pl-4 space-y-1 text-slate-400">
<li>Buka dan login ke portal <a href="https://portal.netify.ai" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline font-medium">BackOne Portal</a>.</li>
<li>Di menu sebelah kiri, navigasikan ke <strong>Settings</strong> &gt; <strong>API Keys</strong>.</li>
@@ -354,3 +350,4 @@ export default function AgentsPage() {
</div>
);
}
+
diff --git a/src/app/(dashboard)/apps/page.tsx b/src/app/(dashboard)/apps/page.tsx
index d8efe96..5fda0f0 100644
--- a/src/app/(dashboard)/apps/page.tsx
+++ b/src/app/(dashboard)/apps/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { useState, useEffect } from "react";
import { useTopApps, AppStat } from "@/lib/api";
@@ -11,7 +11,9 @@ import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip as RechartsTooltip,
export default function AppsPage() {
const [mounted, setMounted] = useState(false);
- const { data, isLoading } = useTopApps(50); // fetch 50 apps
+ const [page, setPage] = useState(0);
+ const pageSize = 20;
+ const { data, isLoading } = useTopApps(pageSize, page * pageSize);
const [selectedApp, setSelectedApp] = useState<AppStat | null>(null);
useEffect(() => {
@@ -23,6 +25,7 @@ export default function AppsPage() {
const top5 = data.slice(0, 5);
const columns: Column<AppStat>[] = [
+ { header: "Last Seen", accessor: (row) => row.timestamp ? new Date(row.timestamp).toLocaleString() : '-' },
{ header: "#", accessor: (row, i) => i + 1 },
{
header: "Application",
@@ -57,17 +60,7 @@ export default function AppsPage() {
return (
<div className="space-y-6">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- Applications
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
- <p className="text-muted-foreground mt-1 text-sm">
- Click any application to see which agents and devices are using it.
- </p>
- </div>
- </div>
+
<Card className="bg-card/50 backdrop-blur-sm border-border/50">
<CardHeader>
@@ -134,3 +127,6 @@ export default function AppsPage() {
</div>
);
}
+
+
+
diff --git a/src/app/(dashboard)/devices/page.tsx b/src/app/(dashboard)/devices/page.tsx
index a6d2602..ab450fe 100644
--- a/src/app/(dashboard)/devices/page.tsx
+++ b/src/app/(dashboard)/devices/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card";
import { DataTable, Column } from "@/components/ui/DataTable";
@@ -10,7 +10,9 @@ import { Loader2, ChevronRight } from "lucide-react";
export default function DevicesPage() {
const [mounted, setMounted] = useState(false);
- const devices = useDevices(1000);
+ const [page, setPage] = useState(0);
+ const pageSize = 50;
+ const devices = useDevices(pageSize, page * pageSize);
const [selectedDevice, setSelectedDevice] = useState<DeviceStat | null>(null);
useEffect(() => {
@@ -20,6 +22,7 @@ export default function DevicesPage() {
if (!mounted) return null;
const columns: Column<DeviceStat>[] = [
+ { header: "Last Seen", accessor: (row) => row.timestamp ? new Date(row.timestamp).toLocaleString() : '-' },
{ header: "#", accessor: (row, i) => i + 1 },
{
header: "IP Address",
@@ -51,7 +54,7 @@ export default function DevicesPage() {
{(isRouted || info) && (
<span className={`text-[10px] font-sans font-medium ${isRouted ? "text-amber-500/90 italic" : "text-slate-400/80"}`}>
{isRouted ? "Via Routed Gateway" : ""}
- {isRouted && info ? ` • ${info}` : (!isRouted ? info : "")}
+ {isRouted && info ? ` • ${info}` : (!isRouted ? info : "")}
</span>
)}
</div>
@@ -77,18 +80,7 @@ export default function DevicesPage() {
return (
<div className="space-y-8 animate-fade-in pb-10">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-3xl font-bold tracking-tight text-white flex items-center gap-3">
- Devices
- {devices.isLoading && <Loader2 className="w-5 h-5 animate-spin text-primary" />}
- </h2>
- <p className="text-muted-foreground mt-1">
- Monitor and manage connected network devices.{" "}
- <span className="text-slate-500 text-xs">Click an IP to see app usage &amp; flows.</span>
- </p>
- </div>
- </div>
+
<Card className="bg-card/80 backdrop-blur-xl border-border/50 animate-slide-up" style={{ animationDelay: "100ms" }}>
<CardHeader className="border-b border-border/50 pb-4 mb-4">
@@ -126,3 +118,4 @@ export default function DevicesPage() {
</div>
);
}
+
diff --git a/src/app/(dashboard)/dns/page.tsx b/src/app/(dashboard)/dns/page.tsx
index 05a7a48..0b8d8a3 100644
--- a/src/app/(dashboard)/dns/page.tsx
+++ b/src/app/(dashboard)/dns/page.tsx
@@ -32,12 +32,7 @@ export default function DNSPage() {
return (
<div className="space-y-6">
- <div className="flex items-center justify-between">
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- DNS Intelligence
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
- </div>
+
<Card className="bg-card/50 backdrop-blur-sm border-border/50">
<CardHeader>
diff --git a/src/app/(dashboard)/events/page.tsx b/src/app/(dashboard)/events/page.tsx
index c521e04..416dae0 100644
--- a/src/app/(dashboard)/events/page.tsx
+++ b/src/app/(dashboard)/events/page.tsx
@@ -105,12 +105,7 @@ function EventsContent() {
return (
<div className="space-y-6">
- <div className="flex items-center justify-between">
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- Network Events
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
- </div>
+
<Card className="bg-card/50 backdrop-blur-sm border-border/50">
<CardHeader>
diff --git a/src/app/(dashboard)/flows/page.tsx b/src/app/(dashboard)/flows/page.tsx
index 115d8ec..3e4064e 100644
--- a/src/app/(dashboard)/flows/page.tsx
+++ b/src/app/(dashboard)/flows/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { useState, useEffect } from "react";
import { useFlows } from "@/lib/api";
@@ -110,12 +110,7 @@ export default function FlowsPage() {
return (
<div className="space-y-6">
- <div className="flex items-center justify-between">
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- Active Flows
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
- </div>
+
<Card className="bg-card/50 backdrop-blur-sm border-border/50">
<CardHeader>
@@ -142,3 +137,4 @@ export default function FlowsPage() {
</div>
);
}
+
diff --git a/src/app/(dashboard)/geography/page.tsx b/src/app/(dashboard)/geography/page.tsx
index 6ddd2e0..9913e33 100644
--- a/src/app/(dashboard)/geography/page.tsx
+++ b/src/app/(dashboard)/geography/page.tsx
@@ -65,15 +65,7 @@ export default function GeographyPage() {
return (
<div className="space-y-8 animate-fade-in pb-10">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-3xl font-bold tracking-tight text-white flex items-center gap-3">
- Geographic Traffic
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-primary" />}
- </h2>
- <p className="text-muted-foreground mt-1">Visualize data flow and activity across the globe.</p>
- </div>
- </div>
+
{showMap && (
<Card className="bg-card/80 backdrop-blur-xl border-border/50 animate-slide-up" style={{ animationDelay: '100ms' }}>
diff --git a/src/app/(dashboard)/intelligence/page.tsx b/src/app/(dashboard)/intelligence/page.tsx
index 3418107..581845a 100644
--- a/src/app/(dashboard)/intelligence/page.tsx
+++ b/src/app/(dashboard)/intelligence/page.tsx
@@ -228,12 +228,7 @@ export default function IntelligencePage() {
return (
<div className="space-y-6">
- <div className="flex items-center justify-between">
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- Deep Packet Inspection Intelligence
- {loadingStats && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
- </div>
+
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{intelItems.map((item, idx) => {
diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx
index b6888fc..83239e6 100644
--- a/src/app/(dashboard)/layout.tsx
+++ b/src/app/(dashboard)/layout.tsx
@@ -1,9 +1,14 @@
import { DashboardLayout } from "@/components/layout/DashboardLayout";
+import { TimeFilterProvider } from "@/contexts/TimeFilterContext";
export default function AppLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
- return <DashboardLayout>{children}</DashboardLayout>;
+ return (
+ <TimeFilterProvider>
+ <DashboardLayout>{children}</DashboardLayout>
+ </TimeFilterProvider>
+ );
}
diff --git a/src/app/(dashboard)/network-intelligence/page.tsx b/src/app/(dashboard)/network-intelligence/page.tsx
index 93e8e40..15c33b3 100644
--- a/src/app/(dashboard)/network-intelligence/page.tsx
+++ b/src/app/(dashboard)/network-intelligence/page.tsx
@@ -36,19 +36,7 @@ export default function NetworkIntelligencePage() {
return (
<div className="space-y-8 animate-fade-in pb-10">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-3xl font-bold tracking-tight text-white flex items-center gap-3">
- Network Intelligence
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-primary" />}
- </h2>
- <p className="text-muted-foreground mt-1">Deep packet inspection analytics and geography.</p>
- </div>
- <div className="flex items-center gap-2 text-sm font-medium text-blue-400 bg-blue-500/10 border border-blue-500/20 px-4 py-2 rounded-lg shadow-[0_0_15px_rgba(59,130,246,0.1)]">
- <Activity className="h-4 w-4" />
- <span>DPI Engine Active</span>
- </div>
- </div>
+
<div className="grid gap-6 md:grid-cols-2">
{/* Left Column: App Categories List */}
diff --git a/src/app/(dashboard)/page.tsx b/src/app/(dashboard)/page.tsx
index 98b2969..b16ca54 100644
--- a/src/app/(dashboard)/page.tsx
+++ b/src/app/(dashboard)/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card";
import { Activity, Download, Upload, ShieldAlert, Zap, Server, Loader2 } from "lucide-react";
@@ -49,15 +49,7 @@ export default function SummaryPage() {
return (
<div className="space-y-8 animate-fade-in pb-10">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-3xl font-bold tracking-tight text-white flex items-center gap-3">
- Summary Overview
- {isLoading && <Loader2 className="w-5 h-5 animate-spin text-primary" />}
- </h2>
- <p className="text-muted-foreground mt-1">Real-time network traffic and intelligence summary.</p>
- </div>
- </div>
+
{/* KPI Cards */}
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6">
@@ -292,3 +284,4 @@ export default function SummaryPage() {
</div>
);
}
+
diff --git a/src/app/(dashboard)/security-audit/page.tsx b/src/app/(dashboard)/security-audit/page.tsx
index 9ee84e9..3a59875 100644
--- a/src/app/(dashboard)/security-audit/page.tsx
+++ b/src/app/(dashboard)/security-audit/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { useState, useEffect } from "react";
import {
@@ -26,9 +26,9 @@ const COLORS = {
};
const RISK_CONFIG = {
- Rawan: { color: "text-red-400", bg: "bg-red-500/20 ring-red-500/40", icon: <ShieldX className="w-3.5 h-3.5" />, dot: "bg-red-500" },
- Sedang: { color: "text-orange-400", bg: "bg-orange-500/20 ring-orange-500/40", icon: <ShieldAlert className="w-3.5 h-3.5" />, dot: "bg-orange-500" },
- Aman: { color: "text-green-400", bg: "bg-green-500/20 ring-green-500/40", icon: <ShieldCheck className="w-3.5 h-3.5" />, dot: "bg-green-500" },
+ Vulnerable: { color: "text-red-400", bg: "bg-red-500/20 ring-red-500/40", icon: <ShieldX className="w-3.5 h-3.5" />, dot: "bg-red-500" },
+ Moderate: { color: "text-orange-400", bg: "bg-orange-500/20 ring-orange-500/40", icon: <ShieldAlert className="w-3.5 h-3.5" />, dot: "bg-orange-500" },
+ Safe: { color: "text-green-400", bg: "bg-green-500/20 ring-green-500/40", icon: <ShieldCheck className="w-3.5 h-3.5" />, dot: "bg-green-500" },
} as const;
export default function SecurityAuditPage() {
@@ -54,9 +54,9 @@ export default function SecurityAuditPage() {
const isLoading = versions.isLoading || ciphers.isLoading || security.isLoading;
// Risk summary counts
- const rawan = secDevices.filter((d) => d.risk_level === "Rawan").length;
- const sedang = secDevices.filter((d) => d.risk_level === "Sedang").length;
- const aman = secDevices.filter((d) => d.risk_level === "Aman").length;
+ const vulnerableCount = secDevices.filter((d) => d.risk_level === "Vulnerable").length;
+ const moderateCount = secDevices.filter((d) => d.risk_level === "Moderate").length;
+ const safeCount = secDevices.filter((d) => d.risk_level === "Safe").length;
const versionColumns: Column<typeof versions.data[0]>[] = [
{ header: "#", accessor: (row, i) => i + 1 },
@@ -134,7 +134,7 @@ export default function SecurityAuditPage() {
{
header: "Risk Level",
accessor: (row) => {
- const cfg = RISK_CONFIG[row.risk_level] ?? RISK_CONFIG.Aman;
+ const cfg = RISK_CONFIG[row.risk_level] ?? RISK_CONFIG.Safe;
return (
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold ring-1 ${cfg.bg} ${cfg.color}`}>
{cfg.icon}
@@ -152,15 +152,7 @@ export default function SecurityAuditPage() {
return (
<div className="space-y-6">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-2xl font-bold tracking-tight text-white flex items-center gap-3">
- Security Audit
- {(isLoading || secDevicesLoading) && <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />}
- </h2>
- <p className="text-muted-foreground mt-1 text-sm">TLS encryption analysis and device-level risk assessment.</p>
- </div>
- </div>
+
{/* Security Overview Cards */}
<div className="grid gap-4 md:grid-cols-3">
@@ -186,32 +178,32 @@ export default function SecurityAuditPage() {
<div className="grid gap-4 md:grid-cols-3">
<Card className="bg-red-950/20 border-red-500/20 backdrop-blur-sm">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium text-red-300">Rawan (Vulnerable)</CardTitle>
+ <CardTitle className="text-sm font-medium text-red-300">Vulnerable</CardTitle>
<ShieldX className="h-4 w-4 text-red-400" />
</CardHeader>
<CardContent>
- <div className="text-3xl font-bold text-red-400">{rawan}</div>
- <p className="text-xs text-red-300/60 mt-1">device{rawan !== 1 ? "s" : ""} at risk</p>
+ <div className="text-3xl font-bold text-red-400">{vulnerableCount}</div>
+ <p className="text-xs text-red-300/60 mt-1">device{vulnerableCount !== 1 ? "s" : ""} at risk</p>
</CardContent>
</Card>
<Card className="bg-orange-950/20 border-orange-500/20 backdrop-blur-sm">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium text-orange-300">Sedang (Moderate)</CardTitle>
+ <CardTitle className="text-sm font-medium text-orange-300">Moderate</CardTitle>
<ShieldAlert className="h-4 w-4 text-orange-400" />
</CardHeader>
<CardContent>
- <div className="text-3xl font-bold text-orange-400">{sedang}</div>
- <p className="text-xs text-orange-300/60 mt-1">device{sedang !== 1 ? "s" : ""} moderate risk</p>
+ <div className="text-3xl font-bold text-orange-400">{moderateCount}</div>
+ <p className="text-xs text-orange-300/60 mt-1">device{moderateCount !== 1 ? "s" : ""} moderate risk</p>
</CardContent>
</Card>
<Card className="bg-green-950/20 border-green-500/20 backdrop-blur-sm">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium text-green-300">Aman (Secure)</CardTitle>
+ <CardTitle className="text-sm font-medium text-green-300">Safe (Secure)</CardTitle>
<ShieldCheck className="h-4 w-4 text-green-400" />
</CardHeader>
<CardContent>
- <div className="text-3xl font-bold text-green-400">{aman}</div>
- <p className="text-xs text-green-300/60 mt-1">device{aman !== 1 ? "s" : ""} secure</p>
+ <div className="text-3xl font-bold text-green-400">{safeCount}</div>
+ <p className="text-xs text-green-300/60 mt-1">device{safeCount !== 1 ? "s" : ""} secure</p>
</CardContent>
</Card>
</div>
@@ -377,3 +369,4 @@ export default function SecurityAuditPage() {
</div>
);
}
+
diff --git a/src/app/(dashboard)/threats/page.tsx b/src/app/(dashboard)/threats/page.tsx
index 522a61a..4410624 100644
--- a/src/app/(dashboard)/threats/page.tsx
+++ b/src/app/(dashboard)/threats/page.tsx
@@ -1,4 +1,4 @@
-"use client";
+"use client";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/Card";
import { DataTable, Column } from "@/components/ui/DataTable";
@@ -13,7 +13,9 @@ import { Suspense } from "react";
function ThreatsContent() {
const [mounted, setMounted] = useState(false);
- const threats = useThreats(100);
+ const [page, setPage] = useState(0);
+ const pageSize = 50;
+ const threats = useThreats(pageSize, page * pageSize);
const searchParams = useSearchParams();
const highlightId = searchParams.get("highlight");
@@ -33,6 +35,7 @@ function ThreatsContent() {
};
const columns: Column<ThreatStat>[] = [
+ { header: "Timestamp", accessor: (row) => row.timestamp ? new Date(row.timestamp).toLocaleString() : '-' },
{ header: "#", accessor: (row, i) => i + 1 },
{ header: "Type", accessor: (row) => row.threat_type || 'Unknown' },
{ header: "Severity", accessor: (row) => getSeverityBadge(row.severity) },
@@ -54,19 +57,7 @@ function ThreatsContent() {
return (
<div className="space-y-8 animate-fade-in pb-10">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-3xl font-bold tracking-tight text-white flex items-center gap-3">
- Threat Intelligence
- {threats.isLoading && <Loader2 className="w-5 h-5 animate-spin text-primary" />}
- </h2>
- <p className="text-muted-foreground mt-1">Monitor and respond to network security threats.</p>
- </div>
- <div className="flex items-center gap-2 text-sm font-medium text-emerald-400 bg-emerald-500/10 border border-emerald-500/20 px-4 py-2 rounded-lg shadow-[0_0_15px_rgba(16,185,129,0.1)]">
- <ShieldCheck className="h-4 w-4" />
- <span>Active Monitoring</span>
- </div>
- </div>
+
<Card className="bg-card/80 backdrop-blur-xl border-border/50 animate-slide-up" style={{ animationDelay: '100ms' }}>
<CardHeader className="border-b border-border/50 pb-4 mb-4">
@@ -103,3 +94,4 @@ export default function ThreatsPage() {
</Suspense>
);
}
+