query(Domain::query()->where('user_id', Auth::id())) ->columns([ TextColumn::make('domain') ->label(__('Domain')) ->searchable() ->sortable(), IconColumn::make('cloudflare') ->label(__('Cloudflare')) ->boolean() ->state(fn (Domain $record) => $this->getZone($record) !== null) ->trueColor('success') ->falseColor('gray'), ]) ->recordActions([ Action::make('connect') ->label(__('Connect')) ->icon('heroicon-o-link') ->color('primary') ->visible(fn (Domain $record) => $this->getZone($record) === null) ->form([ TextInput::make('api_token') ->label(__('Cloudflare API Token')) ->password() ->revealable() ->required(), ]) ->action(function (Domain $record, array $data): void { $token = $data['api_token']; try { $zone = $this->fetchCloudflareZone($record->domain, $token); CloudflareZone::updateOrCreate( [ 'user_id' => Auth::id(), 'domain_id' => $record->id, ], [ 'zone_id' => $zone['id'], 'account_id' => $zone['account']['id'] ?? null, 'api_token' => $token, ] ); Notification::make()->title(__('Cloudflare connected'))->success()->send(); } catch (Exception $e) { Notification::make()->title(__('Connection failed'))->body($e->getMessage())->danger()->send(); } }), Action::make('purge') ->label(__('Purge Cache')) ->icon('heroicon-o-arrow-path') ->color('warning') ->visible(fn (Domain $record) => $this->getZone($record) !== null) ->requiresConfirmation() ->action(function (Domain $record): void { $zone = $this->getZone($record); if (! $zone) { return; } try { $response = Http::withToken($zone->api_token) ->post("https://api.cloudflare.com/client/v4/zones/{$zone->zone_id}/purge_cache", [ 'purge_everything' => true, ]); if (! ($response->json('success') ?? false)) { throw new Exception($response->json('errors.0.message') ?? 'Cloudflare request failed'); } Notification::make()->title(__('Cache purged'))->success()->send(); } catch (Exception $e) { Notification::make()->title(__('Purge failed'))->body($e->getMessage())->danger()->send(); } }), Action::make('disconnect') ->label(__('Disconnect')) ->icon('heroicon-o-x-mark') ->color('gray') ->visible(fn (Domain $record) => $this->getZone($record) !== null) ->requiresConfirmation() ->action(function (Domain $record): void { $zone = $this->getZone($record); if ($zone) { $zone->delete(); } Notification::make()->title(__('Cloudflare disconnected'))->success()->send(); }), ]) ->emptyStateHeading(__('No domains found')) ->emptyStateDescription(__('Add a domain before connecting to a CDN')); } protected function getZone(Domain $record): ?CloudflareZone { return CloudflareZone::query() ->where('user_id', Auth::id()) ->where('domain_id', $record->id) ->first(); } protected function fetchCloudflareZone(string $domain, string $token): array { $response = Http::withToken($token)->get('https://api.cloudflare.com/client/v4/zones', [ 'name' => $domain, ]); if (! ($response->json('success') ?? false)) { throw new Exception($response->json('errors.0.message') ?? 'Cloudflare request failed'); } $zone = $response->json('result.0'); if (! $zone) { throw new Exception(__('Zone not found for :domain', ['domain' => $domain])); } return $zone; } }