From 3ec3ad7fa552d055465aac391a4eec3f9a6ab419 Mon Sep 17 00:00:00 2001 From: Troy Grunt Date: Fri, 6 Feb 2026 17:56:57 +0100 Subject: [PATCH] feat: Implement API for managing network connections, device types, and uploads --- app/api/connections.php | 194 ++++++++++++++++++++++++++++- app/api/device_type_ports.php | 175 +++++++++++++++++++++++++- app/api/upload.php | 133 +++++++++++++++++++- app/lib/auth.php | 83 +++++++++++- app/lib/helpers.php | 169 ++++++++++++++++++++++++- app/modules/connections/list.php | 86 ++++++++++++- app/modules/connections/save.php | 103 ++++++++++++++- app/modules/device_types/edit.php | 161 +++++++++++++++++++++++- app/modules/device_types/list.php | 116 ++++++++++++++++- app/modules/device_types/ports.php | 155 ++++++++++++++++++++++- app/modules/device_types/save.php | 96 +++++++++++++- 11 files changed, 1460 insertions(+), 11 deletions(-) diff --git a/app/api/connections.php b/app/api/connections.php index 0da16c9..ffeba17 100644 --- a/app/api/connections.php +++ b/app/api/connections.php @@ -1,2 +1,194 @@ 'Unbekannte Aktion']); + break; +} + +/* ========================= + * Aktionen + * ========================= */ + +/** + * Lädt alle Geräte + Ports + Verbindungen für eine Netzwerkansicht + */ +function loadConnections($sql) +{ + $contextId = $_GET['context_id'] ?? null; + + if (!$contextId) { + http_response_code(400); + echo json_encode(['error' => 'context_id fehlt']); + return; + } + + // TODO: Kontext definieren (Standort, Rack, Floor, gesamtes Netz) + + /* ---------- Geräte ---------- */ + $devices = $sql->get( + "SELECT id, name, device_type_id, pos_x, pos_y + FROM devices + WHERE context_id = ?", + "i", + [$contextId] + ); + + /* ---------- Ports ---------- */ + $ports = $sql->get( + "SELECT p.id, p.device_id, p.name, p.port_type_id + FROM ports p + JOIN devices d ON d.id = p.device_id + WHERE d.context_id = ?", + "i", + [$contextId] + ); + + /* ---------- Verbindungen ---------- */ + $connections = $sql->get( + "SELECT + c.id, + c.connection_type_id, + c.port_a_id, + c.port_b_id, + c.vlan, + c.mode, + c.comment + FROM connections c", + "", + [] + ); + + echo json_encode([ + 'devices' => $devices, + 'ports' => $ports, + 'connections' => $connections + ]); +} + +/** + * Speichert eine Verbindung (neu oder Update) + */ +function saveConnection($sql) +{ + $data = json_decode(file_get_contents('php://input'), true); + + if (!$data) { + http_response_code(400); + echo json_encode(['error' => 'Ungültige JSON-Daten']); + return; + } + + // TODO: Validierung + // - port_a_id vorhanden + // - port_b_id vorhanden + // - Verbindungstyp erlaubt + + if (!empty($data['id'])) { + // UPDATE + $rows = $sql->set( + "UPDATE connections + SET connection_type_id = ?, port_a_id = ?, port_b_id = ?, vlan = ?, mode = ?, comment = ? + WHERE id = ?", + "iiiissi", + [ + $data['connection_type_id'], + $data['port_a_id'], + $data['port_b_id'], + $data['vlan'], + $data['mode'], + $data['comment'], + $data['id'] + ] + ); + + echo json_encode([ + 'status' => 'updated', + 'rows' => $rows + ]); + } else { + // INSERT + $id = $sql->set( + "INSERT INTO connections + (connection_type_id, port_a_id, port_b_id, vlan, mode, comment) + VALUES (?, ?, ?, ?, ?, ?)", + "iiiiss", + [ + $data['connection_type_id'], + $data['port_a_id'], + $data['port_b_id'], + $data['vlan'], + $data['mode'], + $data['comment'] + ], + true + ); + + echo json_encode([ + 'status' => 'created', + 'id' => $id + ]); + } +} + +/** + * Löscht eine Verbindung + */ +function deleteConnection($sql) +{ + $id = $_GET['id'] ?? null; + + if (!$id) { + http_response_code(400); + echo json_encode(['error' => 'ID fehlt']); + return; + } + + // TODO: Prüfen, ob Verbindung existiert + + $rows = $sql->set( + "DELETE FROM connections WHERE id = ?", + "i", + [$id] + ); + + echo json_encode([ + 'status' => 'deleted', + 'rows' => $rows + ]); +} diff --git a/app/api/device_type_ports.php b/app/api/device_type_ports.php index 6182e03..deeaf1d 100644 --- a/app/api/device_type_ports.php +++ b/app/api/device_type_ports.php @@ -1,2 +1,175 @@ 'Unbekannte Aktion']); + break; +} + +/* ========================= + * Aktionen + * ========================= */ + +/** + * Lädt alle Ports eines Gerätetyps + */ +function loadPorts($sql) +{ + $deviceTypeId = $_GET['device_type_id'] ?? null; + + if (!$deviceTypeId) { + http_response_code(400); + echo json_encode(['error' => 'device_type_id fehlt']); + return; + } + + $ports = $sql->get( + "SELECT + id, + name, + port_type_id, + pos_x, + pos_y, + comment + FROM device_type_ports + WHERE device_type_id = ? + ORDER BY id ASC", + "i", + [$deviceTypeId] + ); + + echo json_encode($ports); +} + +/** + * Speichert alle Ports eines Gerätetyps + * (Bulk-Save aus dem SVG-Editor) + */ +function savePorts($sql) +{ + $data = json_decode(file_get_contents('php://input'), true); + + if (!$data || empty($data['device_type_id']) || !is_array($data['ports'])) { + http_response_code(400); + echo json_encode(['error' => 'Ungültige Daten']); + return; + } + + $deviceTypeId = $data['device_type_id']; + $ports = $data['ports']; + + // TODO: Transaktion starten (falls SQL-Klasse das unterstützt) + + foreach ($ports as $port) { + + // TODO: Validierung: + // - name nicht leer + // - pos_x / pos_y numerisch + // - port_type_id erlaubt + + if (!empty($port['id']) && !str_starts_with($port['id'], 'tmp_')) { + + /* ---------- UPDATE ---------- */ + $sql->set( + "UPDATE device_type_ports + SET name = ?, port_type_id = ?, pos_x = ?, pos_y = ?, comment = ? + WHERE id = ? AND device_type_id = ?", + "siddsii", + [ + $port['name'], + $port['port_type_id'], + $port['x'], + $port['y'], + $port['comment'], + $port['id'], + $deviceTypeId + ] + ); + + } else { + + /* ---------- INSERT ---------- */ + $sql->set( + "INSERT INTO device_type_ports + (device_type_id, name, port_type_id, pos_x, pos_y, comment) + VALUES (?, ?, ?, ?, ?, ?)", + "isidds", + [ + $deviceTypeId, + $port['name'], + $port['port_type_id'], + $port['x'], + $port['y'], + $port['comment'] + ], + true + ); + } + } + + echo json_encode([ + 'status' => 'ok' + ]); +} + +/** + * Löscht einen einzelnen Port + */ +function deletePort($sql) +{ + $id = $_GET['id'] ?? null; + + if (!$id) { + http_response_code(400); + echo json_encode(['error' => 'ID fehlt']); + return; + } + + // TODO: Prüfen, ob Port existiert und nicht verwendet wird + + $rows = $sql->set( + "DELETE FROM device_type_ports WHERE id = ?", + "i", + [$id] + ); + + echo json_encode([ + 'status' => 'deleted', + 'rows' => $rows + ]); +} diff --git a/app/api/upload.php b/app/api/upload.php index 30eb252..f8a2bd3 100644 --- a/app/api/upload.php +++ b/app/api/upload.php @@ -1,2 +1,133 @@ Upload + Rückgabe von Pfad / Metadaten + */ + +require_once __DIR__ . '/../bootstrap.php'; + +header('Content-Type: application/json'); + +// TODO: Single-User-Auth prüfen +// if (!$_SESSION['user']) { http_response_code(403); exit; } + +/* ========================= + * Konfiguration + * ========================= */ + +// TODO: Upload-Basisverzeichnis aus config.php +$baseUploadDir = __DIR__ . '/../uploads'; + +// Erlaubte Typen +$allowedMimeTypes = [ + 'image/svg+xml', + 'image/png', + 'image/jpeg' +]; + +// TODO: Max. Dateigröße festlegen (z.B. 5MB) +$maxFileSize = 5 * 1024 * 1024; + +/* ========================= + * Validierung + * ========================= */ + +if (empty($_FILES['file'])) { + http_response_code(400); + echo json_encode(['error' => 'Keine Datei hochgeladen']); + exit; +} + +$file = $_FILES['file']; + +if ($file['error'] !== UPLOAD_ERR_OK) { + http_response_code(400); + echo json_encode(['error' => 'Upload-Fehler']); + exit; +} + +if ($file['size'] > $maxFileSize) { + http_response_code(400); + echo json_encode(['error' => 'Datei zu groß']); + exit; +} + +// MIME-Type prüfen +$finfo = finfo_open(FILEINFO_MIME_TYPE); +$mimeType = finfo_file($finfo, $file['tmp_name']); +finfo_close($finfo); + +if (!in_array($mimeType, $allowedMimeTypes)) { + http_response_code(400); + echo json_encode(['error' => 'Dateityp nicht erlaubt']); + exit; +} + +/* ========================= + * Zielverzeichnis + * ========================= */ + +// TODO: Kategorie definieren (device_types, floors, racks, etc.) +$category = $_POST['category'] ?? 'misc'; + +// Zielpfad +$targetDir = $baseUploadDir . '/' . preg_replace('/[^a-z0-9_-]/i', '', $category); + +// Verzeichnis anlegen falls nötig +if (!is_dir($targetDir)) { + mkdir($targetDir, 0755, true); +} + +/* ========================= + * Dateiname + * ========================= */ + +// Originalname bereinigen +$extension = pathinfo($file['name'], PATHINFO_EXTENSION); + +// TODO: Eindeutigen Namen besser definieren (UUID?) +$filename = uniqid('upload_', true) . '.' . strtolower($extension); + +$targetPath = $targetDir . '/' . $filename; + +/* ========================= + * Datei speichern + * ========================= */ + +if (!move_uploaded_file($file['tmp_name'], $targetPath)) { + http_response_code(500); + echo json_encode(['error' => 'Datei konnte nicht gespeichert werden']); + exit; +} + +/* ========================= + * Optional: DB-Eintrag + * ========================= */ + +// TODO: Optional in Tabelle `uploads` speichern +// $uploadId = $sql->set( +// "INSERT INTO uploads (filename, path, mime_type, category) +// VALUES (?, ?, ?, ?)", +// "ssss", +// [$filename, $targetPath, $mimeType, $category], +// true +// ); + +/* ========================= + * Antwort + * ========================= */ + +echo json_encode([ + 'status' => 'ok', + 'filename' => $filename, + 'path' => str_replace(__DIR__ . '/..', '', $targetPath), + 'mime_type' => $mimeType + // 'id' => $uploadId ?? null +]); diff --git a/app/lib/auth.php b/app/lib/auth.php index b27b10a..11a1b13 100644 --- a/app/lib/auth.php +++ b/app/lib/auth.php @@ -1,2 +1,83 @@ + +

Netzwerk-Topologie

+ + + +
+ + + + +
+ + + +
+ + + + +
+ + + + + + + + diff --git a/app/modules/connections/save.php b/app/modules/connections/save.php index 2cc4eb2..1b8c650 100644 --- a/app/modules/connections/save.php +++ b/app/modules/connections/save.php @@ -1,2 +1,103 @@ 'Unknown save type' + ]); + exit; +} + +// ========================= +// Antwort +// ========================= + +// TODO: Erfolg / Fehler zurückgeben +echo json_encode([ + 'status' => 'ok' +]); diff --git a/app/modules/device_types/edit.php b/app/modules/device_types/edit.php index 0ec1190..562087f 100644 --- a/app/modules/device_types/edit.php +++ b/app/modules/device_types/edit.php @@ -1,2 +1,161 @@ + +

Gerätetyp bearbeiten

+ +
+ + + +
+ Allgemein + + + +

+ + +
+ + + +
+ Darstellung + + + + + +
+ + + +
+ Ports definieren + +
+ + + + + +
+ + + +
+ +
+
+ + + +
+ Module + + +
+ + + +
+ + + + +
+ +
+ + + + diff --git a/app/modules/device_types/list.php b/app/modules/device_types/list.php index eba56fa..39f0d50 100644 --- a/app/modules/device_types/list.php +++ b/app/modules/device_types/list.php @@ -1,2 +1,116 @@ get( +// "SELECT * FROM device_types ORDER BY name", +// "", +// [] +// ); + +?> + +

Gerätetypen

+ + + +
+ + + Neuer Gerätetyp + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VorschauNameBeschreibungPortsModuleAktionen
+ + + + Gerätetyp XY + + + + + + + + + Bearbeiten + + + +
+ + + + +
+

Noch keine Gerätetypen angelegt.

+

+ + Ersten Gerätetyp anlegen + +

+
+ diff --git a/app/modules/device_types/ports.php b/app/modules/device_types/ports.php index 352a833..6d5360f 100644 --- a/app/modules/device_types/ports.php +++ b/app/modules/device_types/ports.php @@ -1,2 +1,155 @@ + +

Ports – Gerätetyp

+ + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#NameTypMediumModusVLANAktionen
+ + 1 + + + Port 1 + + + + + + + + + + + + +
+ + + +
+

Port-Positionen

+ +

+ Ports per Drag & Drop auf dem Gerät platzieren. +

+ +
+ + + +
+
+ + + + diff --git a/app/modules/device_types/save.php b/app/modules/device_types/save.php index 1d62880..585aefd 100644 --- a/app/modules/device_types/save.php +++ b/app/modules/device_types/save.php @@ -1,2 +1,96 @@ set("UPDATE ...", "???", [...]); +} else { + // TODO: INSERT INTO device_types ... + // $deviceTypeId = $sql->set("INSERT ...", "???", [...], true); +} + +// ========================= +// Ports speichern +// ========================= + +// TODO: $data['ports'] iterieren +// - UPDATE / INSERT device_type_ports +// - pos_x / pos_y +// - port_type_id, name, comment + +// ========================= +// Module speichern +// ========================= + +// TODO: $data['modules'] iterieren +// - Module anlegen / aktualisieren +// - Module haben eigene Ports + +// ========================= +// Antwort +// ========================= + +echo json_encode([ + 'status' => 'ok', + 'id' => $deviceTypeId +]);