11ya/actual-user-bundle
Symfony bundle that keeps user roles and data up to date without forcing re-login. Add ActualUserInterface to your User, switch security to the provided custom user provider, and roles refresh automatically on subsequent requests.
Install the Bundle
composer require 11ya/actual-user-bundle:dev-master
Add to bundles.php (Symfony 4.4+):
return [
// ...
Ilya\ActualUserBundle\IlyaActualUserBundle::class => ['all' => true],
];
Implement ActualUserInterface
Extend your User entity (e.g., src/Security/User.php):
use Ilya\ActualUserBundle\Model\ActualUserInterface;
class User implements ActualUserInterface
{
// Your existing User logic
public function getActualRoles(): array
{
return $this->roles; // Return fresh roles (e.g., from DB)
}
}
Update Security Configuration
In config/packages/security.yaml:
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
role_property: actual_roles # <-- Key change
First Use Case After updating a user’s roles (e.g., via admin panel), call:
$user->setRoles(['ROLE_ADMIN', 'ROLE_USER']);
$entityManager->flush();
The bundle ensures the user’s session roles are refreshed without re-authentication.
Role Updates via API/Forms
$user->setRoles($newRoles);
$em->flush();
$this->get('security.token_storage')->getToken()->setUser($user);
ActualUserProvider intercepts and refreshes roles.Event-Driven Updates
Listen for UserUpdatedEvent (if extended) or use Symfony’s KernelEvents::TERMINATE:
$eventDispatcher->addListener(KernelEvents::TERMINATE, function (TerminateEvent $event) {
$user = $this->get('security.token_storage')->getToken()->getUser();
if ($user instanceof ActualUserInterface) {
$user->getActualRoles(); // Force refresh
}
});
Integration with Voters
Ensure voters use getActualRoles() instead of getRoles():
$roles = $user instanceof ActualUserInterface ? $user->getActualRoles() : $user->getRoles();
security.yaml auto-configuration:
security:
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
role_property: actual_roles
preUpdate() in your User entity to auto-refresh roles:
public function preUpdate()
{
$this->getActualRoles(); // Force refresh
}
Session Locks
$token = $this->get('security.token_storage')->getToken();
$token->setUser($user); // Force session update
Circular Dependencies
getActualRoles() in getRoles() (Symfony’s security layer may call both).Provider Misconfiguration
role_property: actual_roles matches your ActualUserInterface method name.Symfony 4.3+ Cache
php bin/console cache:clear
Check Provider Logs
Enable debug in security.yaml:
debug: true
Look for ActualUserProvider logs during role updates.
Verify Token Refresh Dump the token after role changes:
dump($this->get('security.token_storage')->getToken()->getUser()->getRoles());
Custom Role Refresh Logic
Extend ActualUserProvider:
class CustomActualUserProvider extends ActualUserProvider
{
protected function refreshRoles(UserInterface $user)
{
// Custom logic (e.g., API call)
$user->setRoles($this->fetchFreshRoles());
}
}
Register as a service in services.yaml:
services:
App\Security\CustomActualUserProvider:
tags: [security.user_provider]
Event-Based Refresh Dispatch a custom event after role updates:
$dispatcher->dispatch(new RolesRefreshedEvent($user));
Listen in a subscriber to trigger refreshes.
Multi-Tenant Roles
Override getActualRoles() to scope roles by tenant:
public function getActualRoles(): array
{
return $this->tenant->getRolesForUser($this);
}
How can I help you explore Laravel packages today?