feat(access): only return granted users; add search endpoint
Listing every user in the system on the access page didn't scale —
schools have thousands of user rows. Now:
- index() only returns users that already have a UnifiPageGrant
somewhere. Groups stay fully listed (few of them).
- new searchUsers(q) endpoint returns up to 20 typeahead matches
against name or email (min 2 chars).
v1.5.2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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": {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -76,6 +76,7 @@ Route::middleware(['web', 'auth', 'app.access:unifi'])
|
||||
// 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::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');
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user