diff --git a/client/src/pages/Dashboard.tsx b/client/src/pages/Dashboard.tsx index 375b9fd..717e905 100644 --- a/client/src/pages/Dashboard.tsx +++ b/client/src/pages/Dashboard.tsx @@ -37,10 +37,12 @@ export default function Dashboard() { refetchInterval: 10000, // Refresh every 10s }); - const { data: recentDetections } = useQuery({ - queryKey: ["/api/detections?limit=100"], - refetchInterval: 5000, // Refresh every 5s + const { data: recentDetectionsData } = useQuery<{ detections: Detection[]; total: number }>({ + queryKey: ["/api/detections", { limit: 100 }], + queryFn: () => fetch("/api/detections?limit=100").then(r => r.json()), + refetchInterval: 5000, }); + const recentDetections = recentDetectionsData?.detections; const { data: routers } = useQuery({ queryKey: ["/api/routers"], diff --git a/client/src/pages/DashboardLive.tsx b/client/src/pages/DashboardLive.tsx index 270d064..d85a365 100644 --- a/client/src/pages/DashboardLive.tsx +++ b/client/src/pages/DashboardLive.tsx @@ -16,6 +16,7 @@ interface DashboardStats { attacksByCountry: Record; attacksByType: Record; recentDetections: Detection[]; + blockedCount: number; } export default function DashboardLive() { @@ -32,7 +33,7 @@ export default function DashboardLive() { const attackPercentage = totalTraffic > 0 ? ((totalAttacks / totalTraffic) * 100).toFixed(2) : "0"; const detections = stats?.recentDetections || []; - const blockedAttacks = detections.filter(d => d.blocked).length; + const blockedAttacks = stats?.blockedCount || 0; // Usa dati aggregati giĆ  calcolati dal backend const attacksByCountry = stats?.attacksByCountry || {}; diff --git a/client/src/pages/PublicLists.tsx b/client/src/pages/PublicLists.tsx index 5f2316e..1384d0d 100644 --- a/client/src/pages/PublicLists.tsx +++ b/client/src/pages/PublicLists.tsx @@ -35,7 +35,7 @@ export default function PublicLists() { const [isAddDialogOpen, setIsAddDialogOpen] = useState(false); const [editingList, setEditingList] = useState(null); - const { data: lists, isLoading } = useQuery({ + const { data: lists, isLoading } = useQuery({ queryKey: ["/api/public-lists"], }); diff --git a/client/src/pages/Routers.tsx b/client/src/pages/Routers.tsx index 0e0b493..b72b3c6 100644 --- a/client/src/pages/Routers.tsx +++ b/client/src/pages/Routers.tsx @@ -47,7 +47,7 @@ export default function Routers() { defaultValues: { name: "", ipAddress: "", - apiPort: 8729, + apiPort: 80, username: "", password: "", enabled: true, @@ -167,7 +167,7 @@ export default function Routers() { Aggiungi Router MikroTik - Configura un nuovo router MikroTik per il sistema IDS. Assicurati che l'API RouterOS (porta 8729/8728) sia abilitata. + Configura un nuovo router MikroTik per il sistema IDS. Usa la REST API (porta 80 HTTP o 443 HTTPS). @@ -216,14 +216,14 @@ export default function Routers() { field.onChange(parseInt(e.target.value))} data-testid="input-port" /> - Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API) + Porta REST API MikroTik (80 per HTTP, 443 per HTTPS) @@ -445,14 +445,14 @@ export default function Routers() { field.onChange(parseInt(e.target.value))} data-testid="input-edit-port" /> - Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API) + Porta REST API MikroTik (80 per HTTP, 443 per HTTPS) diff --git a/server/routes.ts b/server/routes.ts index 5839b43..e226486 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -1,9 +1,9 @@ import type { Express } from "express"; import { createServer, type Server } from "http"; import { storage } from "./storage"; -import { insertRouterSchema, insertDetectionSchema, insertWhitelistSchema, insertPublicListSchema, networkAnalytics, routers } from "@shared/schema"; +import { insertRouterSchema, insertDetectionSchema, insertWhitelistSchema, insertPublicListSchema, networkAnalytics, routers, detections, networkLogs } from "@shared/schema"; import { db } from "./db"; -import { desc, eq } from "drizzle-orm"; +import { desc, eq, gte, sql } from "drizzle-orm"; export async function registerRoutes(app: Express): Promise { // Routers @@ -310,7 +310,7 @@ export async function registerRoutes(app: Express): Promise { const text = await response.text(); // Parse IPs based on content type - let ips: Array<{ip: string, cidr?: string}> = []; + let ips: Array<{ip: string, cidr: string | null}> = []; if (contentType.includes('json') || list.url.endsWith('.json')) { // JSON format (Spamhaus DROP v4 JSON) @@ -322,7 +322,7 @@ export async function registerRoutes(app: Express): Promise { const [ip] = entry.cidr.split('/'); ips.push({ ip, cidr: entry.cidr }); } else if (entry.ip) { - ips.push({ ip: entry.ip, cidr: null as any }); + ips.push({ ip: entry.ip, cidr: null }); } } } @@ -342,7 +342,7 @@ export async function registerRoutes(app: Express): Promise { if (match) { const ip = match[1]; const cidr = match[2] ? `${match[1]}${match[2]}` : null; - ips.push({ ip, cidr: cidr as any }); + ips.push({ ip, cidr }); } } } @@ -481,30 +481,35 @@ export async function registerRoutes(app: Express): Promise { // Stats app.get("/api/stats", async (req, res) => { try { - const routers = await storage.getAllRouters(); - const detectionsResult = await storage.getAllDetections({ limit: 1000 }); - const recentLogs = await storage.getRecentLogs(1000); + const routersList = await storage.getAllRouters(); const whitelistResult = await storage.getAllWhitelist({ limit: 1 }); const latestTraining = await storage.getLatestTraining(); - const detectionsList = detectionsResult.detections; - const blockedCount = detectionsList.filter(d => d.blocked).length; - const criticalCount = detectionsList.filter(d => parseFloat(d.riskScore) >= 85).length; - const highCount = detectionsList.filter(d => parseFloat(d.riskScore) >= 70 && parseFloat(d.riskScore) < 85).length; + const detectionStats = await db.select({ + total: sql`count(*)::int`, + blocked: sql`count(*) filter (where blocked = true)::int`, + critical: sql`count(*) filter (where ${detections.riskScore}::numeric >= 85)::int`, + high: sql`count(*) filter (where ${detections.riskScore}::numeric >= 70 and ${detections.riskScore}::numeric < 85)::int`, + }).from(detections); + + const logStats = await db.select({ + count: sql`count(*)::int`, + }).from(networkLogs) + .where(gte(networkLogs.timestamp, new Date(Date.now() - 24 * 60 * 60 * 1000))); res.json({ routers: { - total: routers.length, - enabled: routers.filter(r => r.enabled).length + total: routersList.length, + enabled: routersList.filter(r => r.enabled).length }, detections: { - total: detectionsResult.total, - blocked: blockedCount, - critical: criticalCount, - high: highCount + total: detectionStats[0]?.total || 0, + blocked: detectionStats[0]?.blocked || 0, + critical: detectionStats[0]?.critical || 0, + high: detectionStats[0]?.high || 0 }, logs: { - recent: recentLogs.length + recent: logStats[0]?.count || 0 }, whitelist: { total: whitelistResult.total diff --git a/server/storage.ts b/server/storage.ts index 54520b8..53b6752 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -80,13 +80,14 @@ export interface IStorage { attacksByCountry: Record; attacksByType: Record; recentDetections: Detection[]; + blockedCount: number; }>; // Public Lists getAllPublicLists(): Promise; getPublicListById(id: string): Promise; createPublicList(list: InsertPublicList): Promise; - updatePublicList(id: string, list: Partial): Promise; + updatePublicList(id: string, list: Partial & { lastFetch?: Date | null; lastSuccess?: Date | null }): Promise; deletePublicList(id: string): Promise; // Public Blacklist IPs @@ -453,6 +454,11 @@ export class DatabaseStorage implements IStorage { .orderBy(desc(detections.detectedAt)) .limit(100); + const [blockedResult] = await db + .select({ count: sql`count(*)::int` }) + .from(detections) + .where(eq(detections.blocked, true)); + return { totalPackets, attackPackets, @@ -462,6 +468,7 @@ export class DatabaseStorage implements IStorage { attacksByCountry, attacksByType, recentDetections, + blockedCount: blockedResult?.count || 0, }; } @@ -480,7 +487,7 @@ export class DatabaseStorage implements IStorage { return list; } - async updatePublicList(id: string, updateData: Partial): Promise { + async updatePublicList(id: string, updateData: Partial & { lastFetch?: Date | null; lastSuccess?: Date | null }): Promise { const [list] = await db .update(publicLists) .set(updateData)