Getting Started with FOSUserBundle
Let's get started with FOSUserBundle. By the end of this video you will have:
- installed FOSUserBundle into a Symfony2 project
- updated your database to store your new User entities
- created a brand new User
- learned about the various Roles a User may have, including
ROLE_USER
Once you go beyond the very basic CRUD-style site you might build whilst learning Symfony2, you inevitably start needing the same sorts of modules (or bundles in Symfony-speak) regardless of the type of web site you are building.
User registration and management is perhaps the most common of these modules / bundles.
FOSUserBundle solves this common problem.
Right out of the box it gives us a fully working set of URLs / routes for Registration, Password Resets, Profile Management, along with Login and Log out.
I use FOSUserBundle right here on CodeReviewVideos. I have added some customisation, but everything from Registration through to managing your Profile is part of FOSUserBundle.
I use FOSUserBundle on every other project where I need User management. It's awesome. It installs in a fairly simple manner, and once it is in, it just kinda works.
If you haven't already done so, follow along with the official guide on Getting Started With FOSUserBundle. If you are adding FOSUserBundle into an existing project, be sure to make a full backup of your database before adding in the new User entity data.
When copying over the configuration for app/config/security.yml
from the official docs, be sure to copy in your dev
firewall and any other customisations you may have made.
I won't cover the installation procedure past this point as it really is largely just copy and paste from the docs.
User Management
Once you have installed and done the essential configuration for FOSUserBundle, the next likely step you will want to take is to create your first User account.
As part of the installation procedure, you will have created a User
class (or your own variant) likely extending FOS\UserBundle\Model\User
, and ultimately implementing FOS\UserBundle\Model\UserInterface
.
To get the most from this video, ideally you will follow along with your own installation. If at any point so far you are thinking... Huh? Then please follow the official installation instructions before continuing.
Once you have created your User
entity, you will have created the associated MySQL database table in which to persist your Users. If you are using MongoDB or other databases, this process should largely be similar.
To keep your User
data secure, your FOSUserBundle's User
class has been configured to encode all passwords with bcrypt
:
# http://symfony.com/doc/current/bundles/FOSUserBundle/index.html#step-4-configure-your-application-s-security-yml
# app/config/security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
This stops you from (easily) adding in a new User
directly to your MySQL table.
Thankfully, FOSUserBundle comes with a set of command line tools to manage your application's Users.
We can begin by adding in a new user:
php app/console fos:user:create
# or
php app/console fos:user:create codereview
# or
php app/console fos:user:create codereview chris@codereviewvideos.com
# or
php app/console fos:user:create codereview chris@codereviewvideos.com a_password_here
Note: Any User
objects that you create
this way will be automatically set to enabled.
All are valid ways to use the command. Each of the three arguments (username, email, password) are optional. We will be interactively prompted to add in any arguments we don't supply.
Hint: If adding User
data via the command line like in the above example, put a space before you command so the information is not saved in your terminal history
, revealing any sensitive password / user information. This only works on more recent unix-y systems afaik. Better still, leave the password off and use the interactive prompt.
Symfony is helpful in that whilst there are often lots of available commands available to us, you needn't remember them all as your command line will help you. Can't remember all the available commands? Just type in php app/console
and the full list of available commands will be printed out for your reference.
In the case of FOSUserBundle, we can simply type: php app/console fos
, and hit return, and you will see something similar to:
[InvalidArgumentException]
Command "fos" is not defined.
Did you mean one of these?
fos:user:change-password
fos:user:deactivate
fos:user:activate
fos:user:promote
fos:user:create
fos:user:demote
Again, all these are explained on the command line tools documentation page.
Being able to change a User
's password from the command line is very helpful.
What, perhaps, is less obvious is the usefulness of promote
and demote
.
This command allows us to add and remove Roles from a given User
. We haven't discussed Roles yet, but will do so shortly.
If we were to want to add a specific Role to a given User
at this point, we would need to manually serialize and deserialize the $roles
property of our User
object. This is a bit nasty. So instead, FOSUserBundle promote
and demote
give us a very quick way to add or remove Roles from our User
object, direct from the command line.
The following would give the Role of ROLE_ADMIN
to a user named some_admin_user
:
php app/console fos:user:promote some_admin_user ROLE_ADMIN
Alternatively, you could give the Role of ROLE_SUPER_ADMIN
to the user: some_superadmin_user
by:
php app/console fos:user:promote some_superadmin_user --super
Likewise, we can quickly remove a specific Role by one of the following:
php app/console fos:user:demote some_admin_user ROLE_ADMIN
# and / or
php app/console fos:user:demote some_superadmin_user --super
Both are incredibly handy commands to know about particularly during the application development phase of a project.
Whose Role Is It Anyway?
All this talk of promoting and demoting User
accounts from a given Role, and so far, no one has told us what a Role actually is!
Firstly, it's always helpful to give the official documentation a read where possible.
If you have configured and are using FOSUserBundle, whenever a User
successfully logs in, they are going to get the Role of ROLE_USER
.
This is important to understand, as you don't actually assign the Role of ROLE_USER
explicitly. This can be confusing.
When we created our first User
, we saw that in the database, the User
's Roles column was empty. We could easily add / remove Roles by way of promote
and demote
, but we never added ROLE_USER
. Yet as soon as we log in, we get the Role of ROLE_USER
.
Where Do Roles Come From?
The next confusing point - ROLE_USER
, ROLE_ADMIN
, ROLE_ALLOWED_TO_SWITCH
, etc - where on Earth are these things coming from?
Well, they are made up.
Symfony comes with some suggested roles - ROLE_USER
, ROLE_ADMIN
, ROLE_SUPER_ADMIN
, etc - but we don't have to use them. We could even change from using ROLE_USER
if we really wished. My advice is don't do that, however, as software development is already hard enough, without creating more needless headaches for ourselves.
We are completely free to make up and add any, and as many Roles as we want too.
We could create ROLE_CAN_COMMENT
or ROLE_EATS_CHIPS
or anything we like.
By giving Roles to our Users, we could then restrict parts of our Symfony application to only Users who have the given Role.
The most common use case for this would be to restrict certain paths in our application to only Users with ROLE_ADMIN
, or similar:
# app/config/security.yml
security:
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
But we are just as free to do something like:
# app/config/security.yml
security:
access_control:
- { path: /add-comment$, roles: ROLE_CAN_COMMENT }
Notice, the path
parameter uses regular expressions. In the /add-comment$
example I have omitted the ^
from the start of the path, which means any URL ending in /add-comment
would be restricted to Users
with the Role of ROLE_CAN_COMMENT
.
The concept of access_control
is outside the scope of this video. If interested, this section of the docs is a great place to start.
Symfony will also allow you to restrict Controller actions and other blocks of code according to whether or not the given User has a specific Role. See here for more.
Role Hierarchy
During set-up of FOSUserBundle, we also added in the following:
# app/config/security.yml
security:
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
By providing a role_hierarchy
, we can inherit Roles depending on the Role we have.
If our User
has ROLE_USER
, then they don't inherit / get any other Roles.
If our User
has ROLE_ADMIN
, then they would also be a ROLE_USER
, according to our role_hierarchy
.
Likewise, ROLE_SUPER_ADMIN
inherits ROLE_ADMIN
, which in turn, inherits ROLE_USER
.
We can also add in arrays of Roles. There's no point in me regurgitating the documentation - if you want to know more, this section of the official docs will be of help.