From a57cf4e9be4fb67321f0d2c13222961d0163ac48 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 2 Nov 2025 14:00:55 +0100 Subject: [PATCH] Clean up some classes, extend API validation. --- .../Autocomplete/TransactionController.php | 3 +- .../Models/Account/ListController.php | 14 +-- app/Api/V1/Requests/AggregateFormRequest.php | 2 + .../Autocomplete/AutocompleteApiRequest.php | 3 +- .../AutocompleteTransactionApiRequest.php | 47 ++++++++++ .../Requests/Generic/ObjectTypeApiRequest.php | 90 +++++++++++++++++++ .../Requests/Models/Account/ShowRequest.php | 2 + app/Factory/BillFactory.php | 7 +- app/Factory/CategoryFactory.php | 8 +- app/Factory/PiggyBankFactory.php | 5 +- app/Factory/TagFactory.php | 9 +- app/Factory/TransactionFactory.php | 19 ++-- app/Factory/TransactionGroupFactory.php | 5 +- app/Factory/TransactionJournalMetaFactory.php | 17 ++-- .../Report/Account/MonthReportGenerator.php | 5 +- .../Report/Audit/MonthReportGenerator.php | 4 +- .../Report/Budget/MonthReportGenerator.php | 7 +- .../Report/Category/MonthReportGenerator.php | 7 +- .../Report/Standard/MonthReportGenerator.php | 5 +- .../Standard/MultiYearReportGenerator.php | 5 +- .../Report/Standard/YearReportGenerator.php | 5 +- .../Report/Tag/MonthReportGenerator.php | 5 +- app/Rules/IsAllowedGroupAction.php | 14 ++- .../IsValidTransactionTypeList.php | 56 ++++++++++++ app/Support/Http/Api/TransactionFilter.php | 55 +++++++----- .../Http/Api/ValidatesUserGroupTrait.php | 1 + app/TransactionRules/Actions/LinkToBill.php | 32 ++----- resources/lang/en_US/validation.php | 1 + 28 files changed, 324 insertions(+), 109 deletions(-) create mode 100644 app/Api/V1/Requests/Autocomplete/AutocompleteTransactionApiRequest.php create mode 100644 app/Api/V1/Requests/Generic/ObjectTypeApiRequest.php create mode 100644 app/Rules/TransactionType/IsValidTransactionTypeList.php diff --git a/app/Api/V1/Controllers/Autocomplete/TransactionController.php b/app/Api/V1/Controllers/Autocomplete/TransactionController.php index 2bc5c8314b..cf8302fdf2 100644 --- a/app/Api/V1/Controllers/Autocomplete/TransactionController.php +++ b/app/Api/V1/Controllers/Autocomplete/TransactionController.php @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteApiRequest; +use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteTransactionApiRequest; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; @@ -64,7 +65,7 @@ class TransactionController extends Controller ); } - public function transactions(AutocompleteApiRequest $request): JsonResponse + public function transactions(AutocompleteTransactionApiRequest $request): JsonResponse { $result = $this->repository->searchJournalDescriptions($request->attributes->get('query'), $request->attributes->get('limit')); diff --git a/app/Api/V1/Controllers/Models/Account/ListController.php b/app/Api/V1/Controllers/Models/Account/ListController.php index f830be0844..e5ea31a8b7 100644 --- a/app/Api/V1/Controllers/Models/Account/ListController.php +++ b/app/Api/V1/Controllers/Models/Account/ListController.php @@ -136,12 +136,16 @@ class ListController extends Controller /** * Show all transaction groups related to the account. */ - public function transactions(Request $request, Account $account): JsonResponse + public function transactions(PaginationRequest $request, Account $account): JsonResponse { - $pageSize = $this->parameters->get('limit'); + [ + 'limit' => $limit, + 'offset' => $offset, + 'page' => $page, + ] = $request->attributes->all(); + $type = $request->get('type') ?? 'default'; - $this->parameters->set('type', $type); - $types = $this->mapTransactionTypes($this->parameters->get('type')); + $types = $this->mapTransactionTypes($type); $manager = $this->getManager(); /** @var User $admin */ @@ -151,7 +155,7 @@ class ListController extends Controller /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setUser($admin)->setAccounts(new Collection()->push($account)) - ->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types) + ->withAPIInformation()->setLimit($limit)->setPage($page)->setTypes($types) ; if (null !== $this->parameters->get('start')) { diff --git a/app/Api/V1/Requests/AggregateFormRequest.php b/app/Api/V1/Requests/AggregateFormRequest.php index 001c902fda..eda707b798 100644 --- a/app/Api/V1/Requests/AggregateFormRequest.php +++ b/app/Api/V1/Requests/AggregateFormRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; +use FireflyIII\Exceptions\FireflyException; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; @@ -45,6 +46,7 @@ abstract class AggregateFormRequest extends ApiRequest // instantiate all subrequests and share current requests' bags with them Log::debug('Initializing AggregateFormRequest.'); + foreach ($this->getRequests() as $config) { $requestClass = is_array($config) ? array_shift($config) : $config; diff --git a/app/Api/V1/Requests/Autocomplete/AutocompleteApiRequest.php b/app/Api/V1/Requests/Autocomplete/AutocompleteApiRequest.php index 751f9f580b..7c0c3f40ac 100644 --- a/app/Api/V1/Requests/Autocomplete/AutocompleteApiRequest.php +++ b/app/Api/V1/Requests/Autocomplete/AutocompleteApiRequest.php @@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests\Autocomplete; use FireflyIII\Api\V1\Requests\AggregateFormRequest; use FireflyIII\Api\V1\Requests\DateRequest; +use FireflyIII\Api\V1\Requests\Generic\ObjectTypeApiRequest; use FireflyIII\Api\V1\Requests\Generic\QueryRequest; use FireflyIII\Api\V1\Requests\Models\Account\AccountTypesApiRequest; use FireflyIII\Api\V1\Requests\PaginationRequest; @@ -39,7 +40,7 @@ class AutocompleteApiRequest extends AggregateFormRequest return [ DateRequest::class, [PaginationRequest::class, 'sort_class' => Account::class], - AccountTypesApiRequest::class, + [ObjectTypeApiRequest::class, 'object_type' => Account::class], QueryRequest::class, ]; } diff --git a/app/Api/V1/Requests/Autocomplete/AutocompleteTransactionApiRequest.php b/app/Api/V1/Requests/Autocomplete/AutocompleteTransactionApiRequest.php new file mode 100644 index 0000000000..a6255a4595 --- /dev/null +++ b/app/Api/V1/Requests/Autocomplete/AutocompleteTransactionApiRequest.php @@ -0,0 +1,47 @@ +. + */ + +namespace FireflyIII\Api\V1\Requests\Autocomplete; + +use FireflyIII\Api\V1\Requests\AggregateFormRequest; +use FireflyIII\Api\V1\Requests\DateRequest; +use FireflyIII\Api\V1\Requests\Generic\ObjectTypeApiRequest; +use FireflyIII\Api\V1\Requests\Generic\QueryRequest; +use FireflyIII\Api\V1\Requests\PaginationRequest; +use FireflyIII\Models\Account; +use FireflyIII\Models\Transaction; +use Override; + +class AutocompleteTransactionApiRequest extends AggregateFormRequest +{ + #[Override] + protected function getRequests(): array + { + return [ + DateRequest::class, + [PaginationRequest::class, 'sort_class' => Account::class], + [ObjectTypeApiRequest::class, 'object_type' => Transaction::class], + QueryRequest::class, + ]; + } +} diff --git a/app/Api/V1/Requests/Generic/ObjectTypeApiRequest.php b/app/Api/V1/Requests/Generic/ObjectTypeApiRequest.php new file mode 100644 index 0000000000..bf9b3a496f --- /dev/null +++ b/app/Api/V1/Requests/Generic/ObjectTypeApiRequest.php @@ -0,0 +1,90 @@ +. + */ + +namespace FireflyIII\Api\V1\Requests\Generic; + +use FireflyIII\Api\V1\Requests\ApiRequest; +use FireflyIII\Models\Account; +use FireflyIII\Models\Transaction; +use FireflyIII\Rules\Account\IsValidAccountTypeList; +use FireflyIII\Rules\TransactionType\IsValidTransactionTypeList; +use FireflyIII\Support\Http\Api\AccountFilter; +use FireflyIII\Support\Http\Api\TransactionFilter; +use Illuminate\Validation\Validator; +use RuntimeException; + +class ObjectTypeApiRequest extends ApiRequest +{ + use AccountFilter; + use TransactionFilter; + + private ?string $objectType = null; + + public function handleConfig(array $config): void + { + parent::handleConfig($config); + + $this->objectType = $config['object_type'] ?? null; + + if (!$this->objectType) { + throw new RuntimeException('ObjectTypeApiRequest requires a object_type config'); + } + } + + public function rules(): array + { + $rule = null; + if (Account::class === $this->objectType) { + $rule = new IsValidAccountTypeList(); + } + if (Transaction::class === $this->objectType) { + $rule = new IsValidTransactionTypeList(); + } + return [ + 'types' => $rule, + ]; + } + + public function withValidator(Validator $validator): void + { + $validator->after( + function (Validator $validator): void { + if ($validator->failed()) { + return; + } + $type = $this->convertString('types', 'all'); + $this->attributes->set('type', $type); + switch ($this->objectType) { + default: + $this->attributes->set('types', []); + case Account::class: + $this->attributes->set('types', $this->mapAccountTypes($type)); + break; + case Transaction::class: + $this->attributes->set('types', $this->mapTransactionTypes($type)); + break; + } + } + ); + } +} diff --git a/app/Api/V1/Requests/Models/Account/ShowRequest.php b/app/Api/V1/Requests/Models/Account/ShowRequest.php index ed0a7dafe1..0d7b5f3d1e 100644 --- a/app/Api/V1/Requests/Models/Account/ShowRequest.php +++ b/app/Api/V1/Requests/Models/Account/ShowRequest.php @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Requests\Models\Account; use FireflyIII\Api\V1\Requests\AggregateFormRequest; use FireflyIII\Api\V1\Requests\DateRangeRequest; use FireflyIII\Api\V1\Requests\DateRequest; +use FireflyIII\Api\V1\Requests\Generic\ObjectTypeApiRequest; use FireflyIII\Api\V1\Requests\PaginationRequest; use FireflyIII\Models\Account; @@ -38,6 +39,7 @@ class ShowRequest extends AggregateFormRequest DateRangeRequest::class, DateRequest::class, AccountTypeApiRequest::class, + [ObjectTypeApiRequest::class, 'object_type' => Account::class], ]; } } diff --git a/app/Factory/BillFactory.php b/app/Factory/BillFactory.php index fb284ae921..e7fe5cfa59 100644 --- a/app/Factory/BillFactory.php +++ b/app/Factory/BillFactory.php @@ -31,6 +31,7 @@ use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Services\Internal\Support\BillServiceTrait; use FireflyIII\User; use Illuminate\Database\QueryException; +use Illuminate\Support\Facades\Log; /** * Class BillFactory @@ -47,7 +48,7 @@ class BillFactory */ public function create(array $data): ?Bill { - app('log')->debug(sprintf('Now in %s', __METHOD__), $data); + Log::debug(sprintf('Now in %s', __METHOD__), $data); $factory = app(TransactionCurrencyFactory::class); $currency = $factory->find((int) ($data['currency_id'] ?? null), (string) ($data['currency_code'] ?? null)) ?? app('amount')->getPrimaryCurrencyByUserGroup($this->user->userGroup); @@ -82,8 +83,8 @@ class BillFactory ] ); } catch (QueryException $e) { - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException('400000: Could not store bill.', 0, $e); } diff --git a/app/Factory/CategoryFactory.php b/app/Factory/CategoryFactory.php index 754dba7644..6313198f97 100644 --- a/app/Factory/CategoryFactory.php +++ b/app/Factory/CategoryFactory.php @@ -27,7 +27,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Category; use FireflyIII\User; use Illuminate\Database\QueryException; - +use Illuminate\Support\Facades\Log; /** * Class CategoryFactory */ @@ -43,7 +43,7 @@ class CategoryFactory $categoryId = (int) $categoryId; $categoryName = (string) $categoryName; - app('log')->debug(sprintf('Going to find category with ID %d and name "%s"', $categoryId, $categoryName)); + Log::debug(sprintf('Going to find category with ID %d and name "%s"', $categoryId, $categoryName)); if ('' === $categoryName && 0 === $categoryId) { return null; @@ -72,8 +72,8 @@ class CategoryFactory ] ); } catch (QueryException $e) { - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException('400003: Could not store new category.', 0, $e); } diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php index dc6b401311..9631ba8756 100644 --- a/app/Factory/PiggyBankFactory.php +++ b/app/Factory/PiggyBankFactory.php @@ -38,7 +38,6 @@ use Illuminate\Database\QueryException; use Illuminate\Support\Facades\Log; use function Safe\json_encode; - /** * Class PiggyBankFactory */ @@ -92,7 +91,7 @@ class PiggyBankFactory /** @var PiggyBank $piggyBank */ $piggyBank = PiggyBank::createQuietly($piggyBankData); } catch (QueryException $e) { - app('log')->error(sprintf('Could not store piggy bank: %s', $e->getMessage()), $piggyBankData); + Log::error(sprintf('Could not store piggy bank: %s', $e->getMessage()), $piggyBankData); throw new FireflyException('400005: Could not store new piggy bank.', 0, $e); } @@ -211,7 +210,7 @@ class PiggyBankFactory $current = 1; foreach ($set as $piggyBank) { if ($piggyBank->order !== $current) { - app('log')->debug(sprintf('Piggy bank #%d ("%s") was at place %d but should be on %d', $piggyBank->id, $piggyBank->name, $piggyBank->order, $current)); + Log::debug(sprintf('Piggy bank #%d ("%s") was at place %d but should be on %d', $piggyBank->id, $piggyBank->name, $piggyBank->order, $current)); $piggyBank->order = $current; $piggyBank->save(); } diff --git a/app/Factory/TagFactory.php b/app/Factory/TagFactory.php index e0bb78254c..8c49cf53d4 100644 --- a/app/Factory/TagFactory.php +++ b/app/Factory/TagFactory.php @@ -28,6 +28,7 @@ use FireflyIII\Models\Location; use FireflyIII\Models\Tag; use FireflyIII\Models\UserGroup; use FireflyIII\User; +use Illuminate\Support\Facades\Log; /** * Class TagFactory @@ -40,12 +41,12 @@ class TagFactory public function findOrCreate(string $tag): ?Tag { $tag = trim($tag); - app('log')->debug(sprintf('Now in TagFactory::findOrCreate("%s")', $tag)); + Log::debug(sprintf('Now in TagFactory::findOrCreate("%s")', $tag)); /** @var null|Tag $dbTag */ $dbTag = $this->user->tags()->where('tag', $tag)->first(); if (null !== $dbTag) { - app('log')->debug(sprintf('Tag exists (#%d), return it.', $dbTag->id)); + Log::debug(sprintf('Tag exists (#%d), return it.', $dbTag->id)); return $dbTag; } @@ -60,11 +61,11 @@ class TagFactory ] ); if (!$newTag instanceof Tag) { - app('log')->error(sprintf('TagFactory::findOrCreate("%s") but tag is unexpectedly NULL!', $tag)); + Log::error(sprintf('TagFactory::findOrCreate("%s") but tag is unexpectedly NULL!', $tag)); return null; } - app('log')->debug(sprintf('Created new tag #%d ("%s")', $newTag->id, $newTag->tag)); + Log::debug(sprintf('Created new tag #%d ("%s")', $newTag->id, $newTag->tag)); return $newTag; } diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index 9a1b590bf7..1f53d562f7 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -33,6 +33,7 @@ use FireflyIII\Rules\UniqueIban; use FireflyIII\Services\Internal\Update\AccountUpdateService; use Illuminate\Database\QueryException; use Illuminate\Support\Facades\Validator; +use Illuminate\Support\Facades\Log; /** * Class TransactionFactory @@ -96,9 +97,9 @@ class TransactionFactory /** @var null|Transaction $result */ $result = Transaction::create($data); } catch (QueryException $e) { - app('log')->error(sprintf('Could not create transaction: %s', $e->getMessage()), $data); - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Could not create transaction: %s', $e->getMessage()), $data); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException(sprintf('Query exception when creating transaction: %s', $e->getMessage()), 0, $e); } @@ -106,7 +107,7 @@ class TransactionFactory throw new FireflyException('Transaction is NULL.'); } - app('log')->debug( + Log::debug( sprintf( 'Created transaction #%d (%s %s, account %s), part of journal #%d', $result->id, @@ -138,17 +139,17 @@ class TransactionFactory private function updateAccountInformation(): void { if (!array_key_exists('iban', $this->accountInformation)) { - app('log')->debug('No IBAN information in array, will not update.'); + Log::debug('No IBAN information in array, will not update.'); return; } if ('' !== (string) $this->account->iban) { - app('log')->debug('Account already has IBAN information, will not update.'); + Log::debug('Account already has IBAN information, will not update.'); return; } if ($this->account->iban === $this->accountInformation['iban']) { - app('log')->debug('Account already has this IBAN, will not update.'); + Log::debug('Account already has this IBAN, will not update.'); return; } @@ -157,12 +158,12 @@ class TransactionFactory 'iban' => ['required', new UniqueIban($this->account, $this->account->accountType->type)], ]); if ($validator->fails()) { - app('log')->debug('Invalid or non-unique IBAN, will not update.'); + Log::debug('Invalid or non-unique IBAN, will not update.'); return; } - app('log')->debug('Will update account with IBAN information.'); + Log::debug('Will update account with IBAN information.'); $service = app(AccountUpdateService::class); $service->update($this->account, ['iban' => $this->accountInformation['iban']]); } diff --git a/app/Factory/TransactionGroupFactory.php b/app/Factory/TransactionGroupFactory.php index 10ecf31b52..11bde5fade 100644 --- a/app/Factory/TransactionGroupFactory.php +++ b/app/Factory/TransactionGroupFactory.php @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\UserGroup; use FireflyIII\User; +use Illuminate\Support\Facades\Log; /** * Class TransactionGroupFactory @@ -55,7 +56,7 @@ class TransactionGroupFactory */ public function create(array $data): TransactionGroup { - app('log')->debug('Now in TransactionGroupFactory::create()'); + Log::debug('Now in TransactionGroupFactory::create()'); $this->journalFactory->setUser($data['user']); $this->journalFactory->setUserGroup($data['user_group']); $this->journalFactory->setErrorOnHash($data['error_if_duplicate_hash'] ?? false); @@ -63,7 +64,7 @@ class TransactionGroupFactory try { $collection = $this->journalFactory->create($data); } catch (DuplicateTransactionException $e) { - app('log')->warning('GroupFactory::create() caught journalFactory::create() with a duplicate!'); + Log::warning('GroupFactory::create() caught journalFactory::create() with a duplicate!'); throw new DuplicateTransactionException($e->getMessage(), 0, $e); } diff --git a/app/Factory/TransactionJournalMetaFactory.php b/app/Factory/TransactionJournalMetaFactory.php index 56dd79d1e0..31e9fe4888 100644 --- a/app/Factory/TransactionJournalMetaFactory.php +++ b/app/Factory/TransactionJournalMetaFactory.php @@ -26,6 +26,7 @@ namespace FireflyIII\Factory; use Carbon\Carbon; use FireflyIII\Models\TransactionJournalMeta; +use Illuminate\Support\Facades\Log; /** * Class TransactionJournalMetaFactory @@ -34,27 +35,27 @@ class TransactionJournalMetaFactory { public function updateOrCreate(array $data): ?TransactionJournalMeta { - // app('log')->debug('In updateOrCreate()'); + // Log::debug('In updateOrCreate()'); $value = $data['data']; /** @var null|TransactionJournalMeta $entry */ $entry = $data['journal']->transactionJournalMeta()->where('name', $data['name'])->first(); if (null === $value && null !== $entry) { - // app('log')->debug('Value is empty, delete meta value.'); + // Log::debug('Value is empty, delete meta value.'); $entry->delete(); return null; } if ($data['data'] instanceof Carbon) { - app('log')->debug('Is a carbon object.'); + Log::debug('Is a carbon object.'); $value = $data['data']->toW3cString(); } if ('' === (string) $value) { - // app('log')->debug('Is an empty string.'); + // Log::debug('Is an empty string.'); // don't store blank strings. if (null !== $entry) { - app('log')->debug('Will not store empty strings, delete meta value'); + Log::debug('Will not store empty strings, delete meta value'); $entry->delete(); } @@ -62,13 +63,13 @@ class TransactionJournalMetaFactory } if (null === $entry) { - // app('log')->debug('Will create new object.'); - app('log')->debug(sprintf('Going to create new meta-data entry to store "%s".', $data['name'])); + // Log::debug('Will create new object.'); + Log::debug(sprintf('Going to create new meta-data entry to store "%s".', $data['name'])); $entry = new TransactionJournalMeta(); $entry->transactionJournal()->associate($data['journal']); $entry->name = $data['name']; } - app('log')->debug('Will update value and return.'); + Log::debug('Will update value and return.'); $entry->data = $value; $entry->save(); diff --git a/app/Generator/Report/Account/MonthReportGenerator.php b/app/Generator/Report/Account/MonthReportGenerator.php index f711be2185..bb9e5c8246 100644 --- a/app/Generator/Report/Account/MonthReportGenerator.php +++ b/app/Generator/Report/Account/MonthReportGenerator.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -58,8 +59,8 @@ class MonthReportGenerator implements ReportGeneratorInterface ->render() ; } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.double.report: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.double.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); diff --git a/app/Generator/Report/Audit/MonthReportGenerator.php b/app/Generator/Report/Audit/MonthReportGenerator.php index b920ab172e..e62d609d9d 100644 --- a/app/Generator/Report/Audit/MonthReportGenerator.php +++ b/app/Generator/Report/Audit/MonthReportGenerator.php @@ -105,8 +105,8 @@ class MonthReportGenerator implements ReportGeneratorInterface ->render() ; } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.audit.report: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.audit.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); diff --git a/app/Generator/Report/Budget/MonthReportGenerator.php b/app/Generator/Report/Budget/MonthReportGenerator.php index 7c19c19e54..5ed587a6df 100644 --- a/app/Generator/Report/Budget/MonthReportGenerator.php +++ b/app/Generator/Report/Budget/MonthReportGenerator.php @@ -30,6 +30,7 @@ use FireflyIII\Generator\Report\ReportGeneratorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -72,8 +73,8 @@ class MonthReportGenerator implements ReportGeneratorInterface ->render() ; } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); @@ -132,7 +133,7 @@ class MonthReportGenerator implements ReportGeneratorInterface protected function getExpenses(): array { if (0 !== count($this->expenses)) { - app('log')->debug('Return previous set of expenses.'); + Log::debug('Return previous set of expenses.'); return $this->expenses; } diff --git a/app/Generator/Report/Category/MonthReportGenerator.php b/app/Generator/Report/Category/MonthReportGenerator.php index 61dd7f5cac..8511c426d8 100644 --- a/app/Generator/Report/Category/MonthReportGenerator.php +++ b/app/Generator/Report/Category/MonthReportGenerator.php @@ -30,6 +30,7 @@ use FireflyIII\Generator\Report\ReportGeneratorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -73,8 +74,8 @@ class MonthReportGenerator implements ReportGeneratorInterface ->render() ; } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.category.month: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); @@ -131,7 +132,7 @@ class MonthReportGenerator implements ReportGeneratorInterface protected function getExpenses(): array { if (0 !== count($this->expenses)) { - app('log')->debug('Return previous set of expenses.'); + Log::debug('Return previous set of expenses.'); return $this->expenses; } diff --git a/app/Generator/Report/Standard/MonthReportGenerator.php b/app/Generator/Report/Standard/MonthReportGenerator.php index edbe7910b6..e7cd581f61 100644 --- a/app/Generator/Report/Standard/MonthReportGenerator.php +++ b/app/Generator/Report/Standard/MonthReportGenerator.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -56,8 +57,8 @@ class MonthReportGenerator implements ReportGeneratorInterface try { return view('reports.default.month', compact('accountIds', 'reportType'))->with('start', $this->start)->with('end', $this->end)->render(); } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.default.month: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.default.month: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render report view.'; throw new FireflyException($result, 0, $e); diff --git a/app/Generator/Report/Standard/MultiYearReportGenerator.php b/app/Generator/Report/Standard/MultiYearReportGenerator.php index d5e42a4dcb..7802931a2d 100644 --- a/app/Generator/Report/Standard/MultiYearReportGenerator.php +++ b/app/Generator/Report/Standard/MultiYearReportGenerator.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -60,8 +61,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface compact('accountIds', 'reportType') )->with('start', $this->start)->with('end', $this->end)->render(); } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); diff --git a/app/Generator/Report/Standard/YearReportGenerator.php b/app/Generator/Report/Standard/YearReportGenerator.php index 6ac88700c2..b705cdda61 100644 --- a/app/Generator/Report/Standard/YearReportGenerator.php +++ b/app/Generator/Report/Standard/YearReportGenerator.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -60,8 +61,8 @@ class YearReportGenerator implements ReportGeneratorInterface compact('accountIds', 'reportType') )->with('start', $this->start)->with('end', $this->end)->render(); } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render report view.'; throw new FireflyException($result, 0, $e); diff --git a/app/Generator/Report/Tag/MonthReportGenerator.php b/app/Generator/Report/Tag/MonthReportGenerator.php index 82d1c0c247..26d454e336 100644 --- a/app/Generator/Report/Tag/MonthReportGenerator.php +++ b/app/Generator/Report/Tag/MonthReportGenerator.php @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; use Illuminate\Support\Collection; use Throwable; +use Illuminate\Support\Facades\Log; /** * Class MonthReportGenerator. @@ -67,8 +68,8 @@ class MonthReportGenerator implements ReportGeneratorInterface compact('accountIds', 'reportType', 'tagIds') )->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render(); } catch (Throwable $e) { - app('log')->error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage())); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); diff --git a/app/Rules/IsAllowedGroupAction.php b/app/Rules/IsAllowedGroupAction.php index 7e30cd30ec..d8e8c4f08a 100644 --- a/app/Rules/IsAllowedGroupAction.php +++ b/app/Rules/IsAllowedGroupAction.php @@ -26,6 +26,7 @@ namespace FireflyIII\Rules; use Closure; use FireflyIII\Enums\UserRoleEnum; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; use FireflyIII\User; @@ -68,11 +69,18 @@ class IsAllowedGroupAction implements ValidationRule break; } } - $this->validateUserGroup((int) $value, $fail); + $this->validateUserGroup((int)$value, $fail); } + private function validateUserGroup(int $userGroupId, Closure $fail): void { + try { + throw new FireflyException('Here we are'); + } catch (FireflyException $e) { + Log::error($e->getTraceAsString()); + } + die('here we are'); Log::debug(sprintf('validateUserGroup: %s', static::class)); if (!auth()->check()) { Log::debug('validateUserGroup: user is not logged in, return NULL.'); @@ -82,7 +90,7 @@ class IsAllowedGroupAction implements ValidationRule } /** @var User $user */ - $user = auth()->user(); + $user = auth()->user(); if (0 !== $userGroupId) { Log::debug(sprintf('validateUserGroup: user group submitted, search for memberships in group #%d.', $userGroupId)); } @@ -102,7 +110,7 @@ class IsAllowedGroupAction implements ValidationRule } // need to get the group from the membership: - $userGroup = $this->repository->getById($userGroupId); + $userGroup = $this->repository->getById($userGroupId); if (null === $userGroup) { Log::debug(sprintf('validateUserGroup: group #%d does not exist.', $userGroupId)); $fail('validation.belongs_user_or_user_group')->translate(); diff --git a/app/Rules/TransactionType/IsValidTransactionTypeList.php b/app/Rules/TransactionType/IsValidTransactionTypeList.php new file mode 100644 index 0000000000..4f27b57f00 --- /dev/null +++ b/app/Rules/TransactionType/IsValidTransactionTypeList.php @@ -0,0 +1,56 @@ +translate(); + } + $keys = array_keys($this->transactionTypes); + foreach ($values as $entry) { + $entry = (string)$entry; + if (!in_array($entry, $keys, true)) { + $fail('validation.invalid_transaction_type_list')->translate(); + } + } + } +} diff --git a/app/Support/Http/Api/TransactionFilter.php b/app/Support/Http/Api/TransactionFilter.php index f6f13d77a7..74b8090468 100644 --- a/app/Support/Http/Api/TransactionFilter.php +++ b/app/Support/Http/Api/TransactionFilter.php @@ -31,39 +31,48 @@ use FireflyIII\Enums\TransactionTypeEnum; */ trait TransactionFilter { - /** - * All the types you can request. - */ - protected function mapTransactionTypes(string $type): array - { - $types = [ - 'all' => [ + protected $transactionTypes + = [ + 'all' => [ TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value, TransactionTypeEnum::OPENING_BALANCE->value, TransactionTypeEnum::RECONCILIATION->value, ], - 'withdrawal' => [TransactionTypeEnum::WITHDRAWAL->value], - 'withdrawals' => [TransactionTypeEnum::WITHDRAWAL->value], - 'expense' => [TransactionTypeEnum::WITHDRAWAL->value], - 'expenses' => [TransactionTypeEnum::WITHDRAWAL->value], - 'income' => [TransactionTypeEnum::DEPOSIT->value], - 'deposit' => [TransactionTypeEnum::DEPOSIT->value], - 'deposits' => [TransactionTypeEnum::DEPOSIT->value], - 'transfer' => [TransactionTypeEnum::TRANSFER->value], - 'transfers' => [TransactionTypeEnum::TRANSFER->value], - 'opening_balance' => [TransactionTypeEnum::OPENING_BALANCE->value], - 'reconciliation' => [TransactionTypeEnum::RECONCILIATION->value], - 'reconciliations' => [TransactionTypeEnum::RECONCILIATION->value], - 'special' => [TransactionTypeEnum::OPENING_BALANCE->value, TransactionTypeEnum::RECONCILIATION->value], - 'specials' => [TransactionTypeEnum::OPENING_BALANCE->value, TransactionTypeEnum::RECONCILIATION->value], - 'default' => [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value], + TransactionTypeEnum::WITHDRAWAL->value => [TransactionTypeEnum::WITHDRAWAL->value], + 'withdrawal' => [TransactionTypeEnum::WITHDRAWAL->value], + 'withdrawals' => [TransactionTypeEnum::WITHDRAWAL->value], + 'expense' => [TransactionTypeEnum::WITHDRAWAL->value], + 'expenses' => [TransactionTypeEnum::WITHDRAWAL->value], + TransactionTypeEnum::DEPOSIT->value => [TransactionTypeEnum::DEPOSIT->value], + 'income' => [TransactionTypeEnum::DEPOSIT->value], + 'deposit' => [TransactionTypeEnum::DEPOSIT->value], + 'deposits' => [TransactionTypeEnum::DEPOSIT->value], + TransactionTypeEnum::TRANSFER->value => [TransactionTypeEnum::TRANSFER->value], + 'transfer' => [TransactionTypeEnum::TRANSFER->value], + 'transfers' => [TransactionTypeEnum::TRANSFER->value], + TransactionTypeEnum::OPENING_BALANCE->value => [TransactionTypeEnum::OPENING_BALANCE->value], + 'opening_balance' => [TransactionTypeEnum::OPENING_BALANCE->value], + TransactionTypeEnum::RECONCILIATION->value => [TransactionTypeEnum::RECONCILIATION->value], + 'reconciliation' => [TransactionTypeEnum::RECONCILIATION->value], + 'reconciliations' => [TransactionTypeEnum::RECONCILIATION->value], + 'special' => [TransactionTypeEnum::OPENING_BALANCE->value, TransactionTypeEnum::RECONCILIATION->value], + 'specials' => [TransactionTypeEnum::OPENING_BALANCE->value, TransactionTypeEnum::RECONCILIATION->value], + 'default' => [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value], ]; + + /** + * All the types you can request. + */ + protected function mapTransactionTypes(string $type): array + { $return = []; $parts = explode(',', $type); foreach ($parts as $part) { - $return = array_merge($return, $types[$part] ?? $types['default']); + if(array_key_exists($part, $this->transactionTypes)) { + $return = array_merge($return, $this->transactionTypes[$part]); + } } return array_unique($return); diff --git a/app/Support/Http/Api/ValidatesUserGroupTrait.php b/app/Support/Http/Api/ValidatesUserGroupTrait.php index 3d17a7b42c..2c9db16cb3 100644 --- a/app/Support/Http/Api/ValidatesUserGroupTrait.php +++ b/app/Support/Http/Api/ValidatesUserGroupTrait.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Api; use FireflyIII\Enums\UserRoleEnum; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\UserGroup; use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; use FireflyIII\User; diff --git a/app/TransactionRules/Actions/LinkToBill.php b/app/TransactionRules/Actions/LinkToBill.php index b52f278442..4b118f763b 100644 --- a/app/TransactionRules/Actions/LinkToBill.php +++ b/app/TransactionRules/Actions/LinkToBill.php @@ -31,6 +31,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; /** * Class LinkToBill. @@ -54,29 +55,16 @@ class LinkToBill implements ActionInterface $bill = $repository->findByName($billName); if (null !== $bill && TransactionTypeEnum::WITHDRAWAL->value === $journal['transaction_type_type']) { - $count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id']) - ->where('bill_id', $bill->id)->count() - ; + $count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id'])->where('bill_id', $bill->id)->count(); if (0 !== $count) { - app('log')->error( - sprintf( - 'RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": already set.', - $journal['transaction_journal_id'], - $billName - ) - ); - event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_linked_to_subscription', ['name' => $billName]))); + Log::error(sprintf('RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": already set.', $journal['transaction_journal_id'], $billName)); + // event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_linked_to_subscription', ['name' => $billName]))); return false; } - DB::table('transaction_journals') - ->where('id', '=', $journal['transaction_journal_id']) - ->update(['bill_id' => $bill->id]) - ; - app('log')->debug( - sprintf('RuleAction LinkToBill set the bill of journal #%d to bill #%d ("%s").', $journal['transaction_journal_id'], $bill->id, $bill->name) - ); + DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id'])->update(['bill_id' => $bill->id]); + Log::debug(sprintf('RuleAction LinkToBill set the bill of journal #%d to bill #%d ("%s").', $journal['transaction_journal_id'], $bill->id, $bill->name)); /** @var TransactionJournal $object */ $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); @@ -85,13 +73,7 @@ class LinkToBill implements ActionInterface return true; } - app('log')->error( - sprintf( - 'RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": no such bill found or not a withdrawal.', - $journal['transaction_journal_id'], - $billName - ) - ); + Log::error(sprintf('RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": no such bill found or not a withdrawal.', $journal['transaction_journal_id'], $billName)); event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_subscription', ['name' => $billName]))); return false; diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php index 008eee28b2..833154b1e1 100644 --- a/resources/lang/en_US/validation.php +++ b/resources/lang/en_US/validation.php @@ -25,6 +25,7 @@ declare(strict_types=1); return [ 'invalid_account_list' => 'Invalid account type list', + 'invalid_transaction_type_list' => 'Invalid transaction type list', 'limit_exists' => 'There is already a budget limit (amount) for this budget and currency in the given period.', 'invalid_sort_instruction' => 'The sort instruction is invalid for an object of type ":object".', 'invalid_sort_instruction_index' => 'The sort instruction at index #:index is invalid for an object of type ":object".',