fix(api): try UniFi OS Integration API first for X-API-Key auth
The /api/self/sites and /proxy/network/api/self/sites endpoints belong
to the legacy session-cookie API — they don't accept X-API-Key auth and
return 401 for keys generated in UniFi OS → Control Plane → Integrations.
Adds /proxy/network/integration/v1/sites as the first endpoint tried,
which is the actual home of API keys. Integration response rows look
like { id, internalReference, name }; getSites normalizes them to the
legacy { name, desc } shape using internalReference as the slug so
downstream URLs (which build paths from $this->site) keep working.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -625,8 +625,14 @@ class UnifiApiClient
|
||||
$http = $this->buildRequest();
|
||||
}
|
||||
|
||||
// Try multiple URL patterns
|
||||
// Endpoints, in preferred order:
|
||||
// 1. UniFi OS Integration API — the one X-API-Key keys are issued for
|
||||
// (response shape: [{ id, internalReference, name }])
|
||||
// 2. Legacy /proxy/network/api/self/sites — session-cookie API on
|
||||
// UniFi OS consoles (response: [{ name, desc, ... }])
|
||||
// 3. Legacy /api/self/sites — standalone controller (no /proxy prefix)
|
||||
$paths = [
|
||||
'/proxy/network/integration/v1/sites',
|
||||
'/proxy/network/api/self/sites',
|
||||
'/api/self/sites',
|
||||
];
|
||||
@@ -645,11 +651,28 @@ class UnifiApiClient
|
||||
}
|
||||
|
||||
$data = $response->json('data', $response->json());
|
||||
if (is_array($data) && ! empty($data) && isset($data[0]['name'])) {
|
||||
if (! is_array($data) || empty($data)) {
|
||||
$lastError = "No sites in response from {$path}";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Integration API rows have `internalReference` (== legacy
|
||||
// site slug) and `name` (human-readable). Normalize to
|
||||
// the legacy {name, desc} shape so downstream code that
|
||||
// builds URLs with the site slug keeps working.
|
||||
if (isset($data[0]['internalReference'])) {
|
||||
$data = array_map(fn ($s) => [
|
||||
'name' => $s['internalReference'] ?? 'default',
|
||||
'desc' => $s['name'] ?? $s['internalReference'] ?? 'Default',
|
||||
], $data);
|
||||
}
|
||||
|
||||
if (isset($data[0]['name'])) {
|
||||
Log::debug('unifi.sites_found', ['path' => $path, 'count' => count($data)]);
|
||||
return $data;
|
||||
}
|
||||
$lastError = "No sites in response from {$path}";
|
||||
|
||||
$lastError = "Unexpected response shape from {$path}";
|
||||
} else {
|
||||
$lastError = "HTTP {$response->status()} on {$path}";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user