X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/3b31ac75ec41b3990cea770a9e48e2066bd8e9a3..refs/pull/5685/head:/app/Activity/DispatchWebhookJob.php diff --git a/app/Activity/DispatchWebhookJob.php b/app/Activity/DispatchWebhookJob.php index 5e6380f43..e1771b114 100644 --- a/app/Activity/DispatchWebhookJob.php +++ b/app/Activity/DispatchWebhookJob.php @@ -6,14 +6,15 @@ use BookStack\Activity\Models\Loggable; use BookStack\Activity\Models\Webhook; use BookStack\Activity\Tools\WebhookFormatter; use BookStack\Facades\Theme; +use BookStack\Http\HttpRequestService; use BookStack\Theming\ThemeEvents; use BookStack\Users\Models\User; +use BookStack\Util\SsrUrlValidator; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; class DispatchWebhookJob implements ShouldQueue @@ -24,27 +25,23 @@ class DispatchWebhookJob implements ShouldQueue use SerializesModels; protected Webhook $webhook; - protected string $event; protected User $initiator; protected int $initiatedTime; - - /** - * @var string|Loggable - */ - protected $detail; + protected array $webhookData; /** * Create a new job instance. * * @return void */ - public function __construct(Webhook $webhook, string $event, $detail) + public function __construct(Webhook $webhook, string $event, Loggable|string $detail) { $this->webhook = $webhook; - $this->event = $event; - $this->detail = $detail; $this->initiator = user(); $this->initiatedTime = time(); + + $themeResponse = Theme::dispatch(ThemeEvents::WEBHOOK_CALL_BEFORE, $event, $this->webhook, $detail, $this->initiator, $this->initiatedTime); + $this->webhookData = $themeResponse ?? WebhookFormatter::getDefault($event, $this->webhook, $detail, $this->initiator, $this->initiatedTime)->format(); } /** @@ -52,25 +49,28 @@ class DispatchWebhookJob implements ShouldQueue * * @return void */ - public function handle() + public function handle(HttpRequestService $http) { - $themeResponse = Theme::dispatch(ThemeEvents::WEBHOOK_CALL_BEFORE, $this->event, $this->webhook, $this->detail, $this->initiator, $this->initiatedTime); - $webhookData = $themeResponse ?? WebhookFormatter::getDefault($this->event, $this->webhook, $this->detail, $this->initiator, $this->initiatedTime)->format(); $lastError = null; try { - $response = Http::asJson() - ->withOptions(['allow_redirects' => ['strict' => true]]) - ->timeout($this->webhook->timeout) - ->post($this->webhook->endpoint, $webhookData); - } catch (\Exception $exception) { - $lastError = $exception->getMessage(); - Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with error \"{$lastError}\""); - } + (new SsrUrlValidator())->ensureAllowed($this->webhook->endpoint); + + $client = $http->buildClient($this->webhook->timeout, [ + 'connect_timeout' => 10, + 'allow_redirects' => ['strict' => true], + ]); - if (isset($response) && $response->failed()) { - $lastError = "Response status from endpoint was {$response->status()}"; - Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with status {$response->status()}"); + $response = $client->sendRequest($http->jsonRequest('POST', $this->webhook->endpoint, $this->webhookData)); + $statusCode = $response->getStatusCode(); + + if ($statusCode >= 400) { + $lastError = "Response status from endpoint was {$statusCode}"; + Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with status {$statusCode}"); + } + } catch (\Exception $error) { + $lastError = $error->getMessage(); + Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with error \"{$lastError}\""); } $this->webhook->last_called_at = now();