Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 429cd44ac5 | |||
| 274f210337 | |||
| c0f12ce931 |
@@ -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.11.0",
|
"version": "1.12.1",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|||||||
@@ -181,7 +181,11 @@ class WebhookCheckService
|
|||||||
$prev = DeviceState::where('device_mac', $mac)->first();
|
$prev = DeviceState::where('device_mac', $mac)->first();
|
||||||
if (! $prev) continue;
|
if (! $prev) continue;
|
||||||
|
|
||||||
// Skip planned reboots — these are intentional, not alerts
|
// Skip planned reboots — these are intentional, not alerts.
|
||||||
|
// Two layers: a global suppression window set by RebootAllAps
|
||||||
|
// (Setting, survives any cache driver), plus the per-MAC
|
||||||
|
// cache keys for finer granularity.
|
||||||
|
if ($this->inGlobalRebootSuppression()) continue;
|
||||||
if (Cache::has('unifi:planned_reboot:' . strtolower($mac))) continue;
|
if (Cache::has('unifi:planned_reboot:' . strtolower($mac))) continue;
|
||||||
|
|
||||||
if ($comingOnline) {
|
if ($comingOnline) {
|
||||||
@@ -509,6 +513,8 @@ class WebhookCheckService
|
|||||||
private function checkReboot($aps, array $filter): array
|
private function checkReboot($aps, array $filter): array
|
||||||
{
|
{
|
||||||
$alerts = [];
|
$alerts = [];
|
||||||
|
if ($this->inGlobalRebootSuppression()) return $alerts;
|
||||||
|
|
||||||
foreach ($aps as $ap) {
|
foreach ($aps as $ap) {
|
||||||
if (! empty($filter) && ! in_array($ap['mac'], $filter)) continue;
|
if (! empty($filter) && ! in_array($ap['mac'], $filter)) continue;
|
||||||
if (Cache::has('unifi:planned_reboot:' . strtolower($ap['mac']))) continue;
|
if (Cache::has('unifi:planned_reboot:' . strtolower($ap['mac']))) continue;
|
||||||
@@ -584,6 +590,24 @@ class WebhookCheckService
|
|||||||
return self::buildPlatformPayload($url, $message, $fullPayload);
|
return self::buildPlatformPayload($url, $message, $fullPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a fleet reboot in progress right now? RebootAllAps stamps a
|
||||||
|
* suppression-until timestamp as a Setting; while that timestamp
|
||||||
|
* is in the future, we skip all device-offline / device-online /
|
||||||
|
* unexpected-reboot alerts to avoid flooding webhooks during the
|
||||||
|
* known maintenance window.
|
||||||
|
*/
|
||||||
|
private function inGlobalRebootSuppression(): bool
|
||||||
|
{
|
||||||
|
$until = \App\Models\Setting::get('unifi.reboot_suppression_until');
|
||||||
|
if (! $until) return false;
|
||||||
|
try {
|
||||||
|
return \Carbon\Carbon::parse($until)->isFuture();
|
||||||
|
} catch (\Throwable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public/static helper so the test-webhook endpoint produces the
|
* Public/static helper so the test-webhook endpoint produces the
|
||||||
* same per-platform payload shape that real events do.
|
* same per-platform payload shape that real events do.
|
||||||
|
|||||||
@@ -25,6 +25,31 @@ class UnifiServiceProvider extends ServiceProvider
|
|||||||
$this->loadRoutesFrom(__DIR__ . '/routes/unifi.php');
|
$this->loadRoutesFrom(__DIR__ . '/routes/unifi.php');
|
||||||
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
|
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
|
||||||
|
|
||||||
|
// Tell the shell's NavVisibilityRegistry which unifi nav items
|
||||||
|
// the user can see in the sidebar. Without this the sidebar
|
||||||
|
// would only follow legacy required_permission, hiding pages
|
||||||
|
// the user has been explicitly granted via the Access tab.
|
||||||
|
try {
|
||||||
|
app(\App\Support\NavVisibilityRegistry::class)->register(
|
||||||
|
'unifi.',
|
||||||
|
function (\App\Models\User $user) {
|
||||||
|
if (! \Illuminate\Support\Facades\Schema::hasTable('unifi_page_grants')) {
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
$groupIds = $user->groups()->pluck('groups.id');
|
||||||
|
return UnifiPageGrant::query()
|
||||||
|
->where(function ($q) use ($user, $groupIds) {
|
||||||
|
$q->where(fn ($u) => $u->where('grantee_type', 'user')->where('grantee_id', $user->id))
|
||||||
|
->orWhere(fn ($g) => $g->where('grantee_type', 'group')->whereIn('grantee_id', $groupIds));
|
||||||
|
})
|
||||||
|
->pluck('nav_item_id');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (\Throwable) {
|
||||||
|
// Shell may not have the registry yet (older shell version).
|
||||||
|
// Sidebar will fall back to legacy permission filter.
|
||||||
|
}
|
||||||
|
|
||||||
// Per-page access enforcement for unifi routes. If a unifi page has
|
// Per-page access enforcement for unifi routes. If a unifi page has
|
||||||
// any UnifiPageGrant rows, only super-admins and granted users/
|
// any UnifiPageGrant rows, only super-admins and granted users/
|
||||||
// groups can hit it; otherwise (no grants) it's open per the existing
|
// groups can hit it; otherwise (no grants) it's open per the existing
|
||||||
|
|||||||
Reference in New Issue
Block a user