Merge pull request #3 from friloo/claude/unifi-api-migration-dbNMa
Fix UniFi OS API login validation and HTTP method handling
This commit is contained in:
commit
c418f8c5b5
1 changed files with 40 additions and 17 deletions
|
|
@ -62,12 +62,17 @@ class UniFiController {
|
||||||
|
|
||||||
$data = json_decode($response, true);
|
$data = json_decode($response, true);
|
||||||
|
|
||||||
// UniFi OS gibt ein User-Objekt zurück (unique_id/email), die alte API meta.rc = ok
|
// Expliziter Fehler vom Controller abfangen (meta.rc = error)
|
||||||
$isUnifiOs = is_array($data) && (isset($data['unique_id']) || isset($data['email']));
|
if (isset($data['meta']['rc']) && $data['meta']['rc'] !== 'ok') {
|
||||||
$isOldApi = isset($data['meta']['rc']) && $data['meta']['rc'] === 'ok';
|
$msg = $data['meta']['msg'] ?? 'Zugangsdaten abgelehnt';
|
||||||
|
throw new Exception("Login fehlgeschlagen: $msg");
|
||||||
|
}
|
||||||
|
|
||||||
if (!$isUnifiOs && !$isOldApi) {
|
// HTTP 200 ohne expliziten Fehler = Erfolg
|
||||||
throw new Exception("Login fehlgeschlagen: Ungültige Antwort vom Controller");
|
// UniFi OS liefert X-CSRF-Token im Response-Header (bereits via CURLOPT_HEADERFUNCTION extrahiert)
|
||||||
|
// Fallback: TOKEN-Cookie aus der Cookie-Datei lesen
|
||||||
|
if ($this->csrfToken === null) {
|
||||||
|
$this->csrfToken = $this->readCsrfFromCookieFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -80,6 +85,11 @@ class UniFiController {
|
||||||
$ch = curl_init();
|
$ch = curl_init();
|
||||||
$url = $this->controllerUrl . $endpoint;
|
$url = $this->controllerUrl . $endpoint;
|
||||||
|
|
||||||
|
$headers = ['Content-Type: application/json'];
|
||||||
|
if ($method !== 'GET' && $this->csrfToken !== null) {
|
||||||
|
$headers[] = 'X-CSRF-Token: ' . $this->csrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
$options = [
|
$options = [
|
||||||
CURLOPT_URL => $url,
|
CURLOPT_URL => $url,
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
|
@ -87,17 +97,14 @@ class UniFiController {
|
||||||
CURLOPT_COOKIEFILE => $this->cookieFile,
|
CURLOPT_COOKIEFILE => $this->cookieFile,
|
||||||
CURLOPT_TIMEOUT => 10,
|
CURLOPT_TIMEOUT => 10,
|
||||||
CURLOPT_CONNECTTIMEOUT => 5,
|
CURLOPT_CONNECTTIMEOUT => 5,
|
||||||
CURLOPT_HTTPHEADER => array_filter([
|
CURLOPT_HTTPHEADER => $headers
|
||||||
'Content-Type: application/json',
|
|
||||||
($method === 'POST' && $this->csrfToken !== null)
|
|
||||||
? 'X-CSRF-Token: ' . $this->csrfToken
|
|
||||||
: null
|
|
||||||
])
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($method === 'POST' && $data !== null) {
|
if ($method === 'GET') {
|
||||||
|
$options[CURLOPT_HTTPGET] = true;
|
||||||
|
} elseif ($method === 'POST') {
|
||||||
$options[CURLOPT_POST] = true;
|
$options[CURLOPT_POST] = true;
|
||||||
$options[CURLOPT_POSTFIELDS] = json_encode($data);
|
$options[CURLOPT_POSTFIELDS] = json_encode($data ?? (object)[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_setopt_array($ch, $options);
|
curl_setopt_array($ch, $options);
|
||||||
|
|
@ -154,7 +161,7 @@ class UniFiController {
|
||||||
|
|
||||||
// Alle Voucher abrufen
|
// Alle Voucher abrufen
|
||||||
public function getVouchers() {
|
public function getVouchers() {
|
||||||
$response = $this->apiRequest("/proxy/network/api/s/{$this->siteId}/stat/voucher");
|
$response = $this->apiRequest("/proxy/network/api/s/{$this->siteId}/stat/voucher", null, 'GET');
|
||||||
return $response['data'] ?? [];
|
return $response['data'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,6 +215,22 @@ class UniFiController {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CSRF-Token aus Netscape-Cookie-Datei lesen (Fallback wenn Header nicht gesetzt)
|
||||||
|
private function readCsrfFromCookieFile() {
|
||||||
|
if (!file_exists($this->cookieFile)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
foreach (file($this->cookieFile) as $line) {
|
||||||
|
$line = trim($line);
|
||||||
|
if ($line === '' || $line[0] === '#') continue;
|
||||||
|
$parts = explode("\t", $line);
|
||||||
|
if (count($parts) >= 7 && strtoupper($parts[5]) === 'TOKEN') {
|
||||||
|
return $parts[6];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Voucher-Code formatieren (xxxxx-xxxxx-xxxxx)
|
// Voucher-Code formatieren (xxxxx-xxxxx-xxxxx)
|
||||||
private function formatVoucherCode($code) {
|
private function formatVoucherCode($code) {
|
||||||
$chunks = str_split($code, 5);
|
$chunks = str_split($code, 5);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue