Compare commits

..

3 Commits

Author SHA1 Message Date
Marco Lanzara
0269dc929e 🚀 Release v1.0.110
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-02-16 10:36:31
2026-02-16 10:36:31 +00:00
marco370
2b5dd0646c Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 7294bd1d-c7f3-46ed-9640-2c81e55da0c8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/5aJYCET
2026-02-16 08:14:48 +00:00
marco370
4229c54d62 Improve system accuracy and router configuration for security monitoring
Fixes type mismatches in API responses, updates router configuration to use correct REST API ports, and refactors statistics calculation for improved accuracy.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 2601dca2-8641-4d91-9722-c30ebbbf23af
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/5aJYCET
2026-02-16 08:14:39 +00:00
8 changed files with 57 additions and 42 deletions

View File

@ -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"],

View File

@ -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 || {};

View File

@ -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"],
});

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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"
}
]
}