Download the PHP package serendipity_hq/bundle-users without Composer
On this page you can find all versions of the php package serendipity_hq/bundle-users. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download serendipity_hq/bundle-users
More information about serendipity_hq/bundle-users
Files in serendipity_hq/bundle-users
Package bundle-users
Short Description A Symfony bundle that helps manage users in a Symfony app.
License MIT
Homepage https://github.com/Aerendir/bundle-users
Informations about the package bundle-users
Serendipity HQ Users Bundle
Helps managing users in Symfony apps.
Current Status
Features
Provides some utilities to make easier the management of users in Symfony applications, on top of Symfony's built-in management of users.
Do you like this bundle?
LEAVE A ★
or run
composer global require symfony/thanks && composer thanks
to say thank you to all libraries you use in your current project, this included!
Documentation
The starting point is always the Symfony's documentation.
Once you have configured the UserInterface
entity, configured the security of your app and built the login form, it's time to create your first user, even before you build the registration form.
To make users management easier, SerendipityHQ Users Bundle
provides a command shq:users:create
that permits to create users from the command line.
It works almost out of the box: you only need to tweak just a bit the entity automatically generated by Symfony.
Install the Serendipity HQ Users Bundle
To install the bundle, run:
composer req serendipity_hq/bundle-users
Then activate the bundle in your bundles.php
:
Using the shq:users:create
command
This command is very useful as it permits you to create users in your application before you have created the registration form.
This way you can immediately test the login functionality, but can also automate some tasks in your app, like resetting it in dev environment, without having to create a new user each time from the registration form.
To use the command, you have to do one simple thing: implement the HasPlainPasswordInterface
and its implementing trait in your UserInterface
entity.
The HasPlainPasswordInterface
makes possible to get a series of advantages: we will see them later.
For the moment be sure that you will NEVER save the plain password in the database: it is only useful during the life cycle of a UserInterface
object and permits to your app to implement some basic features.
For the moment, lets implement the interface and the trait.
- Open you
UserInterface
entity (src/App/Entity/User.php
); - Implement the interface
\SerendipityHQ\Bundle\UsersBundle\Model\Property\HasPlainPasswordInterface
- Use the trait
SerendipityHQ\Bundle\UsersBundle\Model\Property\HasPlainPasswordTrait
After these modifications, your entity should appear like this:
Now create your first user using the command line:
Aerendir@SerendipityHQ % bin/console shq:user:create Aerendir 1234
Create user
===========
Password for user Aerendir: 1234
[OK] User Aerendir created.
Aerendir
(the first argument), is the value of the primary property (the one set in the file config/packages/security.yaml
, in security.providers.[your_user_provider].entity.property
);
1234
(the second argument), instead, is the password to assign to the user.
You are ready to test the login of your app: go to http://your_app_url/login
and provide the credentials of the user you have just created.
Now that your login works, we can go further better understanding the purpose of HasPlainPasswordInterface
.
The purpose of HasPlainPasswordInterface
The interface HasPlainPasswordInterface
activates a Doctrine's listener provided by Serendipity HQ Users Bundle.
This listener reads the plain password (managed by the trait HasPlainPasswordTrait
) and automatically encodes it.
This way you will have the plain password available during the life cycle of the user object and:
- You don't have to take care of encryption of the password;
- You can use the plain password to do what you like: send it via email to the user, show it on a page or do what you like.
ATTENTION: Serendipity HQ Users Bundle will never call the method UserInterface::ereaseCredentials()
: this is a responsibility of your app.
Implementing a profile show page
The next step is to make possible for the user to view his/her profile.
You need:
- A
UserProfileController
- A template to show the current profile
1. Create the UserProfileController
2. Create the template user/profile.html.twig
And this is the code for the template that renders the profile:
This is really simple, too, as you will customize it depending on your application.
Implementing a profile edit page
To create an edit profile page we need:
- A
UserType
form type - A route in the
UserProfileController
- A template to show the form
Create the UserType
form type
Use the MakerBundle to do this:
Really simple and it takes only a bunch of seconds!
2. Create the route in the UserProfileController
Lets use the just crated form type in our UserProfileController
:
3. Create the template
Create the file templates/user/edit.html.twig
:
Really simple!
Implementing password editing
Now we are going to start to see the usefulness of Symfony HQ Users Bundle!
We need to implement the ability for the user of changing his/her own password.
To implement this we need:
- A form to make possible for the user to change his/her password
- A
UserPasswordController
- A template to show the form
1. Create the form ChangePasswordType
Hey, you have to do nothing here!
Serendipity HQ Users Bundle comes with a prebuilt form to change the password.
Find it here: src/Form/Type/UserPasswordChangeType.php
It provides three fields:
old_password
plainPassword
- Confirmation of
plainPassword
Under the hood, it uses the RepeatedType
provided by Symfony to ensure that the new password and confirmation password are equals.
And thanks to the interface HasPlainPasswordInterface
, the form can automatically be handled by Serendipity HQ Users Bundle.
All is really easy!
Now we need a route.
2. Create the UserPasswordController::changePassword()
As usual, use the make
command:
The command created both the controller and its template.
Open the controller and remove the index()
route.
Then add the route changePassword()
:
There are some things you should note here:
- The use of annotation
@Security
: in case the current user is not logged in, the route will return aSymfony\Component\Security\Core\Exception\AccessDeniedException
; - The name of the route MUST be the same of the one in Routes::PASSWORD_CHANGE;
- The variable
$user
is indicated as of typeHasPlainPasswordInterface
: the methodPasswordHelper::createFormPasswordChange()
, in fact, accept a variable of typeHasPlainPasswordInterface
; - If the form is submitted and is valid, we simply call
EntityManagerInterface::flush()
: the form, in fact, will automatically update the$user
with the new plain password provided;
All is ready to be used: now your users are able to change their passwords!
Remember to add the links to this page somewhere in your app (typically, in the profile page or in a user menu).
Now we need to make possible for the users to reset their passwords in case they have forgot them.
Implementing password resetting
The flow to reset a password is as follows:
- Show a page where the user can provide his/her main identifier (username, email, phone number, etc.);
- Generate a unique token and send it to the user (via email, SMS or any other channel you like)
- Validate the token and show the user a form that permits to set a new password.
In this example we will assume the following:
- The unique identifier of the user is the email;
- The token will be sent via email.
To implement the entire flow we need:
- Three routes to manage the three steps (reset request, link sent confirmation, reset page)
- The corresponding templates (for the routes and for the email)
- An entity that represents the token
- A listener to send the email
Lets start!
Create the reset request
To make possible to request a reset token, we need:
- A form type
- A route
- A template
Start by adding to the UserPasswordController
the method resetRequest()
:
As you can see, the route is really simple.
There are some things you should note here:
- The name of the route MUST be the same of the one in Routes::PASSWORD_RESET_REQUEST;
- Once we are sure the form hasn't any error, we handle the request through Serendipity HQ Users Bundle and then we simply flush the changes to the database: the bundle, in fact, takes care of all the operations: we only need to flush them (Remember: the bundle will never flush Doctrine!).
Also note that we don't have to build any form: it is built by Serendipity HQ Users Bundle.
Now we need to create the template: this is something really customized on the app, so we need to create it on our own.
We are ready.
Now its time to process this request.
Create the confirmation page
Create the method UserPasswordController::resetRequestReceived()
:
This method is really simple, too.
The only thing you have to note is the call to canAccessPageCheckYourEmail
: this method will read the session of the current (anonymous) user and checks if there is a value previously set in UserPasswordController::resetRequest()
by calling the PasswordManager::handleResetRequest()
.
Now we need to create the last route, the one that will actually make the user able to set his/her new password.
Create the reset page
Create the method UserPasswordController::reset()
:
This method is a bit longer than the others: it has to do a lot of things!
The code is commented, so it is clear what it does.
The only thing to note is, again, the call to the method EntityManager::flush()
: again, the bundle will never flush the database: this is a responsibility of ours.
If you try to reset your password now, you will receive an error and, anyway, there is no code that actually sends the token to the user.
We need to implment those two missing pieces.
Creating the PasswordResetToken
entity
First, we need to create the entity that will represent the reset token.
Create the entity PasswordResetToken
:
This class MUST implement the interface PasswordResetTokenInterface
and will be used by the method handleResetRequest()
in UserPasswordController::resetRequest()
.
You can customize it as you like.
The two things you may want to customize are:
- Your
User
class in theManyToOne
relation; - The namespace of the entity itself.
In this second case, the default namespace used by the bundle is App\Entity\PasswordResetToken
, but you can change it (and also the name of the entity class) by setting the parameter shq_users.token_class
in your configuration.
Creating the subscriber to send the email to the user
To actually send the email to the user, we need a subscriber that listens for the event PasswordResetTokenCreatedEvent
.
Create it:
Now we are done!
Try to reset your password and all should work as expected.
In case something doesn't work, please, open an issue.
Other useful features
- The
UsersManager
(provided by SHQUsersBundle) - Events (The events triggered by the bundle: they are in src/Events)
- Commands (Explanation of the commands available) (How to extend commands)
- Creating a register form
- Creating a login form
- Creating a password reset form
Creating a User with the manager
Method create()
dispatches an event UserCreatedEvent
.
You can listen for it and, if you like, you can set UserCreatedEvent::stopPropagation()
.
If true === UserCreatedEvent::isPropagationStopped()
, then the manager will not persist the user in the database, but will anyway return it.
This way you can decide what to do: create a new user, persist it by yourself, etc.
The manager will never call EntityManager::flush()
: it is always your responsibility to call it and decide if and when to do so.
The method UserInterface::eraseCredentials()
is never called by the bundle: it is a responsibility of yours as we don't know if you need them one more time (for example, to send an email to the registered user with the plain passowrd).
Creating a registration form
When using the make command from Symfony, the generated form type has a field plainPassword
that has the option mapped = false
.
Implement the trait HasPlainPassword
in the User
entity and then remove the option from the form type.
This way, the User
entity will have a field plainPassword
provided by the trait, the form will bind the form field to this property and the Doctrine listener will automatically encode the password.
Also, modify the controller to not encode the password anymore.
How to create a command to manage users
Managing password reset
- Create the repo
PasswordResetTokenRepository
and implement the interfacePasswordResetTokenRepositoryInterface
- Create the controller
PasswordController
(with which methods/routes?)
Handling garbage collection
Do you like this bundle?
LEAVE A ★
or run
composer global require symfony/thanks && composer thanks
to say thank you to all libraries you use in your current project, this included!
All versions of bundle-users with dependencies
ext-json Version *
doctrine/orm Version ^2.7 | ^3.0
nesbot/carbon Version ^2.0 || ^3.0
symfony/console Version ~5.4|~6.4|~7.0
symfony/form Version ~5.4|~6.4|~7.0
symfony/property-access Version ~5.4|~6.4|~7.0
symfony/string Version ~5.4|~6.4|~7.0
symfony/validator Version ~5.4|~6.4|~7.0
thecodingmachine/safe Version ^1.0|^2.0