diff --git a/composer.json b/composer.json index 586b980..08550f1 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.5.1", + "version": "1.5.2", "type": "library", "license": "MIT", "autoload": { diff --git a/src/Http/Controllers/UnifiPagesAccessController.php b/src/Http/Controllers/UnifiPagesAccessController.php index 3268164..3674d3f 100644 --- a/src/Http/Controllers/UnifiPagesAccessController.php +++ b/src/Http/Controllers/UnifiPagesAccessController.php @@ -34,6 +34,12 @@ class UnifiPagesAccessController extends Controller ->get() ->groupBy('nav_item_id'); + // Only return users that ALREADY have grants. The full users list + // can be enormous (thousands of rows); the operator adds more via + // the searchUsers endpoint as needed. + $grantedUserIds = $grants->flatten(1)->where('grantee_type', 'user')->pluck('grantee_id')->unique(); + $users = User::whereIn('id', $grantedUserIds)->orderBy('name')->get(['id', 'name', 'email']); + return response()->json([ 'pages' => $pages->map(fn ($p) => [ 'id' => $p->id, @@ -42,11 +48,34 @@ class UnifiPagesAccessController extends Controller 'user_ids' => $grants->get($p->id, collect())->where('grantee_type', 'user')->pluck('grantee_id')->all(), 'group_ids' => $grants->get($p->id, collect())->where('grantee_type', 'group')->pluck('grantee_id')->all(), ])->values(), - 'users' => User::orderBy('name')->get(['id', 'name', 'email']), + 'users' => $users, 'groups' => Group::orderBy('name')->get(['id', 'name', 'is_super']), ]); } + /** + * Typeahead-style search for users to add to the access matrix. + * Returns up to 20 matches against name or email. Empty query returns + * an empty array — caller must enter at least 2 chars. + */ + public function searchUsers(Request $request) + { + $q = trim((string) $request->query('q', '')); + if (strlen($q) < 2) { + return response()->json(['users' => []]); + } + + $users = User::where(function ($w) use ($q) { + $w->where('name', 'like', '%' . $q . '%') + ->orWhere('email', 'like', '%' . $q . '%'); + }) + ->orderBy('name') + ->limit(20) + ->get(['id', 'name', 'email']); + + return response()->json(['users' => $users]); + } + public function update(Request $request, NavItem $navItem) { $app = DashboardApp::where('slug', 'unifi')->first(); diff --git a/src/routes/unifi.php b/src/routes/unifi.php index 8ca4e35..2829fca 100644 --- a/src/routes/unifi.php +++ b/src/routes/unifi.php @@ -75,8 +75,9 @@ Route::middleware(['web', 'auth', 'app.access:unifi']) // Page Access — super-admin only. Lists unifi pages and lets // operators assign per-page user/group grants. Route::middleware('super.admin')->group(function () { - Route::get('/settings/pages-access', [UnifiPagesAccessController::class, 'index']) ->name('settings.pages-access.index'); - Route::put('/settings/pages-access/{navItem}', [UnifiPagesAccessController::class, 'update']) ->name('settings.pages-access.update'); + Route::get('/settings/pages-access', [UnifiPagesAccessController::class, 'index']) ->name('settings.pages-access.index'); + Route::get('/settings/pages-access/users/search', [UnifiPagesAccessController::class, 'searchUsers'])->name('settings.pages-access.users.search'); + Route::put('/settings/pages-access/{navItem}', [UnifiPagesAccessController::class, 'update']) ->name('settings.pages-access.update'); }); // Cron logs — read-only history of scheduled-task runs.