diff --git a/app/Api/V1/Requests/Webhook/CreateRequest.php b/app/Api/V1/Requests/Webhook/CreateRequest.php index e0284f1667..8ec557bd24 100644 --- a/app/Api/V1/Requests/Webhook/CreateRequest.php +++ b/app/Api/V1/Requests/Webhook/CreateRequest.php @@ -73,7 +73,7 @@ class CreateRequest extends FormRequest $deliveries = implode(',', array_values(config('firefly.webhooks.deliveries'))); return [ - 'title' => 'between:1,512', + 'title' => 'required|between:1,512|uniqueObjectForUser:webhooks,title', 'active' => [new IsBoolean], 'trigger' => sprintf('required|in:%s', $triggers), 'response' => sprintf('required|in:%s', $responses), diff --git a/app/Api/V1/Requests/Webhook/UpdateRequest.php b/app/Api/V1/Requests/Webhook/UpdateRequest.php index 26a4a3f52c..8abd735841 100644 --- a/app/Api/V1/Requests/Webhook/UpdateRequest.php +++ b/app/Api/V1/Requests/Webhook/UpdateRequest.php @@ -57,6 +57,7 @@ class UpdateRequest extends FormRequest $return['trigger'] = $triggers[$return['trigger']] ?? 0; $return['response'] = $responses[$return['response']] ?? 0; $return['delivery'] = $deliveries[$return['delivery']] ?? 0; + $return['secret'] = null !== $this->get('secret'); return $return; } @@ -74,7 +75,7 @@ class UpdateRequest extends FormRequest $webhook = $this->route()->parameter('webhook'); return [ - 'title' => 'between:1,512', + 'title' => sprintf('between:1,512|uniqueObjectForUser:webhooks,title,%d', $webhook->id), 'active' => [new IsBoolean], 'trigger' => sprintf('required|in:%s', $triggers), 'response' => sprintf('required|in:%s', $responses), diff --git a/app/Generator/Webhook/StandardMessageGenerator.php b/app/Generator/Webhook/StandardMessageGenerator.php index 17e7254e57..4031a5b705 100644 --- a/app/Generator/Webhook/StandardMessageGenerator.php +++ b/app/Generator/Webhook/StandardMessageGenerator.php @@ -53,6 +53,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface */ public function generateMessages(): void { + Log::debug(__METHOD__); // get the webhooks: $this->webhooks = $this->getWebhooks(); @@ -105,6 +106,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface foreach ($this->webhooks as $webhook) { $this->runWebhook($webhook); } + Log::debug('Done with StandardMessageGenerator::run'); } /** diff --git a/app/Handlers/Events/StoredGroupEventHandler.php b/app/Handlers/Events/StoredGroupEventHandler.php index a0eee4051a..1cb6dc1ef1 100644 --- a/app/Handlers/Events/StoredGroupEventHandler.php +++ b/app/Handlers/Events/StoredGroupEventHandler.php @@ -86,7 +86,7 @@ class StoredGroupEventHandler */ public function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void { - Log::debug('StoredTransactionGroup:triggerWebhooks'); + Log::debug(__METHOD__); $group = $storedGroupEvent->transactionGroup; $user = $group->user; /** @var MessageGeneratorInterface $engine */ diff --git a/app/Handlers/Events/WebhookEventHandler.php b/app/Handlers/Events/WebhookEventHandler.php index 08c2218568..f6460dac1f 100644 --- a/app/Handlers/Events/WebhookEventHandler.php +++ b/app/Handlers/Events/WebhookEventHandler.php @@ -37,7 +37,7 @@ class WebhookEventHandler */ public function sendWebhookMessages(): void { - // kick offf the job! + // kick off the job! $messages = WebhookMessage ::where('webhook_messages.sent', 0) ->where('webhook_messages.errored', 0) diff --git a/app/Helpers/Webhook/Sha3SignatureGenerator.php b/app/Helpers/Webhook/Sha3SignatureGenerator.php index 78346f9fd1..43d474622d 100644 --- a/app/Helpers/Webhook/Sha3SignatureGenerator.php +++ b/app/Helpers/Webhook/Sha3SignatureGenerator.php @@ -30,7 +30,7 @@ use JsonException; */ class Sha3SignatureGenerator implements SignatureGeneratorInterface { - private int $version = 0; + private int $version = 1; /** * @inheritDoc diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 4146d5972c..6423ff0491 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -110,6 +110,7 @@ class HomeController extends Controller */ public function index(AccountRepositoryInterface $repository) { + var_dump(\Str::random(24)); $types = config('firefly.accountTypesByIdentifier.asset'); $count = $repository->count($types); Log::channel('audit')->info('User visits homepage.'); diff --git a/app/Jobs/SendWebhookMessage.php b/app/Jobs/SendWebhookMessage.php index a36d7a5cff..3aa23faefa 100644 --- a/app/Jobs/SendWebhookMessage.php +++ b/app/Jobs/SendWebhookMessage.php @@ -23,7 +23,7 @@ class SendWebhookMessage implements ShouldQueue /** * Create a new job instance. * - * @return void + * @param WebhookMessage $message */ public function __construct(WebhookMessage $message) { diff --git a/app/Models/Webhook.php b/app/Models/Webhook.php index 3ca961801c..2281de76c5 100644 --- a/app/Models/Webhook.php +++ b/app/Models/Webhook.php @@ -82,7 +82,7 @@ class Webhook extends Model // delivery public const DELIVERY_JSON = 300; - protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'url']; + protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'url', 'title', 'secret']; protected $casts = [ diff --git a/app/Repositories/Webhook/WebhookRepository.php b/app/Repositories/Webhook/WebhookRepository.php index 6837e4fbb4..aa8690c1fc 100644 --- a/app/Repositories/Webhook/WebhookRepository.php +++ b/app/Repositories/Webhook/WebhookRepository.php @@ -25,6 +25,7 @@ namespace FireflyIII\Repositories\Webhook; use FireflyIII\Models\Webhook; use FireflyIII\User; use Illuminate\Support\Collection; +use Str; /** * Class WebhookRepository @@ -54,6 +55,7 @@ class WebhookRepository implements WebhookRepositoryInterface */ public function store(array $data): Webhook { + $secret = $random = Str::random(24); $fullData = [ 'user_id' => $this->user->id, 'active' => $data['active'] ?? false, @@ -61,6 +63,7 @@ class WebhookRepository implements WebhookRepositoryInterface 'trigger' => $data['trigger'], 'response' => $data['response'], 'delivery' => $data['delivery'], + 'secret' => $secret, 'url' => $data['url'], ]; @@ -77,6 +80,12 @@ class WebhookRepository implements WebhookRepositoryInterface $webhook->response = $data['response'] ?? $webhook->response; $webhook->delivery = $data['delivery'] ?? $webhook->delivery; $webhook->url = $data['url'] ?? $webhook->url; + + if (array_key_exists('secret', $data) && null !== $data['secret']) { + $secret = $random = Str::random(24); + $webhook->secret = $secret; + } + $webhook->save(); return $webhook; diff --git a/app/Services/Webhook/StandardWebhookSender.php b/app/Services/Webhook/StandardWebhookSender.php index 7739c14e7b..544942b364 100644 --- a/app/Services/Webhook/StandardWebhookSender.php +++ b/app/Services/Webhook/StandardWebhookSender.php @@ -22,7 +22,9 @@ declare(strict_types=1); namespace FireflyIII\Services\Webhook; +use Exception; use FireflyIII\Helpers\Webhook\SignatureGeneratorInterface; +use FireflyIII\Models\WebhookAttempt; use FireflyIII\Models\WebhookMessage; use GuzzleHttp\Client; use GuzzleHttp\Exception\ClientException; @@ -68,12 +70,17 @@ class StandardWebhookSender implements WebhookSenderInterface try { $json = json_encode($this->message->message, JSON_THROW_ON_ERROR); } catch (JsonException $e) { - // TODO throw Firefly Exception - // $attempt = new WebhookAttempt; - // $attempt->webhookMessage()->associate($this->message); - // $attempt->status_code = 0; - // $attempt->logs = sprintf('Json error: %s', $e->getMessage()); - // $attempt->save(); + Log::error('Did not send message because of a JSON error.'); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + $attempt = new WebhookAttempt; + $attempt->webhookMessage()->associate($this->message); + $attempt->status_code = 0; + $attempt->logs = sprintf('Json error: %s', $e->getMessage()); + $attempt->save(); + $this->message->errored = true; + $this->message->sent = false; + $this->message->save(); return; } @@ -89,7 +96,6 @@ class StandardWebhookSender implements WebhookSenderInterface ], ]; $client = new Client; - //$logs = $this->message->logs ?? []; try { $res = $client->request('POST', $this->message->webhook->url, $options); $this->message->sent = true; @@ -99,22 +105,13 @@ class StandardWebhookSender implements WebhookSenderInterface //$logs[] = sprintf('%s: %s', date('Y-m-d H:i:s'), $e->getMessage()); $this->message->errored = true; $this->message->sent = false; + $this->message->save(); + return; } $this->message->save(); - // $attempt = new WebhookAttempt; - // $attempt->webhookMessage()->associate($this->message); - // $attempt->status_code = $res->getStatusCode(); - // $attempt->logs = ''; - // $attempt->response = (string)$res->getBody(); - // $attempt->save(); - Log::debug(sprintf('Webhook message #%d was sent. Status code %d', $this->message->id, $res->getStatusCode())); Log::debug(sprintf('Webhook request body size: %d bytes', strlen($json))); Log::debug(sprintf('Response body: %s', $res->getBody())); - - //$sender - - //$this->sendMessageV0($this->message); } } diff --git a/app/Transformers/WebhookTransformer.php b/app/Transformers/WebhookTransformer.php index ea99a44380..8ee39231e3 100644 --- a/app/Transformers/WebhookTransformer.php +++ b/app/Transformers/WebhookTransformer.php @@ -55,6 +55,7 @@ class WebhookTransformer extends AbstractTransformer 'updated_at' => $webhook->updated_at->toAtomString(), 'active' => $webhook->active, 'title' => $webhook->title, + 'secret' => $webhook->secret, 'trigger' => $this->getEnum($webhook->trigger), 'response' => $this->getEnum($webhook->response), 'delivery' => $this->getEnum($webhook->delivery), diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index 89b0b59cc5..67de90d5ee 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -655,6 +655,7 @@ class FireflyValidator extends Validator ->where('id', '!=', $existingId) ->where('url', $url)->count(); } + return false; }