mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-13 07:53:16 +00:00
Expand webhook options, allow for budgets.
This commit is contained in:
@@ -24,15 +24,18 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers\System;
|
namespace FireflyIII\Api\V1\Controllers\System;
|
||||||
|
|
||||||
use FireflyIII\Support\Facades\FireflyConfig;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
||||||
|
use FireflyIII\Enums\WebhookDelivery;
|
||||||
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\Support\Binder\EitherConfigKey;
|
use FireflyIII\Support\Binder\EitherConfigKey;
|
||||||
|
use FireflyIII\Support\Facades\FireflyConfig;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,8 +110,8 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'is_demo_site' => $isDemoSite?->data,
|
'is_demo_site' => $isDemoSite?->data,
|
||||||
'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
|
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||||
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
|
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||||
'single_user_mode' => $singleUser?->data,
|
'single_user_mode' => $singleUser?->data,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -139,7 +142,18 @@ class ConfigurationController extends Controller
|
|||||||
'value' => $dynamic[$shortKey],
|
'value' => $dynamic[$shortKey],
|
||||||
'editable' => true,
|
'editable' => true,
|
||||||
];
|
];
|
||||||
|
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
if (str_starts_with($configKey, 'webhook.')) {
|
||||||
|
$data = [
|
||||||
|
'title' => $configKey,
|
||||||
|
'value' => $this->getWebhookConfiguration($configKey),
|
||||||
|
'editable' => false,
|
||||||
|
];
|
||||||
|
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
if (!str_starts_with($configKey, 'configuration.')) {
|
if (!str_starts_with($configKey, 'configuration.')) {
|
||||||
$data = [
|
$data = [
|
||||||
'title' => $configKey,
|
'title' => $configKey,
|
||||||
@@ -162,7 +176,7 @@ class ConfigurationController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(UpdateRequest $request, string $name): JsonResponse
|
public function update(UpdateRequest $request, string $name): JsonResponse
|
||||||
{
|
{
|
||||||
$rules = ['value' => 'required'];
|
$rules = ['value' => 'required'];
|
||||||
if (!$this->repository->hasRole(auth()->user(), 'owner')) {
|
if (!$this->repository->hasRole(auth()->user(), 'owner')) {
|
||||||
$messages = ['value' => '200005: You need the "owner" role to do this.'];
|
$messages = ['value' => '200005: You need the "owner" role to do this.'];
|
||||||
Validator::make([], $rules, $messages)->validate();
|
Validator::make([], $rules, $messages)->validate();
|
||||||
@@ -182,4 +196,33 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getWebhookConfiguration(string $configKey): array
|
||||||
|
{
|
||||||
|
switch ($configKey) {
|
||||||
|
case 'webhook.triggers':
|
||||||
|
$cases = WebhookTrigger::cases();
|
||||||
|
$data = [];
|
||||||
|
foreach ($cases as $c) {
|
||||||
|
$data[$c->name] = $c->value;
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
case 'webhook.responses':
|
||||||
|
$cases = WebhookResponse::cases();
|
||||||
|
$data = [];
|
||||||
|
foreach ($cases as $c) {
|
||||||
|
$data[$c->name] = $c->value;
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
case 'webhook.deliveries':
|
||||||
|
$cases = WebhookDelivery::cases();
|
||||||
|
$data = [];
|
||||||
|
foreach ($cases as $c) {
|
||||||
|
$data[$c->name] = $c->value;
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
default:
|
||||||
|
throw new FireflyException(sprintf('Unknown webhook configuration key "%s".', $configKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers\Webhook;
|
namespace FireflyIII\Api\V1\Controllers\Webhook;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Events\RequestedSendWebhookMessages;
|
use FireflyIII\Events\RequestedSendWebhookMessages;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
||||||
@@ -146,7 +147,7 @@ class ShowController extends Controller
|
|||||||
$engine->setUser(auth()->user());
|
$engine->setUser(auth()->user());
|
||||||
|
|
||||||
// tell the generator which trigger it should look for
|
// tell the generator which trigger it should look for
|
||||||
$engine->setTrigger($webhook->trigger);
|
$engine->setTrigger(WebhookTrigger::tryFrom($webhook->trigger));
|
||||||
// tell the generator which objects to process
|
// tell the generator which objects to process
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
// set the webhook to trigger
|
// set the webhook to trigger
|
||||||
|
@@ -24,11 +24,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Rules\IsBoolean;
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateRequest
|
* Class CreateRequest
|
||||||
@@ -40,11 +44,11 @@ class CreateRequest extends FormRequest
|
|||||||
|
|
||||||
public function getData(): array
|
public function getData(): array
|
||||||
{
|
{
|
||||||
$triggers = Webhook::getTriggersForValidation();
|
$triggers = Webhook::getTriggersForValidation();
|
||||||
$responses = Webhook::getResponsesForValidation();
|
$responses = Webhook::getResponsesForValidation();
|
||||||
$deliveries = Webhook::getDeliveriesForValidation();
|
$deliveries = Webhook::getDeliveriesForValidation();
|
||||||
|
|
||||||
$fields = [
|
$fields = [
|
||||||
'title' => ['title', 'convertString'],
|
'title' => ['title', 'convertString'],
|
||||||
'active' => ['active', 'boolean'],
|
'active' => ['active', 'boolean'],
|
||||||
'trigger' => ['trigger', 'convertString'],
|
'trigger' => ['trigger', 'convertString'],
|
||||||
@@ -55,9 +59,9 @@ class CreateRequest extends FormRequest
|
|||||||
|
|
||||||
// this is the way.
|
// this is the way.
|
||||||
$return = $this->getAllData($fields);
|
$return = $this->getAllData($fields);
|
||||||
$return['trigger'] = $triggers[$return['trigger']] ?? (int) $return['trigger'];
|
$return['trigger'] = $triggers[$return['trigger']] ?? (int)$return['trigger'];
|
||||||
$return['response'] = $responses[$return['response']] ?? (int) $return['response'];
|
$return['response'] = $responses[$return['response']] ?? (int)$return['response'];
|
||||||
$return['delivery'] = $deliveries[$return['delivery']] ?? (int) $return['delivery'];
|
$return['delivery'] = $deliveries[$return['delivery']] ?? (int)$return['delivery'];
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -81,4 +85,44 @@ class CreateRequest extends FormRequest
|
|||||||
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
|
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(
|
||||||
|
function (Validator $validator): void {
|
||||||
|
Log::debug('Validating webhook');
|
||||||
|
$data = $validator->getData();
|
||||||
|
$trigger = $data['trigger'] ?? null;
|
||||||
|
$response = $data['response'] ?? null;
|
||||||
|
if (null === $trigger || null === $response) {
|
||||||
|
Log::debug('No trigger or response, return.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$triggers = array_keys(Webhook::getTriggersForValidation());
|
||||||
|
$responses = array_keys(Webhook::getResponsesForValidation());
|
||||||
|
if (!in_array($trigger, $triggers) || !in_array($response, $responses)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// cannot deliver budget info.
|
||||||
|
if (is_int($trigger)) {
|
||||||
|
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
|
||||||
|
$trigger = WebhookTrigger::from($trigger)->name;
|
||||||
|
}
|
||||||
|
if (is_int($response)) {
|
||||||
|
Log::debug(sprintf('Response was integer (%d).', $response));
|
||||||
|
$response = WebhookResponse::from($response)->name;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
|
||||||
|
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_account_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,11 +24,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Rules\IsBoolean;
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UpdateRequest
|
* Class UpdateRequest
|
||||||
@@ -94,4 +98,43 @@ class UpdateRequest extends FormRequest
|
|||||||
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
|
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(
|
||||||
|
function (Validator $validator): void {
|
||||||
|
Log::debug('Validating webhook');
|
||||||
|
$data = $validator->getData();
|
||||||
|
$trigger = $data['trigger'] ?? null;
|
||||||
|
$response = $data['response'] ?? null;
|
||||||
|
if (null === $trigger || null === $response) {
|
||||||
|
Log::debug('No trigger or response, return.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$triggers = array_keys(Webhook::getTriggersForValidation());
|
||||||
|
$responses = array_keys(Webhook::getResponsesForValidation());
|
||||||
|
if (!in_array($trigger, $triggers) || !in_array($response, $responses)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// cannot deliver budget info.
|
||||||
|
if (is_int($trigger)) {
|
||||||
|
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
|
||||||
|
$trigger = WebhookTrigger::from($trigger)->name;
|
||||||
|
}
|
||||||
|
if (is_int($response)) {
|
||||||
|
Log::debug(sprintf('Response was integer (%d).', $response));
|
||||||
|
$response = WebhookResponse::from($response)->name;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
|
||||||
|
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_account_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,5 +31,6 @@ enum WebhookResponse: int
|
|||||||
{
|
{
|
||||||
case TRANSACTIONS = 200;
|
case TRANSACTIONS = 200;
|
||||||
case ACCOUNTS = 210;
|
case ACCOUNTS = 210;
|
||||||
|
case BUDGET = 230;
|
||||||
case NONE = 220;
|
case NONE = 220;
|
||||||
}
|
}
|
||||||
|
@@ -29,10 +29,11 @@ namespace FireflyIII\Enums;
|
|||||||
*/
|
*/
|
||||||
enum WebhookTrigger: int
|
enum WebhookTrigger: int
|
||||||
{
|
{
|
||||||
case STORE_TRANSACTION = 100;
|
case STORE_TRANSACTION = 100;
|
||||||
// case BEFORE_STORE_TRANSACTION = 101;
|
case UPDATE_TRANSACTION = 110;
|
||||||
case UPDATE_TRANSACTION = 110;
|
case DESTROY_TRANSACTION = 120;
|
||||||
// case BEFORE_UPDATE_TRANSACTION = 111;
|
case STORE_BUDGET = 200;
|
||||||
case DESTROY_TRANSACTION = 120;
|
case UPDATE_BUDGET = 210;
|
||||||
// case BEFORE_DESTROY_TRANSACTION = 121;
|
case DESTROY_BUDGET = 220;
|
||||||
|
case STORE_UPDATE_BUDGET_LIMIT = 230;
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Generator\Webhook;
|
namespace FireflyIII\Generator\Webhook;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ interface MessageGeneratorInterface
|
|||||||
|
|
||||||
public function setObjects(Collection $objects): void;
|
public function setObjects(Collection $objects): void;
|
||||||
|
|
||||||
public function setTrigger(int $trigger): void;
|
public function setTrigger(WebhookTrigger $trigger): void;
|
||||||
|
|
||||||
public function setUser(User $user): void;
|
public function setUser(User $user): void;
|
||||||
|
|
||||||
|
@@ -47,11 +47,11 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
|||||||
*/
|
*/
|
||||||
class StandardMessageGenerator implements MessageGeneratorInterface
|
class StandardMessageGenerator implements MessageGeneratorInterface
|
||||||
{
|
{
|
||||||
private Collection $objects;
|
private Collection $objects;
|
||||||
private int $trigger;
|
private WebhookTrigger $trigger;
|
||||||
private User $user;
|
private User $user;
|
||||||
private int $version = 0;
|
private int $version = 0;
|
||||||
private Collection $webhooks;
|
private Collection $webhooks;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -68,9 +68,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// do some debugging
|
// do some debugging
|
||||||
Log::debug(
|
Log::debug(sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count()));
|
||||||
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
|
|
||||||
);
|
|
||||||
$this->run();
|
$this->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +77,9 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
private function run(): void
|
private function run(): void
|
||||||
{
|
{
|
||||||
Log::debug('Now in StandardMessageGenerator::run');
|
Log::debug('Now in StandardMessageGenerator::run');
|
||||||
@@ -108,7 +109,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
*/
|
*/
|
||||||
private function generateMessage(Webhook $webhook, Model $model): void
|
private function generateMessage(Webhook $webhook, Model $model): void
|
||||||
{
|
{
|
||||||
$class = $model::class;
|
$class = $model::class;
|
||||||
// Line is ignored because all of Firefly III's Models have an id property.
|
// Line is ignored because all of Firefly III's Models have an id property.
|
||||||
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
|
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
|
||||||
|
|
||||||
@@ -116,7 +117,8 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
$basicMessage = [
|
$basicMessage = [
|
||||||
'uuid' => $uuid->toString(),
|
'uuid' => $uuid->toString(),
|
||||||
'user_id' => 0,
|
'user_id' => 0,
|
||||||
'trigger' => WebhookTrigger::from($webhook->trigger)->name,
|
'user_group_id' => 0,
|
||||||
|
'trigger' => $webhook->trigger->name,
|
||||||
'response' => WebhookResponse::from($webhook->response)->name,
|
'response' => WebhookResponse::from($webhook->response)->name,
|
||||||
'url' => $webhook->url,
|
'url' => $webhook->url,
|
||||||
'version' => sprintf('v%d', $this->getVersion()),
|
'version' => sprintf('v%d', $this->getVersion()),
|
||||||
@@ -127,15 +129,14 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
switch ($class) {
|
switch ($class) {
|
||||||
default:
|
default:
|
||||||
// Line is ignored because all of Firefly III's Models have an id property.
|
// Line is ignored because all of Firefly III's Models have an id property.
|
||||||
Log::error(
|
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));
|
||||||
sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TransactionGroup::class:
|
case TransactionGroup::class:
|
||||||
/** @var TransactionGroup $model */
|
/** @var TransactionGroup $model */
|
||||||
$basicMessage['user_id'] = $model->user->id;
|
$basicMessage['user_id'] = $model->user_id;
|
||||||
|
$basicMessage['user_group_id'] = $model->user_group_id;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -143,9 +144,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
// then depends on the response what to put in the message:
|
// then depends on the response what to put in the message:
|
||||||
switch ($webhook->response) {
|
switch ($webhook->response) {
|
||||||
default:
|
default:
|
||||||
Log::error(
|
Log::error(sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response));
|
||||||
sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -156,7 +155,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
|
|
||||||
case WebhookResponse::TRANSACTIONS->value:
|
case WebhookResponse::TRANSACTIONS->value:
|
||||||
/** @var TransactionGroup $model */
|
/** @var TransactionGroup $model */
|
||||||
$transformer = new TransactionGroupTransformer();
|
$transformer = new TransactionGroupTransformer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$basicMessage['content'] = $transformer->transformObject($model);
|
$basicMessage['content'] = $transformer->transformObject($model);
|
||||||
@@ -173,13 +172,13 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
|
|
||||||
case WebhookResponse::ACCOUNTS->value:
|
case WebhookResponse::ACCOUNTS->value:
|
||||||
/** @var TransactionGroup $model */
|
/** @var TransactionGroup $model */
|
||||||
$accounts = $this->collectAccounts($model);
|
$accounts = $this->collectAccounts($model);
|
||||||
$enrichment = new AccountEnrichment();
|
$enrichment = new AccountEnrichment();
|
||||||
$enrichment->setDate(null);
|
$enrichment->setDate(null);
|
||||||
$enrichment->setUser($model->user);
|
$enrichment->setUser($model->user);
|
||||||
$accounts = $enrichment->enrich($accounts);
|
$accounts = $enrichment->enrich($accounts);
|
||||||
foreach ($accounts as $account) {
|
foreach ($accounts as $account) {
|
||||||
$transformer = new AccountTransformer();
|
$transformer = new AccountTransformer();
|
||||||
$transformer->setParameters(new ParameterBag());
|
$transformer->setParameters(new ParameterBag());
|
||||||
$basicMessage['content'][] = $transformer->transform($account);
|
$basicMessage['content'][] = $transformer->transform($account);
|
||||||
}
|
}
|
||||||
@@ -209,7 +208,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
|
|
||||||
private function storeMessage(Webhook $webhook, array $message): void
|
private function storeMessage(Webhook $webhook, array $message): void
|
||||||
{
|
{
|
||||||
$webhookMessage = new WebhookMessage();
|
$webhookMessage = new WebhookMessage();
|
||||||
$webhookMessage->webhook()->associate($webhook);
|
$webhookMessage->webhook()->associate($webhook);
|
||||||
$webhookMessage->sent = false;
|
$webhookMessage->sent = false;
|
||||||
$webhookMessage->errored = false;
|
$webhookMessage->errored = false;
|
||||||
@@ -224,7 +223,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
$this->objects = $objects;
|
$this->objects = $objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTrigger(int $trigger): void
|
public function setTrigger(WebhookTrigger $trigger): void
|
||||||
{
|
{
|
||||||
$this->trigger = $trigger;
|
$this->trigger = $trigger;
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,7 @@ class DestroyedGroupEventHandler
|
|||||||
$engine = app(MessageGeneratorInterface::class);
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
$engine->setUser($user);
|
$engine->setUser($user);
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION->value);
|
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION);
|
||||||
$engine->generateMessages();
|
$engine->generateMessages();
|
||||||
|
|
||||||
event(new RequestedSendWebhookMessages());
|
event(new RequestedSendWebhookMessages());
|
||||||
|
@@ -32,6 +32,7 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
|||||||
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class StoredGroupEventHandler
|
* Class StoredGroupEventHandler
|
||||||
@@ -51,11 +52,11 @@ class StoredGroupEventHandler
|
|||||||
private function processRules(StoredTransactionGroup $storedGroupEvent): void
|
private function processRules(StoredTransactionGroup $storedGroupEvent): void
|
||||||
{
|
{
|
||||||
if (false === $storedGroupEvent->applyRules) {
|
if (false === $storedGroupEvent->applyRules) {
|
||||||
app('log')->info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
Log::info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
app('log')->debug('Now in StoredGroupEventHandler::processRules()');
|
Log::debug('Now in StoredGroupEventHandler::processRules()');
|
||||||
|
|
||||||
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
||||||
$array = [];
|
$array = [];
|
||||||
@@ -65,7 +66,7 @@ class StoredGroupEventHandler
|
|||||||
$array[] = $journal->id;
|
$array[] = $journal->id;
|
||||||
}
|
}
|
||||||
$journalIds = implode(',', $array);
|
$journalIds = implode(',', $array);
|
||||||
app('log')->debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||||
|
|
||||||
// collect rules:
|
// collect rules:
|
||||||
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||||
@@ -98,10 +99,10 @@ class StoredGroupEventHandler
|
|||||||
*/
|
*/
|
||||||
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
||||||
{
|
{
|
||||||
app('log')->debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$group = $storedGroupEvent->transactionGroup;
|
$group = $storedGroupEvent->transactionGroup;
|
||||||
if (false === $storedGroupEvent->fireWebhooks) {
|
if (false === $storedGroupEvent->fireWebhooks) {
|
||||||
app('log')->info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
Log::info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ class StoredGroupEventHandler
|
|||||||
$engine->setUser($user);
|
$engine->setUser($user);
|
||||||
|
|
||||||
// tell the generator which trigger it should look for
|
// tell the generator which trigger it should look for
|
||||||
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION->value);
|
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION);
|
||||||
// tell the generator which objects to process
|
// tell the generator which objects to process
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
// tell the generator to generate the messages
|
// tell the generator to generate the messages
|
||||||
|
@@ -164,7 +164,7 @@ class UpdatedGroupEventHandler
|
|||||||
$engine = app(MessageGeneratorInterface::class);
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
$engine->setUser($user);
|
$engine->setUser($user);
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION->value);
|
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION);
|
||||||
$engine->generateMessages();
|
$engine->generateMessages();
|
||||||
|
|
||||||
event(new RequestedSendWebhookMessages());
|
event(new RequestedSendWebhookMessages());
|
||||||
|
@@ -57,6 +57,11 @@ class EitherConfigKey
|
|||||||
'firefly.rule-actions',
|
'firefly.rule-actions',
|
||||||
'firefly.context-rule-actions',
|
'firefly.context-rule-actions',
|
||||||
'search.operators',
|
'search.operators',
|
||||||
|
|
||||||
|
// webhooks
|
||||||
|
'webhook.triggers',
|
||||||
|
'webhook.responses',
|
||||||
|
'webhook.deliveries',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -57,6 +57,7 @@ return [
|
|||||||
'liability_direction_credit_short',
|
'liability_direction_credit_short',
|
||||||
'liability_direction_null_short',
|
'liability_direction_null_short',
|
||||||
'interest_calc_yearly',
|
'interest_calc_yearly',
|
||||||
|
'loading',
|
||||||
'interest_calc_',
|
'interest_calc_',
|
||||||
'interest_calc_null',
|
'interest_calc_null',
|
||||||
'interest_calc_daily',
|
'interest_calc_daily',
|
||||||
@@ -246,12 +247,19 @@ return [
|
|||||||
'multi_account_warning_withdrawal',
|
'multi_account_warning_withdrawal',
|
||||||
'multi_account_warning_deposit',
|
'multi_account_warning_deposit',
|
||||||
'multi_account_warning_transfer',
|
'multi_account_warning_transfer',
|
||||||
|
|
||||||
'webhook_trigger_STORE_TRANSACTION',
|
'webhook_trigger_STORE_TRANSACTION',
|
||||||
'webhook_trigger_UPDATE_TRANSACTION',
|
'webhook_trigger_UPDATE_TRANSACTION',
|
||||||
'webhook_trigger_DESTROY_TRANSACTION',
|
'webhook_trigger_DESTROY_TRANSACTION',
|
||||||
|
|
||||||
|
'webhook_trigger_STORE_BUDGET',
|
||||||
|
'webhook_trigger_UPDATE_BUDGET',
|
||||||
|
'webhook_trigger_DESTROY_BUDGET',
|
||||||
|
'webhook_trigger_STORE_UPDATE_BUDGET_LIMIT',
|
||||||
|
|
||||||
'webhook_response_TRANSACTIONS',
|
'webhook_response_TRANSACTIONS',
|
||||||
'webhook_response_ACCOUNTS',
|
'webhook_response_ACCOUNTS',
|
||||||
'webhook_response_none_NONE',
|
'webhook_response_NONE',
|
||||||
'webhook_delivery_JSON',
|
'webhook_delivery_JSON',
|
||||||
'actions',
|
'actions',
|
||||||
'meta_data',
|
'meta_data',
|
||||||
|
0
public/v1/js/.gitkeep
Normal file → Executable file
0
public/v1/js/.gitkeep
Normal file → Executable file
@@ -24,7 +24,10 @@
|
|||||||
{{ $t('form.webhook_delivery') }}
|
{{ $t('form.webhook_delivery') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select
|
<div v-if="loading" class="form-control-static">
|
||||||
|
<em class="fa fa-spinner fa-spin"></em> {{ $t('firefly.loading') }}
|
||||||
|
</div>
|
||||||
|
<select v-if="!loading"
|
||||||
ref="bill"
|
ref="bill"
|
||||||
v-model="delivery"
|
v-model="delivery"
|
||||||
:title="$t('form.webhook_delivery')"
|
:title="$t('form.webhook_delivery')"
|
||||||
@@ -49,6 +52,7 @@ export default {
|
|||||||
name: "WebhookDelivery",
|
name: "WebhookDelivery",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
loading: true,
|
||||||
delivery : 0,
|
delivery : 0,
|
||||||
deliveries: [
|
deliveries: [
|
||||||
|
|
||||||
@@ -71,8 +75,24 @@ export default {
|
|||||||
mounted() {
|
mounted() {
|
||||||
this.delivery = this.value;
|
this.delivery = this.value;
|
||||||
this.deliveries = [
|
this.deliveries = [
|
||||||
{id: 300, name: this.$t('firefly.webhook_delivery_JSON')},
|
//{id: 300, name: this.$t('firefly.webhook_delivery_JSON')},
|
||||||
];
|
];
|
||||||
|
axios.get('./api/v1/configuration/webhook.deliveries').then((response) => {
|
||||||
|
for (let key in response.data.data.value) {
|
||||||
|
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.deliveries.push(
|
||||||
|
{
|
||||||
|
id: response.data.data.value[key],
|
||||||
|
name: this.$t('firefly.webhook_delivery_' + key),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
}).catch((error) => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value() {
|
value() {
|
||||||
|
@@ -19,73 +19,89 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||||
<label class="col-sm-4 control-label">
|
<label class="col-sm-4 control-label">
|
||||||
{{ $t('form.webhook_response') }}
|
{{ $t('form.webhook_response') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select
|
<div v-if="loading" class="form-control-static">
|
||||||
ref="bill"
|
<em class="fa fa-spinner fa-spin"></em> {{ $t('firefly.loading') }}
|
||||||
v-model="response"
|
</div>
|
||||||
:title="$t('form.webhook_response')"
|
<select v-if="!loading"
|
||||||
class="form-control"
|
ref="response"
|
||||||
name="webhook_response"
|
v-model="response"
|
||||||
>
|
:title="$t('form.webhook_response')"
|
||||||
<option v-for="response in this.responses"
|
class="form-control"
|
||||||
:label="response.name"
|
name="webhook_response"
|
||||||
:value="response.id">{{ response.name }}
|
>
|
||||||
</option>
|
<option v-for="response in this.responses"
|
||||||
</select>
|
:label="response.name"
|
||||||
<p class="help-block" v-text="$t('firefly.webhook_response_form_help')"></p>
|
:value="response.id">{{ response.name }}
|
||||||
<ul v-for="error in this.error" class="list-unstyled">
|
</option>
|
||||||
<li class="text-danger">{{ error }}</li>
|
</select>
|
||||||
</ul>
|
<p class="help-block" v-text="$t('firefly.webhook_response_form_help')"></p>
|
||||||
|
<ul v-for="error in this.error" class="list-unstyled">
|
||||||
|
<li class="text-danger">{{ error }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "WebhookResponse",
|
name: "WebhookResponse",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
response: 0,
|
loading: true,
|
||||||
responses: [],
|
response: 0,
|
||||||
};
|
responses: [],
|
||||||
},
|
};
|
||||||
props: {
|
|
||||||
error: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
value: {
|
props: {
|
||||||
type: Number,
|
error: {
|
||||||
required: true,
|
type: Array,
|
||||||
}
|
required: true,
|
||||||
},
|
default() {
|
||||||
watch: {
|
return []
|
||||||
value() {
|
}
|
||||||
this.response = this.value;
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value() {
|
||||||
|
this.response = this.value;
|
||||||
|
},
|
||||||
|
response(newValue) {
|
||||||
|
this.$emit('input', newValue);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.response = this.value;
|
||||||
|
this.responses = [];
|
||||||
|
axios.get('./api/v1/configuration/webhook.responses').then((response) => {
|
||||||
|
for (let key in response.data.data.value) {
|
||||||
|
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.responses.push(
|
||||||
|
{
|
||||||
|
id: response.data.data.value[key],
|
||||||
|
name: this.$t('firefly.webhook_response_' + key),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
}).catch((error) => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
hasError() {
|
||||||
|
return this.error?.length > 0;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
response(newValue) {
|
|
||||||
this.$emit('input', newValue);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.response = this.value;
|
|
||||||
this.responses = [
|
|
||||||
{id: 200, name: this.$t('firefly.webhook_response_TRANSACTIONS')},
|
|
||||||
{id: 210, name: this.$t('firefly.webhook_response_ACCOUNTS')},
|
|
||||||
{id: 220, name: this.$t('firefly.webhook_response_none_NONE')},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
hasError() {
|
|
||||||
return this.error?.length > 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -19,73 +19,90 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
<div class="form-group" v-bind:class="{ 'has-error': hasError()}">
|
||||||
<label class="col-sm-4 control-label">
|
<label class="col-sm-4 control-label">
|
||||||
{{ $t('form.webhook_trigger') }}
|
{{ $t('form.webhook_trigger') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select
|
<div v-if="loading" class="form-control-static">
|
||||||
ref="bill"
|
<em class="fa fa-spinner fa-spin"></em> {{ $t('firefly.loading') }}
|
||||||
v-model="trigger"
|
</div>
|
||||||
:title="$t('form.webhook_trigger')"
|
<select v-if="!loading"
|
||||||
class="form-control"
|
ref="trigger"
|
||||||
name="webhook_trigger"
|
v-model="trigger"
|
||||||
>
|
:title="$t('form.webhook_trigger')"
|
||||||
<option v-for="trigger in this.triggers"
|
class="form-control"
|
||||||
:label="trigger.name"
|
name="webhook_trigger"
|
||||||
:value="trigger.id">{{ trigger.name }}
|
>
|
||||||
</option>
|
<option v-for="trigger in this.triggers"
|
||||||
</select>
|
:label="trigger.name"
|
||||||
<p class="help-block" v-text="$t('firefly.webhook_trigger_form_help')"></p>
|
:value="trigger.id">{{ trigger.name }}
|
||||||
<ul v-for="error in this.error" class="list-unstyled">
|
</option>
|
||||||
<li class="text-danger">{{ error }}</li>
|
</select>
|
||||||
</ul>
|
<p class="help-block" v-text="$t('firefly.webhook_trigger_form_help')"></p>
|
||||||
|
<ul v-for="error in this.error" class="list-unstyled">
|
||||||
|
<li class="text-danger">{{ error }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "WebhookTrigger",
|
name: "WebhookTrigger",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
trigger: 0,
|
trigger: 0,
|
||||||
triggers: [],
|
loading: true,
|
||||||
};
|
triggers: [],
|
||||||
},
|
};
|
||||||
props: {
|
|
||||||
error: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
value: {
|
props: {
|
||||||
type: Number,
|
error: {
|
||||||
required: true,
|
type: Array,
|
||||||
}
|
required: true,
|
||||||
},
|
default() {
|
||||||
mounted() {
|
return []
|
||||||
this.trigger = this.value;
|
}
|
||||||
this.triggers = [
|
},
|
||||||
{id: 100, name: this.$t('firefly.webhook_trigger_STORE_TRANSACTION')},
|
value: {
|
||||||
{id: 110, name: this.$t('firefly.webhook_trigger_UPDATE_TRANSACTION')},
|
type: Number,
|
||||||
{id: 120, name: this.$t('firefly.webhook_trigger_DESTROY_TRANSACTION')},
|
required: true,
|
||||||
];
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
mounted() {
|
||||||
value() {
|
this.trigger = this.value;
|
||||||
this.trigger = this.value;
|
this.triggers = [];
|
||||||
|
axios.get('./api/v1/configuration/webhook.triggers').then((response) => {
|
||||||
|
for (let key in response.data.data.value) {
|
||||||
|
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.triggers.push(
|
||||||
|
{
|
||||||
|
id: response.data.data.value[key],
|
||||||
|
name: this.$t('firefly.webhook_trigger_' + key),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log('webhook trigger: id=' + response.data.data.value[key] + ', name=' + key);
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
}).catch((error) => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value() {
|
||||||
|
this.trigger = this.value;
|
||||||
|
},
|
||||||
|
trigger(newValue) {
|
||||||
|
this.$emit('input', newValue);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
hasError() {
|
||||||
|
return this.error?.length > 0;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
trigger(newValue) {
|
|
||||||
this.$emit('input', newValue);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
hasError() {
|
|
||||||
return this.error?.length > 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -19,138 +19,172 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">
|
<h3 class="box-title">
|
||||||
{{ $t('firefly.webhooks') }}
|
{{ $t('firefly.webhooks') }}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
|
||||||
<div class="box-body no-padding">
|
|
||||||
<div style="padding:8px;">
|
|
||||||
<a href="webhooks/create" class="btn btn-success"><span class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-responsive table-hover" v-if="webhooks.length > 0" aria-label="A table.">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Title</th>
|
|
||||||
<th>Responds when</th>
|
|
||||||
<th>Responds with (delivery)</th>
|
|
||||||
<th style="width:20%;">Secret (show / hide)</th>
|
|
||||||
<th>URL</th>
|
|
||||||
<th class="hidden-sm hidden-xs"> </th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="webhook in webhooks" :key="webhook.id">
|
|
||||||
<td>
|
|
||||||
<a :href="'webhooks/show/' + webhook.id">{{ webhook.title }}</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span v-if="webhook.active">{{ triggers[webhook.trigger] }}</span>
|
|
||||||
<span v-if="!webhook.active" class="text-muted"><s>{{ triggers[webhook.trigger] }}</s> ({{ $t('firefly.inactive') }})</span>
|
|
||||||
</td>
|
|
||||||
<td>{{ responses[webhook.response] }} ({{ deliveries[webhook.delivery] }})</td>
|
|
||||||
<td>
|
|
||||||
<em style="cursor:pointer"
|
|
||||||
v-if="webhook.show_secret" class="fa fa-eye" @click="toggleSecret(webhook)"></em>
|
|
||||||
<em style="cursor:pointer"
|
|
||||||
v-if="!webhook.show_secret" class="fa fa-eye-slash" @click="toggleSecret(webhook)"></em>
|
|
||||||
<code v-if="webhook.show_secret">{{ webhook.secret }}</code>
|
|
||||||
<code v-if="!webhook.show_secret">********</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<code :title="webhook.full_url">{{ webhook.url }}</code>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td class="hidden-sm hidden-xs">
|
|
||||||
<div class="btn-group btn-group-xs pull-right">
|
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
{{ $t('firefly.actions') }} <span class="caret"></span></button>
|
|
||||||
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
|
||||||
<li><a :href="'webhooks/show/' + webhook.id"><span class="fa fa-fw fa-search"></span> {{ $t('firefly.inspect') }}</a></li>
|
|
||||||
<li><a :href="'webhooks/edit/' + webhook.id"><span class="fa fa-fw fa-pencil"></span> {{$t( 'firefly.edit') }}</a></li>
|
|
||||||
<li><a :href="'webhooks/delete/' + webhook.id"><span class="fa fa-fw fa-trash"></span> {{ $t('firefly.delete') }}</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
<div class="box-body no-padding">
|
||||||
</tr>
|
<div style="padding:8px;">
|
||||||
</tbody>
|
<a href="webhooks/create" class="btn btn-success"><span
|
||||||
</table>
|
class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="webhooks.length > 0" style="padding:8px;">
|
<table class="table table-responsive table-hover" v-if="webhooks.length > 0" aria-label="A table.">
|
||||||
<a href="webhooks/create" class="btn btn-success"><span class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
<thead>
|
||||||
</div>
|
<tr>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Responds when</th>
|
||||||
|
<th>Responds with (delivery)</th>
|
||||||
|
<th style="width:20%;">Secret (show / hide)</th>
|
||||||
|
<th>URL</th>
|
||||||
|
<th class="hidden-sm hidden-xs"> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="webhook in webhooks" :key="webhook.id">
|
||||||
|
<td>
|
||||||
|
<a :href="'webhooks/show/' + webhook.id">{{ webhook.title }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="webhook.active">{{ triggers[webhook.trigger] }}</span>
|
||||||
|
<span v-if="!webhook.active" class="text-muted"><s>{{ triggers[webhook.trigger] }}</s> ({{
|
||||||
|
$t('firefly.inactive')
|
||||||
|
}})</span>
|
||||||
|
</td>
|
||||||
|
<td>{{ responses[webhook.response] }} ({{ deliveries[webhook.delivery] }})</td>
|
||||||
|
<td>
|
||||||
|
<em style="cursor:pointer"
|
||||||
|
v-if="webhook.show_secret" class="fa fa-eye" @click="toggleSecret(webhook)"></em>
|
||||||
|
<em style="cursor:pointer"
|
||||||
|
v-if="!webhook.show_secret" class="fa fa-eye-slash"
|
||||||
|
@click="toggleSecret(webhook)"></em>
|
||||||
|
<code v-if="webhook.show_secret">{{ webhook.secret }}</code>
|
||||||
|
<code v-if="!webhook.show_secret">********</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<code :title="webhook.full_url">{{ webhook.url }}</code>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td class="hidden-sm hidden-xs">
|
||||||
|
<div class="btn-group btn-group-xs pull-right">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
||||||
|
aria-haspopup="true" aria-expanded="false">
|
||||||
|
{{ $t('firefly.actions') }} <span class="caret"></span></button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-right" role="menu">
|
||||||
|
<li><a :href="'webhooks/show/' + webhook.id"><span
|
||||||
|
class="fa fa-fw fa-search"></span> {{ $t('firefly.inspect') }}</a></li>
|
||||||
|
<li><a :href="'webhooks/edit/' + webhook.id"><span
|
||||||
|
class="fa fa-fw fa-pencil"></span> {{ $t('firefly.edit') }}</a></li>
|
||||||
|
<li><a :href="'webhooks/delete/' + webhook.id"><span
|
||||||
|
class="fa fa-fw fa-trash"></span> {{ $t('firefly.delete') }}</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div v-if="webhooks.length > 0" style="padding:8px;">
|
||||||
|
<a href="webhooks/create" class="btn btn-success"><span
|
||||||
|
class="fa fa-plus fa-fw"></span>{{ $t('firefly.create_new_webhook') }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "Index",
|
name: "Index",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
webhooks: [],
|
webhooks: [],
|
||||||
triggers: {
|
triggers: {
|
||||||
STORE_TRANSACTION: this.$t('firefly.webhook_trigger_STORE_TRANSACTION'),
|
},
|
||||||
UPDATE_TRANSACTION: this.$t('firefly.webhook_trigger_UPDATE_TRANSACTION'),
|
responses: {
|
||||||
DESTROY_TRANSACTION: this.$t('firefly.webhook_trigger_DESTROY_TRANSACTION'),
|
},
|
||||||
},
|
deliveries: {
|
||||||
responses: {
|
},
|
||||||
TRANSACTIONS: this.$t('firefly.webhook_response_TRANSACTIONS'),
|
};
|
||||||
ACCOUNTS: this.$t('firefly.webhook_response_ACCOUNTS'),
|
|
||||||
NONE: this.$t('firefly.webhook_response_none_NONE'),
|
|
||||||
},
|
|
||||||
deliveries: {
|
|
||||||
JSON: this.$t('firefly.webhook_delivery_JSON'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.getWebhooks();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getWebhooks: function () {
|
|
||||||
this.webhooks = [];
|
|
||||||
this.downloadWebhooks(1);
|
|
||||||
},
|
},
|
||||||
toggleSecret: function (webhook) {
|
mounted() {
|
||||||
webhook.show_secret = !webhook.show_secret;
|
this.getOptions();
|
||||||
},
|
},
|
||||||
downloadWebhooks: function (page) {
|
methods: {
|
||||||
axios.get("./api/v1/webhooks?page=" + page).then((response) => {
|
getOptions: function () {
|
||||||
for (let i in response.data.data) {
|
// get triggers
|
||||||
if (response.data.data.hasOwnProperty(i)) {
|
axios.get('./api/v1/configuration/webhook.triggers').then((response) => {
|
||||||
let current = response.data.data[i];
|
for (let key in response.data.data.value) {
|
||||||
let webhook = {
|
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||||
id: current.id,
|
continue;
|
||||||
title: current.attributes.title,
|
}
|
||||||
url: current.attributes.url,
|
this.triggers[key] = this.$t('firefly.webhook_trigger_' + key);
|
||||||
active: current.attributes.active,
|
}
|
||||||
full_url: current.attributes.url,
|
|
||||||
secret: current.attributes.secret,
|
|
||||||
trigger: current.attributes.trigger,
|
|
||||||
response: current.attributes.response,
|
|
||||||
delivery: current.attributes.delivery,
|
|
||||||
show_secret: false,
|
|
||||||
};
|
|
||||||
if(current.attributes.url.length > 20) {
|
|
||||||
webhook.url = current.attributes.url.slice(0, 20) + '...';
|
|
||||||
}
|
|
||||||
this.webhooks.push(webhook);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.data.meta.pagination.current_page < response.data.meta.pagination.total_pages) {
|
// get responses
|
||||||
this.downloadWebhooks(response.data.meta.pagination.current_page + 1);
|
axios.get('./api/v1/configuration/webhook.responses').then((response) => {
|
||||||
}
|
for (let key in response.data.data.value) {
|
||||||
});
|
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||||
},
|
continue;
|
||||||
}
|
}
|
||||||
|
this.responses[key] = this.$t('firefly.webhook_response_' + key);
|
||||||
|
}
|
||||||
|
// get deliveries
|
||||||
|
axios.get('./api/v1/configuration/webhook.deliveries').then((response) => {
|
||||||
|
for (let key in response.data.data.value) {
|
||||||
|
if (!response.data.data.value.hasOwnProperty(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.deliveries[key] = this.$t('firefly.webhook_delivery_' + key);
|
||||||
|
}
|
||||||
|
// get webhooks
|
||||||
|
this.getWebhooks();
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getWebhooks: function () {
|
||||||
|
this.webhooks = [];
|
||||||
|
this.downloadWebhooks(1);
|
||||||
|
},
|
||||||
|
toggleSecret: function (webhook) {
|
||||||
|
webhook.show_secret = !webhook.show_secret;
|
||||||
|
},
|
||||||
|
downloadWebhooks: function (page) {
|
||||||
|
axios.get("./api/v1/webhooks?page=" + page).then((response) => {
|
||||||
|
for (let i in response.data.data) {
|
||||||
|
if (response.data.data.hasOwnProperty(i)) {
|
||||||
|
let current = response.data.data[i];
|
||||||
|
let webhook = {
|
||||||
|
id: current.id,
|
||||||
|
title: current.attributes.title,
|
||||||
|
url: current.attributes.url,
|
||||||
|
active: current.attributes.active,
|
||||||
|
full_url: current.attributes.url,
|
||||||
|
secret: current.attributes.secret,
|
||||||
|
trigger: current.attributes.trigger,
|
||||||
|
response: current.attributes.response,
|
||||||
|
delivery: current.attributes.delivery,
|
||||||
|
show_secret: false,
|
||||||
|
};
|
||||||
|
if (current.attributes.url.length > 20) {
|
||||||
|
webhook.url = current.attributes.url.slice(0, 20) + '...';
|
||||||
|
}
|
||||||
|
this.webhooks.push(webhook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.data.meta.pagination.current_page < response.data.meta.pagination.total_pages) {
|
||||||
|
this.downloadWebhooks(response.data.meta.pagination.current_page + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,9 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'webhook_budget_info' => 'Cannot deliver budget information for transaction related webhooks.',
|
||||||
|
'webhook_account_info' => 'Cannot deliver account information for budget related webhooks.',
|
||||||
|
'webhook_transaction_info' => 'Cannot deliver transaction information for budget related webhooks.',
|
||||||
'invalid_account_type' => 'A piggy bank can only be linked to asset accounts and liabilities',
|
'invalid_account_type' => 'A piggy bank can only be linked to asset accounts and liabilities',
|
||||||
'invalid_account_currency' => 'This account does not use the currency you have selected',
|
'invalid_account_currency' => 'This account does not use the currency you have selected',
|
||||||
'current_amount_too_much' => 'The combined amount in "current_amount" cannot exceed the "target_amount".',
|
'current_amount_too_much' => 'The combined amount in "current_amount" cannot exceed the "target_amount".',
|
||||||
|
Reference in New Issue
Block a user