Skip to content

FOUR-27623 | Users Can View All Cases Without “View All Cases” Permission#8834

Open
mcraeteisha wants to merge 7 commits into
developfrom
defect/FOUR-27623
Open

FOUR-27623 | Users Can View All Cases Without “View All Cases” Permission#8834
mcraeteisha wants to merge 7 commits into
developfrom
defect/FOUR-27623

Conversation

@mcraeteisha
Copy link
Copy Markdown
Contributor

@mcraeteisha mcraeteisha commented May 18, 2026

Issue

Ticket: FOUR-27623

Users without the "View All Cases" permission can still see every case in the platform by navigating directly to /cases/all.

Solution

Added permission checks for view-all-cases.

The web check at ProcessMaker/Http/Controllers/CasesController.phpindex() produces the proper "Not Authorized" page.

ProcessMaker/Http/Controllers/Api/V1_1/CaseController.phpgetAllCases now checks the requested userId and only requires view-all_cases when the request is not scoped to the authenticated user. This protects the data from direct API access while preserving the "My Cases" tab for everyone.

Added test coverage:

tests/Feature/CasesControllerTest.php — three new tests on the web route:

  • testCasesAllPageReturns403WithoutViewAllCasesPermission — non-admin without the permission gets a 403 and sees the "Not Authorized" page text.
  • testCasesAllPageReturns200WithViewAllCasesPermission — once granted, the user can access /cases/all and the cases.casesMain view renders.
  • testCasesOtherTabsRemainAccessibleWithoutViewAllCasesPermission — regression guard that /cases, /cases/in_progress, and /cases/completed stay accessible for everyone.

tests/Feature/Api/V1_1/CaseControllerTest.php — three new tests on the API route:

  • test_get_all_cases_forbidden_without_view_all_cases_permission — an unscoped request (the "All cases" tab) returns 403 for a non-admin without the permission, and 200 once granted.
  • test_get_all_cases_allows_user_to_view_their_own_cases_without_permission— a self-scoped request (userId = self, the "My cases" tab) returns 200 even with no special permission, and other users' cases never leak into the response.
  • test_get_all_cases_forbids_user_from_viewing_another_users_cases_without_permission — asking for another user's cases (userId = other) returns 403 without the permission, and 200 with it. Locks in the regression that any authenticated user could otherwise iterate userIds to enumerate every user's cases.

How To Test

  1. Run phpunit tests/Feature/CasesControllerTest.php
    • Verify testCasesAllPageReturns403WithoutViewAllCasesPermission passes
    • Verify testCasesAllPageReturns200WithViewAllCasesPermission passes
    • Verify testCasesOtherTabsRemainAccessibleWithoutViewAllCasesPermission passes
  2. Run phpunit tests/Feature/Api/V1_1/CaseControllerTest.php
    • Verify test_get_all_cases_forbidden_without_view_all_cases_permission passes
    • Verify test_get_all_cases_allows_user_to_view_their_own_cases_without_permission passes
    • Verify test_get_all_cases_forbids_user_from_viewing_another_users_cases_without_permission passes
  3. Create or modify an existing user.
  4. Ensure the user does not belong to any group whose membership grants View All Cases.
  5. Ensure the user does not have View All Cases granted directly under user permissions (Cases and Requests).
  6. Save the user and log in as them.
  7. Observe that the All Cases menu link is correctly hidden.
  8. Observe that the My Cases menu link is correctly displayed with the user's cases.
  9. Manually navigate to /cases/all in the browser.
    • The user should receive an "Unauthorized" message.

ci:deploy

Code Review Checklist

  • I have pulled this code locally and tested it on my instance, along with any associated packages.
  • This code adheres to ProcessMaker Coding Guidelines.
  • This code includes a unit test or an E2E test that tests its functionality, or is covered by an existing test.
  • This solution fixes the bug reported in the original ticket.
  • This solution does not alter the expected output of a component in a way that would break existing Processes.
  • This solution does not implement any breaking changes that would invalidate documentation or cause existing Processes to fail.
  • This solution has been tested with enterprise packages that rely on its functionality and does not introduce bugs in those packages.
  • This code does not duplicate functionality that already exists in the framework or in ProcessMaker.
  • This ticket conforms to the PRD associated with this part of ProcessMaker.

Add authorization checks for the "All cases" listing. CasesController@index now accepts an optional $type param and aborts with 403 when $type === 'all' and the current user lacks the view-all_cases permission (admins allowed via Gate::before). The API route get_all_cases is also protected with the can:view-all_cases middleware to ensure the underlying endpoint is gated.
Add tests to enforce and validate the 'view-all_cases' permission. API test (Api\V1_1\CaseControllerTest) initializes permissions, creates a non-admin user and sample cases, asserts a 403 response without the permission and 200 with the permission (and checks the returned data count). Web tests (CasesControllerTest) register the Gate/Permission, assert the 'all' cases page returns 403 for users without the permission and 200 for users with it, and confirm other tabs and the default cases page remain accessible. Also add required Gate/Permission imports.
Add authorization in getAllCases to allow users to fetch cases scoped to themselves while requiring the 'view-all_cases' permission for broader queries. The code retrieves the authenticated user and requested userId, allows the request if it's for the user's own cases, and aborts with 403 if the caller lacks the permission (admins continue to be handled via Gate::before).
Ensure the 'view-all_cases' permission row exists and register a Gate in tests so the can:view-all_cases middleware is enforceable. Update the existing forbidden test to define the permission and Gate, and add two new tests: one that confirms a user can view their own cases (scoped by userId) without the global permission, and another that verifies a user cannot view another user's cases without the permission and that granting it restores access. Creates test data via factories and asserts correct response codes and payload counts.
@Kookster310
Copy link
Copy Markdown
Contributor

QA server K8S was successfully deployed https://ci-a92011700c.engk8s.processmaker.net

@eiresendez eiresendez self-requested a review May 18, 2026 23:56
Copy link
Copy Markdown
Contributor

@eiresendez eiresendez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 [ProcessMaker/Http/Controllers/Api/V1_1/CaseController.php:53] The new unscoped get_all_cases permission check breaks existing all-cases search tests. This is confirmed in GitHub Actions: run-phpunit is failing with 8 failures where CaseControllerSearchTest expected 200 but received 403.

Suggested fix: update CaseControllerSearchTest so tests that intentionally exercise all-cases search run as a user with view-all_cases, or pass userId only for tests that should validate self-scoped access.

@processmaker-sonarqube
Copy link
Copy Markdown

@Kookster310
Copy link
Copy Markdown
Contributor

QA server K8S was successfully deployed https://ci-a92011700c.engk8s.processmaker.net

@mcraeteisha mcraeteisha requested a review from eiresendez May 19, 2026 17:40
Copy link
Copy Markdown
Contributor

@eiresendez eiresendez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍

The fix now matches the authorization contract: unscoped get_all_cases requires view-all_cases, while self-scoped userId access remains allowed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants