fix(rotate): record PPSK rotation password + sync banded-SSID siblings
Three bugs reported from prod after a PPSK rotation: 1. unifi.password_rotation.last_password was only saved after a whole-SSID rotation. PPSK-only setups (the typical guest-WiFi case) ran a successful rotation but the setting stayed empty, so the Settings → Tasks UI never showed the current password and the /api/unifi/wifi/current-password endpoint returned 404 "no rotated password recorded yet". The PPSK loop now writes last_password on every successful PPSK rotation. 2. When an SSID is "banded" (band-steering disabled), UniFi splits it into one wlanconf per band — 2.4GHz and 5GHz each get their own _id and their own embedded PPSK array. Rotating the PPSK on one band left the other band with the old password. New UnifiApiClient::getWlanSiblings($wlanId) finds all wlanconfs that share an SSID name; both rotation and the manual modal edit now call updateEmbeddedPpsk on each sibling and update the matching UnifiPpsk DB rows. 3. The manual WiFi modal edit had the same band-blindness as #2 — editing the GUEST PPSK on the 2.4GHz half left the 5GHz half stale. WifiController::ppskUpdate now walks siblings the same way. v1.8.1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -293,9 +293,34 @@ class WifiController extends Controller
|
||||
if (! empty($unifiUpdate)) {
|
||||
if (str_starts_with($record->unifi_id, 'emb_') && isset($unifiUpdate['x_passphrase'])) {
|
||||
// Embedded PPSK update path — modify the WLAN's embedded array.
|
||||
$unifi->updateEmbeddedPpsk($record->wlan_id, $record->x_passphrase, $unifiUpdate['x_passphrase']);
|
||||
// Synthetic id is derived from the new passphrase.
|
||||
$data['unifi_id'] = 'emb_' . substr(hash('sha256', $record->wlan_id . ':' . $unifiUpdate['x_passphrase']), 0, 32);
|
||||
$newPass = $unifiUpdate['x_passphrase'];
|
||||
$oldPass = $record->x_passphrase;
|
||||
$unifi->updateEmbeddedPpsk($record->wlan_id, $oldPass, $newPass);
|
||||
$data['unifi_id'] = 'emb_' . substr(hash('sha256', $record->wlan_id . ':' . $newPass), 0, 32);
|
||||
|
||||
// Also update sibling WLANs (banded SSID — same name
|
||||
// on 2.4 and 5GHz are separate wlanconf rows).
|
||||
foreach ($unifi->getWlanSiblings($record->wlan_id) as $siblingWlanId) {
|
||||
$sibling = UnifiPpsk::where('wlan_id', $siblingWlanId)
|
||||
->where('name', $record->name)
|
||||
->where('state', 'active')
|
||||
->first();
|
||||
$siblingOldPass = $sibling?->x_passphrase ?? $oldPass;
|
||||
try {
|
||||
$unifi->updateEmbeddedPpsk($siblingWlanId, $siblingOldPass, $newPass);
|
||||
if ($sibling) {
|
||||
$sibling->update([
|
||||
'x_passphrase' => $newPass,
|
||||
'unifi_id' => 'emb_' . substr(hash('sha256', $siblingWlanId . ':' . $newPass), 0, 32),
|
||||
]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
\Illuminate\Support\Facades\Log::warning('unifi.ppsk_sibling_update_failed', [
|
||||
'sibling_wlan' => $siblingWlanId,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$unifi->updatePpsk($record->unifi_id, $unifiUpdate);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user