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

Abac Bundle Laravel Package

craftcamp/abac-bundle

Symfony bundle integrating CraftCamp’s PHP ABAC library for attribute-based access control. Define policy rules based on user and resource attributes (roles as attributes too) and enforce permissions via a security service that can return denied attributes for debugging.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require craftcamp/abac-bundle
    

    Register the bundle in config/bundles.php (Symfony 4+):

    return [
        // ...
        CraftCamp\AbacBundle\CraftCampAbacBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration (config/packages/craftcamp_abac.yaml):

    craftcamp_abac:
        configuration_files:
            - '%kernel.project_dir%/config/abac/attributes.yml'
            - '%kernel.project_dir%/config/abac/policy_rules.yml'
    
  3. Define Attributes (config/abac/attributes.yml):

    user:
        class: App\Entity\User
        type: user
        fields:
            role: { name: "Role" }
            is_active: { name: "Active" }
    
  4. Define a Rule (config/abac/policy_rules.yml):

    rules:
        can_edit_post:
            attributes:
                user.role:
                    comparison_type: string
                    comparison: isEqual
                    value: "editor"
    
  5. First Usage (Controller):

    use PhpAbac\Abac;
    
    class PostController extends AbstractController
    {
        public function edit(Abac $abac, Post $post)
        {
            $access = $abac->enforce('can_edit_post', $this->getUser(), $post);
            if ($access !== true) {
                throw $this->createAccessDeniedException();
            }
            // ...
        }
    }
    

Implementation Patterns

Common Workflows

1. Rule-Based Access Control in Controllers

public function update(Abac $abac, $entityId)
{
    $entity = $this->entityManager->find($entityId);
    $access = $abac->enforce('can_update_entity', $this->getUser(), $entity);

    if ($access !== true) {
        $this->denyAccessWithDetails($access);
    }
    // Proceed with update
}

private function denyAccessWithDetails(array $rejectedAttributes)
{
    $this->addFlash('error', 'Access denied. Missing: ' . implode(', ', $rejectedAttributes));
    return $this->redirectToRoute('homepage');
}

2. Dynamic Attribute Values

Use dynamic for runtime values (e.g., environment variables):

rules:
    can_access_during_maintenance:
        attributes:
            environment.is_maintenance:
                comparison_type: boolean
                comparison: isEqual
                value: dynamic

Override in PHP:

$abac->getConfiguration()->setDynamicValue('environment.is_maintenance', getenv('MAINTENANCE_MODE') === 'true');

3. Voter Integration

Combine with Symfony’s Voter for hybrid role/ABAC checks:

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;

class AbacVoter implements VoterInterface
{
    public function __construct(private Abac $abac) {}

    public function vote(Authenticated $token, $subject, array $attributes)
    {
        $rule = $attributes[0] ?? 'default_rule';
        return $this->abac->enforce($rule, $token->getUser(), $subject);
    }
}

4. Caching Rules

Leverage caching for performance-critical rules:

craftcamp_abac:
    cache_options:
        cache_folder: '%kernel.cache_dir%/abac'
        ttl: 3600  # Cache rules for 1 hour

5. Attribute Mapping

Map Eloquent/Laravel models to ABAC attributes:

# config/abac/attributes.yml
post:
    class: App\Models\Post
    type: resource
    fields:
        author.id: { name: "Author ID" }
        published_at:
            name: "Published Date"
            getter: getPublishedAtTimestamp  # Custom getter

Integration Tips

Laravel-Specific Adaptations

  1. Service Provider Setup:

    // config/app.php
    'providers' => [
        // ...
        CraftCamp\AbacBundle\CraftCampAbacServiceProvider::class,
    ],
    
  2. Middleware for Global Checks:

    namespace App\Http\Middleware;
    
    use Closure;
    use PhpAbac\Abac;
    
    class AbacMiddleware
    {
        public function __construct(private Abac $abac) {}
    
        public function handle($request, Closure $next)
        {
            $rule = $request->route()->getName() . '_rule';
            if ($this->abac->enforce($rule, auth()->user(), $request->route()->parameter('resource')) !== true) {
                abort(403);
            }
            return $next($request);
        }
    }
    
  3. Dynamic Rule Loading: Load rules from a database or API:

    $rules = RuleRepository::fetchForRoute($request->route()->getName());
    $abac->getConfiguration()->setRules($rules);
    
  4. Event-Driven Rule Updates: Use Laravel events to update ABAC rules:

    // In a service
    event(new RulesUpdated($newRules));
    
    // Event listener
    public function handle(RulesUpdated $event)
    {
        $abac = app(Abac::class);
        $abac->getConfiguration()->setRules($event->getRules());
    }
    

Gotchas and Tips

Pitfalls

  1. Attribute Naming Conflicts:

    • Ensure attribute paths (e.g., user.role) are unique across configurations.
    • Fix: Use namespaced keys like user.admin_role or user.permissions[*] for arrays.
  2. Dynamic Value Timing:

    • Dynamic values must be set before enforce() is called.
    • Fix: Use a service to set dynamic values pre-request (e.g., middleware).
  3. Caching Stale Rules:

    • Cache invalidation requires manual clearing if rules change at runtime.
    • Fix: Implement a cache tag system or use CacheManagerInterface to clear specific rules.
  4. Case Sensitivity:

    • Attribute names and rule keys are case-sensitive.
    • Fix: Standardize naming (e.g., snake_case or camelCase) in your team’s conventions.
  5. Circular Dependencies:

    • Avoid rules that reference each other indirectly (e.g., rule_a depends on rule_b, which depends on rule_a).
    • Fix: Refactor rules into smaller, reusable components.
  6. Performance with Complex Rules:

    • Rules with many nested conditions or large isIn/isNotIn arrays can slow down enforcement.
    • Fix: Optimize by:
      • Using caching for static rules.
      • Simplifying conditions (e.g., combine isEqual checks with logical operators).

Debugging Tips

  1. Enable Debug Mode:

    craftcamp_abac:
        debug: true  # Logs rule evaluation steps
    

    Check logs for:

    • Which attributes failed validation.
    • The order of rule evaluation.
  2. Inspect Configuration: Dump the loaded configuration to verify setup:

    $config = $abac->getConfiguration();
    dump($config->getAttributes(), $config->getRules());
    
  3. Test Rules Isolated: Use a test controller to validate rules independently:

    public function testRule(Abac $abac)
    {
        $user = new User(); // Mock user
        $resource = new Post(); // Mock resource
        $result = $abac->enforce('test_rule', $user, $resource);
        dump($result); // true or array of rejected attributes
    }
    
  4. Common Errors:

    • "Attribute not found": Verify the attribute path exists in attributes.yml.
    • "Comparison type invalid": Check comparison_type matches the attribute’s data type (e.g., datetime for dates).
    • "Rule not found": Ensure the rule key in enforce() matches the YAML key.

Extension Points

  1. Custom Comparison Operators: Extend PhpAbac\Manager\ComparisonManagerInterface to add operators like isBetween:

    class CustomComparisonManager implements ComparisonManagerInterface
    {
        public function addComparison(string $name, callable $callable)
        {
            $this->comparisons[$name] = $callable;
        }
    }
    

    Register in services.yaml:

    PhpAbac\Manager\ComparisonManagerInterface: '@App\Service\CustomComparisonManager'
    
  2. Attribute Transformers: Transform raw attributes before comparison (e.g., normalize dates):

    $ab
    
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.
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon