Files
WebHookInspector/app/Livewire/Inspector.php
T

192 lines
5.5 KiB
PHP

<?php
namespace App\Livewire;
use App\Actions\ConfigureWebhookEndpointAction;
use App\Actions\DeleteWebhookRequestAction;
use App\Models\User;
use App\Models\WebhookEndpoint;
use App\Models\WebhookRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
class Inspector extends Component
{
use WithPagination;
#[Locked]
public string $endpointId = '';
#[Url]
public string $search = '';
#[Url]
public string $methodFilter = 'ALL';
#[Url]
public ?string $selectedRequestId = null;
public int $responseStatus = 200;
public string $responseHeadersJson = '{}';
public string $responseBody = '{}';
public bool $responseSaved = false;
public bool $showEndpointSettings = false;
public function mount(WebhookEndpoint $endpoint): void
{
Gate::authorize('view', $endpoint);
$this->endpointId = (string) $endpoint->getKey();
$this->responseStatus = $endpoint->response_status;
$this->responseHeadersJson = json_encode(
$endpoint->response_headers ?? [],
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
) ?: '{}';
$this->responseBody = $endpoint->response_body ?? '{}';
}
/**
* @return array<string, string>
*/
public function getListeners(): array
{
$endpoint = $this->endpoint();
$prefix = $endpoint->is_public ? 'echo' : 'echo-private';
return [
$prefix.':webhooks.'.$this->endpointId.',.webhook.request.received' => 'requestReceived',
];
}
/**
* @param array<string, mixed> $event
*/
public function requestReceived(array $event = []): void
{
if (($event['endpointId'] ?? null) === $this->endpointId) {
$this->resetPage();
}
}
public function updatedSearch(): void
{
$this->resetPage();
}
public function updatedMethodFilter(): void
{
$this->resetPage();
}
public function selectRequest(string $requestId): void
{
$webhookRequest = $this->endpoint()->requests()->findOrFail($requestId);
Gate::authorize('view', $webhookRequest);
$this->selectedRequestId = $webhookRequest->getKey();
}
public function clearSelectedRequest(): void
{
$this->selectedRequestId = null;
}
public function deleteRequest(string $requestId, DeleteWebhookRequestAction $deleteWebhookRequest): void
{
$webhookRequest = $this->endpoint()->requests()->findOrFail($requestId);
$deleteWebhookRequest->handle(Auth::user(), $webhookRequest);
if ($this->selectedRequestId === $requestId) {
$this->selectedRequestId = null;
}
}
public function saveResponse(ConfigureWebhookEndpointAction $configureWebhookEndpoint): void
{
$this->validate([
'responseStatus' => ['required', 'integer', 'between:100,599'],
'responseBody' => ['string'],
'responseHeadersJson' => ['required', 'json'],
]);
$headers = json_decode($this->responseHeadersJson, true);
if (! is_array($headers)) {
throw ValidationException::withMessages([
'responseHeadersJson' => 'Response headers must be a JSON object.',
]);
}
/** @var User|null $user */
$user = Auth::user();
$configureWebhookEndpoint->handle(
$user,
$this->endpoint(),
$this->responseStatus,
$headers,
$this->responseBody,
);
$this->responseSaved = true;
}
public function deleteEndpoint(): void
{
$endpoint = $this->endpoint();
Gate::authorize('delete', $endpoint);
$endpoint->delete();
$this->redirectRoute('home');
}
public function render(): View
{
$endpoint = $this->endpoint();
$requestQuery = $endpoint->requests()
->select(['id', 'method', 'request_uri', 'content_type', 'body_size', 'ip_address', 'received_at'])
->when($this->methodFilter !== 'ALL', fn ($query) => $query->where('method', $this->methodFilter))
->when($this->search !== '', function ($query): void {
$search = '%'.$this->search.'%';
$query->where(function ($query) use ($search): void {
$query->where('request_uri', 'like', $search)
->orWhere('ip_address', 'like', $search)
->orWhere('user_agent', 'like', $search);
});
})
->latest('received_at');
$selectedRequest = null;
if ($this->selectedRequestId !== null) {
$selectedRequest = $endpoint->requests()->find($this->selectedRequestId);
if ($selectedRequest instanceof WebhookRequest) {
Gate::authorize('view', $selectedRequest);
}
}
return view('livewire.inspector', [
'endpoint' => $endpoint,
'webhookRequests' => $requestQuery->paginate((int) config('webhooks.page_size', 25)),
'selectedRequest' => $selectedRequest,
]);
}
private function endpoint(): WebhookEndpoint
{
$endpoint = WebhookEndpoint::query()->findOrFail($this->endpointId);
Gate::authorize('view', $endpoint);
return $endpoint;
}
}