agence-adeliom/easy-admin-user-bundle
Symfony bundle adding user authentication and password reset integration for EasyAdmin. Includes a full user flow, CLI command to create users (admin/super-admin), and an EasyAdmin CRUD interface for managing accounts.
Installation
composer require agence-adeliom/easy-admin-user-bundle
Ensure your composer.json includes the Adeliom recipes endpoint for Flex compatibility.
Database Migration
Run the bundle’s migrations to create the required user table:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Configure Security
Update your config/packages/security.yaml to use the bundle’s firewall:
firewalls:
admin:
pattern: ^/admin
form_login:
login_path: easy_admin_user_login
check_path: easy_admin_user_login_check
logout:
path: easy_admin_user_logout
First Use Case Generate a superadmin user via CLI:
php bin/console easy-admin-user:create-user --role=ROLE_SUPER_ADMIN
Access the admin panel at /admin and log in with the generated credentials.
User Management via EasyAdmin
The bundle extends EasyAdmin’s CRUD interface for users. Customize the UserCrudController in src/Controller/Admin/UserCrudController.php:
use AgenceAdeliom\EasyAdminUserBundle\Controller\UserCrudController;
class CustomUserCrudController extends UserCrudController
{
public function configureFields(string $pageName): iterable
{
return [
// Override default fields (e.g., add email visibility)
IdField::new('id'),
EmailField::new('email'),
// ...
];
}
}
Password Reset Flow
The bundle provides a built-in password reset controller. Extend it in config/routes.yaml:
easy_admin_user_reset_password:
path: /admin/reset-password
controller: AgenceAdeliom\EasyAdminUserBundle\Controller\ResetPasswordController
Role-Based Access Control (RBAC)
Define roles in the User entity (e.g., ROLE_ADMIN, ROLE_EDITOR). Use EasyAdmin’s isGranted() in configureActions():
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, DeleteAction::new()
->setIcon('fa fa-trash')
->setLabel('Delete')
->setCssClass('btn btn-danger')
->displayIf(function ($entity) {
return $this->isGranted('ROLE_SUPER_ADMIN');
})
);
}
Custom User Entity
Extend the default User entity (e.g., add lastLoginAt):
namespace App\Entity;
use AgenceAdeliom\EasyAdminUserBundle\Entity\User as BaseUser;
class User extends BaseUser
{
#[ORM\Column(type: 'datetime', nullable: true)]
private ?\DateTimeInterface $lastLoginAt = null;
// Getters/setters...
}
Migration Conflicts
user table, drop it before running migrations to avoid schema conflicts.php bin/console doctrine:schema:drop --force (in dev) and re-migrate.Role Inheritance Issues
ROLE_ADMIN implies ROLE_USER) may not work as expected if roles aren’t prefixed with ROLE_.ROLE_ prefix in the User entity.CSRF Token Mismatch
php bin/console cache:clear) or regenerate the form in your template.Password Hashing Mismatch
auto) may change. Ensure the User entity uses a compatible hasher:
#[ORM\Column(type: 'string')]
private string $password;
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password; // Handled by Symfony's encoder
return $this;
}
Enable Debug Mode
Set APP_DEBUG=true in .env to see detailed errors for login/reset flows.
Check Event Listeners
The bundle dispatches events like easy_admin_user.login.success. Listen to them in config/services.yaml:
services:
App\EventListener\LoginListener:
tags:
- { name: kernel.event_listener, event: easy_admin_user.login.success, method: onLoginSuccess }
Override Templates Customize the login/reset templates by copying them from:
vendor/agence-adeliom/easy-admin-user-bundle/resources/views/
to templates/bundles/easyadminuser/.
Custom User Provider
Replace the default UserProvider by binding a service in config/services.yaml:
services:
AgenceAdeliom\EasyAdminUserBundle\Security\User\UserProvider:
class: App\Security\User\CustomUserProvider
Add Fields to User Entity
Use Doctrine extensions (e.g., Gedmo\Timestampable) for soft deletes or timestamps:
use Gedmo\Mapping\Annotation as Gedmo;
#[Gedmo\SoftDeleteable(fieldName: 'deletedAt')]
class User extends BaseUser { ... }
API Integration Expose user endpoints via API Platform or custom controllers:
#[Route('/api/users', name: 'api_user_list', methods: ['GET'])]
public function listUsers(UserRepository $repo): JsonResponse
{
return new JsonResponse($repo->findAll());
}
Multi-Tenant Support
Add a tenantId field to the User entity and filter queries in the UserCrudController:
public function configureQueryBuilder(QueryBuilder $qb): QueryBuilder
{
return $qb
->andWhere('u.tenantId = :tenantId')
->setParameter('tenantId', $this->getTenantId());
}
How can I help you explore Laravel packages today?