agent === null) { $this->agent = new AgentClient; } return $this->agent; } protected function getUsername(): string { return Auth::user()->username ?? Auth::user()->name ?? 'unknown'; } public function mount(): void { $this->loadDomains(); if (! empty($this->domains)) { $this->selectedDomain = $this->domains[0]['domain'] ?? null; $this->loadProtectedDirectories(); } } protected function loadDomains(): void { $result = $this->getAgent()->send('domain.list', [ 'username' => $this->getUsername(), ]); $this->domains = ($result['success'] ?? false) ? ($result['domains'] ?? []) : []; } public function selectDomain(string $domain): void { $this->selectedDomain = $domain; $this->loadProtectedDirectories(); $this->resetTable(); } public function loadProtectedDirectories(): void { if (! $this->selectedDomain) { $this->protectedDirs = []; return; } $result = $this->getAgent()->send('domain.list_protected_dirs', [ 'domain' => $this->selectedDomain, 'username' => $this->getUsername(), ]); $this->protectedDirs = ($result['success'] ?? false) ? ($result['directories'] ?? []) : []; } public function table(Table $table): Table { return $table ->records(fn () => $this->protectedDirs) ->columns([ TextColumn::make('path') ->label(__('Directory')) ->icon('heroicon-o-folder') ->searchable(), TextColumn::make('name') ->label(__('Protected Area Name')) ->searchable(), TextColumn::make('users_count') ->label(__('Users')) ->badge() ->color('info'), ]) ->actions([ \Filament\Actions\Action::make('manageUsers') ->label(__('Manage Users')) ->icon('heroicon-o-users') ->color('gray') ->modalHeading(fn (array $record): string => __('Manage Users for :path', ['path' => $record['path']])) ->modalWidth('lg') ->form(fn (array $record): array => [ Section::make(__('Current Users')) ->description(__('Users who can access this protected directory.')) ->schema([ \Filament\Schemas\Components\View::make('filament.jabali.components.protected-dir-users') ->viewData(['users' => $record['users'] ?? [], 'path' => $record['path']]), ]), Section::make(__('Add New User')) ->schema([ TextInput::make('new_username') ->label(__('Username')) ->required() ->alphaNum() ->maxLength(32), TextInput::make('new_password') ->label(__('Password')) ->password() ->required() ->minLength(6), ]), ]) ->action(function (array $data, array $record): void { if (empty($data['new_username']) || empty($data['new_password'])) { return; } $result = $this->getAgent()->send('domain.add_protected_dir_user', [ 'domain' => $this->selectedDomain, 'username' => $this->getUsername(), 'path' => $record['path'], 'auth_username' => $data['new_username'], 'auth_password' => $data['new_password'], ]); if ($result['success'] ?? false) { Notification::make() ->title(__('User added')) ->success() ->send(); $this->loadProtectedDirectories(); $this->resetTable(); } else { Notification::make() ->title(__('Failed to add user')) ->body($result['error'] ?? __('Unknown error')) ->danger() ->send(); } }), \Filament\Actions\Action::make('remove') ->label(__('Remove Protection')) ->icon('heroicon-o-lock-open') ->color('danger') ->requiresConfirmation() ->modalHeading(__('Remove Directory Protection')) ->modalDescription(fn (array $record): string => __('Are you sure you want to remove password protection from ":path"? Anyone will be able to access this directory.', ['path' => $record['path']])) ->action(function (array $record): void { $result = $this->getAgent()->send('domain.remove_protected_dir', [ 'domain' => $this->selectedDomain, 'username' => $this->getUsername(), 'path' => $record['path'], ]); if ($result['success'] ?? false) { Notification::make() ->title(__('Protection removed')) ->body(__('Directory ":path" is no longer password protected.', ['path' => $record['path']])) ->success() ->send(); $this->loadProtectedDirectories(); $this->resetTable(); } else { Notification::make() ->title(__('Failed to remove protection')) ->body($result['error'] ?? __('Unknown error')) ->danger() ->send(); } }), ]) ->emptyStateHeading(__('No protected directories')) ->emptyStateDescription(__('Add password protection to directories to restrict access.')) ->emptyStateIcon('heroicon-o-lock-open') ->striped(); } protected function getHeaderActions(): array { return [ $this->addProtectionAction(), ]; } protected function addProtectionAction(): Action { return Action::make('addProtection') ->label(__('Protect Directory')) ->icon('heroicon-o-lock-closed') ->color('primary') ->visible(fn () => $this->selectedDomain !== null) ->modalHeading(__('Protect a Directory')) ->modalDescription(__('Add password protection to a directory. Users will need to enter a username and password to access it.')) ->form([ TextInput::make('path') ->label(__('Directory Path')) ->placeholder('/admin') ->required() ->helperText(__('Path relative to your document root (e.g., /admin, /private, /members)')), TextInput::make('name') ->label(__('Protected Area Name')) ->placeholder(__('Restricted Area')) ->required() ->maxLength(100) ->helperText(__('This name will be shown in the browser login prompt.')), TextInput::make('auth_username') ->label(__('Username')) ->required() ->alphaNum() ->maxLength(32) ->helperText(__('Username for accessing the protected directory.')), TextInput::make('auth_password') ->label(__('Password')) ->password() ->required() ->minLength(6) ->helperText(__('Password for the user. Minimum 6 characters.')), ]) ->action(function (array $data): void { // Normalize path $path = '/'.ltrim(trim($data['path']), '/'); $result = $this->getAgent()->send('domain.add_protected_dir', [ 'domain' => $this->selectedDomain, 'username' => $this->getUsername(), 'path' => $path, 'name' => $data['name'], 'auth_username' => $data['auth_username'], 'auth_password' => $data['auth_password'], ]); if ($result['success'] ?? false) { Notification::make() ->title(__('Directory protected')) ->body(__('Password protection has been added to ":path".', ['path' => $path])) ->success() ->send(); $this->loadProtectedDirectories(); $this->resetTable(); } else { Notification::make() ->title(__('Failed to protect directory')) ->body($result['error'] ?? __('Unknown error')) ->danger() ->send(); } }); } public function deleteProtectedDirUser(string $path, string $authUsername): void { $result = $this->getAgent()->send('domain.remove_protected_dir_user', [ 'domain' => $this->selectedDomain, 'username' => $this->getUsername(), 'path' => $path, 'auth_username' => $authUsername, ]); if ($result['success'] ?? false) { Notification::make() ->title(__('User removed')) ->success() ->send(); $this->loadProtectedDirectories(); $this->resetTable(); } else { Notification::make() ->title(__('Failed to remove user')) ->body($result['error'] ?? __('Unknown error')) ->danger() ->send(); } } }