Securing The Platform: Minimal Access Control Integration Tests

by Omar Yusuf 64 views

Hey guys! Let's dive into a crucial aspect of our platform's security: access control. We need to ensure that our users can only access the data and functionalities they're authorized to. To achieve this, we'll be implementing a set of minimal integration tests focused on verifying the most critical access rules. This approach allows us to validate our current implementation effectively without getting bogged down in complex setups and broad scenarios. Think of it as a targeted strike force ensuring our core defenses are solid.

This article will walk you through the plan for creating these tests, covering the scope, infrastructure, files to be created, test case sketches, success criteria, and relevant references. Let's get started!

Objective

The primary goal here is to deliver a minimal, high-value set of integration tests. These tests will rigorously verify the most critical access rules within our current system. We're aiming for simplicity and efficiency:

  • Keep the infrastructure lean and mean.
  • Reuse our existing test database setup.
  • Seed only the data necessary for each specific test.
  • Defer heavy factories and broad, complex scenarios for later.

By focusing on the essentials, we can quickly gain confidence in our access control mechanisms without the overhead of more extensive testing frameworks. It’s like making sure the locks on the front door work before worrying about the security system for the entire house.

Scope (Now)

Our immediate focus will be on the following key areas:

1) Posts & Pages

  • Platform-only CRUD: Only users with the 'Platform' role should be able to create, update, and delete posts and pages. This is our gatekeeper role.
  • Draft visibility: Platform users can see both draft and published content, while other roles can only view published content. This ensures that unpublished work remains private until it's ready for prime time.

2) Media

  • Platform-only CRUD: Similar to posts and pages, only Platform users can create, update, and delete media assets.
  • Public read for all roles: All authenticated users, regardless of their role, should be able to read media files. This allows for broader access to visual content.

3) FavoriteClinics

  • Patients CRUD own favorites: Patients should be able to create, read, update, and delete their own favorite clinics. This ensures personal preference management.
  • Platform CRUD any: Platform users have full CRUD access to all favorite clinics, providing administrative oversight.
  • Uniqueness (patient+clinic) enforced: We need to ensure that a patient can't add the same clinic to their favorites multiple times. This prevents data duplication and maintains integrity.

4) ClinicStaff

  • Clinic staff update own profile: Clinic staff members can update their own profile information but cannot create or delete staff accounts. This balances self-management with administrative control.
  • Read scoped to their clinic: Staff members can only see other staff members within their own clinic. This maintains privacy and relevance within the clinic's context.
  • Platform full CRUD: Platform users have full CRUD access to all clinic staff accounts, allowing for comprehensive management across the platform.

5) Reviews

  • Patients create-only: Patients can create reviews but cannot update or delete them. This ensures that reviews remain authentic and unedited by the reviewer.
  • Non-platform read approved only: Users without the Platform role can only see reviews that have been approved. This ensures that only vetted feedback is publicly visible.
  • Platform sees all: Platform users can see all reviews, including those that are pending approval. This provides a complete view for moderation and analysis.
  • Platform update sets audit fields: When Platform users update reviews, the system should automatically set audit fields like lastEditedAt and editedBy. This provides a clear audit trail of modifications.

6) Clinics (targeted checks)

  • Clinic staff update own clinic: Clinic staff can update the information for their own clinic but cannot create new clinics or delete existing ones. This allows for clinic-level maintenance without broader administrative privileges.
  • Read approved-only for non-platform: Users without the Platform role can only see clinics that have been approved. This ensures that only vetted clinics are publicly visible.
  • Platform sees all: Platform users can see all clinics, including those that are pending approval.

Out-of-Scope (Defer)

To maintain focus and deliver value quickly, we're deferring the following for now:

  • Doctor specialty/treatment joins and complex networks: These are more complex relationships that can be addressed in a later phase.
  • Factories/TestScenarios layers: We're avoiding the creation of elaborate data factories and test scenarios for this initial phase.
  • End-to-end workflows and performance/scale: These types of tests are important but will be tackled separately to avoid complicating the current scope.

Infrastructure (Minimal)

We're keeping the infrastructure as simple as possible by:

  • Reusing existing Docker-based test DB setup: This leverages our current infrastructure and avoids the need for new setups.
  • Using Payload Local API with overrideAccess: true only for seeding: This allows us to bypass access controls during the seeding process, ensuring we can set up the necessary data for each test.
  • Access assertions with real access (no override) using proper req.user: This is crucial for accurately testing access rules. We'll simulate user requests with the appropriate user roles to ensure that access controls are enforced correctly.
  • Inline seeding per test file, no factory layer yet: Each test file will handle its own seeding, avoiding the complexity of a separate factory layer for now.

Files To Create

We'll be creating the following test files to cover each area:

  • tests/integration/access/pages-posts-access.test.ts
  • tests/integration/access/media-access.test.ts
  • tests/integration/access/favoriteClinics-access.test.ts
  • tests/integration/access/clinicStaff-access.test.ts
  • tests/integration/access/clinics-access.test.ts
  • tests/integration/access/reviews-access.test.ts

Each file will focus on testing the specific access rules for the corresponding collection or feature.

Test Case Sketches

Here's a brief overview of the test cases we'll be implementing in each file:

1) pages-posts-access.test.ts

  • Seed: Create a draft post/page and a published post/page.
  • Assert read visibility by role: Verify that Platform users can see both drafts and published content, while other roles can only see published content.
  • Assert Platform-only mutations: Ensure that only Platform users can create, update, and delete posts and pages.

2) media-access.test.ts

  • Assert public read: Verify that all authenticated users can read media files.
  • Assert Platform-only mutations: Ensure that only Platform users can create, update, and delete media files.

3) favoriteClinics-access.test.ts

  • Seed: Create two patients and two clinics. Seed favorite clinics for one patient (own) and another patient (others).
  • Assert:
    • Patients can CRUD only their own favorites.
    • Platform users can CRUD any favorites.
    • Enforce uniqueness (patient+clinic): Prevent a patient from adding the same clinic multiple times.

4) clinicStaff-access.test.ts

  • Seed: Create two clinics and staff members in each clinic.
  • Assert:
    • Read access is scoped to the staff member's own clinic.
    • Staff can update their own profile only but cannot create or delete staff accounts.
    • Platform users have full CRUD access to all clinic staff accounts.

5) clinics-access.test.ts

  • Seed: Create an approved clinic and a pending clinic.
  • Assert:
    • Non-platform users can only read approved clinics.
    • Platform users can see all clinics.
    • Clinic staff can update their own clinic only.

6) reviews-access.test.ts

  • Seed: Create a patient, a review (pending), and any required relations.
  • Assert:
    • Patients can create reviews but cannot update or delete them.
    • Non-platform users can only read approved reviews.
    • Platform users can see all reviews.
    • Platform updates set audit fields (lastEditedAt, editedBy).
    • Platform users can delete reviews.

Success Criteria (Minimal)

We'll consider this effort a success if we achieve the following:

  • Critical access rules validated against real DB: The tests should effectively validate the core access rules for the collections outlined above using our actual database.
  • Tests are small, fast, and stable: The tests should be concise, execute quickly, and be reliable within our current infrastructure.
  • No additional infra beyond what exists today: We should be able to accomplish this without requiring any new infrastructure components.

References

Here are some helpful references for this task:

  • Permission matrix: docs/security/permission-matrix.md - This document outlines the detailed access control rules for our platform.
  • Collections: src/collections/** (Posts, Pages, Media, FavoriteClinics, ClinicStaff, Clinics, Reviews) - This directory contains the code definitions for the collections we'll be testing.
  • Access helpers: src/access/** - This directory contains helper functions related to access control.

Note

This issue is specifically tracking the implementation plan for minimal integration tests. We're deliberately avoiding the creation of factories or extended scenarios during this phase. Let's focus on getting the core access rules validated first!

Alright, guys, that's the plan! By focusing on these minimal integration tests, we can efficiently validate our access control mechanisms and ensure the security of our platform. Remember, we're aiming for small, fast, and stable tests that cover the most critical access rules. Let's get to work and make sure our platform is secure and reliable! Feel free to ask any questions or share your thoughts in the comments below. Let's build something great together!