feat: add user impersonation service

This commit is contained in:
idevakk
2025-11-17 10:44:19 -08:00
parent f60c986e07
commit a7029b5f57
21 changed files with 1343 additions and 6 deletions

View File

@@ -9,7 +9,9 @@ use App\Filament\Resources\UserResource\Pages\ListUsers;
use App\Filament\Resources\UserResource\RelationManagers\LogsRelationManager;
use App\Filament\Resources\UserResource\RelationManagers\UsageLogsRelationManager;
use App\Models\User;
use App\Services\ImpersonationService;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
@@ -49,6 +51,12 @@ class UserResource extends Resource
->email()
->required()
->maxLength(255),
TextInput::make('password')
->password()
->required()
->minLength(6)
->maxLength(255)
->visibleOn('create'),
TextInput::make('email_verified_at')
->label('Email Verification Status')
->disabled()
@@ -149,8 +157,65 @@ class UserResource extends Resource
])
->recordActions([
EditAction::make(),
Action::make('impersonate')
->label('Login as User')
->icon('heroicon-o-arrow-right-on-rectangle')
->color('warning')
->requiresConfirmation()
->modalHeading('Start User Impersonation')
->modalDescription('This will open a new tab where you will be logged in as this user. All actions will be logged for security. Your admin panel will remain open in this tab.')
->modalSubmitActionLabel('Start Impersonation')
->modalCancelActionLabel('Cancel')
->visible(fn (User $record): bool => auth()->user()?->isSuperAdmin() &&
$record->isNormalUser() &&
! app(ImpersonationService::class)->isImpersonating()
)
->url(function (User $record): string {
$admin = auth()->user();
$impersonationService = app(ImpersonationService::class);
if (! $impersonationService->canImpersonate($admin, $record)) {
Notification::make()
->title('Impersonation Failed')
->body('Unable to start impersonation. Please check permissions and try again.')
->danger()
->send();
return '#';
}
// Return impersonation URL
return route('impersonation.start', $record);
})
->openUrlInNewTab(),
])
->toolbarActions([
Action::make('stopImpersonation')
->label('Stop Impersonating')
->icon('heroicon-o-arrow-left-on-rectangle')
->color('danger')
->visible(fn (): bool => app(ImpersonationService::class)->isImpersonating())
->action(function () {
$impersonationService = app(ImpersonationService::class);
if (! $impersonationService->stopImpersonation(request())) {
Notification::make()
->title('Failed to Stop Impersonation')
->body('Unable to stop impersonation session.')
->danger()
->send();
return;
}
Notification::make()
->title('Impersonation Ended')
->body('You have been returned to your admin account.')
->success()
->send();
return redirect()->to(\Filament\Pages\Dashboard::getUrl());
}),
BulkActionGroup::make([
DeleteBulkAction::make(),
BulkAction::make('updateLevel')