kgalanos/filament-user
Filament User is a Laravel package for adding user management to Filament admin panels. It provides ready-made resources and profile tools for creating, editing, and managing user accounts, helping developers ship common admin user workflows with less boilerplate.
This package bundles four Filament plugins into a single install: filament-export, filament-impersonate, spatie/laravel-permission, and filament-shield. In practice you're getting an admin panel with table exports, user impersonation, and a full role/permission layer wired into Filament's authorization.
First steps after composer require:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
php artisan shield:install admin
php artisan shield:generate --all
User model:
use STS\FilamentImpersonate\Concerns\Impersonatable;
class User extends Authenticatable implements FilamentUser
{
use Impersonatable;
}
Look first at config/filament-shield.php — it controls the super-admin gate, permission naming, and which entities get generated. That file determines almost everything you'll debug later.
Your first useful use case: a UserResource with a roles Select field, ImpersonateAction in the table row actions, and ExportAction in the header. That single screen exercises all four plugins and is the fastest way to confirm the wiring works.
Gate everything through Shield-generated policies. Don't hand-write canViewAny() on resources. Let shield:generate --all produce policies, then attach roles in a seeder:
$admin = Role::create(['name' => 'admin']);
$admin->givePermissionTo(Permission::all());
$editor = Role::create(['name' => 'editor']);
$editor->givePermissionTo(['view_any_user', 'view_user']);
Re-run shield:generate --all any time you add a resource, page, or widget. Treat it as part of your resource scaffolding checklist.
Pair exports with permissions rather than hiding them ad hoc. Export actions respect the resource policy, but if you expose a custom bulk export, gate it explicitly:
Tables\Actions\BulkAction::make('export')
->visible(fn () => auth()->user()->can('view_any_order'))
Prefer queued exports for anything user-facing at scale. filament-export supports queued exports; for tables over a few thousand rows, configure the queue connection so the request doesn't time out. Define explicit ExportColumns instead of exporting the whole model — it keeps memory flat and avoids leaking sensitive columns:
ExportColumn::make('email'),
ExportColumn::make('roles.name')->label('Roles'),
Scope impersonation tightly. Add ImpersonateAction only to resources where it makes sense, and guard it with its own permission rather than leaving it available to every admin:
ImpersonateAction::make()->visible(fn () => auth()->user()->hasRole('super_admin'))
Log impersonation start/stop via the plugin's events if you're in a regulated environment.
Combine the pieces into a coherent workflow. A typical day-to-day pattern: Shield gates the resource → the resource's table has an export action → a super-admin can impersonate a problematic user from the same table to reproduce their view. Document that chain for your team; it's the reason these four packages ship together.
php artisan permission:cache-reset (or cache:forget spatie.permission.cache) after seeding or changing roles in tinker.shield:generate --all overwrites existing policies unless you pass --ignore-existing-policies. Commit your policies and review the diff after each run.filament-impersonate.guard in config. Also confirm Filament::auth() resolves the same guard, or impersonation silently redirects to login.ExportColumn definitions and enable queuing (->queue()), and check the failed-jobs table for silently dropped exports.shield:generate → seed roles. Running the seeder before migration is a common CI failure.php artisan shield:generate --all --panel=admin plus dumping Permission::pluck('name') in tinker tells you instantly whether the problem is generation, caching, or policy resolution.How can I help you explore Laravel packages today?