Compare commits
3 Commits
a3ec75b86b
...
0269dc929e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0269dc929e | ||
|
|
2b5dd0646c | ||
|
|
4229c54d62 |
@ -37,10 +37,12 @@ export default function Dashboard() {
|
||||
refetchInterval: 10000, // Refresh every 10s
|
||||
});
|
||||
|
||||
const { data: recentDetections } = useQuery<Detection[]>({
|
||||
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<Router[]>({
|
||||
queryKey: ["/api/routers"],
|
||||
|
||||
@ -16,6 +16,7 @@ interface DashboardStats {
|
||||
attacksByCountry: Record<string, number>;
|
||||
attacksByType: Record<string, number>;
|
||||
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 || {};
|
||||
|
||||
@ -35,7 +35,7 @@ export default function PublicLists() {
|
||||
const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
|
||||
const [editingList, setEditingList] = useState<any>(null);
|
||||
|
||||
const { data: lists, isLoading } = useQuery({
|
||||
const { data: lists, isLoading } = useQuery<any[]>({
|
||||
queryKey: ["/api/public-lists"],
|
||||
});
|
||||
|
||||
|
||||
@ -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() {
|
||||
<DialogHeader>
|
||||
<DialogTitle>Aggiungi Router MikroTik</DialogTitle>
|
||||
<DialogDescription>
|
||||
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).
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
@ -216,14 +216,14 @@ export default function Routers() {
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="8729"
|
||||
placeholder="80"
|
||||
{...field}
|
||||
onChange={(e) => field.onChange(parseInt(e.target.value))}
|
||||
data-testid="input-port"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API)
|
||||
Porta REST API MikroTik (80 per HTTP, 443 per HTTPS)
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
@ -445,14 +445,14 @@ export default function Routers() {
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="8729"
|
||||
placeholder="80"
|
||||
{...field}
|
||||
onChange={(e) => field.onChange(parseInt(e.target.value))}
|
||||
data-testid="input-edit-port"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API)
|
||||
Porta REST API MikroTik (80 per HTTP, 443 per HTTPS)
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
\restrict m8BX2OAI4IqpPQYg9LDdkx9gw71E8mW7NhAoc6tFhxIWe7hPFxv4gky0SVxio2N
|
||||
\restrict dD9aoEfsbejhZrnq39dZalwHgFaXuIKh3obps9QwB0cunaM36PvpYWXEbzkuxIC
|
||||
|
||||
-- Dumped from database version 16.11 (df20cf9)
|
||||
-- Dumped by pg_dump version 16.10
|
||||
@ -387,5 +387,5 @@ ALTER TABLE ONLY public.public_blacklist_ips
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
\unrestrict m8BX2OAI4IqpPQYg9LDdkx9gw71E8mW7NhAoc6tFhxIWe7hPFxv4gky0SVxio2N
|
||||
\unrestrict dD9aoEfsbejhZrnq39dZalwHgFaXuIKh3obps9QwB0cunaM36PvpYWXEbzkuxIC
|
||||
|
||||
|
||||
@ -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<Server> {
|
||||
// Routers
|
||||
@ -310,7 +310,7 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
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<Server> {
|
||||
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<Server> {
|
||||
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<Server> {
|
||||
// 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<number>`count(*)::int`,
|
||||
blocked: sql<number>`count(*) filter (where blocked = true)::int`,
|
||||
critical: sql<number>`count(*) filter (where ${detections.riskScore}::numeric >= 85)::int`,
|
||||
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({
|
||||
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
|
||||
|
||||
@ -80,13 +80,14 @@ export interface IStorage {
|
||||
attacksByCountry: Record<string, number>;
|
||||
attacksByType: Record<string, number>;
|
||||
recentDetections: Detection[];
|
||||
blockedCount: number;
|
||||
}>;
|
||||
|
||||
// Public Lists
|
||||
getAllPublicLists(): Promise<PublicList[]>;
|
||||
getPublicListById(id: string): Promise<PublicList | undefined>;
|
||||
createPublicList(list: InsertPublicList): Promise<PublicList>;
|
||||
updatePublicList(id: string, list: Partial<InsertPublicList>): Promise<PublicList | undefined>;
|
||||
updatePublicList(id: string, list: Partial<InsertPublicList> & { lastFetch?: Date | null; lastSuccess?: Date | null }): Promise<PublicList | undefined>;
|
||||
deletePublicList(id: string): Promise<boolean>;
|
||||
|
||||
// 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<number>`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<InsertPublicList>): Promise<PublicList | undefined> {
|
||||
async updatePublicList(id: string, updateData: Partial<InsertPublicList> & { lastFetch?: Date | null; lastSuccess?: Date | null }): Promise<PublicList | undefined> {
|
||||
const [list] = await db
|
||||
.update(publicLists)
|
||||
.set(updateData)
|
||||
|
||||
16
version.json
16
version.json
@ -1,7 +1,13 @@
|
||||
{
|
||||
"version": "1.0.109",
|
||||
"lastUpdate": "2026-02-16T07:50:06.148Z",
|
||||
"version": "1.0.110",
|
||||
"lastUpdate": "2026-02-16T10:36:31.538Z",
|
||||
"changelog": [
|
||||
{
|
||||
"version": "1.0.110",
|
||||
"date": "2026-02-16",
|
||||
"type": "patch",
|
||||
"description": "Deployment automatico v1.0.110"
|
||||
},
|
||||
{
|
||||
"version": "1.0.109",
|
||||
"date": "2026-02-16",
|
||||
@ -295,12 +301,6 @@
|
||||
"date": "2025-11-24",
|
||||
"type": "patch",
|
||||
"description": "Deployment automatico v1.0.61"
|
||||
},
|
||||
{
|
||||
"version": "1.0.60",
|
||||
"date": "2025-11-24",
|
||||
"type": "patch",
|
||||
"description": "Deployment automatico v1.0.60"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user