= dcb5bd2790 Feat: implement role-based priority restrictions and permission manager
- Added `priority`-based access logic to restrict role and user management actions.
- Introduced `Permission Manager` UI and routes for permission access control.
- Updated `RoleService` and `AppRoleService` to include `visible` scope for priority filtering.
- Enhanced seeding to assign priorities to default roles and ensure proper hierarchy.
- Updated sidebar, routes, and data structure to handle new permission enums and resource segmentation.
- Improved UI components to dynamically restrict visibility and actions based on role priority.
2026-05-25 10:12:42 +00:00
..

Service Class Guidelines & Flow: ConnectionProviderService

This document outlines the architectural flow, design patterns, and coding guidelines implemented within the ConnectionProviderService class. It serves as a reference for maintaining this service and acts as a blueprint for creating similar service classes within the application.

1. General Coding Guidelines

The service class adheres to several strict Laravel and general PHP best practices to ensure robustness, predictability, and maintainability.

  1. Strict Typing: The file declares strict_types=1 at the top. All method arguments and return values must have explicit type hints.

  2. Data Transfer Objects (DTOs): Instead of passing raw arrays or generic Laravel Request objects, the service utilizes strongly typed DTOs (via Spatie\LaravelData).

    Input: StoreConnectionProviderRequestData

    Output: ConnectionProviderData, PaginatedDataCollection

  3. Database Transactions: All data mutation methods (Create, Update, Delete) are wrapped within DB::transaction() closures to guarantee database integrity. If any part of the operation fails, the entire transaction rolls back.

  4. The #[NoDiscard] Attribute: Read-only methods (search, getAll, getProvider) utilize the #[NoDiscard] attribute. This strictly enforces that the calling code must capture and use the returned data, preventing logic leaks where a developer calls a getter but ignores the result.

  5. Explicit Exception Documentation: Every method that can throw an exception documents it clearly in the PHPDoc block ( e.g., @throws ModelNotFoundException, @throws Throwable).

2. Architectural Flow by Operation

A. Read Operations

Read operations are optimized for memory and performance by explicitly selecting only the necessary columns.

  • search(string $value)

      Flow: Initiates an Eloquent query targeting the slug or name columns using a LIKE operator (%value%).
    
      Returns: An Eloquent Collection of ConnectionProvider models.
    
  • getAll()

      Flow: Queries the database selecting only id, name, and slug. It then paginates the results.
    
      Returns: The paginated result is transformed into a PaginatedDataCollection containing ConnectionProviderData objects.
    
  • getProvider(string $slug)

      Flow: Looks up a specific provider by its slug, selecting only id, name, and slug.
    
      Returns: Transforms the found model into a single ConnectionProviderData object.
    

B. Write Operations (Create / Update)

Write operations rely on DTOs to ensure the data being inserted or updated is pre-validated and formatted correctly.

  • create(StoreConnectionProviderRequestData $data)

      Flow: Opens a DB transaction. Converts the validated DTO to an array and passes it to the Eloquent create method.
    
  • update(string $slug, StoreConnectionProviderRequestData $data)

      Flow: Opens a DB transaction. Locates the model by its slug and updates it using the array representation of the provided DTO.
    

C. Delete Operation (Cascade & Logging)

The delete method contains the most complex flow, handling cascading soft-deletes and custom audit logging.

delete(string $slug)

    Step 1 (Find): Locates the ConnectionProvider by slug or throws a ModelNotFoundException.

    Step 2 (Fetch Relations): Retrieves the id and name of all associated connectedApps to preserve their state for the audit log.

    Step 3 (Cascade Delete): Performs a mass query deletion ($provider->connectedApps()->delete()).

        Note: Because this is a mass delete, individual model events for ConnectedApp will not fire.

    Step 4 (Provider Delete): Disables default logging on the provider to prevent redundant logs, then deletes the provider.

    Step 5 (Audit Log): Manually triggers a comprehensive Spatie Activity log (provider_cascade_deleted). It records the specific user (:causer.name), the provider details, and an array of the deleted child apps.

3. Performance & Security Best Practices

When extending this service or building new ones, adhere strictly to the following patterns demonstrated in the code:

  1. Selective Querying: Always use $model->select(['id', 'column_name']) when returning data to the frontend or DTOs to avoid memory bloat from fetching unused columns (e.g., timestamps, hidden credentials).

  2. Route/Key Binding vs. Service Lookups: Notice that update, delete, and getProvider accept a primitive string $slug / $id rather than an already-resolved Model. This keeps the service decoupled from HTTP routing logic and allows it to be called safely from CLI commands or background jobs.

  3. Auditable Actions: For destructive actions (like cascades), always disable automatic noise and implement a custom, highly detailed activity log so system administrators can trace exactly what data was removed and by whom.