How to apply Laravel Policy to Filament Actions (Export/Import/Custom Actions)?

Hi everyone šŸ‘‹ I'm using FilamentPHP and trying to integrate Laravel Policies into my actions, both default (like Export/Import) and custom ones (like a PublishPost action on a PostResource). --- šŸ”’ Use Case 1: Export / Import Authorization (resource-wide) I want to: * Control visibility of ExportAction and ImportAction using policy * Prevent execution if user is unauthorized In my PostPolicy I have:
public function export(User $user): bool
{
return $user->hasRole('admin');
}

public function import(User $user): bool
{
return $user->hasRole('editor');
}
public function export(User $user): bool
{
return $user->hasRole('admin');
}

public function import(User $user): bool
{
return $user->hasRole('editor');
}
Then in my PostResource, I attach:
use Filament\Actions\ExportAction;
use Filament\Actions\ImportAction;

public static function table(Table $table): Table
{
return $table
->headerActions([
ExportAction::make()
->visible(fn () => auth()->user()->can('export', Post::class))
->authorize(fn () => auth()->user()->can('export', Post::class)),

ImportAction::make()
->visible(fn () => auth()->user()->can('import', Post::class))
->authorize(fn () => auth()->user()->can('import', Post::class)),
]);
}
use Filament\Actions\ExportAction;
use Filament\Actions\ImportAction;

public static function table(Table $table): Table
{
return $table
->headerActions([
ExportAction::make()
->visible(fn () => auth()->user()->can('export', Post::class))
->authorize(fn () => auth()->user()->can('export', Post::class)),

ImportAction::make()
->visible(fn () => auth()->user()->can('import', Post::class))
->authorize(fn () => auth()->user()->can('import', Post::class)),
]);
}
Is this the correct way? Or is there a more idiomatic "Filament way" to handle this?
5 Replies
Kaesa Lyrih
Kaesa LyrihOP•4mo ago
🧩 Use Case 2: Custom action with per-record policy I also have a custom PublishAction where I want to only allow certain users (e.g., editors) to publish certain posts. In PostPolicy I added:
public function publish(User $user, Post $post): bool
{
return $user->id === $post->author_id || $user->hasRole('editor');
}
public function publish(User $user, Post $post): bool
{
return $user->id === $post->author_id || $user->hasRole('editor');
}
And in my PostResource:
use Filament\Tables\Actions\Action;

Action::make('publish')
->action(fn (Post $record) => $record->update(['status' => 'published']))
->visible(fn (Post $record) => auth()->user()->can('publish', $record))
->authorize(fn (Post $record) => auth()->user()->can('publish', $record))
use Filament\Tables\Actions\Action;

Action::make('publish')
->action(fn (Post $record) => $record->update(['status' => 'published']))
->visible(fn (Post $record) => auth()->user()->can('publish', $record))
->authorize(fn (Post $record) => auth()->user()->can('publish', $record))
--- ā“ Questions * Is using ->authorize() and ->visible() like this the recommended way in Filament? * Can Filament auto-detect Laravel policy methods like export, import, or publish? * Is there a more elegant/built-in solution I'm missing? Thanks in advance — any guidance is much appreciated! šŸ™
toeknee
toeknee•4mo ago
Looks good to me, we use canView and canViewAny for access etc and you want to refine them with certain control over the actions which is does well.
Kaesa Lyrih
Kaesa LyrihOP•4mo ago
canViewAny() maybe for export, import need authorized create policy.
Kaesa Lyrih
Kaesa LyrihOP•4mo ago
šŸ“ Use Case 3: Import Failure CSV Authorization via ImportPolicy https://filamentphp.com/docs/4.x/actions/import#authorization I read the docs on customizing access to the failure CSV file for import errors.
By default, only the user who started the import may access the failure CSV. To override this, define your own ImportPolicy and register it in AuthServiceProvider.
I created:
use App\Models\User;
use Filament\Actions\Imports\Models\Import;

public function view(User $user, Import $import): bool
{
// Re-implement default behavior
return $import->user()->is($user);
}
use App\Models\User;
use Filament\Actions\Imports\Models\Import;

public function view(User $user, Import $import): bool
{
// Re-implement default behavior
return $import->user()->is($user);
}
And registered it:
use App\Policies\ImportPolicy;
use Filament\Actions\Imports\Models\Import;

protected $policies = [
Import::class => ImportPolicy::class,
];
use App\Policies\ImportPolicy;
use Filament\Actions\Imports\Models\Import;

protected $policies = [
Import::class => ImportPolicy::class,
];
🧠 Question: Can I make the ImportPolicy apply per resource (e.g. different rules for PostImport, UserImport)? Right now it seems to be a single global Import model — is there a clean way to scope this behavior?
toeknee
toeknee•4mo ago
Not as far as I am aware.

Did you find this page helpful?