|
2 | 2 |
|
3 | 3 | namespace Tests\Feature\Api\V1_1; |
4 | 4 |
|
| 5 | +use Illuminate\Support\Facades\Gate; |
5 | 6 | use Illuminate\Support\Facades\Hash; |
6 | 7 | use ProcessMaker\Constants\CaseStatusConstants; |
7 | 8 | use ProcessMaker\Models\CaseParticipated; |
@@ -476,6 +477,87 @@ public function test_get_my_cases_counters_ok(): void |
476 | 477 | $response->assertJsonFragment(['totalMyRequest' => 5]); |
477 | 478 | } |
478 | 479 |
|
| 480 | + public function test_get_all_cases_forbidden_without_view_all_cases_permission(): void |
| 481 | + { |
| 482 | + // Ensure the permission row exists and register it as a Laravel Gate |
| 483 | + // so $user->can('view-all_cases') is enforceable in tests. |
| 484 | + Permission::firstOrCreate( |
| 485 | + ['name' => 'view-all_cases'], |
| 486 | + ['title' => 'View All Cases'], |
| 487 | + ); |
| 488 | + Gate::define('view-all_cases', fn ($user) => $user->hasPermission('view-all_cases')); |
| 489 | + |
| 490 | + $nonAdmin = User::factory()->create([ |
| 491 | + 'is_administrator' => false, |
| 492 | + ]); |
| 493 | + |
| 494 | + self::createCasesStartedForUser($nonAdmin->id, 3); |
| 495 | + |
| 496 | + // Unscoped request (the "All cases" tab) — denied without the permission. |
| 497 | + $response = $this->actingAs($nonAdmin, 'api') |
| 498 | + ->json('GET', route('api.1.1.cases.all_cases')); |
| 499 | + $response->assertStatus(403); |
| 500 | + |
| 501 | + // Granting the permission restores access to the unscoped query. |
| 502 | + $nonAdmin->giveDirectPermission('view-all_cases'); |
| 503 | + |
| 504 | + $response = $this->actingAs($nonAdmin, 'api') |
| 505 | + ->json('GET', route('api.1.1.cases.all_cases')); |
| 506 | + $response->assertStatus(200); |
| 507 | + $response->assertJsonCount(3, 'data'); |
| 508 | + } |
| 509 | + |
| 510 | + public function test_get_all_cases_allows_user_to_view_their_own_cases_without_permission(): void |
| 511 | + { |
| 512 | + // The endpoint is shared by the "My cases" tab, which scopes the |
| 513 | + // query to the authenticated user. That self-scoped path must work |
| 514 | + // even when the user lacks `view-all_cases`. |
| 515 | + $nonAdmin = User::factory()->create([ |
| 516 | + 'is_administrator' => false, |
| 517 | + ]); |
| 518 | + |
| 519 | + $ownCases = self::createCasesStartedForUser($nonAdmin->id, 4); |
| 520 | + $otherUser = self::createUser('other_user'); |
| 521 | + self::createCasesStartedForUser($otherUser->id, 6); |
| 522 | + |
| 523 | + $response = $this->actingAs($nonAdmin, 'api') |
| 524 | + ->json('GET', route('api.1.1.cases.all_cases', ['userId' => $nonAdmin->id])); |
| 525 | + |
| 526 | + $response->assertStatus(200); |
| 527 | + $response->assertJsonCount($ownCases->count(), 'data'); |
| 528 | + $response->assertJsonMissing(['user_id' => $otherUser->id]); |
| 529 | + } |
| 530 | + |
| 531 | + public function test_get_all_cases_forbids_user_from_viewing_another_users_cases_without_permission(): void |
| 532 | + { |
| 533 | + Permission::firstOrCreate( |
| 534 | + ['name' => 'view-all_cases'], |
| 535 | + ['title' => 'View All Cases'], |
| 536 | + ); |
| 537 | + Gate::define('view-all_cases', fn ($user) => $user->hasPermission('view-all_cases')); |
| 538 | + |
| 539 | + $nonAdmin = User::factory()->create([ |
| 540 | + 'is_administrator' => false, |
| 541 | + ]); |
| 542 | + $otherUser = self::createUser('other_user'); |
| 543 | + self::createCasesStartedForUser($otherUser->id, 2); |
| 544 | + |
| 545 | + // Passing another user's id must require `view-all_cases`; otherwise |
| 546 | + // any authenticated user could iterate userIds to enumerate the |
| 547 | + // entire platform. |
| 548 | + $response = $this->actingAs($nonAdmin, 'api') |
| 549 | + ->json('GET', route('api.1.1.cases.all_cases', ['userId' => $otherUser->id])); |
| 550 | + $response->assertStatus(403); |
| 551 | + |
| 552 | + // With the permission, the same request succeeds. |
| 553 | + $nonAdmin->giveDirectPermission('view-all_cases'); |
| 554 | + |
| 555 | + $response = $this->actingAs($nonAdmin, 'api') |
| 556 | + ->json('GET', route('api.1.1.cases.all_cases', ['userId' => $otherUser->id])); |
| 557 | + $response->assertStatus(200); |
| 558 | + $response->assertJsonCount(2, 'data'); |
| 559 | + } |
| 560 | + |
479 | 561 | public function test_get_all_cases_participants(): void |
480 | 562 | { |
481 | 563 | $userA = $this->createUser('user_a'); |
|
0 commit comments