From 53e46895aa5c78bc9153fa05011e194178afcefd Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 9 Feb 2025 09:30:44 +0100 Subject: [PATCH] Expand a few repositories to support user groups. --- .../Autocomplete/TransactionController.php | 5 +++ app/Api/V1/Controllers/Controller.php | 2 + .../Models/Transaction/StoreController.php | 42 ++++++++++--------- .../Autocomplete/AccountController.php | 1 + app/Factory/TagFactory.php | 8 ++++ app/Factory/TransactionFactory.php | 11 +---- app/Factory/TransactionGroupFactory.php | 11 ++++- app/Factory/TransactionJournalFactory.php | 20 ++++++--- .../Account/AccountRepository.php | 4 +- .../Account/AccountRepositoryInterface.php | 2 + app/Repositories/Bill/BillRepository.php | 11 +---- .../Bill/BillRepositoryInterface.php | 2 + app/Repositories/Budget/BudgetRepository.php | 10 +---- .../Budget/BudgetRepositoryInterface.php | 2 + .../Category/CategoryRepository.php | 3 +- .../Category/CategoryRepositoryInterface.php | 2 + .../PiggyBank/PiggyBankRepository.php | 4 +- .../PiggyBankRepositoryInterface.php | 2 + .../TransactionGroupRepository.php | 13 ++---- .../TransactionGroupRepositoryInterface.php | 2 + .../Http/Api/ValidatesUserGroupTrait.php | 3 +- .../Repositories/UserGroup/UserGroupTrait.php | 37 +++++++++++----- 22 files changed, 121 insertions(+), 76 deletions(-) diff --git a/app/Api/V1/Controllers/Autocomplete/TransactionController.php b/app/Api/V1/Controllers/Autocomplete/TransactionController.php index b6746339a9..15a3215a87 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\AutocompleteRequest; +use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; @@ -41,6 +42,8 @@ class TransactionController extends Controller private TransactionGroupRepositoryInterface $groupRepository; private JournalRepositoryInterface $repository; + protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; + /** * TransactionController constructor. */ @@ -51,10 +54,12 @@ class TransactionController extends Controller function ($request, $next) { /** @var User $user */ $user = auth()->user(); + $userGroup = $this->validateUserGroup($request); $this->repository = app(JournalRepositoryInterface::class); $this->groupRepository = app(TransactionGroupRepositoryInterface::class); $this->repository->setUser($user); $this->groupRepository->setUser($user); + $this->groupRepository->setUserGroup($userGroup); return $next($request); } diff --git a/app/Api/V1/Controllers/Controller.php b/app/Api/V1/Controllers/Controller.php index f256bf06b3..17f665f824 100644 --- a/app/Api/V1/Controllers/Controller.php +++ b/app/Api/V1/Controllers/Controller.php @@ -31,6 +31,7 @@ use FireflyIII\Models\Preference; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Steam; +use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Transformers\V2\AbstractTransformer; use FireflyIII\User; use Illuminate\Database\Eloquent\Model; @@ -59,6 +60,7 @@ abstract class Controller extends BaseController use AuthorizesRequests; use DispatchesJobs; use ValidatesRequests; + use ValidatesUserGroupTrait; protected const string CONTENT_TYPE = 'application/vnd.api+json'; protected const string JSON_CONTENT_TYPE = 'application/json'; diff --git a/app/Api/V1/Controllers/Models/Transaction/StoreController.php b/app/Api/V1/Controllers/Models/Transaction/StoreController.php index 5e42c1e744..3858687025 100644 --- a/app/Api/V1/Controllers/Models/Transaction/StoreController.php +++ b/app/Api/V1/Controllers/Models/Transaction/StoreController.php @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Transaction; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Models\Transaction\StoreRequest; +use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; @@ -37,6 +38,7 @@ use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; use League\Fractal\Resource\Item; @@ -49,6 +51,8 @@ class StoreController extends Controller private TransactionGroupRepositoryInterface $groupRepository; + protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS]; + /** * TransactionController constructor. */ @@ -58,10 +62,12 @@ class StoreController extends Controller $this->middleware( function ($request, $next) { /** @var User $admin */ - $admin = auth()->user(); + $admin = auth()->user(); + $userGroup = $this->validateUserGroup($request); $this->groupRepository = app(TransactionGroupRepositoryInterface::class); $this->groupRepository->setUser($admin); + $this->groupRepository->setUserGroup($userGroup); return $next($request); } @@ -79,51 +85,47 @@ class StoreController extends Controller public function store(StoreRequest $request): JsonResponse { app('log')->debug('Now in API StoreController::store()'); - $data = $request->getAll(); - $data['user'] = auth()->user()->id; + $data = $request->getAll(); + $data['user'] = auth()->user(); + $data['user_group'] = $this->userGroup; - Log::channel('audit') - ->info('Store new transaction over API.', $data) - ; + Log::channel('audit')->info('Store new transaction over API.', $data); try { $transactionGroup = $this->groupRepository->store($data); } catch (DuplicateTransactionException $e) { app('log')->warning('Caught a duplicate transaction. Return error message.'); - $validator = \Validator::make( - ['transactions' => [['description' => $e->getMessage()]]], - ['transactions.0.description' => new IsDuplicateTransaction()] - ); + $validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]); throw new ValidationException($validator); } catch (FireflyException $e) { app('log')->warning('Caught an exception. Return error message.'); app('log')->error($e->getMessage()); $message = sprintf('Internal exception: %s', $e->getMessage()); - $validator = \Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]); + $validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]); throw new ValidationException($validator); } app('preferences')->mark(); - $applyRules = $data['apply_rules'] ?? true; - $fireWebhooks = $data['fire_webhooks'] ?? true; + $applyRules = $data['apply_rules'] ?? true; + $fireWebhooks = $data['fire_webhooks'] ?? true; event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks)); - $manager = $this->getManager(); + $manager = $this->getManager(); /** @var User $admin */ - $admin = auth()->user(); + $admin = auth()->user(); // use new group collector: /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector ->setUser($admin) + ->setUserGroup($this->userGroup) // filter on transaction group. ->setTransactionGroup($transactionGroup) // all info needed for the API: - ->withAPIInformation() - ; + ->withAPIInformation(); $selectedGroup = $collector->getGroups()->first(); if (null === $selectedGroup) { @@ -131,9 +133,9 @@ class StoreController extends Controller } /** @var TransactionGroupTransformer $transformer */ - $transformer = app(TransactionGroupTransformer::class); + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); - $resource = new Item($selectedGroup, $transformer, 'transactions'); + $resource = new Item($selectedGroup, $transformer, 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } diff --git a/app/Api/V2/Controllers/Autocomplete/AccountController.php b/app/Api/V2/Controllers/Autocomplete/AccountController.php index 946828aafb..5752b2f69a 100644 --- a/app/Api/V2/Controllers/Autocomplete/AccountController.php +++ b/app/Api/V2/Controllers/Autocomplete/AccountController.php @@ -32,6 +32,7 @@ use FireflyIII\Models\AccountBalance; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; use FireflyIII\Support\Http\Api\ExchangeRateConverter; +use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Log; diff --git a/app/Factory/TagFactory.php b/app/Factory/TagFactory.php index 36c5a5b50a..f1ec639ea5 100644 --- a/app/Factory/TagFactory.php +++ b/app/Factory/TagFactory.php @@ -26,6 +26,7 @@ namespace FireflyIII\Factory; use FireflyIII\Models\Location; use FireflyIII\Models\Tag; +use FireflyIII\Models\UserGroup; use FireflyIII\User; /** @@ -34,6 +35,7 @@ use FireflyIII\User; class TagFactory { private User $user; + private UserGroup $userGroup; public function findOrCreate(string $tag): ?Tag { @@ -102,5 +104,11 @@ class TagFactory public function setUser(User $user): void { $this->user = $user; + $this->userGroup = $user->userGroup; + } + + public function setUserGroup(UserGroup $userGroup): void + { + $this->userGroup = $userGroup; } } diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index 78def382e2..4238aac71c 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -29,6 +29,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\UserGroup; use FireflyIII\Rules\UniqueIban; use FireflyIII\Services\Internal\Update\AccountUpdateService; use FireflyIII\User; @@ -163,7 +164,7 @@ class TransactionFactory } app('log')->debug('Will update account with IBAN information.'); - $service = app(AccountUpdateService::class); + $service = app(AccountUpdateService::class); $service->update($this->account, ['iban' => $this->accountInformation['iban']]); } @@ -216,12 +217,4 @@ class TransactionFactory { $this->reconciled = $reconciled; } - - /** - * @SuppressWarnings("PHPMD.UnusedFormalParameter") - */ - public function setUser(User $user): void - { - // empty function. - } } diff --git a/app/Factory/TransactionGroupFactory.php b/app/Factory/TransactionGroupFactory.php index cf624bc7a2..4d894a0aea 100644 --- a/app/Factory/TransactionGroupFactory.php +++ b/app/Factory/TransactionGroupFactory.php @@ -27,6 +27,7 @@ namespace FireflyIII\Factory; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\UserGroup; use FireflyIII\User; /** @@ -36,6 +37,7 @@ class TransactionGroupFactory { private TransactionJournalFactory $journalFactory; private User $user; + private UserGroup $userGroup; /** * TransactionGroupFactory constructor. @@ -54,7 +56,8 @@ class TransactionGroupFactory public function create(array $data): TransactionGroup { app('log')->debug('Now in TransactionGroupFactory::create()'); - $this->journalFactory->setUser($this->user); + $this->journalFactory->setUser($data['user']); + $this->journalFactory->setUserGroup($data['user_group']); $this->journalFactory->setErrorOnHash($data['error_if_duplicate_hash'] ?? false); try { @@ -76,7 +79,7 @@ class TransactionGroupFactory $group = new TransactionGroup(); $group->user()->associate($this->user); - $group->userGroup()->associate($data['user_group'] ?? $this->user->userGroup); + $group->userGroup()->associate($data['user_group']); $group->title = $title; $group->save(); @@ -92,4 +95,8 @@ class TransactionGroupFactory { $this->user = $user; } + + public function setUserGroup(UserGroup $userGroup): void { + $this->userGroup = $userGroup; + } } diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index 42c98aefea..0f8e95a8ec 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -34,6 +34,7 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalMeta; +use FireflyIII\Models\UserGroup; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; @@ -69,6 +70,7 @@ class TransactionJournalFactory private PiggyBankRepositoryInterface $piggyRepository; private TransactionTypeRepositoryInterface $typeRepository; private User $user; + private UserGroup $userGroup; /** * Constructor. @@ -176,8 +178,6 @@ class TransactionJournalFactory if (true === FireflyConfig::get('utc', false)->data) { $carbon->setTimezone('UTC'); } - // $carbon->setTimezone('UTC'); - try { // validate source and destination using a new Validator. $this->validateAccounts($row); @@ -228,7 +228,7 @@ class TransactionJournalFactory $journal = TransactionJournal::create( [ 'user_id' => $this->user->id, - 'user_group_id' => $this->user->user_group_id, + 'user_group_id' => $this->userGroup->id, 'transaction_type_id' => $type->id, 'bill_id' => $billId, 'transaction_currency_id' => $currency->id, @@ -244,7 +244,6 @@ class TransactionJournalFactory /** Create two transactions. */ $transactionFactory = app(TransactionFactory::class); - $transactionFactory->setUser($this->user); $transactionFactory->setJournal($journal); $transactionFactory->setAccount($sourceAccount); $transactionFactory->setCurrency($currency); @@ -263,7 +262,6 @@ class TransactionJournalFactory /** @var TransactionFactory $transactionFactory */ $transactionFactory = app(TransactionFactory::class); - $transactionFactory->setUser($this->user); $transactionFactory->setJournal($journal); $transactionFactory->setAccount($destinationAccount); $transactionFactory->setAccountInformation($destInfo); @@ -405,6 +403,7 @@ class TransactionJournalFactory public function setUser(User $user): void { $this->user = $user; + $this->userGroup = $user->userGroup; $this->currencyRepository->setUser($this->user); $this->tagFactory->setUser($user); $this->billRepository->setUser($this->user); @@ -414,6 +413,17 @@ class TransactionJournalFactory $this->accountRepository->setUser($this->user); } + public function setUserGroup(UserGroup $userGroup): void { + $this->userGroup = $userGroup; + $this->currencyRepository->setUserGroup($userGroup); + $this->tagFactory->setUserGroup($userGroup); + $this->billRepository->setUserGroup($userGroup); + $this->budgetRepository->setUserGroup($userGroup); + $this->categoryRepository->setUserGroup($userGroup); + $this->piggyRepository->setUserGroup($userGroup); + $this->accountRepository->setUserGroup($userGroup); + } + private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array { app('log')->debug(sprintf('Now in %s', __METHOD__)); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 1966133d5d..f5b492b4f1 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -40,6 +40,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Services\Internal\Destroy\AccountDestroyService; use FireflyIII\Services\Internal\Update\AccountUpdateService; use FireflyIII\Support\Facades\Steam; +use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; @@ -51,7 +52,8 @@ use Illuminate\Support\Collection; */ class AccountRepository implements AccountRepositoryInterface { - private User $user; + use UserGroupTrait; + /** * Moved here from account CRUD. diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index f79883c064..20e1fafb16 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Location; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -148,6 +149,7 @@ interface AccountRepositoryInterface public function searchAccountNr(string $query, array $types, int $limit): Collection; public function setUser(null|Authenticatable|User $user): void; + public function setUserGroup(UserGroup $userGroup): void; public function store(array $data): Account; diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 1d8bb2ebd2..25471b2397 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -38,6 +38,7 @@ use FireflyIII\Services\Internal\Destroy\BillDestroyService; use FireflyIII\Services\Internal\Update\BillUpdateService; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Facades\Amount; +use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Query\JoinClause; @@ -51,8 +52,7 @@ use Illuminate\Support\Facades\Log; class BillRepository implements BillRepositoryInterface { use CreatesObjectGroups; - - private User $user; + use UserGroupTrait; public function billEndsWith(string $query, int $limit): Collection { @@ -294,13 +294,6 @@ class BillRepository implements BillRepositoryInterface return $result; } - public function setUser(null|Authenticatable|User $user): void - { - if ($user instanceof User) { - $this->user = $user; - } - } - public function getPaginator(int $size): LengthAwarePaginator { return $this->user->bills() diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index c74467cc31..2e50edca39 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Bill; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Bill; +use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Pagination\LengthAwarePaginator; @@ -39,6 +40,7 @@ interface BillRepositoryInterface public function billEndsWith(string $query, int $limit): Collection; public function billStartsWith(string $query, int $limit): Collection; + public function setUserGroup(UserGroup $userGroup): void; /** * Add correct order to bills. diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 452f62e4d0..6b19e6eced 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -41,6 +41,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface; use FireflyIII\Services\Internal\Destroy\BudgetDestroyService; use FireflyIII\Support\Http\Api\ExchangeRateConverter; +use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\QueryException; @@ -52,7 +53,7 @@ use Illuminate\Support\Facades\Log; */ class BudgetRepository implements BudgetRepositoryInterface { - private User $user; + use UserGroupTrait; public function budgetEndsWith(string $query, int $limit): Collection { @@ -154,13 +155,6 @@ class BudgetRepository implements BudgetRepositoryInterface return $return; } - public function setUser(null|Authenticatable|User $user): void - { - if ($user instanceof User) { - $this->user = $user; - } - } - public function getActiveBudgets(): Collection { return $this->user->budgets()->where('active', true) diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index 972181b6f9..918ba2273f 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -27,6 +27,7 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\AutoBudget; use FireflyIII\Models\Budget; +use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -39,6 +40,7 @@ interface BudgetRepositoryInterface public function budgetEndsWith(string $query, int $limit): Collection; public function budgetStartsWith(string $query, int $limit): Collection; + public function setUserGroup(UserGroup $userGroup): void; /** * Returns the amount that is budgeted in a period. diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 91fe6a6cce..53d25b6686 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -33,6 +33,7 @@ use FireflyIII\Models\RecurrenceTransactionMeta; use FireflyIII\Models\RuleAction; use FireflyIII\Services\Internal\Destroy\CategoryDestroyService; use FireflyIII\Services\Internal\Update\CategoryUpdateService; +use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -43,7 +44,7 @@ use Illuminate\Support\Facades\Log; */ class CategoryRepository implements CategoryRepositoryInterface { - private User $user; + use UserGroupTrait; public function categoryEndsWith(string $query, int $limit): Collection { diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index 94e7bd7c48..f5e7a6b995 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Category; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Category; +use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -87,6 +88,7 @@ interface CategoryRepositoryInterface public function searchCategory(string $query, int $limit): Collection; public function setUser(null|Authenticatable|User $user): void; + public function setUserGroup(UserGroup $userGroup): void; /** * @throws FireflyException diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index 7f420ab30f..aaecbf30da 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -36,6 +36,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\Facades\Steam; +use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -48,7 +49,8 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface { use ModifiesPiggyBanks; - private User $user; + use UserGroupTrait; + public function destroyAll(): void { diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index c99e6df4b3..12551ef4e7 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -29,6 +29,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -136,6 +137,7 @@ interface PiggyBankRepositoryInterface public function setOrder(PiggyBank $piggyBank, int $newOrder): bool; public function setUser(null|Authenticatable|User $user): void; + public function setUserGroup(UserGroup $userGroup): void; /** * Store new piggy bank. diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepository.php b/app/Repositories/TransactionGroup/TransactionGroupRepository.php index 0182ee40a2..3fad4bb248 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepository.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepository.php @@ -43,6 +43,7 @@ use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; use FireflyIII\Services\Internal\Update\GroupUpdateService; use FireflyIII\Support\NullArrayObject; +use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Builder; @@ -53,7 +54,7 @@ use Illuminate\Support\Collection; */ class TransactionGroupRepository implements TransactionGroupRepositoryInterface { - private User $user; + use UserGroupTrait; public function countAttachments(int $journalId): int { @@ -163,13 +164,6 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface return $result; } - public function setUser(null|Authenticatable|User $user): void - { - if ($user instanceof User) { - $this->user = $user; - } - } - /** * Get the note text for a journal (by ID). */ @@ -408,7 +402,8 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface { /** @var TransactionGroupFactory $factory */ $factory = app(TransactionGroupFactory::class); - $factory->setUser($this->user); + $factory->setUser($data['user']); + $factory->setUserGroup($data['user_group']); try { return $factory->create($data); diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php index 380d1d05da..c0bc7c35f8 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Location; use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\UserGroup; use FireflyIII\Support\NullArrayObject; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; @@ -98,6 +99,7 @@ interface TransactionGroupRepositoryInterface public function getTags(int $journalId): array; public function setUser(null|Authenticatable|User $user): void; + public function setUserGroup(UserGroup $userGroup): void; /** * Create a new transaction group. diff --git a/app/Support/Http/Api/ValidatesUserGroupTrait.php b/app/Support/Http/Api/ValidatesUserGroupTrait.php index 8220baac56..244d77ae6b 100644 --- a/app/Support/Http/Api/ValidatesUserGroupTrait.php +++ b/app/Support/Http/Api/ValidatesUserGroupTrait.php @@ -38,6 +38,7 @@ use Illuminate\Support\Facades\Log; */ trait ValidatesUserGroupTrait { + protected ?UserGroup $userGroup = null; /** * An "undocumented" filter * @@ -98,7 +99,7 @@ trait ValidatesUserGroupTrait foreach ($roles as $role) { if ($user->hasRoleInGroupOrOwner($group, $role)) { Log::debug(sprintf('validateUserGroup: User has role "%s" in group #%d, return the group.', $role->value, $groupId)); - + $this->userGroup = $group; return $group; } Log::debug(sprintf('validateUserGroup: User does NOT have role "%s" in group #%d, continue searching.', $role->value, $groupId)); diff --git a/app/Support/Repositories/UserGroup/UserGroupTrait.php b/app/Support/Repositories/UserGroup/UserGroupTrait.php index 72559775ec..58029d00d5 100644 --- a/app/Support/Repositories/UserGroup/UserGroupTrait.php +++ b/app/Support/Repositories/UserGroup/UserGroupTrait.php @@ -24,45 +24,63 @@ declare(strict_types=1); namespace FireflyIII\Support\Repositories\UserGroup; +use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\GroupMembership; use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; +use Illuminate\Support\Facades\Log; /** * Trait UserGroupTrait */ trait UserGroupTrait { - protected User $user; - protected UserGroup $userGroup; + protected ?User $user = null; + protected ?UserGroup $userGroup = null; public function getUserGroup(): UserGroup { return $this->userGroup; } + public function checkUserGroupAccess(UserRoleEnum $role): bool + { + $result = $this->user->hasRoleInGroupOrOwner($this->userGroup, $role); + if($result) { + Log::debug(sprintf('User #%d has role %s in group #%d or is owner/full.', $this->user->id, $role->value, $this->userGroup->id)); + return true; + } + Log::warning(sprintf('User #%d DOES NOT have role %s in group #%d.', $this->user->id, $role->value, $this->userGroup->id)); + return false; + } + /** * TODO This method does not check if the user has access to this particular user group. */ public function setUserGroup(UserGroup $userGroup): void { + if (null === $this->user) { + Log::warning(sprintf('User is not set in repository %s', get_class($this))); + } $this->userGroup = $userGroup; } /** * @throws FireflyException */ - public function setUser(null|Authenticatable|User $user): void + public function setUser(null | Authenticatable | User $user): void { if ($user instanceof User) { - $this->user = $user; + $this->user = $user; if (null === $user->userGroup) { throw new FireflyException(sprintf('User #%d has no user group.', $user->id)); } $this->userGroup = $user->userGroup; + return; } + throw new FireflyException(sprintf('Object is of class %s, not User.', get_class($user))); } /** @@ -70,19 +88,18 @@ trait UserGroupTrait */ public function setUserGroupById(int $userGroupId): void { - $memberships = GroupMembership::where('user_id', $this->user->id) - ->where('user_group_id', $userGroupId) - ->count() - ; + $memberships = GroupMembership::where('user_id', $this->user->id) + ->where('user_group_id', $userGroupId) + ->count(); if (0 === $memberships) { throw new FireflyException(sprintf('User #%d has no access to administration #%d', $this->user->id, $userGroupId)); } /** @var null|UserGroup $userGroup */ - $userGroup = UserGroup::find($userGroupId); + $userGroup = UserGroup::find($userGroupId); if (null === $userGroup) { throw new FireflyException(sprintf('Cannot find administration for user #%d', $this->user->id)); } - $this->userGroup = $userGroup; + $this->setUserGroup($userGroup); } }