From f51ed2ccd948270595b7bf57be90a797b7e01ea8 Mon Sep 17 00:00:00 2001 From: Ankit Kabra <164159992+ankit-canyon@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:12:18 +0530 Subject: [PATCH] [AIDAPP-301] Prevent users from viewing service requests of types that they are not managers or auditors of (#277) * Prevent users from viewing service requests of types that they are not managers or auditors of * removed pysh file * Resolve suggestions * chore: fix code style --------- Co-authored-by: ankit-canyon --- .../Pages/ListServiceRequests.php | 9 +- .../src/Policies/ServiceRequestPolicy.php | 12 ++ .../ListServiceRequestsTest.php | 87 ++++++++++++ .../ServiceRequest/ViewServiceRequestTest.php | 127 +++++++++++++++--- 4 files changed, 214 insertions(+), 21 deletions(-) diff --git a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php index 96772b2aa..24af61276 100644 --- a/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php +++ b/app-modules/service-management/src/Filament/Resources/ServiceRequestResource/Pages/ListServiceRequests.php @@ -74,7 +74,14 @@ public function table(Table $table): Table 'sla', ], 'status', - ])) + ]) + ->when(! auth()->user()->hasRole('authorization.super_admin'), function (Builder $q) { + return $q->whereHas('priority.type.managers', function (Builder $query): void { + $query->where('teams.id', auth()->user()->teams()->first()?->getKey()); + })->orWhereHas('priority.type.auditors', function (Builder $query): void { + $query->where('teams.id', auth()->user()->teams()->first()?->getKey()); + }); + })) ->columns([ IdColumn::make(), TextColumn::make('service_request_number') diff --git a/app-modules/service-management/src/Policies/ServiceRequestPolicy.php b/app-modules/service-management/src/Policies/ServiceRequestPolicy.php index 0f7099c59..691ff524e 100644 --- a/app-modules/service-management/src/Policies/ServiceRequestPolicy.php +++ b/app-modules/service-management/src/Policies/ServiceRequestPolicy.php @@ -76,6 +76,18 @@ public function view(Authenticatable $authenticatable, ServiceRequest $serviceRe return Response::deny('You do not have permission to view this service request.'); } + if (! auth()->user()->hasRole('authorization.super_admin')) { + $team = auth()->user()->teams()->first(); + + if (! $serviceRequest?->priority?->type?->managers()->exists() && ! $serviceRequest?->priority?->type?->auditors()->exists()) { + return Response::deny("You don't have permission to view this service request because you're not an auditor or manager."); + } + + if (! $serviceRequest?->priority?->type?->managers->contains('id', $team?->getKey()) && ! $serviceRequest?->priority?->type?->auditors->contains('id', $team?->getKey())) { + return Response::deny("You don't have permission to view this service request because you're not an auditor or manager."); + } + } + return $authenticatable->canOrElse( abilities: ['service_request.*.view', "service_request.{$serviceRequest->id}.view"], denyResponse: 'You do not have permission to view this service request.' diff --git a/app-modules/service-management/tests/ServiceRequest/ListServiceRequestsTest.php b/app-modules/service-management/tests/ServiceRequest/ListServiceRequestsTest.php index 417d89baf..5158ad2f2 100644 --- a/app-modules/service-management/tests/ServiceRequest/ListServiceRequestsTest.php +++ b/app-modules/service-management/tests/ServiceRequest/ListServiceRequestsTest.php @@ -35,6 +35,7 @@ */ use App\Models\User; +use AidingApp\Team\Models\Team; use function Tests\asSuperAdmin; @@ -46,6 +47,8 @@ use AidingApp\Contact\Models\Contact; use AidingApp\Contact\Models\Organization; use AidingApp\ServiceManagement\Models\ServiceRequest; +use AidingApp\ServiceManagement\Models\ServiceRequestType; +use AidingApp\ServiceManagement\Models\ServiceRequestPriority; use AidingApp\ServiceManagement\Models\ServiceRequestAssignment; use AidingApp\ServiceManagement\Filament\Resources\ServiceRequestResource; use AidingApp\ServiceManagement\Filament\Resources\ServiceRequestResource\Pages\ListServiceRequests; @@ -164,3 +167,87 @@ ) ->assertCanNotSeeTableRecords($serviceRequestsNotInOrganization); }); + +test('service requests only visible to service request type managers', function () { + $settings = app(LicenseSettings::class); + + $settings->data->addons->serviceManagement = true; + + $settings->save(); + + $user = User::factory()->licensed([Contact::getLicenseType()])->create(); + + $user->givePermissionTo('service_request.view-any'); + + $team = Team::factory()->create(); + + $user->teams()->attach($team); + + $user->refresh(); + + actingAs($user); + + $serviceRequests = ServiceRequest::factory() + ->count(3) + ->create(); + + $serviceRequestType = ServiceRequestType::factory()->create(); + + $serviceRequestType->managers()->attach($team); + + $serviceRequestsWithManager = ServiceRequest::factory()->state([ + 'priority_id' => ServiceRequestPriority::factory()->create([ + 'type_id' => $serviceRequestType->getKey(), + ])->getKey(), + ]) + ->count(3) + ->create(); + + livewire(ListServiceRequests::class) + ->assertCanSeeTableRecords( + $serviceRequestsWithManager + ) + ->assertCanNotSeeTableRecords($serviceRequests); +}); + +test('service requests only visible to service request type auditors', function () { + $settings = app(LicenseSettings::class); + + $settings->data->addons->serviceManagement = true; + + $settings->save(); + + $user = User::factory()->licensed([Contact::getLicenseType()])->create(); + + $user->givePermissionTo('service_request.view-any'); + + $team = Team::factory()->create(); + + $user->teams()->attach($team); + + $user->refresh(); + + actingAs($user); + + $serviceRequests = ServiceRequest::factory() + ->count(3) + ->create(); + + $serviceRequestType = ServiceRequestType::factory()->create(); + + $serviceRequestType->auditors()->attach($team); + + $serviceRequestsWithAuditors = ServiceRequest::factory()->state([ + 'priority_id' => ServiceRequestPriority::factory()->create([ + 'type_id' => $serviceRequestType->getKey(), + ])->getKey(), + ]) + ->count(3) + ->create(); + + livewire(ListServiceRequests::class) + ->assertCanSeeTableRecords( + $serviceRequestsWithAuditors + ) + ->assertCanNotSeeTableRecords($serviceRequests); +}); diff --git a/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php b/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php index c7965e10a..96194f0b3 100644 --- a/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php +++ b/app-modules/service-management/tests/ServiceRequest/ViewServiceRequestTest.php @@ -35,6 +35,7 @@ */ use App\Models\User; +use AidingApp\Team\Models\Team; use function Tests\asSuperAdmin; @@ -43,9 +44,12 @@ use function Pest\Laravel\actingAs; use function Pest\Livewire\livewire; +use AidingApp\Contact\Models\Contact; use AidingApp\Authorization\Enums\LicenseType; use AidingApp\ServiceManagement\Models\ServiceRequest; +use AidingApp\ServiceManagement\Models\ServiceRequestType; use AidingApp\ServiceManagement\Models\ServiceRequestStatus; +use AidingApp\ServiceManagement\Models\ServiceRequestPriority; use AidingApp\ServiceManagement\Enums\SystemServiceRequestClassification; use AidingApp\ServiceManagement\Filament\Resources\ServiceRequestResource; use AidingApp\ServiceManagement\Filament\Resources\ServiceRequestResource\Pages\ManageAssignments; @@ -89,15 +93,7 @@ $serviceRequest = ServiceRequest::factory()->create(); - actingAs($user) - ->get( - ServiceRequestResource::getUrl('view', [ - 'record' => $serviceRequest, - ]) - )->assertForbidden(); - - $user->givePermissionTo('service_request.view-any'); - $user->givePermissionTo('service_request.*.view'); + asSuperAdmin($user); actingAs($user) ->get( @@ -116,12 +112,9 @@ $user = User::factory()->licensed(LicenseType::cases())->create(); - $user->givePermissionTo('service_request.view-any'); - $user->givePermissionTo('service_request.*.view'); - $serviceRequest = ServiceRequest::factory()->create(); - actingAs($user) + asSuperAdmin($user) ->get( ServiceRequestResource::getUrl('view', [ 'record' => $serviceRequest, @@ -143,17 +136,12 @@ test('service request lock icon is shown when status classification closed', function (string $pages) { $user = User::factory()->licensed(LicenseType::cases())->create(); - $user->givePermissionTo('service_request.view-any'); - $user->givePermissionTo('service_request.*.view'); - $user->givePermissionTo('service_request_assignment.view-any'); - $user->givePermissionTo('service_request_update.view-any'); - - actingAs($user); + asSuperAdmin($user); $serviceRequest = ServiceRequest::factory([ 'status_id' => ServiceRequestStatus::factory()->create([ 'classification' => SystemServiceRequestClassification::Closed, - ])->id, + ])->getKey(), ])->create(); livewire($pages, [ @@ -166,3 +154,102 @@ ManageAssignments::class, ManageServiceRequestUpdate::class, ]); + +test('service requests not authorized if user is not an auditor or manager of the service request type', function () { + $settings = app(LicenseSettings::class); + + $settings->data->addons->serviceManagement = true; + + $settings->save(); + + $user = User::factory()->licensed([Contact::getLicenseType()])->create(); + + $user->givePermissionTo('service_request.view-any'); + $user->givePermissionTo('service_request.*.view'); + + $user->refresh(); + + actingAs($user); + + $serviceRequest = ServiceRequest::factory() + ->create(); + + livewire(ViewServiceRequest::class, [ + 'record' => $serviceRequest->getRouteKey(), + ]) + ->assertForbidden(); +}); + +test('view service request page visible if the user is an auditor of the service request type', function () { + $settings = app(LicenseSettings::class); + + $settings->data->addons->serviceManagement = true; + + $settings->save(); + + $user = User::factory()->licensed([Contact::getLicenseType()])->create(); + + $user->givePermissionTo('service_request.view-any'); + $user->givePermissionTo('service_request.*.view'); + + $team = Team::factory()->create(); + + $user->teams()->attach($team); + + $user->refresh(); + + actingAs($user); + + $serviceRequestType = ServiceRequestType::factory()->create(); + + $serviceRequestType->auditors()->attach($team); + + $serviceRequestsWithAuditor = ServiceRequest::factory()->state([ + 'priority_id' => ServiceRequestPriority::factory()->create([ + 'type_id' => $serviceRequestType->getKey(), + ])->getKey(), + ]) + ->create(); + + livewire(ViewServiceRequest::class, [ + 'record' => $serviceRequestsWithAuditor->getRouteKey(), + ]) + ->assertSuccessful(); +}); + +test('view service request page visible if the user is a manager of the service request type', function () { + $settings = app(LicenseSettings::class); + + $settings->data->addons->serviceManagement = true; + + $settings->save(); + + $user = User::factory()->licensed([Contact::getLicenseType()])->create(); + + $user->givePermissionTo('service_request.view-any'); + $user->givePermissionTo('service_request.*.view'); + + $team = Team::factory()->create(); + + $user->teams()->attach($team); + + $user->refresh(); + + actingAs($user); + + $serviceRequestType = ServiceRequestType::factory()->create(); + + $serviceRequestType->managers()->attach($team); + + $serviceRequestsWithManager = ServiceRequest::factory()->state([ + 'priority_id' => ServiceRequestPriority::factory()->create([ + 'type_id' => $serviceRequestType->getKey(), + ])->getKey(), + ]) + ->create(); + + livewire(ViewServiceRequest::class, [ + 'record' => $serviceRequestsWithManager->getRouteKey(), + ]) + ->assertSuccessful(); +});