Update Mikrotik router connection settings and remove redundant tests
Removes the connection testing functionality and updates the default API port to 8729 for Mikrotik routers. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 54ecaeb2-ec77-4629-8d8d-e3bc4f663bec Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/31VdIyL
This commit is contained in:
parent
81d3617b6b
commit
7eb0991cb5
@ -24,7 +24,7 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { Server, Plus, Trash2, Edit, Wifi, WifiOff } from "lucide-react";
|
import { Server, Plus, Trash2, Edit } from "lucide-react";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
@ -37,7 +37,6 @@ export default function Routers() {
|
|||||||
const [addDialogOpen, setAddDialogOpen] = useState(false);
|
const [addDialogOpen, setAddDialogOpen] = useState(false);
|
||||||
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
||||||
const [editingRouter, setEditingRouter] = useState<Router | null>(null);
|
const [editingRouter, setEditingRouter] = useState<Router | null>(null);
|
||||||
const [testingRouterId, setTestingRouterId] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const { data: routers, isLoading } = useQuery<Router[]>({
|
const { data: routers, isLoading } = useQuery<Router[]>({
|
||||||
queryKey: ["/api/routers"],
|
queryKey: ["/api/routers"],
|
||||||
@ -48,7 +47,7 @@ export default function Routers() {
|
|||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: "",
|
name: "",
|
||||||
ipAddress: "",
|
ipAddress: "",
|
||||||
apiPort: 443,
|
apiPort: 8729,
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
@ -124,28 +123,6 @@ export default function Routers() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const testConnectionMutation = useMutation({
|
|
||||||
mutationFn: async (id: string) => {
|
|
||||||
const response = await apiRequest("POST", `/api/routers/${id}/test`);
|
|
||||||
return response;
|
|
||||||
},
|
|
||||||
onSuccess: (data: any) => {
|
|
||||||
toast({
|
|
||||||
title: "Connessione riuscita",
|
|
||||||
description: data.message || "Il router è raggiungibile e le credenziali sono corrette",
|
|
||||||
});
|
|
||||||
setTestingRouterId(null);
|
|
||||||
},
|
|
||||||
onError: (error: any) => {
|
|
||||||
toast({
|
|
||||||
title: "Connessione fallita",
|
|
||||||
description: error.message || "Impossibile connettersi al router. Verifica IP, porta e credenziali.",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
setTestingRouterId(null);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleAddSubmit = (data: InsertRouter) => {
|
const handleAddSubmit = (data: InsertRouter) => {
|
||||||
addMutation.mutate(data);
|
addMutation.mutate(data);
|
||||||
};
|
};
|
||||||
@ -169,11 +146,6 @@ export default function Routers() {
|
|||||||
setEditDialogOpen(true);
|
setEditDialogOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTestConnection = (id: string) => {
|
|
||||||
setTestingRouterId(id);
|
|
||||||
testConnectionMutation.mutate(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-6 p-6" data-testid="page-routers">
|
<div className="flex flex-col gap-6 p-6" data-testid="page-routers">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@ -195,7 +167,7 @@ export default function Routers() {
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Aggiungi Router MikroTik</DialogTitle>
|
<DialogTitle>Aggiungi Router MikroTik</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Configura un nuovo router MikroTik per il sistema IDS. Assicurati che l'API REST sia abilitata.
|
Configura un nuovo router MikroTik per il sistema IDS. Assicurati che l'API RouterOS (porta 8729/8728) sia abilitata.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
@ -240,18 +212,18 @@ export default function Routers() {
|
|||||||
name="apiPort"
|
name="apiPort"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Porta REST API</FormLabel>
|
<FormLabel>Porta API</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="443"
|
placeholder="8729"
|
||||||
{...field}
|
{...field}
|
||||||
onChange={(e) => field.onChange(parseInt(e.target.value))}
|
onChange={(e) => field.onChange(parseInt(e.target.value))}
|
||||||
data-testid="input-port"
|
data-testid="input-port"
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Porta REST API MikroTik (443 HTTPS o 80 HTTP)
|
Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API)
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
@ -396,24 +368,11 @@ export default function Routers() {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="flex-1"
|
className="flex-1"
|
||||||
onClick={() => handleTestConnection(router.id)}
|
|
||||||
disabled={testingRouterId === router.id}
|
|
||||||
data-testid={`button-test-${router.id}`}
|
|
||||||
>
|
|
||||||
{testingRouterId === router.id ? (
|
|
||||||
<WifiOff className="h-4 w-4 mr-2 animate-pulse" />
|
|
||||||
) : (
|
|
||||||
<Wifi className="h-4 w-4 mr-2" />
|
|
||||||
)}
|
|
||||||
{testingRouterId === router.id ? "Test..." : "Test"}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => handleEdit(router)}
|
onClick={() => handleEdit(router)}
|
||||||
data-testid={`button-edit-${router.id}`}
|
data-testid={`button-edit-${router.id}`}
|
||||||
>
|
>
|
||||||
<Edit className="h-4 w-4" />
|
<Edit className="h-4 w-4 mr-2" />
|
||||||
|
Modifica
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@ -482,18 +441,18 @@ export default function Routers() {
|
|||||||
name="apiPort"
|
name="apiPort"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Porta REST API</FormLabel>
|
<FormLabel>Porta API</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="443"
|
placeholder="8729"
|
||||||
{...field}
|
{...field}
|
||||||
onChange={(e) => field.onChange(parseInt(e.target.value))}
|
onChange={(e) => field.onChange(parseInt(e.target.value))}
|
||||||
data-testid="input-edit-port"
|
data-testid="input-edit-port"
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
Porta REST API MikroTik (443 HTTPS o 80 HTTP)
|
Porta RouterOS API MikroTik (8729 per API-SSL, 8728 per API)
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@ -53,88 +53,6 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/routers/:id/test", async (req, res) => {
|
|
||||||
try {
|
|
||||||
const router = await storage.getRouterById(req.params.id);
|
|
||||||
if (!router) {
|
|
||||||
return res.status(404).json({ error: "Router not found" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test connessione REST API MikroTik
|
|
||||||
// Usa HTTPS per porta 443, HTTP per altre
|
|
||||||
const protocol = router.apiPort === 443 ? 'https' : 'http';
|
|
||||||
const testUrl = `${protocol}://${router.ipAddress}:${router.apiPort}/rest/system/resource`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Timeout di 10 secondi per il test
|
|
||||||
const controller = new AbortController();
|
|
||||||
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
||||||
|
|
||||||
const response = await fetch(testUrl, {
|
|
||||||
method: 'GET',
|
|
||||||
signal: controller.signal,
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Basic ' + Buffer.from(`${router.username}:${router.password}`).toString('base64')
|
|
||||||
},
|
|
||||||
// Ignora errori certificato SSL self-signed (comune in MikroTik)
|
|
||||||
// @ts-ignore - Node.js fetch options
|
|
||||||
rejectUnauthorized: false
|
|
||||||
});
|
|
||||||
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
|
|
||||||
// Verifica status: 200 = OK, 401 = credenziali errate ma raggiungibile
|
|
||||||
if (response.status === 200) {
|
|
||||||
// Successo! Aggiorna lastSync
|
|
||||||
await db.update(routers).set({ lastSync: new Date() }).where(eq(routers.id, router.id));
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
success: true,
|
|
||||||
message: `Router ${router.name} connesso con successo! REST API funzionante.`,
|
|
||||||
status: response.status
|
|
||||||
});
|
|
||||||
} else if (response.status === 401 || response.status === 403) {
|
|
||||||
// Router raggiungibile ma credenziali errate
|
|
||||||
res.status(401).json({
|
|
||||||
error: "Autenticazione fallita",
|
|
||||||
message: `Router raggiungibile ma le credenziali sono errate. Verifica username e password.`,
|
|
||||||
status: response.status
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Altro errore HTTP
|
|
||||||
res.status(response.status).json({
|
|
||||||
error: `Errore HTTP ${response.status}`,
|
|
||||||
message: `Il router risponde ma con stato ${response.status}: ${response.statusText}`,
|
|
||||||
status: response.status
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (fetchError: any) {
|
|
||||||
console.error('[Router TEST] Connection failed:', fetchError.message);
|
|
||||||
|
|
||||||
// Differenzia gli errori
|
|
||||||
if (fetchError.name === 'AbortError') {
|
|
||||||
res.status(408).json({
|
|
||||||
error: "Timeout: Il router non risponde entro 5 secondi",
|
|
||||||
message: `Impossibile connettersi a ${router.ipAddress}:${router.apiPort}. Verifica che il router sia acceso e raggiungibile.`
|
|
||||||
});
|
|
||||||
} else if (fetchError.code === 'ECONNREFUSED') {
|
|
||||||
res.status(503).json({
|
|
||||||
error: "Connessione rifiutata",
|
|
||||||
message: `Il router a ${router.ipAddress}:${router.apiPort} rifiuta la connessione. Verifica che l'API REST sia abilitata.`
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.status(503).json({
|
|
||||||
error: "Errore di connessione",
|
|
||||||
message: `${fetchError.message}. Verifica IP, porta e firewall.`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('[Router TEST] Error:', error);
|
|
||||||
res.status(500).json({ error: "Failed to test router connection" });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Network Logs
|
// Network Logs
|
||||||
app.get("/api/logs", async (req, res) => {
|
app.get("/api/logs", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export const routers = pgTable("routers", {
|
|||||||
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
|
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
|
||||||
name: text("name").notNull(),
|
name: text("name").notNull(),
|
||||||
ipAddress: text("ip_address").notNull().unique(),
|
ipAddress: text("ip_address").notNull().unique(),
|
||||||
apiPort: integer("api_port").notNull().default(443),
|
apiPort: integer("api_port").notNull().default(8729),
|
||||||
username: text("username").notNull(),
|
username: text("username").notNull(),
|
||||||
password: text("password").notNull(),
|
password: text("password").notNull(),
|
||||||
enabled: boolean("enabled").notNull().default(true),
|
enabled: boolean("enabled").notNull().default(true),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user