alchemy/acl-bundle
Symfony bundle providing a simple ACL API. Configure object types, alias your UserRepository, and add Redis cache for access tokens. Exposes endpoints to list, upsert, and delete ACEs by user/group, object type/id, with permission masks and wildcards.
Pros:
#[Attribute]), enabling declarative ACLs.Publication#42), which Laravel’s built-in Gate/Policy lacks natively. Useful for SaaS platforms with dynamic access rules./permissions/aces, /permissions/ace) can be consumed by Laravel’s HTTP client (Illuminate\Support\Facades\Http) for admin panels or background jobs.Redis facade, reducing latency for permission checks.metadata: {expires_at: "2024-12-31"}), which can be mapped to Laravel’s attributes or accessors.Cons:
symfony/options-resolver, symfony/attribute), which may conflict with Laravel’s ecosystem. Mitigate with composer.json overrides or a custom wrapper.Gate/Policy uses named methods (can('edit')), while this bundle uses numeric masks (mask: 7). Requires a translation layer (e.g., maskToPermission() helper).#[Attribute] or accessors. Requires custom serialization/deserialization.Core Components:
UserRepositoryInterface with Laravel’s App\Models\User via a facade or service container alias.alchemy_acl.objects (YAML) to Laravel’s config (config/acl.php):
'objects' => [
'publication' => App\Models\Publication::class,
'asset' => App\Models\Asset::class,
],
#[Attribute] for declarative ACLs:
use Alchemy\AclBundle\Attribute\AclObject;
#[AclObject(objectType: 'publication')]
class Publication extends Model { ... }
Acl::registerObject('publication', Publication::class)).Redis facade to configure the accessToken.cache pool:
Cache::extend('accessToken', function () {
return Cache::repository(new RedisStore(config('cache.redis')));
});
Http client:
$aces = Http::get('http://symfony-app/permissions/aces', [
'objectType' => 'publication',
'objectId' => 'pub-42',
]);
AclService::getAces()).Challenges:
"extra": {
"laravel": {
"dont-discover": ["symfony/*"]
}
}
Events system.Gate logic:
class AclMask {
public static function maskToPermission(int $mask): string {
return match ($mask) {
1 => 'view',
2 => 'edit',
4 => 'delete',
7 => 'full-access',
default => 'unknown',
};
}
}
symfony/* packages (e.g., symfony/http-foundation vs. Laravel’s Illuminate/Http). Requires isolation testing in a separate repo.#[Attribute]. Test with:
$reflection = new ReflectionClass(Publication::class);
$attributes = $reflection->getAttributes(AclObject::class);
php artisan optimize:clear && php -d opcache.enable=0 artisan tinker
Attribute system may not fully support Laravel’s #[Attribute] syntax. Fallback to YAML config if needed.AclFacade) to abstract Symfony dependencies.alchemy_acl.objects in YAML if metadata fails.LogEntry) before applying to Publication/Asset.Symfony Dependency Strategy:
spatie/laravel-permission + custom object-level logic)?Metadata Implementation:
#[Attribute] or Symfony’s metadata system? If the latter, how will we handle reflection differences?Permission Mask Design:
Gate (e.g., mask: 7 → can('full-access')) or create a hybrid system?publish) be defined? Via masks or additional metadata?Performance Tradeoffs:
Illuminate\Support\Facades\Cache)?metadata.expires_at) impact DB performance?Admin Tooling:
spatie/laravel-permission UI)?Migration Path:
Gate/Policy logic coexist with this bundle? Should we deprecate Gates in favor of the bundle’s API?spatie/laravel-permission?Laravel Compatibility:
Redis facade works seamlessly with the bundle’s accessToken.cache.Illuminate\Support\Facades\Http.#[Attribute] can replace Symfony’s metadata system with minimal effort.laravel-doctrine/orm).Events system.Hybrid Architecture:
symfony/attribute → illuminate/support/Traits).Acl::getAces() → `How can I help you explore Laravel packages today?