fix(rotate): don't skip when only PPSKs are flagged; move webhooks under /settings
* Password rotation was short-circuiting any run that had no whole-SSID wlan_ids configured, even if there were PPSKs with rotate_password=true in the database. The PPSK rotation block lived after the early-return, so per-PPSK rotation never fired. Now we only skip when there's nothing at all to rotate (neither wlan_ids nor PPSK opt-ins). * Webhook routes moved from /app/network/webhooks to /app/network/settings/webhooks so the URL reflects that this is a settings tab. Route names unchanged. v1.5.3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dashboard/unifi",
|
"name": "dashboard/unifi",
|
||||||
"description": "UniFi network management, WiFi stats, and captive portal authentication for the Dashboard platform",
|
"description": "UniFi network management, WiFi stats, and captive portal authentication for the Dashboard platform",
|
||||||
"version": "1.5.2",
|
"version": "1.5.3",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|||||||
@@ -32,9 +32,16 @@ class RotatePasswords extends Command
|
|||||||
$run = UnifiCronRun::record('rotate-passwords', $triggeredBy, null, function () use ($unifi, $force) {
|
$run = UnifiCronRun::record('rotate-passwords', $triggeredBy, null, function () use ($unifi, $force) {
|
||||||
$wlanIdsJson = Setting::get('unifi.password_rotation.wlan_ids', '[]');
|
$wlanIdsJson = Setting::get('unifi.password_rotation.wlan_ids', '[]');
|
||||||
$wlanIds = json_decode($wlanIdsJson, true);
|
$wlanIds = json_decode($wlanIdsJson, true);
|
||||||
|
if (! is_array($wlanIds)) $wlanIds = [];
|
||||||
|
|
||||||
if (empty($wlanIds) || ! is_array($wlanIds)) {
|
$ppskQuery = UnifiPpsk::where('rotate_password', true)
|
||||||
return ['status' => 'skipped', 'reason' => 'no SSIDs configured for rotation'];
|
->where('state', 'active')
|
||||||
|
->whereNotNull('unifi_id');
|
||||||
|
|
||||||
|
// Skip only if there's nothing at all to rotate — neither
|
||||||
|
// whole-SSID rotation targets nor per-PPSK rotation opt-ins.
|
||||||
|
if (empty($wlanIds) && ! $ppskQuery->exists()) {
|
||||||
|
return ['status' => 'skipped', 'reason' => 'no SSIDs or PPSKs configured for rotation'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$wordlist = Setting::get('unifi.password_rotation.wordlist', '');
|
$wordlist = Setting::get('unifi.password_rotation.wordlist', '');
|
||||||
@@ -66,7 +73,7 @@ class RotatePasswords extends Command
|
|||||||
|
|
||||||
$rotatedPpsks = [];
|
$rotatedPpsks = [];
|
||||||
$failedPpsks = [];
|
$failedPpsks = [];
|
||||||
foreach (UnifiPpsk::where('rotate_password', true)->where('state', 'active')->whereNotNull('unifi_id')->get() as $ppsk) {
|
foreach ($ppskQuery->get() as $ppsk) {
|
||||||
$newPass = $passwords[array_rand($passwords)];
|
$newPass = $passwords[array_rand($passwords)];
|
||||||
try {
|
try {
|
||||||
$unifi->updatePpsk($ppsk->unifi_id, ['x_passphrase' => $newPass]);
|
$unifi->updatePpsk($ppsk->unifi_id, ['x_passphrase' => $newPass]);
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ Route::middleware(['web', 'auth', 'app.access:unifi'])
|
|||||||
// Cron logs — read-only history of scheduled-task runs.
|
// Cron logs — read-only history of scheduled-task runs.
|
||||||
Route::get('/settings/cron-logs', [UnifiCronLogsController::class, 'index'])->name('settings.cron-logs.index');
|
Route::get('/settings/cron-logs', [UnifiCronLogsController::class, 'index'])->name('settings.cron-logs.index');
|
||||||
|
|
||||||
// Webhooks
|
// Webhooks — lives under /settings/* so it reads as a settings tab.
|
||||||
Route::get('/webhooks', [WebhookController::class, 'index']) ->name('webhooks.index');
|
Route::get('/settings/webhooks', [WebhookController::class, 'index']) ->name('webhooks.index');
|
||||||
Route::post('/webhooks', [WebhookController::class, 'store']) ->name('webhooks.store');
|
Route::post('/settings/webhooks', [WebhookController::class, 'store']) ->name('webhooks.store');
|
||||||
Route::put('/webhooks/{webhook}', [WebhookController::class, 'update']) ->name('webhooks.update');
|
Route::put('/settings/webhooks/{webhook}', [WebhookController::class, 'update']) ->name('webhooks.update');
|
||||||
Route::delete('/webhooks/{webhook}', [WebhookController::class, 'destroy'])->name('webhooks.destroy');
|
Route::delete('/settings/webhooks/{webhook}', [WebhookController::class, 'destroy'])->name('webhooks.destroy');
|
||||||
Route::post('/webhooks/{webhook}/test', [WebhookController::class, 'test']) ->name('webhooks.test');
|
Route::post('/settings/webhooks/{webhook}/test', [WebhookController::class, 'test']) ->name('webhooks.test');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user