diff --git a/app-modules/user/src/Filament/Admin/Resources/Users/Tables/UsersTable.php b/app-modules/user/src/Filament/Admin/Resources/Users/Tables/UsersTable.php index 14a664cd..d0f26b97 100644 --- a/app-modules/user/src/Filament/Admin/Resources/Users/Tables/UsersTable.php +++ b/app-modules/user/src/Filament/Admin/Resources/Users/Tables/UsersTable.php @@ -10,6 +10,8 @@ use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Table; +use He4rt\User\Models\User; +use STS\FilamentImpersonate\Actions\Impersonate; class UsersTable { @@ -31,6 +33,13 @@ public static function configure(Table $table): Table ]) ->recordActions([ EditAction::make(), + Impersonate::make() + ->visible(fn (User $record) => (bool) $record->character?->tenant?->slug) + ->redirectTo(function (User $record): string { + $tenantName = $record->character?->tenant?->slug; + + return '/app/'.$tenantName; + }), ]) ->toolbarActions([ BulkActionGroup::make([ diff --git a/app-modules/user/src/Filament/User/Pages/Dashboard.php b/app-modules/user/src/Filament/User/Pages/UserDashboard.php similarity index 88% rename from app-modules/user/src/Filament/User/Pages/Dashboard.php rename to app-modules/user/src/Filament/User/Pages/UserDashboard.php index 488536c6..6aee903c 100644 --- a/app-modules/user/src/Filament/User/Pages/Dashboard.php +++ b/app-modules/user/src/Filament/User/Pages/UserDashboard.php @@ -9,7 +9,7 @@ use He4rt\Tenant\Models\Tenant; use Livewire\Attributes\Computed; -class Dashboard extends FilamentDashboard +class UserDashboard extends FilamentDashboard { protected string $view = 'users::filament.app-dashboard'; @@ -25,6 +25,6 @@ public function mount(): void #[Computed] public function stats() { - return auth()->user()->character()->where('tenant_id', '=', $this->tenant->getKey())->first(); + return auth()->user()->character()->where('tenant_id', '=', $this->tenant?->getKey())->first(); } } diff --git a/app-modules/user/src/Plugins/AppUserPanelPlugin.php b/app-modules/user/src/Plugins/AppUserPanelPlugin.php index 99c1f0aa..7da1895c 100644 --- a/app-modules/user/src/Plugins/AppUserPanelPlugin.php +++ b/app-modules/user/src/Plugins/AppUserPanelPlugin.php @@ -8,7 +8,7 @@ use Filament\Contracts\Plugin; use Filament\Panel; use He4rt\Events\Filament\App\EventModels\Widgets\LatestEvents; -use He4rt\User\Filament\User\Pages\Dashboard; +use He4rt\User\Filament\User\Pages\UserDashboard; use He4rt\User\Filament\User\Pages\UserProfile; class AppUserPanelPlugin implements Plugin @@ -22,7 +22,7 @@ public function register(Panel $panel): void { $panel->pages([ UserProfile::class, - Dashboard::class, + UserDashboard::class, ]); $panel->widgets([ LatestEvents::class, diff --git a/app-modules/user/tests/Feature/Filament/Admin/Resources/User/ListUsersTest.php b/app-modules/user/tests/Feature/Filament/Admin/Resources/User/ListUsersTest.php index 478fb3c4..a08dbab2 100644 --- a/app-modules/user/tests/Feature/Filament/Admin/Resources/User/ListUsersTest.php +++ b/app-modules/user/tests/Feature/Filament/Admin/Resources/User/ListUsersTest.php @@ -7,7 +7,8 @@ it('renders the list of users', function (): void { $users = User::factory()->count(5)->create(); - + $admin = User::factory()->create(); + $this->actingAs($admin); $this->livewire(ListUsers::class) ->assertOk() ->assertCanSeeTableRecords($users); diff --git a/app-modules/user/tests/Feature/Filament/App/Pages/DashboardPageTest.php b/app-modules/user/tests/Feature/Filament/App/Pages/DashboardPageTest.php index 048db596..7b76e066 100644 --- a/app-modules/user/tests/Feature/Filament/App/Pages/DashboardPageTest.php +++ b/app-modules/user/tests/Feature/Filament/App/Pages/DashboardPageTest.php @@ -7,7 +7,7 @@ use He4rt\Events\Models\EventModel; use He4rt\Season\Models\Season; use He4rt\Tenant\Models\Tenant; -use He4rt\User\Filament\User\Pages\Dashboard; +use He4rt\User\Filament\User\Pages\UserDashboard; use He4rt\User\Models\User; use Illuminate\Support\Facades\Date; @@ -43,14 +43,14 @@ }); it('should render', function (): void { - livewire(Dashboard::class) + livewire(UserDashboard::class) ->assertOk(); }); it('should be able to see user experience/stats', function (): void { $nextLevelXp = $this->character->percentageExperience + $this->character->experience; - livewire(Dashboard::class) + livewire(UserDashboard::class) ->assertOk() ->assertSeeTextInOrder(['Level', $this->character->level]) ->assertSeeTextInOrder(['Reputation', $this->character->reputation]) @@ -60,7 +60,7 @@ it('should be able to see events details', function (): void { $this->events->each(function (EventModel $event): void { - livewire(Dashboard::class) + livewire(UserDashboard::class) ->assertOk() ->assertSeeText($event->title) ->assertSeeText(Date::parse($event->starts_at)->format('d/m/Y H:i')) diff --git a/app/Providers/Filament/UserPanelProvider.php b/app/Providers/Filament/UserPanelProvider.php index ac1d708b..21213dd8 100644 --- a/app/Providers/Filament/UserPanelProvider.php +++ b/app/Providers/Filament/UserPanelProvider.php @@ -14,7 +14,6 @@ use Filament\PanelProvider; use Filament\Support\Colors\Color; use He4rt\Tenant\Models\Tenant; -use He4rt\User\Filament\User\Pages\Dashboard; use He4rt\User\Filament\User\Pages\UserProfile; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Cookie\Middleware\EncryptCookies; @@ -47,9 +46,6 @@ public function panel(Panel $panel): Panel ]) ->discoverResources(in: app_path('Filament/Resources'), for: 'App\Filament\Resources') ->discoverPages(in: app_path('Filament/Pages'), for: 'App\Filament\Pages') - ->pages([ - Dashboard::class, - ]) ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\Filament\Widgets') ->middleware([ EncryptCookies::class, diff --git a/composer.json b/composer.json index eeab3259..f13ec580 100644 --- a/composer.json +++ b/composer.json @@ -46,6 +46,7 @@ "predis/predis": "^2.4.1", "ryangjchandler/commonmark-blade-block": "^1.1", "spatie/laravel-medialibrary": "^11.17.5", + "stechstudio/filament-impersonate": "^4.0", "symfony/browser-kit": "v7.0.8", "torchlight/torchlight-commonmark": "^0.6.0", "torchlight/torchlight-laravel": "^0.6.1" diff --git a/composer.lock b/composer.lock index c5442800..71805d44 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ee344901251f841ca3c1dbc4dc0ddd66", + "content-hash": "696762fb4f67de6fdfa95c6fce4681f5", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -3876,6 +3876,73 @@ }, "time": "2025-11-13T14:57:49+00:00" }, + { + "name": "lab404/laravel-impersonate", + "version": "1.7.7", + "source": { + "type": "git", + "url": "https://github.com/404labfr/laravel-impersonate.git", + "reference": "5033f3433a55ca8bb2cc3e4a018a39dd8a327a9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/404labfr/laravel-impersonate/zipball/5033f3433a55ca8bb2cc3e4a018a39dd8a327a9f", + "reference": "5033f3433a55ca8bb2cc3e4a018a39dd8a327a9f", + "shasum": "" + }, + "require": { + "laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", + "php": "^7.2 | ^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "orchestra/testbench": "^4.0 | ^5.0 | ^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0", + "phpunit/phpunit": "^7.5 | ^8.0 | ^9.0 | ^10.0 | ^11.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Lab404\\Impersonate\\ImpersonateServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Lab404\\Impersonate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marceau Casals", + "email": "marceau@casals.fr" + } + ], + "description": "Laravel Impersonate is a plugin that allows to you to authenticate as your users.", + "keywords": [ + "auth", + "impersonate", + "impersonation", + "laravel", + "laravel-package", + "laravel-plugin", + "package", + "plugin", + "user" + ], + "support": { + "issues": "https://github.com/404labfr/laravel-impersonate/issues", + "source": "https://github.com/404labfr/laravel-impersonate/tree/1.7.7" + }, + "time": "2025-02-24T16:18:38+00:00" + }, { "name": "laracord/framework", "version": "dev-next", @@ -9611,6 +9678,48 @@ ], "time": "2025-01-13T13:04:43+00:00" }, + { + "name": "stechstudio/filament-impersonate", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/stechstudio/filament-impersonate.git", + "reference": "4467c97308210f1a2c7bd8c4511bc6f976dd16e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stechstudio/filament-impersonate/zipball/4467c97308210f1a2c7bd8c4511bc6f976dd16e9", + "reference": "4467c97308210f1a2c7bd8c4511bc6f976dd16e9", + "shasum": "" + }, + "require": { + "filament/filament": "^4.0", + "lab404/laravel-impersonate": "^1.7" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "STS\\FilamentImpersonate\\FilamentImpersonateServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "STS\\FilamentImpersonate\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A Filament package to impersonate your users.", + "support": { + "issues": "https://github.com/stechstudio/filament-impersonate/issues", + "source": "https://github.com/stechstudio/filament-impersonate/tree/4.0.1" + }, + "time": "2025-08-13T20:47:08+00:00" + }, { "name": "symfony/browser-kit", "version": "v7.0.8", @@ -17449,6 +17558,6 @@ "platform": { "php": "^8.3" }, - "platform-dev": {}, + "platform-dev": [], "plugin-api-version": "2.6.0" } diff --git a/database/seeders/BaseSeeder.php b/database/seeders/BaseSeeder.php index d8dae058..37a2b74c 100644 --- a/database/seeders/BaseSeeder.php +++ b/database/seeders/BaseSeeder.php @@ -50,6 +50,21 @@ public function run(): void ->recycle($tenant) ->createOne(); + User::factory() + ->count(5) + ->create() + ->each(function (User $user, $index) use ($tenant): void { + $idx = $index + 1; + $user->update([ + 'username' => 'fake_user_'.$idx, + 'name' => 'Fake User '.$idx, + ]); + Character::factory()->recycle($user)->recycle($tenant)->create(); + Information::factory()->recycle($user)->create(); + Address::factory()->recycle($user)->create(); + Provider::factory()->recycle($user)->recycle($tenant)->create(); + }); + EventModel::factory() ->withStatus() ->recycle($tenant)