Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Simple Acl Bundle Laravel Package

alexdpy/simple-acl-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require alexdpy/simple-acl-bundle
    
  2. Enable the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony <4):
    AlexDpy\AclBundle\AlexDpyAclBundle::class => ['all' => true],
    
  3. Configure the database provider (e.g., Doctrine DBAL):
    # config/services.yaml
    services:
        app.acl.database_provider:
            class: AlexDpy\Acl\Database\Provider\DoctrineDbalProvider
            arguments: ['@doctrine.dbal.default_connection']
    
  4. Update your database schema (follow ACL library instructions).
  5. Configure the bundle:
    # config/packages/alex_dpy_simple_acl.yaml
    alex_dpy_simple_acl:
        database_provider: app.acl.database_provider
    
  6. First use case: Inject the ACL service and check permissions:
    use AlexDpy\AclBundle\Service\AclService;
    
    class MyController extends AbstractController
    {
        public function __construct(private AclService $acl)
        {}
    
        public function index()
        {
            $canEdit = $this->acl->isGranted('edit', 'resource_id', 'user_id');
            // ...
        }
    }
    

Implementation Patterns

Core Workflows

  1. Defining Permissions: Use the AclService to dynamically assign permissions:

    $this->acl->allow('edit', 'post:1', 'user:1'); // Allow user:1 to edit post:1
    $this->acl->deny('delete', 'post:*', 'user:*'); // Deny all users from deleting any post
    
  2. Checking Permissions:

    if ($this->acl->isGranted('view', 'profile:123', 'user:456')) {
        // Render profile
    }
    
  3. Bulk Operations:

    // Grant all permissions for a role
    $this->acl->allow('*', 'article:*', 'role:admin');
    
  4. Resource Hierarchies: Leverage wildcards (*) for hierarchical resources (e.g., post:1/comments/*).

Integration Tips

  • Symfony Security Integration: Use the ACL service in a Voter:

    public function vote(AuthenticatedEntityInterface $user, $subject, array $attributes)
    {
        $acl = $this->container->get('alex_dpy_simple_acl.acl');
        return $acl->isGranted($attributes[0], $subject->getId(), $user->getId());
    }
    
  • Form-Level Permissions: Dynamically disable form fields based on ACL checks:

    {% if app.acl.isGranted('edit', 'post.id', app.user.id) %}
        {{ form_row(form.title) }}
    {% endif %}
    
  • API Gateways: Use middleware to validate ACLs for incoming requests:

    public function handle(Request $request, Closure $next)
    {
        if (!$this->acl->isGranted('access', $request->get('resource'), $request->get('user'))) {
            throw new AccessDeniedException();
        }
        return $next($request);
    }
    
  • Event-Driven Permissions: Trigger ACL updates on entity events (e.g., post.updated):

    public function onPostUpdated(PostUpdatedEvent $event)
    {
        $this->acl->allow('edit', 'post:'.$event->getPost()->getId(), $event->getUser()->getId());
    }
    

Gotchas and Tips

Pitfalls

  1. Schema Mismatches:

    • Ensure your database schema matches the ACL library’s requirements.
    • Fix: Drop and recreate tables if migrations fail:
      php bin/console doctrine:schema:drop --force
      php bin/console doctrine:schema:update --force
      
  2. Caching Issues:

    • The cache provider must match the configured namespace (simple_acl by default).
    • Fix: Clear the cache after schema updates:
      php bin/console cache:clear
      
  3. Wildcard Overuse:

    • Overly permissive wildcards (e.g., *:*) can bypass security.
    • Tip: Audit permissions regularly with:
      $this->acl->getPermissions('user:1'); // List all permissions for a user
      
  4. Case Sensitivity:

    • Resource/requester IDs are case-sensitive in comparisons.
    • Tip: Normalize IDs (e.g., strtolower()) if case-insensitive matching is needed.
  5. MaskBuilder Conflicts:

    • Custom MaskBuilder classes must implement AlexDpy\Acl\MaskBuilderInterface.
    • Fix: Extend the default builder:
      class CustomMaskBuilder extends \AlexDpy\Acl\MaskBuilder
      {
          public function build($permissions) { /* ... */ }
      }
      

Debugging

  • Enable Logging: Configure the ACL service to log decisions:

    alex_dpy_simple_acl:
        database_provider: app.acl.database_provider
        debug: true # Logs all permission checks to Symfony's logger
    
  • Query Inspection: Use Doctrine’s query logging to verify ACL queries:

    doctrine:
        dbal:
            logging: true
            profiling: true
    
  • Common Errors:

    • "Provider not found": Verify database_provider service ID matches config.yml.
    • "Table not found": Run migrations or check schema.table_name config.
    • "Invalid mask": Ensure permissions use valid bitmask values (e.g., 1, 2, 4).

Extension Points

  1. Custom Providers: Extend AlexDpy\Acl\Database\Provider\AbstractProvider for non-DBAL storage (e.g., Redis):

    class RedisAclProvider extends AbstractProvider
    {
        public function __construct(Connection $redis)
        {
            $this->connection = $redis;
        }
        // Implement required methods
    }
    
  2. Dynamic Permission Generation: Use the AclService to generate permissions on-the-fly:

    $this->acl->generatePermissions('role:admin', [
        'create' => 'post:*',
        'edit'   => 'post:*',
        'delete' => 'post:*',
    ]);
    
  3. Permission Inheritance: Implement a trait to inherit permissions from parent roles:

    trait RoleInheritanceTrait
    {
        public function allow($permission, $resource, $requester)
        {
            if (str_starts_with($requester, 'role:')) {
                $parentRoles = $this->getParentRoles($requester);
                foreach ($parentRoles as $role) {
                    $this->allow($permission, $resource, $role);
                }
            }
            parent::allow($permission, $resource, $requester);
        }
    }
    
  4. Audit Trails: Log ACL changes to a separate table:

    public function allow($permission, $resource, $requester)
    {
        $result = parent::allow($permission, $resource, $requester);
        $this->logAclChange($permission, $resource, $requester, 'allow');
        return $result;
    }
    
  5. Performance Optimization:

    • Batch Updates: Use transactions for bulk permission updates:
      $this->acl->beginTransaction();
      try {
          $this->acl->allow('view', 'post:*', 'user:1');
          $this->acl->allow('edit', 'post:*', 'user:1');
          $this->acl->commit();
      } catch (\Exception $e) {
          $this->acl->rollBack();
          throw $e;
      }
      
    • Cache Invalidation: Manually invalidate cache for specific resources:
      $this->acl->invalidateCache('post:123');
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views
spatie/ignition-contracts