Restrict removing owner from organization

This commit is contained in:
Constantin Graf
2024-05-21 18:53:20 +02:00
parent 98eea87b5f
commit 2c20e941da
5 changed files with 36 additions and 1 deletions

View File

@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace App\Exceptions\Api;
class CanNotRemoveOwnerFromOrganization extends ApiException
{
public const string KEY = 'can_not_remove_owner_from_organization';
}

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Http\Controllers\Api\V1;
use App\Enums\Role;
use App\Exceptions\Api\CanNotRemoveOwnerFromOrganization;
use App\Exceptions\Api\EntityStillInUseApiException;
use App\Exceptions\Api\UserNotPlaceholderApiException;
use App\Http\Requests\V1\Member\MemberIndexRequest;
@@ -72,7 +73,7 @@ class MemberController extends Controller
/**
* Remove a member of the organization.
*
* @throws AuthorizationException|EntityStillInUseApiException
* @throws AuthorizationException|EntityStillInUseApiException|CanNotRemoveOwnerFromOrganization
*
* @operationId removeMember
*/
@@ -86,6 +87,9 @@ class MemberController extends Controller
if (ProjectMember::query()->whereBelongsToOrganization($organization)->where('user_id', $member->user_id)->exists()) {
throw new EntityStillInUseApiException('member', 'project_member');
}
if ($member->role === Role::Owner->value) {
throw new CanNotRemoveOwnerFromOrganization();
}
$member->delete();

View File

@@ -2,6 +2,7 @@
declare(strict_types=1);
use App\Exceptions\Api\CanNotRemoveOwnerFromOrganization;
use App\Exceptions\Api\EntityStillInUseApiException;
use App\Exceptions\Api\InactiveUserCanNotBeUsedApiException;
use App\Exceptions\Api\TimeEntryCanNotBeRestartedApiException;
@@ -17,5 +18,6 @@ return [
InactiveUserCanNotBeUsedApiException::KEY => 'Inactive user can not be used',
UserIsAlreadyMemberOfProjectApiException::KEY => 'User is already a member of the project',
EntityStillInUseApiException::KEY => 'The :modelToDelete is still used by a :modelInUse and can not be deleted.',
CanNotRemoveOwnerFromOrganization::KEY => 'Can not remove owner from organization',
],
];

View File

@@ -141,6 +141,23 @@ class MemberEndpointTest extends ApiEndpointTestAbstract
$response->assertStatus(403);
}
public function test_destroy_member_fails_if_member_is_owner(): void
{
// Arrange
$data = $this->createUserWithPermission([
'members:delete',
]);
$memberToDelete = Member::factory()->forOrganization($data->organization)->role(Role::Owner)->create();
Passport::actingAs($data->user);
// Act
$response = $this->deleteJson(route('api.v1.members.destroy', [$data->organization->getKey(), $memberToDelete->getKey()]));
// Assert
$response->assertStatus(400);
$response->assertJsonPath('message', 'Can not remove owner from organization');
}
public function test_destroy_member_fails_if_member_is_not_part_of_org(): void
{
// Arrange

View File

@@ -7,6 +7,7 @@ namespace Tests\Unit\Service\Import;
use App\Models\Organization;
use App\Service\Import\ImportService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class ImportServiceTest extends TestCase
@@ -16,6 +17,7 @@ class ImportServiceTest extends TestCase
public function test_import_gets_importer_from_provider_runs_importer_and_returns_report(): void
{
// Arrange
Storage::fake('s3');
$organization = Organization::factory()->create();
$data = file_get_contents(storage_path('tests/toggl_time_entries_import_test_1.csv'));