Add router management functionality with GenieACS integration
This commit is contained in:
@@ -283,4 +283,288 @@ HTML;
|
||||
self::sendError("E-Mail konnte nicht gesendet werden. Bitte kontaktieren Sie den Support.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GenieACS instance
|
||||
* @return GenieACS
|
||||
*/
|
||||
private function getGenieACS() {
|
||||
$host = defined('GENIEACS_HOST') ? GENIEACS_HOST : 'http://acs.xinon.at:3000';
|
||||
$username = defined('GENIEACS_USERNAME') ? GENIEACS_USERNAME : 'admin';
|
||||
$password = defined('GENIEACS_PASSWORD') ? GENIEACS_PASSWORD : 'savemanfb545aw';
|
||||
|
||||
return new GenieACS($host, $username, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if GenieACS task response indicates success
|
||||
* @param mixed $result
|
||||
* @return bool
|
||||
*/
|
||||
private static function isGenieAcsTaskSuccess($result) {
|
||||
// Null or empty array can indicate success (204 No Content)
|
||||
if ($result === null || (is_array($result) && empty($result))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Has explicit success flag
|
||||
if (isset($result['success']) && $result['success']) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Array of tasks with _id (task created successfully)
|
||||
if (is_array($result)) {
|
||||
// Check if it's an array of task objects
|
||||
foreach ($result as $item) {
|
||||
if (is_array($item) && isset($item['_id'])) {
|
||||
return true; // Task was created
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get devices from GenieACS and match by IP
|
||||
*/
|
||||
protected function genieacsGetDeviceByIpAction() {
|
||||
try {
|
||||
$ip = $_GET['ip'] ?? null;
|
||||
if (!$ip) {
|
||||
self::sendError("IP address is required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$devices = $acs->getDevices();
|
||||
|
||||
if (!$devices || !is_array($devices)) {
|
||||
self::returnJson(['success' => false, 'message' => 'No devices found']);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find device by matching external IP
|
||||
$matchedDevice = null;
|
||||
foreach ($devices as $device) {
|
||||
$externalIp = GenieACS::getExternalIP($device);
|
||||
if ($externalIp === $ip) {
|
||||
$matchedDevice = $device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$matchedDevice) {
|
||||
self::returnJson(['success' => false, 'message' => 'No device found with this IP']);
|
||||
return;
|
||||
}
|
||||
|
||||
$deviceId = GenieACS::getDeviceId($matchedDevice);
|
||||
$deviceInfo = GenieACS::getDeviceInfo($matchedDevice);
|
||||
$managementIp = GenieACS::getManagementIP($matchedDevice);
|
||||
|
||||
self::returnJson([
|
||||
'success' => true,
|
||||
'deviceId' => $deviceId,
|
||||
'deviceInfo' => $deviceInfo,
|
||||
'ip' => $ip,
|
||||
'managementIp' => $managementIp
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS getDeviceByIp error: " . $e->getMessage());
|
||||
self::sendError("Error fetching device: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot device via GenieACS
|
||||
*/
|
||||
protected function genieacsRebootDeviceAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
|
||||
if (!$deviceId) {
|
||||
self::sendError("Device ID is required");
|
||||
}
|
||||
|
||||
error_log("GenieACS reboot request for device: " . $deviceId);
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->rebootDevice($deviceId);
|
||||
|
||||
error_log("GenieACS reboot result: " . json_encode($result));
|
||||
|
||||
if (self::isGenieAcsTaskSuccess($result)) {
|
||||
self::returnJson(['success' => true, 'message' => 'Reboot task created', 'result' => $result]);
|
||||
} else {
|
||||
self::returnJson(['success' => false, 'message' => 'Failed to create reboot task', 'result' => $result]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS rebootDevice error: " . $e->getMessage());
|
||||
self::sendError("Error rebooting device: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh device information
|
||||
*/
|
||||
protected function genieacsRefreshDeviceAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
|
||||
if (!$deviceId) {
|
||||
self::sendError("Device ID is required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->refreshDevice($deviceId);
|
||||
|
||||
if (self::isGenieAcsTaskSuccess($result)) {
|
||||
self::returnJson(['success' => true, 'message' => 'Refresh task created', 'result' => $result]);
|
||||
} else {
|
||||
self::returnJson(['success' => false, 'message' => 'Failed to create refresh task', 'result' => $result]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS refreshDevice error: " . $e->getMessage());
|
||||
self::sendError("Error refreshing device: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device parameters
|
||||
*/
|
||||
protected function genieacsGetParametersAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
$parameters = $input['parameters'] ?? [];
|
||||
|
||||
if (!$deviceId || empty($parameters)) {
|
||||
self::sendError("Device ID and parameters are required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->getParameterValues($deviceId, $parameters);
|
||||
|
||||
// Check if result is a successful task response
|
||||
if (self::isGenieAcsTaskSuccess($result)) {
|
||||
self::returnJson(['success' => true, 'message' => 'Get parameters task created', 'result' => $result]);
|
||||
} else {
|
||||
self::returnJson(['success' => false, 'message' => 'Failed to create get parameters task', 'result' => $result]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS getParameters error: " . $e->getMessage());
|
||||
self::sendError("Error getting parameters: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set device parameters
|
||||
*/
|
||||
protected function genieacsSetParametersAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
$parameters = $input['parameters'] ?? [];
|
||||
|
||||
if (!$deviceId || empty($parameters)) {
|
||||
self::sendError("Device ID and parameters are required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->setParameterValues($deviceId, $parameters);
|
||||
|
||||
if (self::isGenieAcsTaskSuccess($result)) {
|
||||
self::returnJson(['success' => true, 'message' => 'Set parameters task created', 'result' => $result]);
|
||||
} else {
|
||||
self::returnJson(['success' => false, 'message' => 'Failed to create set parameters task', 'result' => $result]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS setParameters error: " . $e->getMessage());
|
||||
self::sendError("Error setting parameters: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full device information
|
||||
*/
|
||||
protected function genieacsGetDeviceInfoAction() {
|
||||
try {
|
||||
$deviceId = $_GET['deviceId'] ?? null;
|
||||
|
||||
if (!$deviceId) {
|
||||
self::sendError("Device ID is required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$device = $acs->getDevice($deviceId);
|
||||
|
||||
if (!$device) {
|
||||
self::sendError("Device not found");
|
||||
}
|
||||
|
||||
$deviceInfo = GenieACS::getDeviceInfo($device);
|
||||
$externalIp = GenieACS::getExternalIP($device);
|
||||
$macAddress = GenieACS::getMacAddress($device);
|
||||
|
||||
self::returnJson([
|
||||
'success' => true,
|
||||
'deviceInfo' => $deviceInfo,
|
||||
'externalIp' => $externalIp,
|
||||
'macAddress' => $macAddress,
|
||||
'fullData' => $device
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS getDeviceInfo error: " . $e->getMessage());
|
||||
self::sendError("Error getting device info: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping an IP address via GenieACS
|
||||
*/
|
||||
protected function genieacsPingAction() {
|
||||
try {
|
||||
$ip = $_GET['ip'] ?? null;
|
||||
|
||||
if (!$ip) {
|
||||
self::sendError("IP address is required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->ping($ip);
|
||||
|
||||
self::returnJson(['success' => true, 'result' => $result]);
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS ping error: " . $e->getMessage());
|
||||
self::sendError("Error pinging: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory reset device via GenieACS
|
||||
*/
|
||||
protected function genieacsFactoryResetAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
|
||||
if (!$deviceId) {
|
||||
self::sendError("Device ID is required");
|
||||
}
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->factoryResetDevice($deviceId);
|
||||
|
||||
if (self::isGenieAcsTaskSuccess($result)) {
|
||||
self::returnJson(['success' => true, 'message' => 'Factory reset task created', 'result' => $result]);
|
||||
} else {
|
||||
self::returnJson(['success' => false, 'message' => 'Failed to create factory reset task', 'result' => $result]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("GenieACS factoryReset error: " . $e->getMessage());
|
||||
self::sendError("Error factory resetting device: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
471
lib/GenieACS/GenieACS.php
Normal file
471
lib/GenieACS/GenieACS.php
Normal file
@@ -0,0 +1,471 @@
|
||||
<?php
|
||||
|
||||
class GenieACS {
|
||||
private $log;
|
||||
private $baseurl;
|
||||
private $username;
|
||||
private $password;
|
||||
private $jwt_token;
|
||||
|
||||
public function __construct($baseurl, $username, $password) {
|
||||
$this->log = mfLoghandler::singleton();
|
||||
|
||||
$this->baseurl = rtrim($baseurl, '/');
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
|
||||
if (!$this->baseurl || !$this->username || !$this->password) {
|
||||
throw new Exception("Invalid Arguments");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate and retrieve JWT token
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _authenticate() {
|
||||
$session_key = "genieacs.{$this->baseurl}.jwt";
|
||||
$session = new mfConfig($session_key);
|
||||
|
||||
// Check if we have a valid cached token (valid for 1 hour)
|
||||
if ($session->value() && (time() - $session->edit) < 3600) {
|
||||
$this->jwt_token = $session->value();
|
||||
return true;
|
||||
}
|
||||
|
||||
$url = $this->baseurl . '/login';
|
||||
|
||||
$ctx_options = [
|
||||
"http" => [
|
||||
"ignore_errors" => true,
|
||||
"method" => "POST",
|
||||
"header" => [
|
||||
"Accept: application/json, text/*",
|
||||
"Content-Type: application/json; charset=UTF-8",
|
||||
],
|
||||
"content" => json_encode([
|
||||
"username" => $this->username,
|
||||
"password" => $this->password,
|
||||
]),
|
||||
]
|
||||
];
|
||||
|
||||
$ctx = stream_context_create($ctx_options);
|
||||
$response = file_get_contents($url, false, $ctx);
|
||||
|
||||
// Extract JWT from response headers
|
||||
if (isset($http_response_header)) {
|
||||
foreach ($http_response_header as $header) {
|
||||
if (stripos($header, 'set-cookie') !== false && stripos($header, 'genieacs-ui-jwt=') !== false) {
|
||||
preg_match('/genieacs-ui-jwt=([^;]+)/', $header, $matches);
|
||||
if (isset($matches[1])) {
|
||||
$this->jwt_token = $matches[1];
|
||||
|
||||
// Cache the token
|
||||
$session->value($this->jwt_token);
|
||||
$session->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Authentication failed - could not retrieve JWT token");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a GET request to the API
|
||||
* @param string $endpoint
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _get($endpoint) {
|
||||
if (!$this->jwt_token) {
|
||||
$this->_authenticate();
|
||||
}
|
||||
|
||||
$url = $this->baseurl . $endpoint;
|
||||
|
||||
$ctx_options = [
|
||||
'http' => [
|
||||
'ignore_errors' => true,
|
||||
'method' => 'GET',
|
||||
'header' => [
|
||||
'Cookie: genieacs-ui-jwt=' . $this->jwt_token,
|
||||
'Accept: application/json',
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
$ctx = stream_context_create($ctx_options);
|
||||
$response = file_get_contents($url, false, $ctx);
|
||||
|
||||
// Check if we got a 401 and need to re-authenticate
|
||||
if (isset($http_response_header)) {
|
||||
foreach ($http_response_header as $header) {
|
||||
if (stripos($header, 'HTTP/') === 0 && stripos($header, '401') !== false) {
|
||||
// Token expired, re-authenticate and retry
|
||||
$this->jwt_token = null;
|
||||
$this->_authenticate();
|
||||
return $this->_get($endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a POST request to the API
|
||||
* @param string $endpoint
|
||||
* @param array $data
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _post($endpoint, $data) {
|
||||
if (!$this->jwt_token) {
|
||||
$this->_authenticate();
|
||||
}
|
||||
|
||||
$url = $this->baseurl . $endpoint;
|
||||
$jsonData = json_encode($data);
|
||||
|
||||
$ctx_options = [
|
||||
'http' => [
|
||||
'ignore_errors' => true,
|
||||
'method' => 'POST',
|
||||
'header' => [
|
||||
'Cookie: genieacs-ui-jwt=' . $this->jwt_token,
|
||||
'Accept: application/json',
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen($jsonData)
|
||||
],
|
||||
'content' => $jsonData,
|
||||
]
|
||||
];
|
||||
|
||||
$ctx = stream_context_create($ctx_options);
|
||||
$response = file_get_contents($url, false, $ctx);
|
||||
|
||||
// Log for debugging
|
||||
error_log("GenieACS POST to $url: " . $jsonData);
|
||||
error_log("GenieACS response: " . ($response ?: 'empty'));
|
||||
|
||||
// Check if we got a 401 and need to re-authenticate
|
||||
if (isset($http_response_header)) {
|
||||
foreach ($http_response_header as $header) {
|
||||
error_log("GenieACS response header: " . $header);
|
||||
if (stripos($header, 'HTTP/') === 0 && stripos($header, '401') !== false) {
|
||||
// Token expired, re-authenticate and retry
|
||||
$this->jwt_token = null;
|
||||
$this->_authenticate();
|
||||
return $this->_post($endpoint, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If response is empty or false, it might still be successful (204 No Content)
|
||||
if ($response === false || $response === '') {
|
||||
// Check if status code indicates success
|
||||
if (isset($http_response_header)) {
|
||||
foreach ($http_response_header as $header) {
|
||||
if (stripos($header, 'HTTP/') === 0) {
|
||||
if (stripos($header, '200') !== false || stripos($header, '202') !== false || stripos($header, '204') !== false) {
|
||||
return ['success' => true];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all devices
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getDevices() {
|
||||
return $this->_get('/api/devices');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific device by ID
|
||||
* @param string $deviceId Device ID (will be URL-encoded automatically)
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getDevice($deviceId) {
|
||||
return $this->_get('/api/devices/' . rawurlencode($deviceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a task for a device
|
||||
* @param string $deviceId Device ID (will be URL-encoded automatically)
|
||||
* @param array $tasks Array of tasks to execute
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*
|
||||
* Example:
|
||||
* $tasks = [
|
||||
* ["name" => "getParameterValues", "parameterNames" => ["InternetGatewayDevice.User.1.Username"]]
|
||||
* ];
|
||||
*/
|
||||
public function createTask($deviceId, $tasks) {
|
||||
return $this->_post('/api/devices/' . rawurlencode($deviceId) . '/tasks', $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameter values from a device
|
||||
* @param string $deviceId URL-encoded device ID
|
||||
* @param array $parameterNames Array of parameter names to retrieve
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getParameterValues($deviceId, $parameterNames) {
|
||||
$tasks = [
|
||||
[
|
||||
"name" => "getParameterValues",
|
||||
"parameterNames" => $parameterNames
|
||||
]
|
||||
];
|
||||
return $this->createTask($deviceId, $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parameter values on a device
|
||||
* @param string $deviceId URL-encoded device ID
|
||||
* @param array $parameterValues Array of parameter name => value pairs
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setParameterValues($deviceId, $parameterValues) {
|
||||
$tasks = [
|
||||
[
|
||||
"name" => "setParameterValues",
|
||||
"parameterValues" => $parameterValues
|
||||
]
|
||||
];
|
||||
return $this->createTask($deviceId, $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh device information
|
||||
* @param string $deviceId URL-encoded device ID
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function refreshDevice($deviceId) {
|
||||
$tasks = [
|
||||
[
|
||||
"name" => "refreshObject",
|
||||
"objectName" => ""
|
||||
]
|
||||
];
|
||||
return $this->createTask($deviceId, $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboot a device
|
||||
* @param string $deviceId URL-encoded device ID
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rebootDevice($deviceId) {
|
||||
$tasks = [
|
||||
[
|
||||
"name" => "reboot"
|
||||
]
|
||||
];
|
||||
return $this->createTask($deviceId, $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory reset a device
|
||||
* @param string $deviceId URL-encoded device ID
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function factoryResetDevice($deviceId) {
|
||||
$tasks = [
|
||||
[
|
||||
"name" => "factoryReset"
|
||||
]
|
||||
];
|
||||
return $this->createTask($deviceId, $tasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping an IP address
|
||||
* @param string $ip IP address to ping
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*
|
||||
* Returns: {
|
||||
* "packetsTransmitted": 3,
|
||||
* "packetsReceived": 3,
|
||||
* "packetLoss": 0,
|
||||
* "min": 2.674,
|
||||
* "avg": 3.054,
|
||||
* "max": 3.34,
|
||||
* "mdev": 0.28
|
||||
* }
|
||||
*/
|
||||
public function ping($ip) {
|
||||
return $this->_get('/api/ping/' . $ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file from a device
|
||||
* @param string $deviceId URL-encoded device ID
|
||||
* @param string $fileType File type to download
|
||||
* @param string $fileName Optional file name
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function downloadFile($deviceId, $fileType, $fileName = null) {
|
||||
$task = [
|
||||
"name" => "download",
|
||||
"fileType" => $fileType
|
||||
];
|
||||
|
||||
if ($fileName) {
|
||||
$task["fileName"] = $fileName;
|
||||
}
|
||||
|
||||
return $this->createTask($deviceId, [$task]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse device data from API response to extract useful information
|
||||
* @param array $deviceData Raw device data from API
|
||||
* @return array Parsed device information
|
||||
*/
|
||||
public static function parseDeviceData($deviceData) {
|
||||
$parsed = [];
|
||||
|
||||
foreach ($deviceData as $key => $value) {
|
||||
// Extract simple values
|
||||
if (isset($value['value']) && is_array($value['value'])) {
|
||||
$parsed[$key] = $value['value'][0];
|
||||
}
|
||||
}
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device ID from device data
|
||||
* @param array $deviceData Raw device data from API
|
||||
* @return string|null Device ID
|
||||
*/
|
||||
public static function getDeviceId($deviceData) {
|
||||
if (isset($deviceData['DeviceID.ID']['value'][0])) {
|
||||
return $deviceData['DeviceID.ID']['value'][0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MAC address from device data
|
||||
* @param array $deviceData Raw device data from API
|
||||
* @return string|null MAC address
|
||||
*/
|
||||
public static function getMacAddress($deviceData) {
|
||||
// Try WAN connection MAC address first
|
||||
if (isset($deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress']['value'][0])) {
|
||||
return $deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress']['value'][0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get external IP address from device data
|
||||
* @param array $deviceData Raw device data from API
|
||||
* @return string|null External IP address
|
||||
*/
|
||||
public static function getExternalIP($deviceData) {
|
||||
// Try to get from WAN IP Connection
|
||||
if (isset($deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress']['value'][0])) {
|
||||
return $deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress']['value'][0];
|
||||
}
|
||||
|
||||
// Try alternative connection
|
||||
if (isset($deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.2.ExternalIPAddress']['value'][0])) {
|
||||
return $deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.2.ExternalIPAddress']['value'][0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get management/local IP address from device data (private IP)
|
||||
* @param array $deviceData Raw device data from API
|
||||
* @return string|null Management IP address
|
||||
*/
|
||||
public static function getManagementIP($deviceData) {
|
||||
// Check both WAN connections and return the one with a private IP
|
||||
$ips = [];
|
||||
|
||||
if (isset($deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress']['value'][0])) {
|
||||
$ips[] = $deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress']['value'][0];
|
||||
}
|
||||
|
||||
if (isset($deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.2.ExternalIPAddress']['value'][0])) {
|
||||
$ips[] = $deviceData['InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.2.ExternalIPAddress']['value'][0];
|
||||
}
|
||||
|
||||
// Return the first private IP found (10.x.x.x, 172.16-31.x.x, 192.168.x.x)
|
||||
foreach ($ips as $ip) {
|
||||
if (self::isPrivateIP($ip)) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
|
||||
// If no private IP found, return first IP
|
||||
return $ips[0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an IP address is in a private range
|
||||
* @param string $ip IP address
|
||||
* @return bool True if private IP
|
||||
*/
|
||||
private static function isPrivateIP($ip) {
|
||||
$parts = explode('.', $ip);
|
||||
if (count($parts) !== 4) return false;
|
||||
|
||||
$first = (int)$parts[0];
|
||||
$second = (int)$parts[1];
|
||||
|
||||
// 10.0.0.0 - 10.255.255.255
|
||||
if ($first === 10) return true;
|
||||
|
||||
// 172.16.0.0 - 172.31.255.255
|
||||
if ($first === 172 && $second >= 16 && $second <= 31) return true;
|
||||
|
||||
// 192.168.0.0 - 192.168.255.255
|
||||
if ($first === 192 && $second === 168) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get device manufacturer, model, and version info
|
||||
* @param array $deviceData Raw device data from API
|
||||
* @return array Device info
|
||||
*/
|
||||
public static function getDeviceInfo($deviceData) {
|
||||
return [
|
||||
'manufacturer' => $deviceData['DeviceID.Manufacturer']['value'][0] ?? null,
|
||||
'productClass' => $deviceData['DeviceID.ProductClass']['value'][0] ?? null,
|
||||
'oui' => $deviceData['DeviceID.OUI']['value'][0] ?? null,
|
||||
'serialNumber' => $deviceData['DeviceID.SerialNumber']['value'][0] ?? null,
|
||||
'hardwareVersion' => $deviceData['InternetGatewayDevice.DeviceInfo.HardwareVersion']['value'][0] ?? null,
|
||||
'softwareVersion' => $deviceData['InternetGatewayDevice.DeviceInfo.SoftwareVersion']['value'][0] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,8 @@ Vue.component('radius-users', {
|
||||
class="fa-duotone fa-circle-info"></i></button>
|
||||
<button class="ghost-btn" @click="openTransferModal(item.username)" data-tooltip="Transfer Statistik"
|
||||
data-tooltip-align="left"><i class="fa-duotone fa-chart-line"></i></button>
|
||||
<!-- <button class="ghost-btn" @click="openRouterManagement(item)" data-tooltip="Router Management"-->
|
||||
<!-- data-tooltip-align="left"><i class="fa-duotone fa-router"></i></button>-->
|
||||
</td>
|
||||
</template>
|
||||
<template #observer>
|
||||
@@ -393,6 +395,135 @@ Vue.component('radius-users', {
|
||||
</div>
|
||||
</div>
|
||||
</radius-modal>
|
||||
<radius-modal :show="showRouterModal" :title="'Router Management - ' + (routerData.username || '')" @close="closeRouterModal" modal-class="modal-card-wide">
|
||||
<div class="modal-body-scrollable">
|
||||
<div v-if="routerLoading" class="table-placeholder" style="min-height: 300px;">
|
||||
<div class="btn-loader" style="width: 50px; height: 50px;"></div>
|
||||
<div style="margin-top: 16px;">Router wird gesucht...</div>
|
||||
</div>
|
||||
<div v-else-if="!routerDevice" class="table-placeholder" style="min-height: 300px;">
|
||||
<i class="fa-duotone fa-router-slash" style="font-size: 48px; opacity: 0.3;"></i>
|
||||
<div style="margin-top: 16px;">Kein Router mit dieser IP gefunden</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="kv-redesign">
|
||||
<div class="kv-row"><span class="kv-label">Hersteller</span><code class="kv-value">{{ routerDevice.deviceInfo.manufacturer || '—' }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Modell</span><code class="kv-value">{{ routerDevice.deviceInfo.productClass || '—' }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Hardware Version</span><code class="kv-value">{{ routerDevice.deviceInfo.hardwareVersion || '—' }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Software Version</span><code class="kv-value">{{ routerDevice.deviceInfo.softwareVersion || '—' }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Seriennummer</span><code class="kv-value">{{ routerDevice.deviceInfo.serialNumber || '—' }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Device ID</span>
|
||||
<div class="kv-value inline-copy">
|
||||
<code>{{ routerDevice.deviceId || '—' }}</code>
|
||||
<button v-if="routerDevice.deviceId" class="icon-btn sm" @click="copy(routerDevice.deviceId, $event)" data-tooltip="Kopieren"><i class="fa-duotone fa-copy copy-icon"></i><i class="fa-duotone fa-check check-icon"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kv-row"><span class="kv-label">Externe IP</span>
|
||||
<div class="kv-value inline-copy">
|
||||
<code>{{ routerDevice.ip || '—' }}</code>
|
||||
<button v-if="routerDevice.ip" class="icon-btn sm" @click="copy(routerDevice.ip, $event)" data-tooltip="Kopieren"><i class="fa-duotone fa-copy copy-icon"></i><i class="fa-duotone fa-check check-icon"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kv-row"><span class="kv-label">Management IP</span>
|
||||
<div class="kv-value inline-copy">
|
||||
<code>{{ routerDevice.managementIp || '—' }}</code>
|
||||
<button v-if="routerDevice.managementIp" class="icon-btn sm" @click="copy(routerDevice.managementIp, $event)" data-tooltip="Kopieren"><i class="fa-duotone fa-copy copy-icon"></i><i class="fa-duotone fa-check check-icon"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kv-row"><span class="kv-label">Management Username</span>
|
||||
<div class="kv-value inline-copy">
|
||||
<code v-if="!loadingUsername">{{ managementUsername || '—' }}</code>
|
||||
<div v-else class="skeleton-line" style="width: 100px; height: 16px;"></div>
|
||||
<button v-if="managementUsername && !loadingUsername" class="icon-btn sm" @click="copy(managementUsername, $event)" data-tooltip="Kopieren"><i class="fa-duotone fa-copy copy-icon"></i><i class="fa-duotone fa-check check-icon"></i></button>
|
||||
<button class="icon-btn sm" @click="fetchManagementUsername" :disabled="loadingUsername" data-tooltip="Aktualisieren" data-tooltip-align="left">
|
||||
<i class="fa-duotone fa-arrows-rotate" :class="{'fa-spin': loadingUsername}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<h4 style="margin-bottom: 12px; font-size: 14px; font-weight: 600;">Router Aktionen</h4>
|
||||
<div class="grid g-3 cols-3">
|
||||
<button class="ghost-btn" @click="refreshRouter" :disabled="routerActionLoading" style="padding: 12px;">
|
||||
<i class="fa-duotone fa-arrows-rotate"></i> Aktualisieren
|
||||
</button>
|
||||
<button class="ghost-btn" @click="rebootRouter" :disabled="routerActionLoading" style="padding: 12px;">
|
||||
<i class="fa-duotone fa-power-off"></i> Neustart
|
||||
</button>
|
||||
<button class="ghost-btn" @click="pingRouter" :disabled="routerActionLoading" style="padding: 12px;">
|
||||
<i class="fa-duotone fa-signal-bars"></i> Ping
|
||||
</button>
|
||||
<button class="danger-btn" @click="confirmFactoryReset" :disabled="routerActionLoading" style="padding: 12px;">
|
||||
<i class="fa-duotone fa-triangle-exclamation"></i> Factory Reset
|
||||
</button>
|
||||
<button class="ghost-btn" @click="showParameterModal = true" :disabled="routerActionLoading" style="padding: 12px;">
|
||||
<i class="fa-duotone fa-sliders"></i> Parameter lesen
|
||||
</button>
|
||||
<button class="ghost-btn" @click="showSetParameterModal = true" :disabled="routerActionLoading" style="padding: 12px;">
|
||||
<i class="fa-duotone fa-pen-to-square"></i> Parameter setzen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="pingResult" class="mt-3">
|
||||
<h4 style="margin-bottom: 12px; font-size: 14px; font-weight: 600;">Ping Ergebnis</h4>
|
||||
<div class="kv-redesign">
|
||||
<div class="kv-row"><span class="kv-label">Pakete gesendet</span><code class="kv-value">{{ pingResult.packetsTransmitted }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Pakete empfangen</span><code class="kv-value">{{ pingResult.packetsReceived }}</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Paketverlust</span><code class="kv-value">{{ pingResult.packetLoss }}%</code></div>
|
||||
<div class="kv-row"><span class="kv-label">Min / Avg / Max</span><code class="kv-value">{{ pingResult.min }} / {{ pingResult.avg }} / {{ pingResult.max }} ms</code></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</radius-modal>
|
||||
|
||||
<radius-modal :show="showParameterModal" title="Parameter lesen" @close="showParameterModal = false">
|
||||
<div>
|
||||
<div class="field">
|
||||
<label style="margin-bottom: 8px; font-size: 14px;">Parameter Name</label>
|
||||
<div class="input-wrap">
|
||||
<i class="fa-duotone fa-code input-icon"></i>
|
||||
<input class="ri" type="text" v-model.trim="parameterName" placeholder="z.B. InternetGatewayDevice.User.1.Username">
|
||||
</div>
|
||||
<p class="muted small" style="margin-top: 4px;">Geben Sie den vollständigen Parameter-Pfad ein</p>
|
||||
</div>
|
||||
<div class="cluster" style="justify-content: flex-end; margin-top: 24px; gap: 12px;">
|
||||
<button class="ghost-btn" @click="showParameterModal = false">Abbrechen</button>
|
||||
<button class="primary-btn" @click="getParameter" :disabled="!parameterName || routerActionLoading">
|
||||
<span v-if="!routerActionLoading">Lesen</span>
|
||||
<span v-else class="btn-loader"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</radius-modal>
|
||||
|
||||
<radius-modal :show="showSetParameterModal" title="Parameter setzen" @close="showSetParameterModal = false">
|
||||
<div>
|
||||
<div class="field">
|
||||
<label style="margin-bottom: 8px; font-size: 14px;">Parameter Name</label>
|
||||
<div class="input-wrap">
|
||||
<i class="fa-duotone fa-code input-icon"></i>
|
||||
<input class="ri" type="text" v-model.trim="setParameterName" placeholder="z.B. InternetGatewayDevice.User.1.Password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field mt-2">
|
||||
<label style="margin-bottom: 8px; font-size: 14px;">Wert</label>
|
||||
<div class="input-wrap">
|
||||
<i class="fa-duotone fa-input-text input-icon"></i>
|
||||
<input class="ri" type="text" v-model.trim="setParameterValue" placeholder="Neuer Wert">
|
||||
</div>
|
||||
</div>
|
||||
<div class="cluster" style="justify-content: flex-end; margin-top: 24px; gap: 12px;">
|
||||
<button class="ghost-btn" @click="showSetParameterModal = false">Abbrechen</button>
|
||||
<button class="primary-btn" @click="setParameter" :disabled="!setParameterName || !setParameterValue || routerActionLoading">
|
||||
<span v-if="!routerActionLoading">Setzen</span>
|
||||
<span v-else class="btn-loader"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</radius-modal>
|
||||
</div>
|
||||
`,
|
||||
data: () => ({
|
||||
@@ -426,7 +557,20 @@ Vue.component('radius-users', {
|
||||
showEmailModal: false,
|
||||
recipientEmail: '',
|
||||
showExtensionIdModal: false,
|
||||
extensionId: 'jglijfiddilckddlmbnlojmmlahboffh'
|
||||
extensionId: 'jglijfiddilckddlmbnlojmmlahboffh',
|
||||
showRouterModal: false,
|
||||
routerLoading: false,
|
||||
routerActionLoading: false,
|
||||
routerData: {},
|
||||
routerDevice: null,
|
||||
pingResult: null,
|
||||
showParameterModal: false,
|
||||
parameterName: '',
|
||||
showSetParameterModal: false,
|
||||
setParameterName: '',
|
||||
setParameterValue: '',
|
||||
managementUsername: '',
|
||||
loadingUsername: false
|
||||
}),
|
||||
computed: {
|
||||
hasFilters() {
|
||||
@@ -821,6 +965,275 @@ Vue.component('radius-users', {
|
||||
},
|
||||
plugins: [chartBackgroundColorPlugin]
|
||||
});
|
||||
},
|
||||
async openRouterManagement(item) {
|
||||
this.showRouterModal = true;
|
||||
this.routerLoading = true;
|
||||
this.routerData = item;
|
||||
this.routerDevice = null;
|
||||
this.pingResult = null;
|
||||
this.managementUsername = '';
|
||||
|
||||
try {
|
||||
// First get the IP from radacct
|
||||
const r = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/proxyUnsecureHTTPRequestToRadius?action2=fetchRadacct&username=${encodeURIComponent(item.username)}`);
|
||||
if (r.ok) {
|
||||
const radacct = await r.json();
|
||||
if (radacct && radacct.ip) {
|
||||
// Now fetch device from GenieACS using this IP
|
||||
const deviceResponse = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetDeviceByIp?ip=${encodeURIComponent(radacct.ip)}`);
|
||||
if (deviceResponse.ok) {
|
||||
const deviceData = await deviceResponse.json();
|
||||
if (deviceData.success) {
|
||||
this.routerDevice = deviceData;
|
||||
// Automatically fetch management username
|
||||
await this.fetchManagementUsername();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error fetching router:', e);
|
||||
window.notify('error', 'Fehler beim Laden des Routers');
|
||||
}
|
||||
|
||||
this.routerLoading = false;
|
||||
},
|
||||
closeRouterModal() {
|
||||
this.showRouterModal = false;
|
||||
this.routerData = {};
|
||||
this.routerDevice = null;
|
||||
this.pingResult = null;
|
||||
this.showParameterModal = false;
|
||||
this.showSetParameterModal = false;
|
||||
this.parameterName = '';
|
||||
this.setParameterName = '';
|
||||
this.setParameterValue = '';
|
||||
this.managementUsername = '';
|
||||
this.loadingUsername = false;
|
||||
},
|
||||
async refreshRouter() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId) return;
|
||||
|
||||
this.routerActionLoading = true;
|
||||
try {
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsRefreshDevice`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({deviceId: this.routerDevice.deviceId})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
window.notify('success', 'Router-Aktualisierung gestartet');
|
||||
} else {
|
||||
window.notify('error', data.message || 'Fehler beim Aktualisieren');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error refreshing router:', e);
|
||||
window.notify('error', 'Fehler beim Aktualisieren des Routers');
|
||||
}
|
||||
this.routerActionLoading = false;
|
||||
},
|
||||
async rebootRouter() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId) return;
|
||||
if (!confirm('Möchten Sie den Router wirklich neu starten?')) return;
|
||||
|
||||
this.routerActionLoading = true;
|
||||
try {
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsRebootDevice`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({deviceId: this.routerDevice.deviceId})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
window.notify('success', 'Router-Neustart gestartet');
|
||||
} else {
|
||||
window.notify('error', data.message || 'Fehler beim Neustart');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error rebooting router:', e);
|
||||
window.notify('error', 'Fehler beim Neustarten des Routers');
|
||||
}
|
||||
this.routerActionLoading = false;
|
||||
},
|
||||
async pingRouter() {
|
||||
if (!this.routerDevice) return;
|
||||
|
||||
// Use management IP for ping, fallback to external IP
|
||||
const pingIp = this.routerDevice.managementIp || this.routerDevice.ip;
|
||||
if (!pingIp) return;
|
||||
|
||||
this.routerActionLoading = true;
|
||||
this.pingResult = null;
|
||||
try {
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsPing?ip=${encodeURIComponent(pingIp)}`);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success && data.result) {
|
||||
this.pingResult = data.result;
|
||||
window.notify('success', 'Ping erfolgreich');
|
||||
} else {
|
||||
window.notify('error', 'Ping fehlgeschlagen');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error pinging router:', e);
|
||||
window.notify('error', 'Fehler beim Pingen des Routers');
|
||||
}
|
||||
this.routerActionLoading = false;
|
||||
},
|
||||
async confirmFactoryReset() {
|
||||
if (!confirm('ACHTUNG: Möchten Sie den Router wirklich auf Werkseinstellungen zurücksetzen? Diese Aktion kann nicht rückgängig gemacht werden!')) return;
|
||||
if (!confirm('Sind Sie sicher? Alle Einstellungen gehen verloren!')) return;
|
||||
|
||||
await this.factoryResetRouter();
|
||||
},
|
||||
async factoryResetRouter() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId) return;
|
||||
|
||||
this.routerActionLoading = true;
|
||||
try {
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsFactoryReset`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({deviceId: this.routerDevice.deviceId})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
window.notify('success', 'Factory Reset gestartet');
|
||||
} else {
|
||||
window.notify('error', data.message || 'Fehler beim Factory Reset');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error factory resetting router:', e);
|
||||
window.notify('error', 'Fehler beim Factory Reset');
|
||||
}
|
||||
this.routerActionLoading = false;
|
||||
},
|
||||
async getParameter() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId || !this.parameterName) return;
|
||||
|
||||
this.routerActionLoading = true;
|
||||
try {
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetParameters`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
deviceId: this.routerDevice.deviceId,
|
||||
parameters: [this.parameterName]
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
window.notify('success', 'Parameter-Abfrage gestartet. Überprüfen Sie das GenieACS-Interface für Ergebnisse.');
|
||||
this.showParameterModal = false;
|
||||
this.parameterName = '';
|
||||
} else {
|
||||
window.notify('error', data.message || 'Fehler beim Lesen des Parameters');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error getting parameter:', e);
|
||||
window.notify('error', 'Fehler beim Lesen des Parameters');
|
||||
}
|
||||
this.routerActionLoading = false;
|
||||
},
|
||||
async setParameter() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId || !this.setParameterName || !this.setParameterValue) return;
|
||||
|
||||
this.routerActionLoading = true;
|
||||
try {
|
||||
const parameters = {};
|
||||
parameters[this.setParameterName] = this.setParameterValue;
|
||||
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsSetParameters`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
deviceId: this.routerDevice.deviceId,
|
||||
parameters: parameters
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
window.notify('success', 'Parameter erfolgreich gesetzt');
|
||||
this.showSetParameterModal = false;
|
||||
this.setParameterName = '';
|
||||
this.setParameterValue = '';
|
||||
} else {
|
||||
window.notify('error', data.message || 'Fehler beim Setzen des Parameters');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error setting parameter:', e);
|
||||
window.notify('error', 'Fehler beim Setzen des Parameters');
|
||||
}
|
||||
this.routerActionLoading = false;
|
||||
},
|
||||
async fetchManagementUsername() {
|
||||
if (!this.routerDevice || !this.routerDevice.deviceId) return;
|
||||
|
||||
this.loadingUsername = true;
|
||||
try {
|
||||
const response = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetParameters`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
deviceId: this.routerDevice.deviceId,
|
||||
parameters: ['InternetGatewayDevice.User.1.Username']
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
window.notify('success', 'Username-Abfrage gestartet. Bitte warten Sie einen Moment und klicken Sie erneut auf Aktualisieren.');
|
||||
|
||||
// Wait a bit and then fetch the device data to get the updated value
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const deviceResponse = await fetch(`${window.TT_CONFIG.BASE_PATH}/Radius/genieacsGetDeviceInfo?deviceId=${encodeURIComponent(this.routerDevice.deviceId)}`);
|
||||
if (deviceResponse.ok) {
|
||||
const deviceInfo = await deviceResponse.json();
|
||||
if (deviceInfo.success && deviceInfo.fullData) {
|
||||
// Extract username from device data
|
||||
const usernameData = deviceInfo.fullData['InternetGatewayDevice.User.1.Username'];
|
||||
if (usernameData && usernameData.value && usernameData.value[0]) {
|
||||
this.managementUsername = usernameData.value[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error fetching updated device info:', e);
|
||||
} finally {
|
||||
this.loadingUsername = false;
|
||||
}
|
||||
}, 3000);
|
||||
} else {
|
||||
this.loadingUsername = false;
|
||||
window.notify('error', data.message || 'Fehler beim Lesen des Usernames');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error fetching management username:', e);
|
||||
window.notify('error', 'Fehler beim Lesen des Usernames');
|
||||
this.loadingUsername = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user