diff --git a/app/Api/V2/Controllers/UserGroup/DestroyController.php b/app/Api/V2/Controllers/UserGroup/DestroyController.php index 27254ace92..123b9eded6 100644 --- a/app/Api/V2/Controllers/UserGroup/DestroyController.php +++ b/app/Api/V2/Controllers/UserGroup/DestroyController.php @@ -26,10 +26,52 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Controllers\UserGroup; use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Enums\UserRoleEnum; +use FireflyIII\Models\UserGroup; +use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class DestroyController */ class DestroyController extends Controller { + private UserGroupRepositoryInterface $repository; + + /** + * + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->repository = app(UserGroupRepositoryInterface::class); + + return $next($request); + } + ); + } + + /** + * @param Request $request + * @param UserGroup $userGroup + * + * @return JsonResponse + */ + public function destroy(Request $request, UserGroup $userGroup): JsonResponse + { + /** @var User $user */ + $user = auth()->user(); + // need owner role or system owner role to delete user group. + $access = $user->hasRoleInGroup($userGroup, UserRoleEnum::OWNER, false, true); + if (false === $access) { + throw new NotFoundHttpException(); + } + $this->repository->destroy($userGroup); + return response()->json([], 204); + } } diff --git a/app/Models/CurrencyExchangeRate.php b/app/Models/CurrencyExchangeRate.php index 05c23410b9..7147f80134 100644 --- a/app/Models/CurrencyExchangeRate.php +++ b/app/Models/CurrencyExchangeRate.php @@ -29,6 +29,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Carbon; /** @@ -66,6 +67,8 @@ use Illuminate\Support\Carbon; */ class CurrencyExchangeRate extends Model { + use SoftDeletes; + /** @var array Convert these fields to other data types */ protected $casts = [ @@ -108,7 +111,7 @@ class CurrencyExchangeRate extends Model protected function rate(): Attribute { return Attribute::make( - get: fn ($value) => (string)$value, + get: fn($value) => (string)$value, ); } @@ -118,7 +121,7 @@ class CurrencyExchangeRate extends Model protected function userRate(): Attribute { return Attribute::make( - get: fn ($value) => (string)$value, + get: fn($value) => (string)$value, ); } } diff --git a/app/Models/UserGroup.php b/app/Models/UserGroup.php index 20e68bfd51..21941ef0d9 100644 --- a/app/Models/UserGroup.php +++ b/app/Models/UserGroup.php @@ -109,6 +109,16 @@ class UserGroup extends Model return $this->hasMany(Account::class); } + /** + * Link to attachments. + * + * @return HasMany + */ + public function attachments(): HasMany + { + return $this->hasMany(Attachment::class); + } + /** * Link to bills. * @@ -139,6 +149,26 @@ class UserGroup extends Model return $this->hasMany(Budget::class); } + /** + * Link to categories. + * + * @return HasMany + */ + public function categories(): HasMany + { + return $this->hasMany(Category::class); + } + + /** + * Link to exchange rates. + * + * @return HasMany + */ + public function currencyExchangeRates(): HasMany + { + return $this->hasMany(CurrencyExchangeRate::class); + } + /** * * @return HasMany @@ -148,6 +178,14 @@ class UserGroup extends Model return $this->hasMany(GroupMembership::class); } + /** + * @return HasMany + */ + public function objectGroups(): HasMany + { + return $this->hasMany(ObjectGroup::class); + } + /** * Link to piggy banks. * @@ -158,6 +196,46 @@ class UserGroup extends Model return $this->hasManyThrough(PiggyBank::class, Account::class); } + /** + * @return HasMany + */ + public function recurrences(): HasMany + { + return $this->hasMany(Recurrence::class); + } + + /** + * @return HasMany + */ + public function ruleGroups(): HasMany + { + return $this->hasMany(RuleGroup::class); + } + + /** + * @return HasMany + */ + public function rules(): HasMany + { + return $this->hasMany(Rule::class); + } + + /** + * @return HasMany + */ + public function tags(): HasMany + { + return $this->hasMany(Tag::class); + } + + /** + * @return HasMany + */ + public function transactionGroups(): HasMany + { + return $this->hasMany(TransactionGroup::class); + } + /** * Link to transaction journals. * @@ -167,4 +245,12 @@ class UserGroup extends Model { return $this->hasMany(TransactionJournal::class); } + + /** + * @return HasMany + */ + public function webhooks(): HasMany + { + return $this->hasMany(Webhook::class); + } } diff --git a/app/Repositories/UserGroup/UserGroupRepository.php b/app/Repositories/UserGroup/UserGroupRepository.php index 4071067c08..333800766b 100644 --- a/app/Repositories/UserGroup/UserGroupRepository.php +++ b/app/Repositories/UserGroup/UserGroupRepository.php @@ -39,6 +39,61 @@ class UserGroupRepository implements UserGroupRepositoryInterface { private User $user; + /** + * @inheritDoc + */ + public function destroy(UserGroup $userGroup): void + { + app('log')->debug(sprintf('Going to destroy user group #%d ("%s").', $userGroup->id, $userGroup->title)); + $memberships = $userGroup->groupMemberships()->get(); + /** @var GroupMembership $membership */ + foreach ($memberships as $membership) { + /** @var User $user */ + $user = $membership->user()->first(); + if (null === $user) { + continue; + } + app('log')->debug(sprintf('Processing membership #%d (user #%d "%s")', $membership->id, $user->id, $user->email)); + // user has memberships of other groups? + $count = $user->groupMemberships()->where('user_group_id', '!=', $userGroup->id)->count(); + if (0 === $count) { + app('log')->debug('User has no other memberships and needs a new administration.'); + // makeNewAdmin() + // assignToUser(). + } + // user has other memberships, select one at random and assign it to the user. + if ($count > 0) { + // findAndAssign() + } + // deleteMembership() + } + // all users are now moved away from user group. + // time to DESTROY all objects. + // TODO piggy banks linked to accounts were deleting. + $userGroup->piggyBanks()->delete(); + $userGroup->accounts()->delete(); + $userGroup->availableBudgets()->delete(); + $userGroup->attachments()->delete(); + $userGroup->bills()->delete(); + $userGroup->budgets()->delete(); + $userGroup->categories()->delete(); + $userGroup->currencyExchangeRates()->delete(); + $userGroup->objectGroups()->delete(); + $userGroup->recurrences()->delete(); + $userGroup->rules()->delete(); + $userGroup->ruleGroups()->delete(); + $userGroup->tags()->delete(); + $userGroup->transactionJournals()->delete(); // TODO needs delete service probably. + $userGroup->transactionGroups()->delete(); // TODO needs delete service probably. + $userGroup->webhooks()->delete(); + + // user group deletion should also delete everything else. + // for all users, if this is the primary user group switch to the first alternative. + // if they have no other memberships, create a new user group for them. + $userGroup->delete(); + + } + /** * Returns all groups the user is member in. * diff --git a/app/Repositories/UserGroup/UserGroupRepositoryInterface.php b/app/Repositories/UserGroup/UserGroupRepositoryInterface.php index 143d7b2a60..f703d917a0 100644 --- a/app/Repositories/UserGroup/UserGroupRepositoryInterface.php +++ b/app/Repositories/UserGroup/UserGroupRepositoryInterface.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\UserGroup; +use FireflyIII\Models\UserGroup; use FireflyIII\User; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Support\Collection; @@ -34,6 +35,13 @@ use Illuminate\Support\Collection; */ interface UserGroupRepositoryInterface { + /** + * @param UserGroup $userGroup + * + * @return void + */ + public function destroy(UserGroup $userGroup): void; + /** * @return Collection */ diff --git a/routes/api.php b/routes/api.php index 0b9456f0c2..e7ea26fe69 100644 --- a/routes/api.php +++ b/routes/api.php @@ -83,7 +83,7 @@ Route::group( */ Route::group( [ - 'namespace' => 'FireflyIII\Api\V2\Controllers', + 'namespace' => 'FireflyIII\Api\V2\Controllers\Summary', 'prefix' => 'v2/net-worth', 'as' => 'api.v2.net-worth.', ], @@ -215,6 +215,7 @@ Route::group( Route::get('', ['uses' => 'ShowController@index', 'as' => 'index']); Route::post('', ['uses' => 'StoreController@store', 'as' => 'store']); Route::get('{userGroup}', ['uses' => 'ShowController@show', 'as' => 'show']); + Route::delete('{userGroup}', ['uses' => 'DestroyController@destroy', 'as' => 'destroy']); } );