Refactors storage to use a database backend, introducing schemas and functions for routers, network logs, detections, whitelist, and training history. Integrates Drizzle ORM with Neon Postgres for data persistence. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528 Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 4e9219bb-e0f1-4799-bb3f-6c759dc16069 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/c9ITWqD
137 lines
4.8 KiB
TypeScript
137 lines
4.8 KiB
TypeScript
import { sql, relations } from "drizzle-orm";
|
|
import { pgTable, text, varchar, integer, timestamp, decimal, boolean, index } 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(8728),
|
|
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()`),
|
|
routerId: varchar("router_id").references(() => routers.id).notNull(),
|
|
timestamp: timestamp("timestamp").notNull(),
|
|
sourceIp: text("source_ip").notNull(),
|
|
destIp: text("dest_ip"),
|
|
sourcePort: integer("source_port"),
|
|
destPort: integer("dest_port"),
|
|
protocol: text("protocol"),
|
|
action: text("action"),
|
|
bytes: integer("bytes"),
|
|
packets: integer("packets"),
|
|
loggedAt: timestamp("logged_at").defaultNow().notNull(),
|
|
}, (table) => ({
|
|
sourceIpIdx: index("source_ip_idx").on(table.sourceIp),
|
|
timestampIdx: index("timestamp_idx").on(table.timestamp),
|
|
routerIdIdx: index("router_id_idx").on(table.routerId),
|
|
}));
|
|
|
|
// 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(),
|
|
}, (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),
|
|
}));
|
|
|
|
// 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(),
|
|
});
|
|
|
|
// Relations
|
|
export const routersRelations = relations(routers, ({ many }) => ({
|
|
logs: many(networkLogs),
|
|
}));
|
|
|
|
export const networkLogsRelations = relations(networkLogs, ({ one }) => ({
|
|
router: one(routers, {
|
|
fields: [networkLogs.routerId],
|
|
references: [routers.id],
|
|
}),
|
|
}));
|
|
|
|
// Insert schemas
|
|
export const insertRouterSchema = createInsertSchema(routers).omit({
|
|
id: true,
|
|
createdAt: true,
|
|
lastSync: true,
|
|
});
|
|
|
|
export const insertNetworkLogSchema = createInsertSchema(networkLogs).omit({
|
|
id: true,
|
|
loggedAt: 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,
|
|
});
|
|
|
|
// 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>;
|