Can now send webhook messages.

This commit is contained in:
James Cole
2020-12-02 19:30:09 +01:00
parent 35c9367819
commit eb80578e30
8 changed files with 162 additions and 7 deletions

View File

@@ -0,0 +1,30 @@
<?php
/*
* RequestedSendWebhookMessages.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Events;
use Illuminate\Queue\SerializesModels;
class RequestedSendWebhookMessages extends Event
{
use SerializesModels;
}

View File

@@ -21,6 +21,8 @@
namespace FireflyIII\Generator\Webhook;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\StoredWebhookMessage;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup;
@@ -93,6 +95,7 @@ class WebhookMessageGenerator
foreach ($this->webhooks as $webhook) {
$this->runWebhook($webhook);
}
event(new RequestedSendWebhookMessages);
}
/**
@@ -166,7 +169,7 @@ class WebhookMessageGenerator
* @param Webhook $webhook
* @param array $message
*/
private function storeMessage(Webhook $webhook, array $message): void
private function storeMessage(Webhook $webhook, array $message): WebhookMessage
{
$webhookMessage = new WebhookMessage;
$webhookMessage->webhook()->associate($webhook);
@@ -176,6 +179,8 @@ class WebhookMessageGenerator
$webhookMessage->message = $message;
$webhookMessage->logs = null;
$webhookMessage->save();
return $webhookMessage;
}

View File

@@ -27,7 +27,6 @@ use FireflyIII\Generator\Webhook\WebhookMessageGenerator;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\TransactionRules\Engine\RuleEngine;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use Illuminate\Support\Collection;
use Log;
@@ -87,8 +86,7 @@ class StoredGroupEventHandler
$engine->setUser($user);
$engine->setTransactionGroups(new Collection([$group]));
$engine->setTrigger(Webhook::TRIGGER_STORE_TRANSACTION);
$messages= $engine->generateMessages();
$engine->generateMessages();
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*
* WebhookEventHandler.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Handlers\Events;
use Exception;
use FireflyIII\Models\WebhookMessage;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use JsonException;
use Log;
/**
* Class WebhookEventHandler
*/
class WebhookEventHandler
{
/**
*
*/
public function sendWebhookMessages(): void
{
$max = (int)config('firefly.webhooks.max_attempts');
$max = 0 === $max ? 3 : $max;
$messages = WebhookMessage::where('sent', 0)
->where('attempts', '<=', $max)
->get();
Log::debug(sprintf('Going to send %d webhook message(s)', $messages->count()));
/** @var WebhookMessage $message */
foreach ($messages as $message) {
$this->sendMessage($message);
}
}
/**
* @param WebhookMessage $message
*/
private function sendMessage(WebhookMessage $message): void
{
Log::debug(sprintf('Trying to send webhook message #%d', $message->id));
try {
$json = json_encode($message->message, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
$message->attempts++;
$message->logs[] = sprintf('%s: %s', date('Y-m-d H:i:s'), sprintf('Json error: %s', $e->getMessage()));
$message->save();
return;
}
$user = $message->webhook->user;
try {
$token = $user->generateAccessToken();
} catch (Exception $e) {
$message->attempts++;
$message->logs[] = sprintf('%s: %s', date('Y-m-d H:i:s'), sprintf('Could not generate token: %s', $e->getMessage()));
$message->save();
return;
}
$accessToken = app('preferences')->getForUser($user, 'access_token', $token);
$signature = hash_hmac('sha3-256', $json, $accessToken->data, false);
$options = [
'body' => $json,
'headers' => [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'Signature' => $signature,
'connect_timeout' => 3.14,
'User-Agent' => sprintf('FireflyIII/%s', config('firefly.version')),
'timeout' => 10,
],
];
$client = new Client;
$logs = $message->logs ?? [];
try {
$res = $client->request('GET', $message->webhook->url, $options);
$message->sent = true;
} catch (ClientException|Exception $e) {
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$logs[] = sprintf('%s: %s', date('Y-m-d H:i:s'), $e->getMessage());
$message->errored = true;
$message->sent = false;
}
$message->attempts++;
$message->logs = $logs;
$message->save();
Log::debug(sprintf('Webhook message #%d was sent. Status code %d', $message->id, $res->getStatusCode()));
Log::debug(sprintf('Response body: %s', $res->getBody()));
}
}

View File

@@ -61,6 +61,7 @@ class WebhookMessage extends Model
'errored' => 'boolean',
'uuid' => 'string',
'message' => 'json',
'logs' => 'json',
];
/**

View File

@@ -29,8 +29,10 @@ use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword;
use FireflyIII\Events\RequestedReportOnJournals;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Events\RequestedVersionCheckStatus;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Events\StoredWebhookMessage;
use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Handlers\Events\SendEmailVerificationNotification;
@@ -112,6 +114,11 @@ class EventServiceProvider extends ServiceProvider
AccessTokenCreated::class => [
'FireflyIII\Handlers\Events\APIEventHandler@accessTokenCreated',
],
// Webhook related event:
RequestedSendWebhookMessages::class => [
'FireflyIII\Handlers\Events\WebhookEventHandler@sendWebhookMessages',
],
];
/**