ids.alfacom.it/shared/schema.ts
marco370 dd8d38375d Update router connection test to use REST API and default port 443
Adjusted the router connection test to target the MikroTik REST API on port 443 by default, and handle authentication and status codes accordingly.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1d0150b7-28d2-4cd9-bb13-5d7a63792aab
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/31VdIyL
2025-11-25 11:05:32 +00:00

200 lines
7.7 KiB
TypeScript

import { sql, relations } from "drizzle-orm";
import { pgTable, text, varchar, integer, timestamp, decimal, boolean, index, bigint, unique } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";
// Router MikroTik configuration
export const routers = pgTable("routers", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
name: text("name").notNull(),
ipAddress: text("ip_address").notNull().unique(),
apiPort: integer("api_port").notNull().default(443),
username: text("username").notNull(),
password: text("password").notNull(),
enabled: boolean("enabled").notNull().default(true),
lastSync: timestamp("last_sync"),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
// Network logs from MikroTik (syslog)
export const networkLogs = pgTable("network_logs", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
routerName: text("router_name").notNull(), // Hostname dal syslog
timestamp: timestamp("timestamp").notNull(),
sourceIp: text("source_ip").notNull(),
sourcePort: integer("source_port"),
destinationIp: text("destination_ip"),
destinationPort: integer("destination_port"),
protocol: text("protocol"),
action: text("action"),
packetLength: integer("packet_length"),
rawMessage: text("raw_message"),
createdAt: timestamp("created_at").defaultNow().notNull(),
}, (table) => ({
sourceIpIdx: index("source_ip_idx").on(table.sourceIp),
timestampIdx: index("timestamp_idx").on(table.timestamp),
routerNameIdx: index("router_name_idx").on(table.routerName),
}));
// Detected threats/anomalies
export const detections = pgTable("detections", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
sourceIp: text("source_ip").notNull(),
riskScore: decimal("risk_score", { precision: 5, scale: 2 }).notNull(),
confidence: decimal("confidence", { precision: 5, scale: 2 }).notNull(),
anomalyType: text("anomaly_type").notNull(),
reason: text("reason"),
logCount: integer("log_count").notNull(),
firstSeen: timestamp("first_seen").notNull(),
lastSeen: timestamp("last_seen").notNull(),
blocked: boolean("blocked").notNull().default(false),
blockedAt: timestamp("blocked_at"),
detectedAt: timestamp("detected_at").defaultNow().notNull(),
// Geolocation & AS info
country: text("country"),
countryCode: text("country_code"),
city: text("city"),
organization: text("organization"),
asNumber: text("as_number"),
asName: text("as_name"),
isp: text("isp"),
}, (table) => ({
sourceIpIdx: index("detection_source_ip_idx").on(table.sourceIp),
riskScoreIdx: index("risk_score_idx").on(table.riskScore),
detectedAtIdx: index("detected_at_idx").on(table.detectedAt),
countryIdx: index("country_idx").on(table.country),
}));
// Whitelist per IP fidati
export const whitelist = pgTable("whitelist", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
ipAddress: text("ip_address").notNull().unique(),
comment: text("comment"),
reason: text("reason"),
createdBy: text("created_by"),
active: boolean("active").notNull().default(true),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
// ML Training history
export const trainingHistory = pgTable("training_history", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
modelVersion: text("model_version").notNull(),
recordsProcessed: integer("records_processed").notNull(),
featuresCount: integer("features_count").notNull(),
accuracy: decimal("accuracy", { precision: 5, scale: 2 }),
trainingDuration: integer("training_duration"),
status: text("status").notNull(),
notes: text("notes"),
trainedAt: timestamp("trained_at").defaultNow().notNull(),
});
// Network analytics - aggregazioni permanenti per statistiche long-term
export const networkAnalytics = pgTable("network_analytics", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
date: timestamp("date", { mode: 'date' }).notNull(),
hour: integer("hour"), // NULL = giornaliera, 0-23 = oraria
// Traffico totale
totalPackets: integer("total_packets").notNull().default(0),
totalBytes: bigint("total_bytes", { mode: 'number' }).notNull().default(0),
uniqueIps: integer("unique_ips").notNull().default(0),
// Traffico normale (non anomalo)
normalPackets: integer("normal_packets").notNull().default(0),
normalBytes: bigint("normal_bytes", { mode: 'number' }).notNull().default(0),
normalUniqueIps: integer("normal_unique_ips").notNull().default(0),
topNormalIps: text("top_normal_ips"), // JSON: [{ip, packets, bytes, country}]
// Attacchi/Anomalie
attackPackets: integer("attack_packets").notNull().default(0),
attackBytes: bigint("attack_bytes", { mode: 'number' }).notNull().default(0),
attackUniqueIps: integer("attack_unique_ips").notNull().default(0),
attacksByCountry: text("attacks_by_country"), // JSON: {IT: 5, RU: 30}
attacksByType: text("attacks_by_type"), // JSON: {ddos: 10, port_scan: 5}
topAttackers: text("top_attackers"), // JSON: [{ip, country, risk_score, packets}]
// Dettagli geografici (tutto il traffico)
trafficByCountry: text("traffic_by_country"), // JSON: {IT: {normal: 100, attacks: 5}}
createdAt: timestamp("created_at").defaultNow().notNull(),
}, (table) => ({
dateHourIdx: index("network_analytics_date_hour_idx").on(table.date, table.hour),
dateIdx: index("network_analytics_date_idx").on(table.date),
// CRITICAL: Vincolo UNIQUE per ON CONFLICT in aggregator
dateHourUnique: unique("network_analytics_date_hour_key").on(table.date, table.hour),
}));
// Schema version tracking for database migrations
export const schemaVersion = pgTable("schema_version", {
id: integer("id").primaryKey().default(1),
version: integer("version").notNull().default(0),
appliedAt: timestamp("applied_at").defaultNow().notNull(),
description: text("description"),
});
// Relations
export const routersRelations = relations(routers, ({ many }) => ({
logs: many(networkLogs),
}));
// Rimossa relazione router (non più FK)
// Insert schemas
export const insertRouterSchema = createInsertSchema(routers).omit({
id: true,
createdAt: true,
lastSync: true,
});
export const insertNetworkLogSchema = createInsertSchema(networkLogs).omit({
id: true,
createdAt: true,
});
export const insertDetectionSchema = createInsertSchema(detections).omit({
id: true,
detectedAt: true,
});
export const insertWhitelistSchema = createInsertSchema(whitelist).omit({
id: true,
createdAt: true,
});
export const insertTrainingHistorySchema = createInsertSchema(trainingHistory).omit({
id: true,
trainedAt: true,
});
export const insertSchemaVersionSchema = createInsertSchema(schemaVersion).omit({
appliedAt: true,
});
export const insertNetworkAnalyticsSchema = createInsertSchema(networkAnalytics).omit({
id: true,
createdAt: true,
});
// Types
export type Router = typeof routers.$inferSelect;
export type InsertRouter = z.infer<typeof insertRouterSchema>;
export type NetworkLog = typeof networkLogs.$inferSelect;
export type InsertNetworkLog = z.infer<typeof insertNetworkLogSchema>;
export type Detection = typeof detections.$inferSelect;
export type InsertDetection = z.infer<typeof insertDetectionSchema>;
export type Whitelist = typeof whitelist.$inferSelect;
export type InsertWhitelist = z.infer<typeof insertWhitelistSchema>;
export type TrainingHistory = typeof trainingHistory.$inferSelect;
export type InsertTrainingHistory = z.infer<typeof insertTrainingHistorySchema>;
export type SchemaVersion = typeof schemaVersion.$inferSelect;
export type InsertSchemaVersion = z.infer<typeof insertSchemaVersionSchema>;
export type NetworkAnalytics = typeof networkAnalytics.$inferSelect;
export type InsertNetworkAnalytics = z.infer<typeof insertNetworkAnalyticsSchema>;