Skip to content

Conversation

@GautierDele
Copy link
Member

@GautierDele GautierDele commented Apr 16, 2025

Summary by CodeRabbit

  • New Features

    • Introduced GitHub Sponsors support for the repository.
    • Added automated workflow for updating Packagist package metadata on new releases.
  • Documentation

    • Expanded README with detailed introduction, requirements, installation, and usage instructions.
  • Refactor

    • Replaced static boolean flags for access control with relationship-based and permission-driven logic across models, factories, and tests.
    • Updated callback signatures and usage in access control logic for improved clarity and flexibility.
  • Bug Fixes

    • Improved test reliability by using explicit authorization gates and relationship-based model factories.
  • Chores

    • Added new database migrations and model relationships to support client and user associations.
    • Simplified and updated test setup and data factories to align with new access control mechanisms.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 16, 2025

Walkthrough

This update introduces significant changes to the access control system and its supporting test infrastructure. The perimeter and control logic is refactored to use permission-based checks and explicit Eloquent relationships instead of boolean flags. The test suite and database schema are restructured to align with these changes, introducing new factories, migrations, and relationships for Client, User, and Model entities. The documentation is expanded, and new GitHub workflow and funding configuration files are added. The overall focus is on shifting from static attributes to dynamic, relationship-driven, and permission-based access control.

Changes

Files / Groups Change Summary
.github/FUNDING.yml Added GitHub Sponsors configuration with a sponsor username.
.github/workflows/packagist-deploy.yml Introduced a GitHub Actions workflow for Packagist deployment on release creation.
README.md Expanded documentation with package introduction, requirements, usage, and examples.
src/Controls/Control.php, src/Perimeters/Perimeter.php Refactored perimeter callback signatures and internal logic to use permission-based checks; updated method parameters and invocation patterns.
tests/Feature/ControlsQueryTest.php, tests/Feature/ControlsScoutQueryTest.php,
tests/Feature/ControlsShouldTest.php
Updated tests to define Laravel Gates for permissions instead of using user boolean flags; refactored model factory usage to leverage new perimeter-specific states.
tests/Feature/PerimetersTest.php Simplified to only test client and shared perimeters; removed user attribute logic and unused imports.
tests/Feature/TestCase.php Modified test setup to create and authenticate a user associated with a client.
tests/Support/Access/Controls/ModelControl.php Refactored perimeter logic to use permission-based callbacks and relationship-aware filtering; removed static boolean checks.
tests/Support/Database/Factories/ClientFactory.php Added a new factory for the Client model.
tests/Support/Database/Factories/ModelFactory.php Removed boolean attributes; added perimeter-specific state methods for client, shared, and own perimeters.
tests/Support/Database/Factories/UserFactory.php Removed boolean attributes from the user factory definition.
tests/Support/Database/migrations/2013_04_00_000000_create_clients_table.php Added migration for the clients table.
tests/Support/Database/migrations/2014_00_00_000000_create_users_table.php Removed boolean columns; added a nullable foreign key to clients.
tests/Support/Database/migrations/2023_04_00_000000_create_models_table.php Removed boolean and string columns; added foreign keys for author_id and client_id.
tests/Support/Database/migrations/2023_05_00_000000_create_models_shared_with_users_table.php Added migration for the pivot table linking models and users.
tests/Support/Models/Client.php Added new Client model with relationships to users and models.
tests/Support/Models/Model.php Added relationships: author, client, and sharedWithUsers.
tests/Support/Models/User.php Removed boolean attributes; added relationships: client, models, and sharedModels.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Gate
    participant Control
    participant Perimeter
    participant Model

    User->>Gate: can('view client models')
    Gate-->>User: true/false

    User->>Control: applies(user, method, model)
    Control->>Perimeter: applyAllowedCallback(user, method)
    Perimeter-->>Control: permission result
    Control->>Perimeter: applyShouldCallback(user, model)
    Perimeter-->>Control: model match result
    Control-->>User: access allowed/denied

    User->>Model: query (with Control filters)
    Model->>Control: filter query by perimeter (e.g., client_id, author_id, sharedWithUsers)
    Control-->>Model: filtered query
Loading

Possibly related PRs

  • ✨ scout queries #11: Refactors access control perimeter callbacks and query filtering logic, closely related to the current PR's changes in perimeter and control class logic.
  • Feature/reworked package #5: Involves major restructuring of the Control class and perimeter callback signatures, overlapping with this PR's refactoring of access control logic.

Poem

🐇
With perimeters redefined and gates now in play,
Models and users find new paths each day.
Relationships bloom where booleans once stood,
Factories and clients join the neighborhood.
Controls query with purpose, permissions in hand—
A hop forward for access, across this code land!
🌱✨

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72fe8ac and 3e5feb0.

📒 Files selected for processing (3)
  • src/Perimeters/Perimeter.php (3 hunks)
  • tests/Support/Database/migrations/2013_04_00_000000_create_clients_table.php (1 hunks)
  • tests/Support/Database/migrations/2023_05_00_000000_create_models_shared_with_users_table.php (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/Support/Database/migrations/2013_04_00_000000_create_clients_table.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/Support/Database/migrations/2023_05_00_000000_create_models_shared_with_users_table.php
  • src/Perimeters/Perimeter.php

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (10)
.github/FUNDING.yml (1)

1-1: Add a newline at end of file for formatting consistency.

The FUNDING.yml content is correct. For best practices and to satisfy some linters, add a newline at the end of the file.

-github: GautierDele
+github: GautierDele
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 1-1: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/packagist-deploy.yml (1)

1-20: Add a newline at end of file for formatting consistency.

The workflow is well-structured and secure. For best practices and to satisfy some linters, add a newline at the end of the file.

-          api_token: ${{ secrets.PACKAGIST_TOKEN }}
+          api_token: ${{ secrets.PACKAGIST_TOKEN }}
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 20-20: no new line character at the end of file

(new-line-at-end-of-file)

tests/Support/Database/migrations/2013_04_00_000000_create_clients_table.php (1)

15-19: Consider adding a unique constraint to the client name.

The clients table looks well-structured. Since this appears to be part of a multi-tenant architecture, you might want to consider making the client name unique to prevent duplicate client entries.

 Schema::create('clients', function (Blueprint $table) {
     $table->id();
-    $table->string('name');
+    $table->string('name')->unique();
     $table->timestamps();
 });
tests/Feature/TestCase.php (1)

11-19: Consider adding helper methods for different user-client scenarios.

While the current setup creates a standard user with a client for all tests, you might want to consider adding helper methods for creating users with specific client relationships to support more targeted testing scenarios.

/**
 * Create a user with a specific client
 *
 * @param Client|null $client
 * @return User
 */
protected function createUserWithClient(?Client $client = null): User
{
    return UserFactory::new()
        ->for($client ?? Client::factory())
        ->createOne();
}

/**
 * Create and authenticate a user with a specific client
 *
 * @param Client|null $client
 * @return $this
 */
protected function withAuthenticatedUserForClient(?Client $client = null)
{
    $user = $this->createUserWithClient($client);
    return $this->withAuthenticatedUser($user);
}
tests/Support/Database/migrations/2014_00_00_000000_create_users_table.php (1)

21-21: Consider adding an index to the client_id column.

Since you'll likely query users by client frequently, adding an index to the client_id column could improve query performance.

-$table->foreignIdFor(\Lomkit\Access\Tests\Support\Models\Client::class, 'client_id')->nullable()->constrained();
+$table->foreignIdFor(\Lomkit\Access\Tests\Support\Models\Client::class, 'client_id')->nullable()->constrained()->index();
tests/Support/Database/Factories/ClientFactory.php (1)

10-11: Incorrect PHPDoc type specification

The PHPDoc comment indicates this factory extends Factory for the User model, but the actual class creates instances of the Client model.

-/**
- * @extends \Illuminate\Database\Eloquent\Factories\Factory<User>
- */
+/**
+ * @extends \Illuminate\Database\Eloquent\Factories\Factory<Client>
+ */
tests/Feature/PerimetersTest.php (1)

14-19: Consider adding more comprehensive perimeter tests

While the simplification of these tests makes sense with the refactoring, consider adding more comprehensive tests that verify the actual relationships and permission checks that would occur in production code.

Some examples:

  • Test that a client perimeter only allows access to models belonging to the user's client
  • Test that a shared perimeter allows access only to models explicitly shared with the user
  • Test the interaction between different perimeters in realistic scenarios
README.md (1)

55-55: Grammar correction needed.

The word "setup" is a noun. For the verb form, use "set up" with a space.

-Then setup your policy:
+Then set up your policy:
🧰 Tools
🪛 LanguageTool

[grammar] ~55-~55: The word “setup” is a noun. The verb is spelled with a space.
Context: ... }), // ... Then setup your policy: php class PostPoli...

(NOUN_VERB_CONFUSION)

tests/Feature/ControlsQueryTest.php (2)

26-28: Always returning true for 'view client models'
This is fine for testing but be aware that it enables unrestricted access. If you want to test permission failures, consider adding more realistic checks.


126-131: Gates for 'view shared models' and 'view own models'
Again, returning true enables universal access. This may be intentional for test coverage, but keep in mind it doesn’t test permission denial.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99b9d0d and 72fe8ac.

📒 Files selected for processing (21)
  • .github/FUNDING.yml (1 hunks)
  • .github/workflows/packagist-deploy.yml (1 hunks)
  • README.md (1 hunks)
  • src/Controls/Control.php (3 hunks)
  • src/Perimeters/Perimeter.php (3 hunks)
  • tests/Feature/ControlsQueryTest.php (7 hunks)
  • tests/Feature/ControlsScoutQueryTest.php (2 hunks)
  • tests/Feature/ControlsShouldTest.php (2 hunks)
  • tests/Feature/PerimetersTest.php (1 hunks)
  • tests/Feature/TestCase.php (2 hunks)
  • tests/Support/Access/Controls/ModelControl.php (1 hunks)
  • tests/Support/Database/Factories/ClientFactory.php (1 hunks)
  • tests/Support/Database/Factories/ModelFactory.php (2 hunks)
  • tests/Support/Database/Factories/UserFactory.php (0 hunks)
  • tests/Support/Database/migrations/2013_04_00_000000_create_clients_table.php (1 hunks)
  • tests/Support/Database/migrations/2014_00_00_000000_create_users_table.php (1 hunks)
  • tests/Support/Database/migrations/2023_04_00_000000_create_models_table.php (1 hunks)
  • tests/Support/Database/migrations/2023_05_00_000000_create_models_shared_with_users_table.php (1 hunks)
  • tests/Support/Models/Client.php (1 hunks)
  • tests/Support/Models/Model.php (1 hunks)
  • tests/Support/Models/User.php (1 hunks)
💤 Files with no reviewable changes (1)
  • tests/Support/Database/Factories/UserFactory.php
🧰 Additional context used
🧬 Code Graph Analysis (9)
tests/Feature/TestCase.php (3)
tests/Support/Models/Client.php (1)
  • Client (9-36)
tests/Support/Database/Factories/UserFactory.php (1)
  • UserFactory (12-41)
tests/TestCase.php (1)
  • withAuthenticatedUser (82-85)
tests/Support/Models/Model.php (2)
tests/Support/Models/User.php (2)
  • User (10-64)
  • client (50-53)
tests/Support/Models/Client.php (1)
  • Client (9-36)
src/Controls/Control.php (1)
src/Perimeters/Perimeter.php (3)
  • applyAllowedCallback (76-79)
  • should (102-107)
  • applyShouldCallback (38-41)
tests/Feature/ControlsShouldTest.php (5)
tests/Support/Models/Model.php (1)
  • Model (11-40)
tests/Support/Models/User.php (1)
  • User (10-64)
tests/Support/Access/Controls/ModelControl.php (1)
  • ModelControl (13-74)
src/Controls/Control.php (1)
  • applies (49-68)
tests/Support/Database/Factories/ModelFactory.php (1)
  • clientPerimeter (26-29)
tests/Support/Database/migrations/2014_00_00_000000_create_users_table.php (1)
tests/Support/Models/Client.php (1)
  • Client (9-36)
tests/Support/Database/migrations/2023_04_00_000000_create_models_table.php (2)
tests/Support/Models/User.php (1)
  • User (10-64)
tests/Support/Models/Client.php (1)
  • Client (9-36)
tests/Support/Database/Factories/ModelFactory.php (2)
tests/Support/Models/Model.php (3)
  • client (31-34)
  • Model (11-40)
  • sharedWithUsers (36-39)
tests/Support/Models/User.php (1)
  • client (50-53)
tests/Support/Database/migrations/2023_05_00_000000_create_models_shared_with_users_table.php (4)
tests/Support/Database/migrations/2023_04_00_000000_create_models_table.php (1)
  • up (13-25)
tests/Support/Database/migrations/2014_00_00_000000_create_users_table.php (1)
  • up (13-25)
tests/Support/Models/Model.php (1)
  • Model (11-40)
tests/Support/Models/User.php (1)
  • User (10-64)
tests/Feature/PerimetersTest.php (4)
tests/Support/Access/Perimeters/ClientPerimeter.php (1)
  • ClientPerimeter (7-9)
src/Perimeters/Perimeter.php (2)
  • allowed (88-93)
  • applyAllowedCallback (76-79)
tests/Support/Models/Model.php (1)
  • Model (11-40)
tests/Support/Access/Perimeters/SharedPerimeter.php (1)
  • SharedPerimeter (7-9)
🪛 YAMLlint (1.35.1)
.github/FUNDING.yml

[error] 1-1: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/packagist-deploy.yml

[error] 20-20: no new line character at the end of file

(new-line-at-end-of-file)

🪛 LanguageTool
README.md

[grammar] ~55-~55: The word “setup” is a noun. The verb is spelled with a space.
Context: ... }), // ... Then setup your policy: php class PostPoli...

(NOUN_VERB_CONFUSION)

🔇 Additional comments (46)
tests/Support/Database/migrations/2013_04_00_000000_create_clients_table.php (1)

7-21: LGTM: Migration structure follows best practices.

The migration follows Laravel best practices with proper class structure, docblocks, and naming conventions. The file is properly ordered (2013_* timestamp) to run before user migrations that will reference this table.

tests/Feature/TestCase.php (2)

6-6: LGTM: Adding Client model import for relationship.

Properly adds the import for the Client model needed for the factory relationship in setUp.


15-18: LGTM: TestCase now creates users with client association.

The updated setUp method now creates users with an associated client, which aligns well with the refactored permission-based access control system. This ensures all tests run with properly related entities.

tests/Support/Database/migrations/2023_05_00_000000_create_models_shared_with_users_table.php (1)

7-21: LGTM: Pivot table migration supports many-to-many relationships.

The migration properly creates a pivot table with appropriate foreign keys and timestamps, supporting the many-to-many relationship between models and users for the model sharing functionality.

tests/Support/Database/migrations/2014_00_00_000000_create_users_table.php (1)

21-21: LGTM: Foreign key replaces boolean flags for access control.

Adding the client_id foreign key is a good refactoring approach, replacing the boolean flags previously used for access control with a relationship-based approach. This provides more flexibility and maintainability.

tests/Support/Database/Factories/ClientFactory.php (1)

1-27: Well-structured factory implementation

The ClientFactory implementation follows Laravel's factory pattern correctly, with proper namespace, class extension, model specification, and a clean definition method.

tests/Support/Models/Client.php (1)

9-36: Well-implemented Client model with appropriate relationships

The Client model is properly structured with all necessary components:

  • Extends Authenticatable for potential auth functionality
  • Uses HasFactory trait
  • Properly implements newFactory()
  • Defines appropriate fillable attributes
  • Establishes correct relationships with Model and User entities

This implementation aligns well with the broader refactoring toward relationship-based access control.

tests/Support/Models/Model.php (1)

26-39: Good relationship structure for access control

The newly added relationship methods (author(), client(), and sharedWithUsers()) are well-implemented and follow Laravel conventions. These relationships establish the foundation for the permission-based access control system, replacing the previous boolean flags approach with a more flexible and explicit model.

tests/Feature/PerimetersTest.php (2)

14-14: Simplified perimeter test with updated callback signature

The test now uses the updated perimeter callback signature that includes a $method parameter, aligning with changes in the perimeter implementation. The test is simplified to use a fixed boolean return.


19-19: Simplified perimeter test with updated callback signature

The SharedPerimeter test also adopts the updated perimeter callback signature with the $method parameter, consistent with the ClientPerimeter test and the overall refactoring approach.

README.md (3)

5-13: LGTM! Clear and informative introduction.

The introduction now clearly communicates the package's purpose, requirements, and provides links to comprehensive documentation, making it much easier for users to get started.


16-53: Well-structured example that demonstrates the permission-based approach.

The code examples effectively illustrate how to define perimeters with permission checks ($user->can()) and relationship-based logic ($model->client()->is($user->client)). This aligns perfectly with the refactored design that uses Laravel Gates and Eloquent relationships instead of boolean flags.


57-70: LGTM! Clear usage examples for policy implementation and query execution.

The policy setup and usage examples clearly demonstrate how to extend ControlledPolicy and how to use the controlled queries and authorization checks.

tests/Support/Models/User.php (1)

49-63: LGTM! Well-structured Eloquent relationships that replace boolean flags.

The refactoring from boolean flags to explicit Eloquent relationships is a significant improvement:

  1. client() - Creates a belongs-to relationship with the Client model
  2. models() - Establishes a has-many relationship for models authored by this user
  3. sharedModels() - Implements a many-to-many relationship for shared models

This approach provides better encapsulation, type safety, and follows Laravel's conventions for model relationships.

tests/Support/Database/migrations/2023_04_00_000000_create_models_table.php (1)

21-22: LGTM! Improved database schema with proper relationships.

Replacing boolean flags with foreign key relationships is a significant improvement that:

  1. Enables proper relational integrity through foreign key constraints
  2. Supports the relationship-driven access control approach
  3. Makes queries more efficient by leveraging database indexes on foreign keys

The author_id and client_id fields align perfectly with the relationships defined in the User model.

src/Controls/Control.php (4)

52-52: LGTM! Updated allowed callback to include method parameter.

The method parameter is now correctly passed to the applyAllowedCallback method, allowing for dynamic permission checks based on the specific action being performed.


59-59: LGTM! Updated should callback to remove method parameter.

The method parameter has been removed from the applyShouldCallback call, aligning with the updated signature in the Perimeter class that now focuses solely on the user-model relationship.


121-121: LGTM! Consistent permission check for view action in query control.

The 'view' action is now explicitly passed to the applyAllowedCallback method, making the permission check consistent with the overall design that uses method-specific permissions.


150-150: LGTM! Consistent permission check for view action in Scout query control.

Similar to the standard query control, the Scout query control now correctly passes the 'view' action to the applyAllowedCallback method, ensuring consistent permission checking across different query types.

tests/Support/Database/Factories/ModelFactory.php (4)

6-6: Added Auth facade import to support perimeter factory states.

This import is necessary to access the authenticated user data in the newly added perimeter-specific factory state methods.


26-29: Well-implemented client perimeter factory state.

The clientPerimeter() method properly associates models with the authenticated user's client using the for() factory method. This elegantly replaces the previous boolean is_client approach with an actual relationship.


31-36: Good use of afterCreating to handle the many-to-many relationship.

The sharedPerimeter() method correctly uses the afterCreating hook to establish the many-to-many relationship with the sharedWithUsers pivot table. This approach is appropriate since many-to-many relationships typically need to be established after the model is created.


38-41: Clean implementation of author relationship.

The ownPerimeter() method correctly associates the model with the authenticated user as its author using the for() method with a named relationship.

tests/Feature/ControlsShouldTest.php (4)

6-8: Appropriate imports for the new authorization approach.

The added imports support the shift from attribute-based to gate-based authorization, which is a more standard Laravel approach.


19-21: Effective shift to Gate-based authorization.

Replacing direct user attribute updates with Laravel Gate definitions is a more maintainable and flexible approach to authorization.


28-34: Good combination of Gate definition and updated factory usage.

The test properly defines a gate for client models viewing and uses the new clientPerimeter() factory state to create a test model with the appropriate relationship, ensuring the test accurately reflects the new relationship-based access control system.


154-162: Well-structured multi-gate test for overlayed perimeter.

This test correctly defines multiple gates to test the overlaying behavior between shared and global perimeters, which is an important aspect of the access control system.

tests/Feature/ControlsScoutQueryTest.php (4)

4-6: Proper imports for Gate-based authorization in Scout queries.

The added imports align with the shift to gate-based authorization throughout the codebase.


20-27: Updated Scout query test with appropriate gate definition.

The test correctly defines a gate for viewing client models and asserts that the Scout query includes the client_id filter. The assertion has been properly updated to check for the relationship-based filter instead of a boolean flag.


32-42: Comprehensive test for overlayed perimeters in Scout queries.

The test properly defines gates for both client and shared models, and correctly verifies that both filters are applied to the Scout query. The updated assertion checks for relationship-based filters rather than boolean flags.


47-57: Good test coverage for distant perimeter relationships.

The test properly defines gates for own and shared models and verifies that the Scout query correctly includes both author_id and shared_with_users filters.

src/Perimeters/Perimeter.php (3)

25-26: Updated callback signatures for better permission control.

The default callbacks have been updated to better reflect their responsibilities:

  1. shouldCallback no longer needs the method parameter since it only checks if a model falls within a perimeter
  2. allowedCallback now explicitly requires the method parameter for fine-grained permission checking

This change better separates the concerns of permission checking and perimeter applicability.


38-41: Simplified shouldCallback implementation.

Removing the method parameter from applyShouldCallback aligns with the updated callback signature and clarifies that this check is only about whether a model belongs to a perimeter, not about permission to perform a specific action.


76-79: Enhanced allowedCallback with method parameter.

Adding the method parameter to applyAllowedCallback enables more fine-grained permission checks based on the specific action being performed, which is a key aspect of the new permission-based access control system.

tests/Feature/ControlsQueryTest.php (9)

6-6: New Gate import looks correct
No issues: the import is necessary for gate definitions below.


8-8: User model import
This allows referencing Gate definitions with the User class correctly.


46-51: Permissive gates for 'view client models' and 'view shared models'
Defining both gates to return true allows broad access in tests. If coverage of permission failures is needed, you might want additional condition checks.


73-78: Permissive gates for 'view shared models' and 'view own models'
Returning true grants unlimited access. Acceptable for broad test coverage but doesn't simulate denied scenarios.


101-103: Gate definition for 'view shared models' returning true
No immediate concerns; fits the pattern of permissive test gates.


106-106: Utilizing new perimeter factory states
Using ->clientPerimeter(), ->sharedPerimeter(), and ->ownPerimeter() clarifies test setup and aligns with the relationship-based model.

Also applies to: 110-110, 114-114


134-134: Client perimeter plus additional states and explicit where condition
Chaining multiple perimeter states is consistent with the new approach. Ensure Auth::user()->client cannot be null in these tests—otherwise this query can fail.

Also applies to: 138-139, 143-143, 147-147


157-162: Defining gates for 'view shared models' and 'view own models'
Returning true is typical for test stubs, but consider variations if testing different permission levels.


165-165: Chaining perimeter states and narrowing the query by client
No major issues; just ensure Auth::user()->client is guaranteed to be set for this scenario to avoid null references.

Also applies to: 169-170, 174-174, 178-178

tests/Support/Access/Controls/ModelControl.php (3)

19-20: SharedPerimeter logic

  • The allowed callback delegates to Gate::can(...) for 'shared models'.
  • The should callback verifies the model is actually shared with the user, which is correct.
  • The scoutQuery uses 'shared_with_users'; confirm your Scout indexing supports this field.
  • The query uses orWhereHas('sharedWithUsers') to retrieve shared models, which aligns with the intended logic.

Also applies to: 22-23, 26-26, 29-31


34-36: GlobalPerimeter logic

  • The allowed callback correctly checks 'global models' permissions.
  • The should callback always returns true, meaning a fully open perimeter.
  • The scoutQuery and query apply no restrictions, consistent with global access.

Also applies to: 37-38, 41-41, 44-44


47-49: ClientPerimeter logic

  • The allowed callback checks 'client models' via Gate::can(...).
  • The should callback enforces model->client() matching user->client.
  • The queries filter by client_id. Verify user->client is always defined to avoid null references.

Also applies to: 50-51, 54-54, 57-57

Comment on lines +109 to 115
Gate::define('view client models', function (User $user) {
return true;
});

$model = Model::factory()
->create([
'allowed_methods' => 'create',
]);
->create();

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Gate definition mismatch in global perimeter test.

The test is checking for 'view' permission but defines a gate for 'view client models'. For a global perimeter test, the gate should define 'view global models' to properly test the global perimeter logic.

-        Gate::define('view client models', function (User $user) {
+        Gate::define('view global models', function (User $user) {
            return true;
        });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Gate::define('view client models', function (User $user) {
return true;
});
$model = Model::factory()
->create([
'allowed_methods' => 'create',
]);
->create();
Gate::define('view global models', function (User $user) {
return true;
});
$model = Model::factory()
->create();

@GautierDele GautierDele merged commit 56fbcd8 into master Apr 17, 2025
21 checks passed
@GautierDele GautierDele deleted the feature/refactored branch April 17, 2025 06:57
@coderabbitai coderabbitai bot mentioned this pull request Jul 21, 2025
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