Installation Add the bundle via Composer:
composer require dinhkhanh/mongodb-acl-bundle
Register the bundle in config/bundles.php (Symfony):
DinhKhanh\MongoDBAclBundle\MongoDBAclBundle::class => ['all' => true],
Configuration Publish the default config:
php artisan vendor:publish --provider="DinhKhanh\MongoDBAclBundle\MongoDBAclBundle" --tag="config"
Update config/mongodb_acl.php with your MongoDB connection details and ACL rules structure.
First Use Case
Define a basic ACL rule in a model (e.g., User):
use DinhKhanh\MongoDBAclBundle\Model\AclAwareInterface;
class User implements AclAwareInterface
{
public function getAclRules()
{
return [
'edit_profile' => ['read', 'write'],
'manage_posts' => ['read', 'write', 'delete'],
];
}
}
Check permissions in a controller:
use DinhKhanh\MongoDBAclBundle\Acl\AclChecker;
public function updateProfile(Request $request, AclChecker $acl)
{
$user = $request->user();
if ($acl->isGranted($user, 'edit_profile', 'write')) {
// Allow update
}
}
Role-Based Access Control (RBAC)
Extend the bundle to support roles by overriding getAclRules():
public function getAclRules()
{
$rules = [];
if ($this->role === 'admin') {
$rules['manage_users'] = ['read', 'write', 'delete'];
}
return $rules;
}
Dynamic Rule Assignment Use middleware to assign temporary rules (e.g., for moderators):
public function handle($request, Closure $next)
{
$request->user()->setTemporaryRule('approve_content', ['read', 'write']);
return $next($request);
}
Integration with MongoDB Documents Attach ACLs to MongoDB documents via embedded arrays:
$document->acl = [
'owner' => $user->id,
'permissions' => ['read' => ['group:admins', 'user:'.$user->id]],
];
$document->save();
Cache Permissions: Cache getAclRules() results in the model to avoid repeated DB calls:
protected $aclRulesCached = false;
public function getAclRules()
{
if (!$this->aclRulesCached) {
$this->aclRules = $this->fetchRulesFromDb();
$this->aclRulesCached = true;
}
return $this->aclRules;
}
Bulk Permission Checks:
$users = User::whereIn('id', [$id1, $id2])->get();
$permissions = $acl->checkMultiple($users, 'edit_profile', 'write');
Event-Driven Rule Updates:
Listen for eloquent.saved events to update ACLs:
Event::listen('eloquent.saved: User', function ($user) {
if ($user->wasChanged('role')) {
$user->invalidateAclCache(); // Hypothetical method
}
});
Missing Interface Implementation
Forgetting to implement AclAwareInterface will cause runtime errors. Always extend or implement:
class User implements AclAwareInterface { ... }
Overlapping Rules
Rules defined in both getAclRules() and embedded MongoDB documents may conflict. Prioritize one source (e.g., embedded docs override model rules).
Performance with Large Datasets Avoid querying ACLs for every request. Cache results aggressively or use a dedicated permission table.
MongoDB Indexing
Ensure proper indexing on fields used in ACL queries (e.g., owner, permissions.group):
db.collection.createIndex({ "acl.owner": 1, "acl.permissions.group": 1 });
Enable Logging Configure Monolog to log ACL checks:
'debug' => env('APP_DEBUG', false),
'log_checks' => true, // Add to config/mongodb_acl.php
Check Rule Resolution
Override AclChecker to log resolved rules:
public function isGranted($subject, $rule, $permission)
{
$result = parent::isGranted($subject, $rule, $permission);
\Log::debug("ACL Check: {$subject} -> {$rule}.{$permission} = {$result}");
return $result;
}
Custom Permission Providers Extend the bundle by creating a custom provider:
class CustomAclProvider implements AclProviderInterface
{
public function getRules($subject)
{
// Fetch rules from external API, Redis, etc.
}
}
Register it in config/mongodb_acl.php:
'providers' => [
'custom' => DinhKhanh\MongoDBAclBundle\Acl\CustomAclProvider::class,
],
MongoDB Schema Validation Add validation to embedded ACL documents:
Schema::create('posts', function (Blueprint $collection) {
$collection->json('acl')->validate(function ($acl) {
return isset($acl->owner) && isset($acl->permissions);
});
});
Event Listeners Trigger events for ACL changes:
// In config/mongodb_acl.php
'events' => [
'acl.updated' => \App\Listeners\LogAclChange::class,
],
How can I help you explore Laravel packages today?