Compare commits

..

No commits in common. "0269dc929e392206384d4aa36d297f77c4c2131e" and "a3ec75b86bb84614ed5d00c90f5d4f27271d9490" have entirely different histories.

8 changed files with 42 additions and 57 deletions

View File

@ -37,12 +37,10 @@ export default function Dashboard() {
refetchInterval: 10000, // Refresh every 10s refetchInterval: 10000, // Refresh every 10s
}); });
const { data: recentDetectionsData } = useQuery<{ detections: Detection[]; total: number }>({ const { data: recentDetections } = useQuery<Detection[]>({
queryKey: ["/api/detections", { limit: 100 }], queryKey: ["/api/detections?limit=100"],
queryFn: () => fetch("/api/detections?limit=100").then(r => r.json()), refetchInterval: 5000, // Refresh every 5s
refetchInterval: 5000,
}); });
const recentDetections = recentDetectionsData?.detections;
const { data: routers } = useQuery<Router[]>({ const { data: routers } = useQuery<Router[]>({
queryKey: ["/api/routers"], queryKey: ["/api/routers"],

View File

@ -16,7 +16,6 @@ interface DashboardStats {
attacksByCountry: Record<string, number>; attacksByCountry: Record<string, number>;
attacksByType: Record<string, number>; attacksByType: Record<string, number>;
recentDetections: Detection[]; recentDetections: Detection[];
blockedCount: number;
} }
export default function DashboardLive() { export default function DashboardLive() {
@ -33,7 +32,7 @@ export default function DashboardLive() {
const attackPercentage = totalTraffic > 0 ? ((totalAttacks / totalTraffic) * 100).toFixed(2) : "0"; const attackPercentage = totalTraffic > 0 ? ((totalAttacks / totalTraffic) * 100).toFixed(2) : "0";
const detections = stats?.recentDetections || []; const detections = stats?.recentDetections || [];
const blockedAttacks = stats?.blockedCount || 0; const blockedAttacks = detections.filter(d => d.blocked).length;
// Usa dati aggregati già calcolati dal backend // Usa dati aggregati già calcolati dal backend
const attacksByCountry = stats?.attacksByCountry || {}; const attacksByCountry = stats?.attacksByCountry || {};

View File

@ -35,7 +35,7 @@ export default function PublicLists() {
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false); const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
const [editingList, setEditingList] = useState<any>(null); const [editingList, setEditingList] = useState<any>(null);
const { data: lists, isLoading } = useQuery<any[]>({ const { data: lists, isLoading } = useQuery({
queryKey: ["/api/public-lists"], queryKey: ["/api/public-lists"],
}); });

View File

@ -47,7 +47,7 @@ export default function Routers() {
defaultValues: { defaultValues: {
name: "", name: "",
ipAddress: "", ipAddress: "",
apiPort: 80, apiPort: 8729,
username: "", username: "",
password: "", password: "",
enabled: true, enabled: true,
@ -167,7 +167,7 @@ export default function Routers() {
<DialogHeader> <DialogHeader>
<DialogTitle>Aggiungi Router MikroTik</DialogTitle> <DialogTitle>Aggiungi Router MikroTik</DialogTitle>
<DialogDescription> <DialogDescription>
Configura un nuovo router MikroTik per il sistema IDS. Usa la REST API (porta 80 HTTP o 443 HTTPS). Configura un nuovo router MikroTik per il sistema IDS. Assicurati che l'API RouterOS (porta 8729/8728) sia abilitata.
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
@ -216,14 +216,14 @@ export default function Routers() {
<FormControl> <FormControl>
<Input <Input
type="number" type="number"
placeholder="80" placeholder="8729"
{...field} {...field}
onChange={(e) => field.onChange(parseInt(e.target.value))} onChange={(e) => field.onChange(parseInt(e.target.value))}
data-testid="input-port" data-testid="input-port"
/> />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
Porta REST API MikroTik (80 per HTTP, 443 per HTTPS) Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API)
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>
@ -445,14 +445,14 @@ export default function Routers() {
<FormControl> <FormControl>
<Input <Input
type="number" type="number"
placeholder="80" placeholder="8729"
{...field} {...field}
onChange={(e) => field.onChange(parseInt(e.target.value))} onChange={(e) => field.onChange(parseInt(e.target.value))}
data-testid="input-edit-port" data-testid="input-edit-port"
/> />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
Porta REST API MikroTik (80 per HTTP, 443 per HTTPS) Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API)
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
</FormItem> </FormItem>

View File

@ -2,7 +2,7 @@
-- PostgreSQL database dump -- PostgreSQL database dump
-- --
\restrict dD9aoEfsbejhZrnq39dZalwHgFaXuIKh3obps9QwB0cunaM36PvpYWXEbzkuxIC \restrict m8BX2OAI4IqpPQYg9LDdkx9gw71E8mW7NhAoc6tFhxIWe7hPFxv4gky0SVxio2N
-- Dumped from database version 16.11 (df20cf9) -- Dumped from database version 16.11 (df20cf9)
-- Dumped by pg_dump version 16.10 -- Dumped by pg_dump version 16.10
@ -387,5 +387,5 @@ ALTER TABLE ONLY public.public_blacklist_ips
-- PostgreSQL database dump complete -- PostgreSQL database dump complete
-- --
\unrestrict dD9aoEfsbejhZrnq39dZalwHgFaXuIKh3obps9QwB0cunaM36PvpYWXEbzkuxIC \unrestrict m8BX2OAI4IqpPQYg9LDdkx9gw71E8mW7NhAoc6tFhxIWe7hPFxv4gky0SVxio2N

View File

@ -1,9 +1,9 @@
import type { Express } from "express"; import type { Express } from "express";
import { createServer, type Server } from "http"; import { createServer, type Server } from "http";
import { storage } from "./storage"; import { storage } from "./storage";
import { insertRouterSchema, insertDetectionSchema, insertWhitelistSchema, insertPublicListSchema, networkAnalytics, routers, detections, networkLogs } from "@shared/schema"; import { insertRouterSchema, insertDetectionSchema, insertWhitelistSchema, insertPublicListSchema, networkAnalytics, routers } from "@shared/schema";
import { db } from "./db"; import { db } from "./db";
import { desc, eq, gte, sql } from "drizzle-orm"; import { desc, eq } from "drizzle-orm";
export async function registerRoutes(app: Express): Promise<Server> { export async function registerRoutes(app: Express): Promise<Server> {
// Routers // Routers
@ -310,7 +310,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
const text = await response.text(); const text = await response.text();
// Parse IPs based on content type // Parse IPs based on content type
let ips: Array<{ip: string, cidr: string | null}> = []; let ips: Array<{ip: string, cidr?: string}> = [];
if (contentType.includes('json') || list.url.endsWith('.json')) { if (contentType.includes('json') || list.url.endsWith('.json')) {
// JSON format (Spamhaus DROP v4 JSON) // JSON format (Spamhaus DROP v4 JSON)
@ -322,7 +322,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
const [ip] = entry.cidr.split('/'); const [ip] = entry.cidr.split('/');
ips.push({ ip, cidr: entry.cidr }); ips.push({ ip, cidr: entry.cidr });
} else if (entry.ip) { } else if (entry.ip) {
ips.push({ ip: entry.ip, cidr: null }); ips.push({ ip: entry.ip, cidr: null as any });
} }
} }
} }
@ -342,7 +342,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
if (match) { if (match) {
const ip = match[1]; const ip = match[1];
const cidr = match[2] ? `${match[1]}${match[2]}` : null; const cidr = match[2] ? `${match[1]}${match[2]}` : null;
ips.push({ ip, cidr }); ips.push({ ip, cidr: cidr as any });
} }
} }
} }
@ -481,35 +481,30 @@ export async function registerRoutes(app: Express): Promise<Server> {
// Stats // Stats
app.get("/api/stats", async (req, res) => { app.get("/api/stats", async (req, res) => {
try { try {
const routersList = await storage.getAllRouters(); const routers = await storage.getAllRouters();
const detectionsResult = await storage.getAllDetections({ limit: 1000 });
const recentLogs = await storage.getRecentLogs(1000);
const whitelistResult = await storage.getAllWhitelist({ limit: 1 }); const whitelistResult = await storage.getAllWhitelist({ limit: 1 });
const latestTraining = await storage.getLatestTraining(); const latestTraining = await storage.getLatestTraining();
const detectionStats = await db.select({ const detectionsList = detectionsResult.detections;
total: sql<number>`count(*)::int`, const blockedCount = detectionsList.filter(d => d.blocked).length;
blocked: sql<number>`count(*) filter (where blocked = true)::int`, const criticalCount = detectionsList.filter(d => parseFloat(d.riskScore) >= 85).length;
critical: sql<number>`count(*) filter (where ${detections.riskScore}::numeric >= 85)::int`, const highCount = detectionsList.filter(d => parseFloat(d.riskScore) >= 70 && parseFloat(d.riskScore) < 85).length;
high: sql<number>`count(*) filter (where ${detections.riskScore}::numeric >= 70 and ${detections.riskScore}::numeric < 85)::int`,
}).from(detections);
const logStats = await db.select({
count: sql<number>`count(*)::int`,
}).from(networkLogs)
.where(gte(networkLogs.timestamp, new Date(Date.now() - 24 * 60 * 60 * 1000)));
res.json({ res.json({
routers: { routers: {
total: routersList.length, total: routers.length,
enabled: routersList.filter(r => r.enabled).length enabled: routers.filter(r => r.enabled).length
}, },
detections: { detections: {
total: detectionStats[0]?.total || 0, total: detectionsResult.total,
blocked: detectionStats[0]?.blocked || 0, blocked: blockedCount,
critical: detectionStats[0]?.critical || 0, critical: criticalCount,
high: detectionStats[0]?.high || 0 high: highCount
}, },
logs: { logs: {
recent: logStats[0]?.count || 0 recent: recentLogs.length
}, },
whitelist: { whitelist: {
total: whitelistResult.total total: whitelistResult.total

View File

@ -80,14 +80,13 @@ export interface IStorage {
attacksByCountry: Record<string, number>; attacksByCountry: Record<string, number>;
attacksByType: Record<string, number>; attacksByType: Record<string, number>;
recentDetections: Detection[]; recentDetections: Detection[];
blockedCount: number;
}>; }>;
// Public Lists // Public Lists
getAllPublicLists(): Promise<PublicList[]>; getAllPublicLists(): Promise<PublicList[]>;
getPublicListById(id: string): Promise<PublicList | undefined>; getPublicListById(id: string): Promise<PublicList | undefined>;
createPublicList(list: InsertPublicList): Promise<PublicList>; createPublicList(list: InsertPublicList): Promise<PublicList>;
updatePublicList(id: string, list: Partial<InsertPublicList> & { lastFetch?: Date | null; lastSuccess?: Date | null }): Promise<PublicList | undefined>; updatePublicList(id: string, list: Partial<InsertPublicList>): Promise<PublicList | undefined>;
deletePublicList(id: string): Promise<boolean>; deletePublicList(id: string): Promise<boolean>;
// Public Blacklist IPs // Public Blacklist IPs
@ -454,11 +453,6 @@ export class DatabaseStorage implements IStorage {
.orderBy(desc(detections.detectedAt)) .orderBy(desc(detections.detectedAt))
.limit(100); .limit(100);
const [blockedResult] = await db
.select({ count: sql<number>`count(*)::int` })
.from(detections)
.where(eq(detections.blocked, true));
return { return {
totalPackets, totalPackets,
attackPackets, attackPackets,
@ -468,7 +462,6 @@ export class DatabaseStorage implements IStorage {
attacksByCountry, attacksByCountry,
attacksByType, attacksByType,
recentDetections, recentDetections,
blockedCount: blockedResult?.count || 0,
}; };
} }
@ -487,7 +480,7 @@ export class DatabaseStorage implements IStorage {
return list; return list;
} }
async updatePublicList(id: string, updateData: Partial<InsertPublicList> & { lastFetch?: Date | null; lastSuccess?: Date | null }): Promise<PublicList | undefined> { async updatePublicList(id: string, updateData: Partial<InsertPublicList>): Promise<PublicList | undefined> {
const [list] = await db const [list] = await db
.update(publicLists) .update(publicLists)
.set(updateData) .set(updateData)

View File

@ -1,13 +1,7 @@
{ {
"version": "1.0.110", "version": "1.0.109",
"lastUpdate": "2026-02-16T10:36:31.538Z", "lastUpdate": "2026-02-16T07:50:06.148Z",
"changelog": [ "changelog": [
{
"version": "1.0.110",
"date": "2026-02-16",
"type": "patch",
"description": "Deployment automatico v1.0.110"
},
{ {
"version": "1.0.109", "version": "1.0.109",
"date": "2026-02-16", "date": "2026-02-16",
@ -301,6 +295,12 @@
"date": "2025-11-24", "date": "2025-11-24",
"type": "patch", "type": "patch",
"description": "Deployment automatico v1.0.61" "description": "Deployment automatico v1.0.61"
},
{
"version": "1.0.60",
"date": "2025-11-24",
"type": "patch",
"description": "Deployment automatico v1.0.60"
} }
] ]
} }