needlogin = true; $me = new User(); $me->loadMe(); $this->me = $me; $this->layout()->set("me", $me); if (!$me->is(["Admin", "netowner", "lineplanner", "pipeplanner", "pipeworker", "lineworker"])) { $this->redirect("Dashboard"); } if ($this->me->is(["Admin"])) { $this->allowedPops = null; } else { $networkIds = array_column($this->me->getProperty('my_networks'), 'id'); $pops = PopNetworkModel::search(['Networks' => $networkIds]); foreach ($pops as $pop) { $popIds[] = $pop->pop_id; } $this->allowedPops = $popIds; } } protected function indexAction() { $deviceManufacturers = array_map(function ($deviceManufacturer) { return [ "id" => $deviceManufacturer->id, "name" => $deviceManufacturer->name, "creator" => $deviceManufacturer->creator->name, "created" => $deviceManufacturer->create, ]; }, DevicemanufactorModel::getAll()); $deviceTypes = array_map(function ($deviceType) { return [ "id" => $deviceType->id, "name" => $deviceType->name, "manufacturer" => $deviceType->devicemanufactor->name, "price" => $deviceType->price, "power" => $deviceType->power, "creator" => $deviceType->creator->name, "created" => $deviceType->create, ]; }, DevicetypeModel::getAll()); $this->layout()->set('additionalJS', [ "plugins/chart.js/chart.4.4.6.js", "plugins/chart.js/chartjs-adapter-moment.min.js", "plugins/chart.js/chartjs-plugin-zoom.min.js" ]); $JSGlobals = ["BASE_URL" => self::getUrl(""), "DASHBOARD_URL" => self::getUrl("Dashboard"), "MFAPPNAME" => MFAPPNAME_SLUG, "PAGE_TITLE" => "Devices", "PATH" => [ ["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")], ["text" => "Devices", "href" => self::getUrl("Device")] ], "DEVICE_MANUFACTURERS" => $deviceManufacturers, "DEVICE_TYPES" => $deviceTypes, "DEVICES" => $this->getDevices(), "IS_ADMIN" => $this->me->is(["Admin"]), "ZABBIX_URL" => (defined("ZABBIX_URL")) ? ZABBIX_URL : "", "GRAFANA_URL" => (defined("GRAFANA_URL")) ? GRAFANA_URL : "", ]; $this->layout()->set("vueViewName", "Device"); $this->layout()->set("JSGlobals", $JSGlobals); $this->layout()->setTemplate("VueViews/Vue"); } protected function detailAction() { $id = $this->request->id; if (!is_numeric($id) || !$id) { $this->layout()->setFlash("Gerät nicht gefunden", "error"); $this->redirect("Device"); } $device = new Device($id); if ($device->id != $id) { $this->layout()->setFlash("Gerät nicht gefunden", "error"); $this->redirect("Device"); } if (!$this->me->is(["Admin"])) { if (!in_array($device->pop_id, $this->allowedPops)) { $this->layout()->setFlash("Gerät nicht gefunden", "error"); $this->redirect("Device"); } } $this->layout()->setTemplate("Device/Detail"); $devicesconfig = DeviceModel::getconifg($id); $devices = DeviceModel::getOne($id); $devicesall = DeviceModel::getAll(); if ($devices->devicetype->olt == "1") { $customer = DeviceModel::getOltCustomer($device->ip); } else { $customer = []; } $this->layout()->set("devicesconfig", $devicesconfig); $this->layout()->set("devices", $devices); $this->layout()->set("devicesall", $devicesall); $this->layout()->set("customer", $customer); } protected function addAction() { $this->layout()->setTemplate("Device/Form"); $this->layout()->set("devicetypes", DevicetypeModel::getAll()); $this->layout()->set("pops", PopModel::getAll()); $this->layout()->set("devices", DeviceModel::getAll()); } protected function editAction() { $id = $this->request->id; if (!is_numeric($id) || !$id) { $this->layout()->setFlash("Device nicht gefunden", "error"); $this->redirect("Device"); } $device = new Device($id); if ($device->id != $id) { $this->layout()->setFlash("Device nicht gefunden", "error"); $this->redirect("Device"); } $this->layout()->set("device", $device); $this->addAction(); } protected function saveAction() { if (!$this->me->is(["Admin"])) { $this->layout()->setFlash("Keine Berechtigung", "error"); $this->redirect("Device"); } $r = $this->request; $id = $r->id; //var_dump($r->get());exit; if (is_numeric($id) && $id > 0) { $mode = "edit"; $device = new Device($id); if (!$device->id) { $this->layout()->setFlash("Device nicht gefunden", "error"); $this->redirect("Device"); } } else { $mode = "add"; } $data = []; $data['name'] = trim($r->name); $data['devicetype_id'] = $r->devicetype_id; $data['parent_id'] = $r->parent_id; $data['autobackup'] = trim($r->autobackup); $data['backup_check'] = trim($r->backup_check); if (trim($r->pop_id) == "0") { $data['pop_id'] = NULL; } else { $data['pop_id'] = $r->pop_id; } if (!(trim($r->addr_street))) { $data['addr_street'] = NULL; $data['addr_number'] = NULL; $data['addr_extended'] = NULL; $data['addr_zip'] = NULL; $data['addr_city'] = NULL; } else { $data['addr_street'] = $r->addr_street; $data['addr_number'] = $r->addr_number; $data['addr_extended'] = $r->addr_extended; $data['addr_zip'] = $r->addr_zip; $data['addr_city'] = $r->addr_city; } if (!trim($r->gps_lat) || !trim($r->gps_long)) { $data['gps_lat'] = NULL; $data['gps_long'] = NULL; } else { $data['gps_lat'] = $r->gps_lat; $data['gps_long'] = $r->gps_long; } if ($data['autobackup'] != "1") { $data['autobackup'] = "0"; } if ($data['backup_check'] != "1") { $data['backup_check'] = "0"; } if (!$data['parent_id']) { $data['parent_id'] = NULL; } $data['ip'] = $r->ip; $data['mac'] = $r->mac; $data['serial'] = $r->serial; if ($r->snmp_version) { $data['snmp_version'] = $r->snmp_version; } else { $data['snmp_version'] = NULL; } if (empty(trim($r->price))) { $data['price'] = "0.00"; } else { $data['price'] = $r->price; } if (empty(trim($r->power))) { $data['power'] = "0.0"; } else { $data['power'] = $r->power; } $data['comment'] = $r->comment; $ipv4_validation_regex = "/^(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/"; if (!$data['name']) { $this->layout()->setFlash("Name darf nicht leer sein", "error"); $this->redirect("Device"); } if (!$data['ip']) { $this->layout()->setFlash("IP-Adresse darf nicht leer sein", "error"); $this->redirect("Device"); } else if (!preg_match($ipv4_validation_regex, trim($data['ip']))) { $this->layout()->setFlash("IP-Adresse ist nicht gültig", "error"); $this->redirect("Device"); } // var_dump($_FILES); // var_dump($upload); // exit; if ($mode == "edit") { $device->update($data); } else { $device = DeviceModel::create($data); } // var_dump($device); // exit; $id = $device->save(); $returnUrl = "Device"; $returnAction = "Index"; $returnVariables = array(); $returnAnker = ""; if ($this->request->returnto) { if (strpos($this->request->returnto, "-") !== false) { $urls = explode('-', $this->request->returnto); $urlCounter = 0; $returnUrlGen = ""; foreach ($urls as $url) { if ($urlCounter > 0) { $returnUrlGen .= "/"; } $returnUrlGen .= ucfirst($url); $urlCounter++; } $returnAction = ""; $returnVariables['id'] = $id; $returnUrl = $returnUrlGen; } else { $returnUrl = ucfirst($this->request->returnto); } } if (!$id) { $returnVariables['id'] = $r->id; if ($mode == "edit") { $this->layout()->setFlash("Device konnte nicht gespeichert werden", "error"); } else if ($mode = "add") { $this->layout()->setFlash("Device konnte nicht angelegt werden", "error"); } $this->redirect($returnUrl, $returnAction, $returnVariables, $returnAnker); } if ($mode == "edit") { $this->layout()->setFlash("Device erfolgreich geändert", "success"); } else if ($mode = "add") { $this->layout()->setFlash("Device erfolgreich angelegt", "success"); } $this->redirect($returnUrl, $returnAction, $returnVariables, $returnAnker); } protected function apiAction() { if (!$this->me->is(["Admin"])) { $return = false; } $do = $this->request->do; $format = $this->request->format; $filename = $this->request->filename; $id = $this->request->id; $ip = $this->request->ip; $portid = $this->request->portid; $ports = $this->request->ports; $adv = $this->request->adv; $ont = $this->request->ont; $data = []; switch ($do) { case "getDevices": header('Content-Type: application/json'); die(json_encode($this->getDevices())); case "getconfig": $this->getConfig($id, $format, $filename); break; case "createconfig": $this->createConfig($ip); break; case "uploadFile": $this->uploadFile($id); break; case "getoltinfo": $this->getoltInfo($ip, $portid, $adv); break; case "getontinfo": $this->getontInfo($ip, $portid, $ont); break; case "getontinfomac": $this->getontInfoMac($ip, $portid, $ont); break; case "changeoltsplitter": $this->changeoltSplitter($id, $portid, $ports); break; case "deviceoltserviceporttimestamp": $this->deviceoltserviceporttimestamp($ip); break; case "deviceoltserviceportrefresh": $this->deviceoltserviceportrefresh($ip); break; case "getZabbixConsolidationData": $this->getZabbixConsolidationData(); break; case "getZabbixTemplates": $this->getZabbixTemplates(); break; case "createZabbixHost": $this->createZabbixHost(); break; case "updateZabbixCoordinates": $this->updateZabbixCoordinates(); break; default: $return = false; } } protected function deleteAction() { $id = $this->request->id; $device = new Device($id); if (!$device->id || $device->id != $id) { $this->layout()->setFlash("Gerätetyp nicht gefunden.", "error"); $this->redirect("Device"); } $device->delete(); $this->redirect("Device"); } private function getConfig($id, $format, $filename) { $configDownload = DeviceModel::getconifgdownload($id, $format); // // header('Content-Type: application/octet-stream'); header('Content-Type: text/plain'); header('Content-disposition: attachment; filename="' . $filename . '"'); echo $configDownload; exit; } private function uploadFile($id) { $r = $this->request; $file = $_FILES; $response = DeviceModel::uploadFile($id, $file); echo $response; die(); } private function createConfig($ip) { $r = $this->request; $id = $r->id; $createConfig = DeviceModel::configcreate($ip); if ($createConfig->success === "true") { $this->layout()->setFlash("Backup wurde erfolgreich erstellt", "success"); } elseif (!TT_MBI_API_ENABLE) { $this->layout()->setFlash("Backup konnte nicht erstellt werden. Fehler: Schnittstellenserver wurde vom Admin deaktiviert.", "error"); } else { $this->layout()->setFlash("Backup konnte nicht erstellt werden. Fehler: " . $createConfig->error, "error"); } $returnUrl = "Device"; $returnAction = "Detail"; $returnVariables['id'] = $id; $this->redirect($returnUrl, $returnAction, $returnVariables); } private function changeoltSplitter($id, $portid, $ports) { $changeOltSplitter = DeviceModel::changeoltSplitter($id, $portid, $ports); echo json_encode($changeOltSplitter); exit; } private function getoltInfo($ip, $portid, $adv) { $r = $this->request; $id = $r->id; $getOltInfo = DeviceModel::getoltInfo($ip, $portid, $adv); echo json_encode($getOltInfo); exit; } private function getontInfo($ip, $portid, $ont) { $r = $this->request; $id = $r->id; $getOntInfo = DeviceModel::getontInfo($ip, $portid, $ont); echo json_encode($getOntInfo); exit; } private function deviceoltserviceporttimestamp($ip) { $deviceoltserviceporttimestamp = DeviceModel::deviceoltserviceporttimestamp($ip); echo json_encode($deviceoltserviceporttimestamp); exit; } private function deviceoltserviceportrefresh($ip) { $deviceoltserviceportrefresh = DeviceModel::deviceoltserviceportrefresh($ip); echo json_encode($deviceoltserviceportrefresh); exit; } private function getontInfoMac($ip, $portid, $ont) { $r = $this->request; $id = $r->id; $getOntInfo = DeviceModel::getontInfoMac($ip, $portid, $ont); echo json_encode($getOntInfo); exit; } private function getDevices() { if (!$this->me->is(["Admin"])) { if ($this->allowedPops === null) return []; } $devices = DeviceModel::search(['popIds' => $this->allowedPops]); foreach ($devices as $device) { $locationText = ""; $locationUrl = ""; if ($device->pop_id && trim($device->pop->name)) { $locationText = $device->pop->name; $locationUrl = self::getUrl("Pop", "Detail", ["id" => $device->pop->id]); } else if (trim($device->addr_street)) { $locationText = $device->addr_street . " " . $device->addr_number . ", " . $device->addr_zip . " " . $device->addr_city; $locationUrl = "http://maps.google.com/?q=" . $locationText; } else if (trim($device->gps_lat)) { $locationText = $device->gps_lat . " , " . $device->gps_long; $locationUrl = "http://maps.google.com/?q=" . $locationText; } $backup = 'na'; if ($device->last_config_backup) { if (time() - $device->last_config_backup <= 172800) { $backup = 'ok'; if ($device->autobackup == 1) { $backup = 'auto'; } } else { $backup = 'aged'; } } $data[] = [ "id" => $device->id, "name" => $device->name, "devicetype" => $device->devicetype->name, "devicemanufactor" => $device->devicetype->devicemanufactor->name, "locationText" => $locationText, "locationUrl" => $locationUrl, "ip" => $device->ip, "mac" => $device->mac, "serial" => $device->serial, "zabbix_online" => $device->zabbix_online, "zabbix_host_id" => $device->zabbix_host_id, "price" => $device->price != "0.00" ? $device->price : $device->devicetype->price, "power" => $device->power != "0.00" ? intval($device->power) : intval($device->devicetype->power), "backup" => $backup, ]; } return $data ?? []; } protected function zabbixConsolidationAction() { if (!$this->me->is(["Admin"])) { $this->layout()->setFlash("Keine Berechtigung", "error"); $this->redirect("Dashboard"); } $JSGlobals = [ "BASE_URL" => self::getUrl(""), "API_URL" => self::getUrl("Device", "api"), "DEVICE_TYPES" => DevicetypeModel::getAll(), "POPS" => PopModel::getAll(), "PAGE_TITLE" => "Zabbix Consolidation", "PATH" => [ ["text" => MFAPPNAME_SLUG, "href" => self::getUrl("Dashboard")], ["text" => "Devices", "href" => self::getUrl("Device")], ["text" => "Zabbix Consolidation", "href" => self::getUrl("Device", "zabbixConsolidation")] ] ]; $this->layout()->set("vueViewName", "DeviceZabbixConsolidation"); $this->layout()->set("JSGlobals", $JSGlobals); $this->layout()->setTemplate("VueViews/Vue"); } protected function getZabbixConsolidationData() { $zabbix = new Zabbix(ZABBIX_API_URL, ZABBIX_API_KEY); $theToolDevices = DeviceModel::getAll(); $excludedGroupIds = [2, 4, 6, 7]; $allZabbixHosts = $zabbix->getAllHostsWithDetails(); $zabbixHosts = array_filter($allZabbixHosts, function($host) use ($excludedGroupIds) { $hostGroupIds = array_column($host['hostgroups'] ?? [], 'groupid'); if (empty($hostGroupIds)) { return true; } return empty(array_intersect($hostGroupIds, $excludedGroupIds)); }); $theToolDevicesByName = []; $theToolDevicesByIp = []; foreach ($theToolDevices as $device) { if ($device->ip === '127.0.0.1') continue; $theToolDevicesByName[$device->name] = $device; if (!empty($device->ip)) { $theToolDevicesByIp[$device->ip] = $device; } } $zabbixHostsByVisibleName = []; $zabbixHostsByIp = []; foreach ($zabbixHosts as $host) { if (!empty($host['name'])) { $zabbixHostsByVisibleName[$host['name']] = $host; } if (!empty($host['host'])) { $zabbixHostsByIp[$host['host']] = $host; } } $results = [ 'mismatchedNames' => [], 'inTheToolOnly' => [], 'inZabbixOnly' => [], 'noSnmp' => [], 'noCoordsInZabbix' => [], 'mismatchedCoords' => [], ]; foreach ($theToolDevices as $ttDevice) { if ($ttDevice->ip === '127.0.0.1') continue; $deviceDetails = new Device($ttDevice->id); $theToolData = ['id' => $deviceDetails->id, 'data' => (array) $deviceDetails->data]; if ($deviceDetails->pop && $deviceDetails->pop->id) { $theToolData['data']['pop'] = (array) $deviceDetails->pop->data; } if (!isset($zabbixHostsByVisibleName[$ttDevice->name]) && !isset($zabbixHostsByIp[$ttDevice->ip])) { $results['inTheToolOnly'][] = $theToolData; } else { if (isset($zabbixHostsByVisibleName[$ttDevice->name])) { $zbxHost = $zabbixHostsByVisibleName[$ttDevice->name]; $ttLat = (float)($theToolData['data']['pop']['gps_lat'] ?? $theToolData['data']['gps_lat'] ?? 0); $ttLon = (float)($theToolData['data']['pop']['gps_long'] ?? $theToolData['data']['gps_long'] ?? 0); $zbxLat = (float)($zbxHost['inventory']['location_lat'] ?? 0); $zbxLon = (float)($zbxHost['inventory']['location_lon'] ?? 0); if (($ttLat || $ttLon || $zbxLat || $zbxLon) && (abs($ttLat - $zbxLat) > 0.0001 || abs($ttLon - $zbxLon) > 0.0001)) { $results['mismatchedCoords'][] = ['theTool' => $theToolData, 'zabbix' => $zbxHost]; } } } } foreach ($zabbixHosts as $zbxHost) { if (empty($zbxHost['name'])) continue; if (!isset($theToolDevicesByName[$zbxHost['name']])) { $results['inZabbixOnly'][] = $zbxHost; } $hasSnmp = false; if (!empty($zbxHost['parentTemplates'])) { foreach ($zbxHost['parentTemplates'] as $template) { if (stripos($template['name'], 'icmp ping') === false) { $hasSnmp = true; break; } } } if (!$hasSnmp) { $results['noSnmp'][] = $zbxHost; } $zbxLat = (float)($zbxHost['inventory']['location_lat'] ?? 0); $zbxLon = (float)($zbxHost['inventory']['location_lon'] ?? 0); $theToolDeviceForCoords = $theToolDevicesByName[$zbxHost['name']] ?? null; $theToolDataForCoords = null; if($theToolDeviceForCoords){ $deviceDetails = new Device($theToolDeviceForCoords->id); $theToolDataForCoords = ['id' => $deviceDetails->id, 'data' => (array) $deviceDetails->data]; if ($deviceDetails->pop && $deviceDetails->pop->id) { $theToolDataForCoords['data']['pop'] = (array) $deviceDetails->pop->data; } } if ($zbxLat == 0 && $zbxLon == 0) { $results['noCoordsInZabbix'][] = [ 'zabbix' => $zbxHost, 'theTool' => $theToolDataForCoords ]; } } foreach ($zabbixHosts as $zbxHost) { if(isset($theToolDevicesByIp[$zbxHost['host']])) { $ttDeviceFromIp = new Device($theToolDevicesByIp[$zbxHost['host']]->id); $theToolData = ['id' => $ttDeviceFromIp->id, 'data' => $ttDeviceFromIp->data]; if ($ttDeviceFromIp->pop && $ttDeviceFromIp->pop->id) { $theToolData['data']['pop'] = $ttDeviceFromIp->pop->data; } if($ttDeviceFromIp->name !== $zbxHost['name']){ $results['mismatchedNames'][] = ['theTool' => $theToolData, 'zabbix' => $zbxHost]; } } } self::returnJson($results); } protected function getZabbixTemplates() { $zabbix = new Zabbix(ZABBIX_API_URL, ZABBIX_API_KEY); $templateNames = [ "ICMP Ping", "1_Default XINON Template", "1_XINON Extreme EXOS by SNMP", "1_MIKROTIK_TEMPLATE" ]; $templates = $zabbix->getTemplatesByNames($templateNames); $formattedTemplates = array_map(function($template) { return ['value' => $template['templateid'], 'text' => $template['name']]; }, $templates); self::returnJson($formattedTemplates); } protected function createZabbixHost() { $this->postData = json_decode(file_get_contents('php://input'), true); $deviceId = $this->postData['deviceId'] ?? null; $templateIds = $this->postData['templateIds'] ?? null; if (!$deviceId || !$templateIds) { self::sendError("Device ID or Template ID is missing."); } $device = DeviceModel::getOne($deviceId); if (!$device || !$device->id) { self::sendError("Device not found in TheTool."); } $zabbix = new Zabbix(ZABBIX_API_URL, ZABBIX_API_KEY); $groupName = "Discovered hosts"; $existingHosts = $zabbix->getHosts($device->name, $device->ip); if (!empty($existingHosts)) { self::sendError("Host with this name or IP already exists in Zabbix."); } $groupId = $zabbix->getHostGroupIdByName($groupName); if (!$groupId) { self::sendError("Host group '$groupName' not found in Zabbix."); } $result = $zabbix->createHost($device->name, $device->ip, $groupId, $templateIds); if (isset($result['hostids'])) { $device->zabbix_host_id = $result['hostids'][0]; $device->save(); self::returnJson(['success' => true, 'message' => 'Host successfully created in Zabbix and linked in TheTool.']); } else { self::sendError("Failed to create host in Zabbix: " . json_encode($result['error'] ?? 'Unknown error')); } } protected function updateTheToolCoordinatesAction() { $deviceId = $this->postData['deviceId'] ?? null; $lat = $this->postData['lat'] ?? null; $lon = $this->postData['lon'] ?? null; if (!$deviceId || $lat === null || $lon === null) { self::sendError("Device ID or coordinates are missing."); } $device = new Device($deviceId); if (!$device->id) { self::sendError("Device not found."); } if ($device->pop_id) { self::sendError("Koordinaten können nicht geändert werden, da sie vom POP-Standort geerbt werden."); } $device->update([ 'gps_lat' => $lat, 'gps_long' => $lon ]); $device->save(); self::returnJson(['success' => true, 'message' => 'TheTool coordinates updated successfully.']); } protected function updateZabbixCoordinates() { $this->postData = json_decode(file_get_contents('php://input'), true); $hostId = $this->postData['hostId'] ?? null; $lat = $this->postData['lat'] ?? null; $lon = $this->postData['lon'] ?? null; if (!$hostId || $lat === null || $lon === null) { self::sendError("Host ID or coordinates are missing."); } $zabbix = new Zabbix(ZABBIX_API_URL, ZABBIX_API_KEY); $inventoryData = [ 'location_lat' => (string)$lat, 'location_lon' => (string)$lon, ]; $result = $zabbix->updateHostInventory($hostId, $inventoryData); if (isset($result['hostids'])) { self::returnJson(['success' => true, 'message' => 'Coordinates updated successfully in Zabbix.']); } else { self::sendError("Failed to update coordinates in Zabbix: " . json_encode($result['error'] ?? 'Unknown error')); } } }