Hide all resources depending on user

Is there a quick way to revoke all access to resources if for example, the current logged in user does not have in_admin:1 on their model? I currently 'hide' them by doing the following in my AppServiceProvider, essentially rendering an empty nav: view()->composer('*', function ($view) { if (!auth()->user()->is_admin) { Filament::navigation(function (NavigationBuilder $builder): NavigationBuilder { return $builder; }); } }); However, if I navigate to /posts, I will still be able to access the resource anyway. I guess what I'm asking is how can I do this without creating a policy for every one of my models, and have some sort of global gate that wraps around resources somewhere to check the user state. Posted this on the Github Discussions, but haven't had a response. Cheers all https://github.com/filamentphp/filament/discussions/6983
8 Replies
jgreco
jgreco2y ago
Not sure of a way to handle this from a Provider, but I've done this within the Resource files (ex. UserResource.php):
public static function canViewAny(): bool
{
return auth()->user()->is_admin;
}
public static function canViewAny(): bool
{
return auth()->user()->is_admin;
}
when the viewAny permission is false, the entire resource is disabled. Then you don't have to create all of the model policies
Josh777
Josh777OP2y ago
Wouldn't I have to repeat the same logic on every resource though?
jgreco
jgreco2y ago
Correct. You could put this method in a trait and re-use it, if you wanted. If, for some reason, you absolutely must manage this from a Provider, maybe something like this might work?
Filament::serving(function () {

$resources = collect(Filament::getResources())->filter(function ($resource) {
return !str($resource)->contains('TeamResource');
})->toArray();
Filament::registerResources($resources);
Filament::serving(function () {

$resources = collect(Filament::getResources())->filter(function ($resource) {
return !str($resource)->contains('TeamResource');
})->toArray();
Filament::registerResources($resources);
adjust the logic within the filter method. I haven't tested this, but in theory it might do what you need
benshawuk
benshawuk2y ago
Filament
Users - Admin Panel - Filament
The elegant TALL stack admin panel for Laravel artisans.
Josh777
Josh777OP2y ago
@benshawuk I still want them to be able to login and access the dashboard
benshawuk
benshawuk2y ago
Ah, right. I used the Filament Shield plugin for this. (If users don't have permission to a model, the link doesn't show up in the navigation sidebar).
Josh777
Josh777OP2y ago
Yeah that's essentially describing a policy though, which is what I was aiming to avoid, but think I'll just bite the bullet for now
benshawuk
benshawuk2y ago
OK, well you could hard code it on the resource itself? shouldRegisterNavigation() (takes care of the navigation) Also, it's quite hacky but I worked around it like this (though it feels wrong to put this in the query builder, it does work as a safety net, to stop access via the direct URL):
public static function getEloquentQuery(): Builder
{
// Deny access if user does not have "view any" access to "All Users" resource
if (!auth()->user()->hasPermissionTo('view_any_all::user')) {
abort(403);
}
public static function getEloquentQuery(): Builder
{
// Deny access if user does not have "view any" access to "All Users" resource
if (!auth()->user()->hasPermissionTo('view_any_all::user')) {
abort(403);
}

Did you find this page helpful?