Make sure webhooks are generated in a generic way for future expansion.

This commit is contained in:
James Cole
2020-12-05 06:47:16 +01:00
parent 4a7e185c44
commit deb829dfdb
5 changed files with 70 additions and 39 deletions

View File

@@ -46,9 +46,9 @@ interface MessageGeneratorInterface
public function setUser(User $user): void; public function setUser(User $user): void;
/** /**
* @param Collection $transactionGroups * @param Collection $objects
*/ */
public function setTransactionGroups(Collection $transactionGroups): void; public function setObjects(Collection $objects): void;
/** /**
* @param int $trigger * @param int $trigger

View File

@@ -21,7 +21,6 @@
namespace FireflyIII\Generator\Webhook; namespace FireflyIII\Generator\Webhook;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
@@ -31,6 +30,7 @@ use FireflyIII\Models\WebhookMessage;
use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Log; use Log;
use Ramsey\Uuid\Uuid; use Ramsey\Uuid\Uuid;
@@ -43,7 +43,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
{ {
private int $version = 1; private int $version = 1;
private User $user; private User $user;
private Collection $transactionGroups; private Collection $objects;
private int $trigger; private int $trigger;
private Collection $webhooks; private Collection $webhooks;
@@ -52,8 +52,13 @@ class StandardMessageGenerator implements MessageGeneratorInterface
*/ */
public function generateMessages(): void public function generateMessages(): void
{ {
// get the webhooks:
$this->webhooks = $this->getWebhooks(); $this->webhooks = $this->getWebhooks();
Log::debug(sprintf('Generate messages for %d group(s) and %d webhook(s).', $this->transactionGroups->count(), $this->webhooks->count()));
// do some debugging
Log::debug(
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
);
$this->run(); $this->run();
} }
@@ -66,11 +71,11 @@ class StandardMessageGenerator implements MessageGeneratorInterface
} }
/** /**
* @param Collection $transactionGroups * @param Collection $objects
*/ */
public function setTransactionGroups(Collection $transactionGroups): void public function setObjects(Collection $objects): void
{ {
$this->transactionGroups = $transactionGroups; $this->objects = $objects;
} }
/** /**
@@ -90,15 +95,16 @@ class StandardMessageGenerator implements MessageGeneratorInterface
} }
/** /**
* Will also trigger a send. *
*/ */
private function run(): void private function run(): void
{ {
Log::debug('Now in StandardMessageGenerator::run');
/** @var Webhook $webhook */ /** @var Webhook $webhook */
foreach ($this->webhooks as $webhook) { foreach ($this->webhooks as $webhook) {
$this->runWebhook($webhook); $this->runWebhook($webhook);
} }
event(new RequestedSendWebhookMessages); //event(new RequestedSendWebhookMessages);
} }
/** /**
@@ -106,32 +112,46 @@ class StandardMessageGenerator implements MessageGeneratorInterface
*/ */
private function runWebhook(Webhook $webhook): void private function runWebhook(Webhook $webhook): void
{ {
/** @var TransactionGroup $transactionGroup */ Log::debug(sprintf('Now in runWebhook(#%d)', $webhook->id));
foreach ($this->transactionGroups as $transactionGroup) { /** @var Model $object */
$this->generateMessage($webhook, $transactionGroup); foreach ($this->objects as $object) {
$this->generateMessage($webhook, $object);
} }
} }
/** /**
* @param Webhook $webhook * @param Webhook $webhook
* @param TransactionGroup $transactionGroup * @param Model $model
*/ */
private function generateMessage(Webhook $webhook, TransactionGroup $transactionGroup): void private function generateMessage(Webhook $webhook, Model $model): void
{ {
Log::debug(sprintf('Generating message for webhook #%d and transaction group #%d.', $webhook->id, $transactionGroup->id)); $class = get_class($model);
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
// message depends on what the webhook sets. $uuid = Uuid::uuid4();
$uuid = Uuid::uuid4(); $basicMessage = [
$message = [
'user_id' => $transactionGroup->user->id,
'trigger' => config('firefly.webhooks.triggers')[$webhook->trigger],
'url' => $webhook->url,
'uuid' => $uuid->toString(), 'uuid' => $uuid->toString(),
'version' => sprintf('v%d',$this->getVersion()), 'user_id' => 0,
'trigger' => config('firefly.webhooks.triggers')[$webhook->trigger],
'response' => config('firefly.webhooks.responses')[$webhook->response], 'response' => config('firefly.webhooks.responses')[$webhook->response],
'url' => $webhook->url,
'version' => sprintf('v%d', $this->getVersion()),
'content' => [], 'content' => [],
]; ];
// depends on the model how user_id is set:
switch ($class) {
default:
Log::error(sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id));
return;
case TransactionGroup::class:
/** @var TransactionGroup $model */
$basicMessage['user_id'] = $model->user->id;
break;
}
// then depends on the response what to put in the message:
switch ($webhook->response) { switch ($webhook->response) {
default: default:
Log::error( Log::error(
@@ -140,25 +160,29 @@ class StandardMessageGenerator implements MessageGeneratorInterface
return; return;
case Webhook::RESPONSE_NONE: case Webhook::RESPONSE_NONE:
$message['content'] = []; $basicMessage['content'] = [];
break; break;
case Webhook::RESPONSE_TRANSACTIONS: case Webhook::RESPONSE_TRANSACTIONS:
$transformer = new TransactionGroupTransformer; $transformer = new TransactionGroupTransformer;
try { try {
$message['content'] = $transformer->transformObject($transactionGroup); $basicMessage['content'] = $transformer->transformObject($model);
} catch (FireflyException $e) { } catch (FireflyException $e) {
$message['content'] = ['error' => 'Internal error prevented Firefly III from including data', 'message' => $e->getMessage()]; Log::error(
sprintf('The transformer could not include the requested transaction group for webhook #%d: %s', $webhook->id, $e->getMessage())
);
return;
} }
break; break;
case Webhook::RESPONSE_ACCOUNTS: case Webhook::RESPONSE_ACCOUNTS:
$accounts = $this->collectAccounts($transactionGroup); $accounts = $this->collectAccounts($model);
foreach ($accounts as $account) { foreach ($accounts as $account) {
$transformer = new AccountTransformer; $transformer = new AccountTransformer;
$transformer->setParameters(new ParameterBag); $transformer->setParameters(new ParameterBag);
$message['content'][] = $transformer->transform($account); $basicMessage['content'][] = $transformer->transform($account);
} }
} }
$this->storeMessage($webhook, $message); $this->storeMessage($webhook, $basicMessage);
} }
/** /**
@@ -195,6 +219,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
$webhookMessage->uuid = $message['uuid']; $webhookMessage->uuid = $message['uuid'];
$webhookMessage->message = $message; $webhookMessage->message = $message;
$webhookMessage->save(); $webhookMessage->save();
Log::debug(sprintf('Stored new webhook message #%d', $webhookMessage->id));
return $webhookMessage; return $webhookMessage;
} }

View File

@@ -85,8 +85,12 @@ class StoredGroupEventHandler
/** @var MessageGeneratorInterface $engine */ /** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class); $engine = app(MessageGeneratorInterface::class);
$engine->setUser($user); $engine->setUser($user);
$engine->setTransactionGroups(new Collection([$group]));
// tell the generator which trigger it should look for
$engine->setTrigger(Webhook::TRIGGER_STORE_TRANSACTION); $engine->setTrigger(Webhook::TRIGGER_STORE_TRANSACTION);
// tell the generator which objects to process
$engine->setObjects(new Collection([$group]));
// tell the generator to generate the messages
$engine->generateMessages(); $engine->generateMessages();
} }

View File

@@ -24,6 +24,8 @@ namespace FireflyIII\Providers;
use FireflyIII\Generator\Chart\Basic\ChartJsGenerator; use FireflyIII\Generator\Chart\Basic\ChartJsGenerator;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface; use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
use FireflyIII\Generator\Webhook\StandardMessageGenerator;
use FireflyIII\Helpers\Attachments\AttachmentHelper; use FireflyIII\Helpers\Attachments\AttachmentHelper;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Helpers\Fiscal\FiscalHelper; use FireflyIII\Helpers\Fiscal\FiscalHelper;
@@ -231,10 +233,10 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(TelemetryRepositoryInterface::class, TelemetryRepository::class); $this->app->bind(TelemetryRepositoryInterface::class, TelemetryRepository::class);
// webhooks: // webhooks:
$this->app->bind(MessageGeneratorInterface::class, StandardMessageGenerator::class);
$this->app->bind(SignatureGeneratorInterface::class,Sha3SignatureGenerator::class); $this->app->bind(SignatureGeneratorInterface::class,Sha3SignatureGenerator::class);
$this->app->bind(WebhookSenderInterface::class, StandardWebhookSender::class); $this->app->bind(WebhookSenderInterface::class, StandardWebhookSender::class);
// password verifier thing // password verifier thing
$this->app->bind(Verifier::class, PwndVerifierV2::class); $this->app->bind(Verifier::class, PwndVerifierV2::class);

View File

@@ -825,17 +825,17 @@ return [
'webhooks' => [ 'webhooks' => [
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3), 'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
'triggers' => [ 'triggers' => [
100 => 'TRIGGER_STORE_TRANSACTION', Webhook::TRIGGER_STORE_TRANSACTION => 'TRIGGER_STORE_TRANSACTION',
110 => 'TRIGGER_UPDATE_TRANSACTION', Webhook::TRIGGER_UPDATE_TRANSACTION => 'TRIGGER_UPDATE_TRANSACTION',
120 => 'TRIGGER_DESTROY_TRANSACTION', Webhook::TRIGGER_DESTROY_TRANSACTION => 'TRIGGER_DESTROY_TRANSACTION',
], ],
'responses' => [ 'responses' => [
200 => 'RESPONSE_TRANSACTIONS', Webhook::RESPONSE_TRANSACTIONS => 'RESPONSE_TRANSACTIONS',
210 => 'RESPONSE_ACCOUNTS', Webhook::RESPONSE_ACCOUNTS => 'RESPONSE_ACCOUNTS',
220 => 'RESPONSE_NONE', Webhook::RESPONSE_NONE => 'RESPONSE_NONE',
], ],
'deliveries' => [ 'deliveries' => [
300 => 'DELIVERY_JSON', Webhook::DELIVERY_JSON => 'DELIVERY_JSON',
], ],
], ],
]; ];