From 75e5115aa339cc40a33cc7936a0408777c0ee1ff Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 23 Sep 2023 07:15:41 +0200 Subject: [PATCH] Update repositories, remove references to admin id --- .../Autocomplete/AccountController.php | 4 +- .../Controllers/Chart/AccountController.php | 2 +- .../Controllers/Chart/BalanceController.php | 2 +- .../Controllers/Model/Bill/ShowController.php | 1 + .../Model/Transaction/StoreController.php | 3 - .../Summary/NetWorthController.php | 14 +- .../Autocomplete/AutocompleteRequest.php | 15 +- app/Helpers/Report/NetWorth.php | 33 +- app/Http/Requests/AccountFormRequest.php | 27 +- .../UserGroups/Account/AccountRepository.php | 27 + .../Account/AccountRepositoryInterface.php | 8 + app/Transformers/UserTransformer.php | 17 +- .../ValidatesAdministrationAccess.php | 2 + package-lock.json | 2 +- package.json | 2 +- .../transactions/CreateTransaction.vue | 1899 +++++++++-------- 16 files changed, 1047 insertions(+), 1011 deletions(-) diff --git a/app/Api/V2/Controllers/Autocomplete/AccountController.php b/app/Api/V2/Controllers/Autocomplete/AccountController.php index cfab89a40b..7d06c0a5de 100644 --- a/app/Api/V2/Controllers/Autocomplete/AccountController.php +++ b/app/Api/V2/Controllers/Autocomplete/AccountController.php @@ -67,9 +67,9 @@ class AccountController extends Controller * TODO list of checks * 1. use dates from ParameterBag * 2. Request validates dates - * 3. Request includes user_group_id as administration_id + * 3. Request includes user_group_id * 4. Endpoint is documented. - * 5. Collector uses administration_id + * 5. Collector uses user_group_id * * @param AutocompleteRequest $request * diff --git a/app/Api/V2/Controllers/Chart/AccountController.php b/app/Api/V2/Controllers/Chart/AccountController.php index aa5a5bef7a..b45fa09e9f 100644 --- a/app/Api/V2/Controllers/Chart/AccountController.php +++ b/app/Api/V2/Controllers/Chart/AccountController.php @@ -76,7 +76,7 @@ class AccountController extends Controller * If a transaction has foreign currency = native currency, the foreign amount will be used, no conversion * will take place. * - * TODO validate and set administration_id from request + * TODO validate and set user_group_id from request * * @param DateRequest $request * diff --git a/app/Api/V2/Controllers/Chart/BalanceController.php b/app/Api/V2/Controllers/Chart/BalanceController.php index 6c56e97313..8ba070f627 100644 --- a/app/Api/V2/Controllers/Chart/BalanceController.php +++ b/app/Api/V2/Controllers/Chart/BalanceController.php @@ -71,7 +71,7 @@ class BalanceController extends Controller * If the transaction being processed is already in native currency OR if the * foreign amount is in the native currency, the amount will not be converted. * - * TODO validate and set administration_id + * TODO validate and set user_group_id * TODO collector set group, not user * * @param BalanceChartRequest $request diff --git a/app/Api/V2/Controllers/Model/Bill/ShowController.php b/app/Api/V2/Controllers/Model/Bill/ShowController.php index 992524d430..33fece0c92 100644 --- a/app/Api/V2/Controllers/Model/Bill/ShowController.php +++ b/app/Api/V2/Controllers/Model/Bill/ShowController.php @@ -52,6 +52,7 @@ class ShowController extends Controller function ($request, $next) { $this->repository = app(BillRepositoryInterface::class); + // new way of user group validation $userGroup = $this->validateUserGroup($request); if (null !== $userGroup) { $this->repository->setUserGroup($userGroup); diff --git a/app/Api/V2/Controllers/Model/Transaction/StoreController.php b/app/Api/V2/Controllers/Model/Transaction/StoreController.php index 01aebcb56a..dc14f8b22e 100644 --- a/app/Api/V2/Controllers/Model/Transaction/StoreController.php +++ b/app/Api/V2/Controllers/Model/Transaction/StoreController.php @@ -62,8 +62,6 @@ class StoreController extends Controller /** * TODO this method is practically the same as the V1 method and borrows as much code as possible. - * TODO still it duplicates a lot. - * TODO the v1 endpoints will never support separate administrations, this is an important distinction. * * @return JsonResponse * @throws FireflyException @@ -74,7 +72,6 @@ class StoreController extends Controller app('log')->debug('Now in API v2 StoreController::store()'); $data = $request->getAll(); - $data['user'] = auth()->user()->id; $userGroup = $request->getUserGroup(); $data['user_group'] = $userGroup; diff --git a/app/Api/V2/Controllers/Summary/NetWorthController.php b/app/Api/V2/Controllers/Summary/NetWorthController.php index 7700a135d7..553721d3f6 100644 --- a/app/Api/V2/Controllers/Summary/NetWorthController.php +++ b/app/Api/V2/Controllers/Summary/NetWorthController.php @@ -26,8 +26,9 @@ namespace FireflyIII\Api\V2\Controllers\Summary; use FireflyIII\Api\V2\Controllers\Controller; use FireflyIII\Api\V2\Request\Generic\SingleDateRequest; -use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Report\NetWorthInterface; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use Illuminate\Http\JsonResponse; /** @@ -35,6 +36,9 @@ use Illuminate\Http\JsonResponse; */ class NetWorthController extends Controller { + use ValidatesUserGroupTrait; + use ConvertsExchangeRates; + private NetWorthInterface $netWorth; /** @@ -46,7 +50,12 @@ class NetWorthController extends Controller $this->middleware( function ($request, $next) { $this->netWorth = app(NetWorthInterface::class); - $this->netWorth->setUser(auth()->user()); + + // new way of user group validation + $userGroup = $this->validateUserGroup($request); + if (null !== $userGroup) { + $this->netWorth->setUserGroup($userGroup); + } return $next($request); } @@ -63,7 +72,6 @@ class NetWorthController extends Controller */ public function get(SingleDateRequest $request): JsonResponse { - throw new FireflyException('deprecated use of thing.'); $date = $request->getDate(); $result = $this->netWorth->sumNetWorthByCurrency($date); $converted = $this->cerSum($result); diff --git a/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php b/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php index 8a73be5eac..35b63cd42c 100644 --- a/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php +++ b/app/Api/V2/Request/Autocomplete/AutocompleteRequest.php @@ -24,13 +24,10 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Request\Autocomplete; use FireflyIII\Enums\UserRoleEnum; -use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\AccountType; -use FireflyIII\Models\UserRole; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\User; -use FireflyIII\Validation\Administration\ValidatesAdministrationAccess; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Validator; @@ -39,13 +36,12 @@ use Illuminate\Validation\Validator; */ class AutocompleteRequest extends FormRequest { + protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS]; use ConvertsDataTypes; use ChecksLogin; - use ValidatesAdministrationAccess; /** * @return array - * @throws FireflyException */ public function getData(): array { @@ -63,11 +59,10 @@ class AutocompleteRequest extends FormRequest $user = auth()->user(); return [ - 'types' => $array, - 'query' => $this->convertString('query'), - 'date' => $this->getCarbonDate('date'), - 'limit' => $limit, - 'administration_id' => (int)($this->get('administration_id', null) ?? $user->getAdministrationId()), + 'types' => $array, + 'query' => $this->convertString('query'), + 'date' => $this->getCarbonDate('date'), + 'limit' => $limit, ]; } diff --git a/app/Helpers/Report/NetWorth.php b/app/Helpers/Report/NetWorth.php index 5b089c6159..f8505c7321 100644 --- a/app/Helpers/Report/NetWorth.php +++ b/app/Helpers/Report/NetWorth.php @@ -29,8 +29,8 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\UserGroup; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\User; @@ -39,6 +39,8 @@ use Illuminate\Support\Collection; use JsonException; /** + * This class can handle both request with and without a user group and will return the appropriate repository when + * necessary. * * Class NetWorth */ @@ -49,7 +51,7 @@ class NetWorth implements NetWorthInterface private CurrencyRepositoryInterface $currencyRepos; private User $user; - private UserGroup $userGroup; + private null | UserGroup $userGroup; /** * @param Collection $accounts @@ -67,7 +69,7 @@ class NetWorth implements NetWorthInterface $cache->addProperty('net-worth-by-accounts'); $cache->addProperty($ids); if ($cache->has()) { - //return $cache->get(); + return $cache->get(); } app('log')->debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d'))); @@ -96,7 +98,7 @@ class NetWorth implements NetWorthInterface /** @var Account $account */ foreach ($accounts as $account) { app('log')->debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name)); - $currency = $this->adminAccountRepository->getAccountCurrency($account); + $currency = $this->getRepository()->getAccountCurrency($account); $currencyId = (int)$currency->id; $balance = '0'; $nativeBalance = '0'; @@ -137,6 +139,17 @@ class NetWorth implements NetWorthInterface return $netWorth; } + /** + * @return AdminAccountRepositoryInterface|AccountRepositoryInterface + */ + private function getRepository(): AdminAccountRepositoryInterface | AccountRepositoryInterface + { + if (null === $this->userGroup) { + return $this->accountRepository; + } + return $this->adminAccountRepository; + } + /** * Returns the user's net worth in an array with the following layout: * @@ -181,7 +194,7 @@ class NetWorth implements NetWorthInterface /** @var Account $account */ foreach ($accounts as $account) { // Log::debug(sprintf('Now at account #%d: "%s"', $account->id, $account->name)); - $currencyId = (int)$this->accountRepository->getMetaValue($account, 'currency_id'); + $currencyId = (int)$this->getRepository()->getMetaValue($account, 'currency_id'); $currencyId = 0 === $currencyId ? $default->id : $currencyId; // Log::debug(sprintf('Currency ID is #%d', $currencyId)); @@ -227,7 +240,8 @@ class NetWorth implements NetWorthInterface if (null === $user) { return; } - $this->user = $user; + $this->user = $user; + $this->userGroup = null; // make repository: $this->accountRepository = app(AccountRepositoryInterface::class); @@ -239,7 +253,6 @@ class NetWorth implements NetWorthInterface /** * @inheritDoc - * @throws FireflyException */ public function setUserGroup(UserGroup $userGroup): void { @@ -260,7 +273,7 @@ class NetWorth implements NetWorthInterface $return = []; $balances = app('steam')->balancesByAccounts($accounts, $date); foreach ($accounts as $account) { - $currency = $this->accountRepository->getAccountCurrency($account); + $currency = $this->getRepository()->getAccountCurrency($account); $balance = $balances[$account->id] ?? '0'; // always subtract virtual balance. @@ -288,13 +301,13 @@ class NetWorth implements NetWorthInterface */ private function getAccounts(): Collection { - $accounts = $this->accountRepository->getAccountsByType( + $accounts = $this->getRepository()->getAccountsByType( [AccountType::ASSET, AccountType::DEFAULT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE] ); $filtered = new Collection(); /** @var Account $account */ foreach ($accounts as $account) { - if (1 === (int)$this->accountRepository->getMetaValue($account, 'include_net_worth')) { + if (1 === (int)$this->getRepository()->getMetaValue($account, 'include_net_worth')) { $filtered->push($account); } } diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index 95896d7579..cff35136c8 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -26,24 +26,21 @@ namespace FireflyIII\Http\Requests; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Models\Account; use FireflyIII\Models\Location; -use FireflyIII\Models\UserRole; use FireflyIII\Rules\UniqueIban; use FireflyIII\Support\Request\AppendsLocationData; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; -use FireflyIII\Validation\Administration\ValidatesAdministrationAccess; use Illuminate\Foundation\Http\FormRequest; -use Illuminate\Validation\Validator; /** * Class AccountFormRequest. */ class AccountFormRequest extends FormRequest { + protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS]; use ConvertsDataTypes; use AppendsLocationData; use ChecksLogin; - use ValidatesAdministrationAccess; /** * Get all data. @@ -53,7 +50,6 @@ class AccountFormRequest extends FormRequest public function getAccountData(): array { $data = [ - 'administration_id' => $this->convertInteger('administration_id'), 'name' => $this->convertString('name'), 'active' => $this->boolean('active'), 'account_type_name' => $this->convertString('objectType'), @@ -73,9 +69,6 @@ class AccountFormRequest extends FormRequest 'include_net_worth' => '1', 'liability_direction' => $this->convertString('liability_direction'), ]; - if (0 === $data['administration_id']) { - $data['administration_id'] = auth()->user()->getAdministrationId(); - } $data = $this->appendLocationData($data, 'location'); if (false === $this->boolean('include_net_worth')) { @@ -110,7 +103,6 @@ class AccountFormRequest extends FormRequest $types = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); $rules = [ - 'administration_id' => 'min:1|max:16777216|numeric', 'name' => 'required|max:1024|min:1|uniqueAccountForUser', 'opening_balance' => 'numeric|nullable|max:1000000000', 'opening_balance_date' => 'date|required_with:opening_balance|nullable', @@ -140,21 +132,4 @@ class AccountFormRequest extends FormRequest return $rules; } - - /** - * Configure the validator instance with special rules for after the basic validation rules. - * - * @param Validator $validator - * - * @return void - */ - public function withValidator(Validator $validator): void - { - $validator->after( - function (Validator $validator) { - // validate if the account can access this administration - $this->validateAdministration($validator, [UserRoleEnum::MANAGE_TRANSACTIONS->value]); - } - ); - } } diff --git a/app/Repositories/UserGroups/Account/AccountRepository.php b/app/Repositories/UserGroups/Account/AccountRepository.php index 9b7acaf693..061ad83872 100644 --- a/app/Repositories/UserGroups/Account/AccountRepository.php +++ b/app/Repositories/UserGroups/Account/AccountRepository.php @@ -32,6 +32,7 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; /** * Class AccountRepository @@ -40,6 +41,32 @@ class AccountRepository implements AccountRepositoryInterface { use UserGroupTrait; + /** + * @inheritDoc + */ + public function findByName(string $name, array $types): ?Account + { + $query = $this->userGroup->accounts(); + + if (0 !== count($types)) { + $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); + $query->whereIn('account_types.type', $types); + } + Log::debug(sprintf('Searching for account named "%s" (of user #%d) of the following type(s)', $name, $this->user->id), ['types' => $types]); + + $query->where('accounts.name', $name); + /** @var Account $account */ + $account = $query->first(['accounts.*']); + if (null === $account) { + Log::debug(sprintf('There is no account with name "%s" of types', $name), $types); + + return null; + } + Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id)); + + return $account; + } + /** * @param Account $account * diff --git a/app/Repositories/UserGroups/Account/AccountRepositoryInterface.php b/app/Repositories/UserGroups/Account/AccountRepositoryInterface.php index 2e3bbc6c1c..347baff32f 100644 --- a/app/Repositories/UserGroups/Account/AccountRepositoryInterface.php +++ b/app/Repositories/UserGroups/Account/AccountRepositoryInterface.php @@ -41,6 +41,14 @@ interface AccountRepositoryInterface */ public function find(int $accountId): ?Account; + /** + * @param string $name + * @param array $types + * + * @return Account|null + */ + public function findByName(string $name, array $types): ?Account; + /** * @param Account $account * diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php index 2d10f04d24..790ec698eb 100644 --- a/app/Transformers/UserTransformer.php +++ b/app/Transformers/UserTransformer.php @@ -48,15 +48,14 @@ class UserTransformer extends AbstractTransformer $this->repository = $this->repository ?? app(UserRepositoryInterface::class); return [ - 'id' => (int)$user->id, - 'administration_id' => (string)$user->getAdministrationId(), - 'created_at' => $user->created_at->toAtomString(), - 'updated_at' => $user->updated_at->toAtomString(), - 'email' => $user->email, - 'blocked' => 1 === (int)$user->blocked, - 'blocked_code' => '' === $user->blocked_code ? null : $user->blocked_code, - 'role' => $this->repository->getRoleByUser($user), - 'links' => [ + 'id' => (int)$user->id, + 'created_at' => $user->created_at->toAtomString(), + 'updated_at' => $user->updated_at->toAtomString(), + 'email' => $user->email, + 'blocked' => 1 === (int)$user->blocked, + 'blocked_code' => '' === $user->blocked_code ? null : $user->blocked_code, + 'role' => $this->repository->getRoleByUser($user), + 'links' => [ [ 'rel' => 'self', 'uri' => '/users/' . $user->id, diff --git a/app/Validation/Administration/ValidatesAdministrationAccess.php b/app/Validation/Administration/ValidatesAdministrationAccess.php index 61a13ccf64..ecd88233ec 100644 --- a/app/Validation/Administration/ValidatesAdministrationAccess.php +++ b/app/Validation/Administration/ValidatesAdministrationAccess.php @@ -34,6 +34,7 @@ use Illuminate\Support\Facades\Log; use Illuminate\Validation\Validator; /** + * @deprecated * Trait ValidatesAdministrationAccess */ trait ValidatesAdministrationAccess @@ -45,6 +46,7 @@ trait ValidatesAdministrationAccess * @return void * @throws AuthenticationException * @throws FireflyException + * @deprecated */ protected function validateAdministration(Validator $validator, array $allowedRoles): void { diff --git a/package-lock.json b/package-lock.json index e7e16191bb..5b325d1103 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "@popperjs/core": "^2.11.8", "alpinejs": "^3.13.0", "bootstrap": "^5.3.0", - "bootstrap5-autocomplete": "^1.1.20", + "bootstrap5-autocomplete": "^1.1.22", "chart.js": "^4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.12.0", diff --git a/package.json b/package.json index 393801fa53..c170c8dfae 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@popperjs/core": "^2.11.8", "alpinejs": "^3.13.0", "bootstrap": "^5.3.0", - "bootstrap5-autocomplete": "^1.1.20", + "bootstrap5-autocomplete": "^1.1.22", "chart.js": "^4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.12.0", diff --git a/resources/assets/js/components/transactions/CreateTransaction.vue b/resources/assets/js/components/transactions/CreateTransaction.vue index d16c16c1b6..e233fe84fe 100644 --- a/resources/assets/js/components/transactions/CreateTransaction.vue +++ b/resources/assets/js/components/transactions/CreateTransaction.vue @@ -19,984 +19,995 @@ -->