From 429cd44ac59eb3df3de9c43afe6a2cd5e2832d57 Mon Sep 17 00:00:00 2001 From: jwed Date: Fri, 5 Jun 2026 12:12:58 -0400 Subject: [PATCH] fix: register unifi pages with shell NavVisibilityRegistry; v1.12.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Access tab persists user/group grants in unifi_page_grants and the existing RouteMatched listener honors them on the request path, but NavItem::visibleTo() only consulted the page's required_permission — so a granted user never saw the menu entry to reach the page. Register the unifi.* prefix with the shell's NavVisibilityRegistry so the sidebar lists exactly the pages the grant table allows. Co-Authored-By: Claude Opus 4.7 --- composer.json | 2 +- src/UnifiServiceProvider.php | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d973d84..035d5e5 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "dashboard/unifi", "description": "UniFi network management, WiFi stats, and captive portal authentication for the Dashboard platform", - "version": "1.12.0", + "version": "1.12.1", "type": "library", "license": "MIT", "autoload": { diff --git a/src/UnifiServiceProvider.php b/src/UnifiServiceProvider.php index 4edd241..2bbefc6 100644 --- a/src/UnifiServiceProvider.php +++ b/src/UnifiServiceProvider.php @@ -25,6 +25,31 @@ class UnifiServiceProvider extends ServiceProvider $this->loadRoutesFrom(__DIR__ . '/routes/unifi.php'); $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 // any UnifiPageGrant rows, only super-admins and granted users/ // groups can hit it; otherwise (no grants) it's open per the existing