ids.alfacom.it/server/storage.ts
marco370 cbd03d9e64 Add network analytics and live dashboard features
Introduce new network analytics capabilities with persistent storage, hourly and daily aggregations, and enhanced frontend visualizations. This includes API endpoints for retrieving analytics data, systemd services for automated aggregation, and UI updates for live and historical dashboards. Additionally, country flag emojis are now displayed on the detections page.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 3c14f651-7633-4128-8526-314b4942b3a0
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/oGXAoP7
2025-11-22 11:34:36 +00:00

273 lines
8.1 KiB
TypeScript

import {
routers,
networkLogs,
detections,
whitelist,
trainingHistory,
networkAnalytics,
type Router,
type InsertRouter,
type NetworkLog,
type InsertNetworkLog,
type Detection,
type InsertDetection,
type Whitelist,
type InsertWhitelist,
type TrainingHistory,
type InsertTrainingHistory,
type NetworkAnalytics,
} from "@shared/schema";
import { db } from "./db";
import { eq, desc, and, gte, sql, inArray } from "drizzle-orm";
export interface IStorage {
// Routers
getAllRouters(): Promise<Router[]>;
getRouterById(id: string): Promise<Router | undefined>;
createRouter(router: InsertRouter): Promise<Router>;
updateRouter(id: string, router: Partial<InsertRouter>): Promise<Router | undefined>;
deleteRouter(id: string): Promise<boolean>;
// Network Logs
getRecentLogs(limit: number): Promise<NetworkLog[]>;
getLogsByIp(sourceIp: string, limit: number): Promise<NetworkLog[]>;
createLog(log: InsertNetworkLog): Promise<NetworkLog>;
getLogsForTraining(limit: number, minTimestamp?: Date): Promise<NetworkLog[]>;
// Detections
getAllDetections(limit: number): Promise<Detection[]>;
getDetectionByIp(sourceIp: string): Promise<Detection | undefined>;
createDetection(detection: InsertDetection): Promise<Detection>;
updateDetection(id: string, detection: Partial<InsertDetection>): Promise<Detection | undefined>;
getUnblockedDetections(): Promise<Detection[]>;
// Whitelist
getAllWhitelist(): Promise<Whitelist[]>;
getWhitelistByIp(ipAddress: string): Promise<Whitelist | undefined>;
createWhitelist(whitelist: InsertWhitelist): Promise<Whitelist>;
deleteWhitelist(id: string): Promise<boolean>;
isWhitelisted(ipAddress: string): Promise<boolean>;
// Training History
getTrainingHistory(limit: number): Promise<TrainingHistory[]>;
createTrainingHistory(history: InsertTrainingHistory): Promise<TrainingHistory>;
getLatestTraining(): Promise<TrainingHistory | undefined>;
// Network Analytics
getAnalyticsByDateRange(startDate: Date, endDate: Date, hourly?: boolean): Promise<NetworkAnalytics[]>;
getRecentAnalytics(days: number, hourly?: boolean): Promise<NetworkAnalytics[]>;
// System
testConnection(): Promise<boolean>;
}
export class DatabaseStorage implements IStorage {
// Routers
async getAllRouters(): Promise<Router[]> {
return await db.select().from(routers).orderBy(desc(routers.createdAt));
}
async getRouterById(id: string): Promise<Router | undefined> {
const [router] = await db.select().from(routers).where(eq(routers.id, id));
return router || undefined;
}
async createRouter(insertRouter: InsertRouter): Promise<Router> {
const [router] = await db.insert(routers).values(insertRouter).returning();
return router;
}
async updateRouter(id: string, updateData: Partial<InsertRouter>): Promise<Router | undefined> {
const [router] = await db
.update(routers)
.set(updateData)
.where(eq(routers.id, id))
.returning();
return router || undefined;
}
async deleteRouter(id: string): Promise<boolean> {
const result = await db.delete(routers).where(eq(routers.id, id));
return result.rowCount !== null && result.rowCount > 0;
}
// Network Logs
async getRecentLogs(limit: number): Promise<NetworkLog[]> {
return await db
.select()
.from(networkLogs)
.orderBy(desc(networkLogs.timestamp))
.limit(limit);
}
async getLogsByIp(sourceIp: string, limit: number): Promise<NetworkLog[]> {
return await db
.select()
.from(networkLogs)
.where(eq(networkLogs.sourceIp, sourceIp))
.orderBy(desc(networkLogs.timestamp))
.limit(limit);
}
async createLog(insertLog: InsertNetworkLog): Promise<NetworkLog> {
const [log] = await db.insert(networkLogs).values(insertLog).returning();
return log;
}
async getLogsForTraining(limit: number, minTimestamp?: Date): Promise<NetworkLog[]> {
const conditions = minTimestamp
? and(gte(networkLogs.timestamp, minTimestamp))
: undefined;
return await db
.select()
.from(networkLogs)
.where(conditions)
.orderBy(desc(networkLogs.timestamp))
.limit(limit);
}
// Detections
async getAllDetections(limit: number): Promise<Detection[]> {
return await db
.select()
.from(detections)
.orderBy(desc(detections.detectedAt))
.limit(limit);
}
async getDetectionByIp(sourceIp: string): Promise<Detection | undefined> {
const [detection] = await db
.select()
.from(detections)
.where(eq(detections.sourceIp, sourceIp))
.orderBy(desc(detections.detectedAt))
.limit(1);
return detection || undefined;
}
async createDetection(insertDetection: InsertDetection): Promise<Detection> {
const [detection] = await db
.insert(detections)
.values(insertDetection)
.returning();
return detection;
}
async updateDetection(
id: string,
updateData: Partial<InsertDetection>
): Promise<Detection | undefined> {
const [detection] = await db
.update(detections)
.set(updateData)
.where(eq(detections.id, id))
.returning();
return detection || undefined;
}
async getUnblockedDetections(): Promise<Detection[]> {
return await db
.select()
.from(detections)
.where(eq(detections.blocked, false))
.orderBy(desc(detections.riskScore));
}
// Whitelist
async getAllWhitelist(): Promise<Whitelist[]> {
return await db
.select()
.from(whitelist)
.where(eq(whitelist.active, true))
.orderBy(desc(whitelist.createdAt));
}
async getWhitelistByIp(ipAddress: string): Promise<Whitelist | undefined> {
const [item] = await db
.select()
.from(whitelist)
.where(and(eq(whitelist.ipAddress, ipAddress), eq(whitelist.active, true)));
return item || undefined;
}
async createWhitelist(insertWhitelist: InsertWhitelist): Promise<Whitelist> {
const [item] = await db.insert(whitelist).values(insertWhitelist).returning();
return item;
}
async deleteWhitelist(id: string): Promise<boolean> {
const result = await db.delete(whitelist).where(eq(whitelist.id, id));
return result.rowCount !== null && result.rowCount > 0;
}
async isWhitelisted(ipAddress: string): Promise<boolean> {
const item = await this.getWhitelistByIp(ipAddress);
return item !== undefined;
}
// Training History
async getTrainingHistory(limit: number): Promise<TrainingHistory[]> {
return await db
.select()
.from(trainingHistory)
.orderBy(desc(trainingHistory.trainedAt))
.limit(limit);
}
async createTrainingHistory(insertHistory: InsertTrainingHistory): Promise<TrainingHistory> {
const [history] = await db
.insert(trainingHistory)
.values(insertHistory)
.returning();
return history;
}
async getLatestTraining(): Promise<TrainingHistory | undefined> {
const [history] = await db
.select()
.from(trainingHistory)
.orderBy(desc(trainingHistory.trainedAt))
.limit(1);
return history || undefined;
}
// Network Analytics
async getAnalyticsByDateRange(startDate: Date, endDate: Date, hourly: boolean = false): Promise<NetworkAnalytics[]> {
const hourCondition = hourly
? sql`hour IS NOT NULL`
: sql`hour IS NULL`;
return await db
.select()
.from(networkAnalytics)
.where(
and(
gte(networkAnalytics.date, startDate),
sql`${networkAnalytics.date} <= ${endDate}`,
hourCondition
)
)
.orderBy(desc(networkAnalytics.date), desc(networkAnalytics.hour));
}
async getRecentAnalytics(days: number, hourly: boolean = false): Promise<NetworkAnalytics[]> {
const startDate = new Date();
startDate.setDate(startDate.getDate() - days);
return this.getAnalyticsByDateRange(startDate, new Date(), hourly);
}
async testConnection(): Promise<boolean> {
try {
await db.execute(sql`SELECT 1`);
return true;
} catch (error) {
console.error('[DB ERROR] Connection test failed:', error);
return false;
}
}
}
export const storage = new DatabaseStorage();