Crear nuevos, editar su información, añadir o eliminar roles, permitir el registro a usuarios anónimos, recuperar contraseña, etc.

Como ya vimos en el capítulo sobre bundles , FOSUserBundle es el bundle más utilizado para solucionar este problema recurrente. Muchas distribuciones basadas en Symfony ya lo integran por defecto.

Hasta ahora, lo único que hemos hecho en la aplicación de ejemplo es proteger la ruta /admin bajo un firewall que require autenticación de un usuario con role ROLE_ADMIN . Para una aplicación personal nos puede servir, pero no para el proyecto de un cliente.

Vamos por tanto a integrar FOSUserBundle en nuestra aplicación.

Primeros pasos con FOSUserBundle

Esta librería incluso tiene su propio apartado en la documentación oficial de Symfony.

Primeros pasos con FOSUserBundle .

Primero, instalar el bundle:

composer require friendsofsymfony/user-bundle "~1.3"

Activarlo en AppKernel.php

<?php
public function registerBundles()
{
    $bundles = array(
        //...
        new FOS\UserBundle\FOSUserBundle(),
    );

El siguiente paso es crear nuestra entidad User para gestionar los usuarios. Para ello tenemos que hacer que nuestra entidad herede de FOS\UserBundle\Entity\User y mapear el campo id manteniendo la definición del mismo en la clase original.

<?php

namespace AppBundle\Entity;

use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    public function __construct()
    {
        parent::__construct();
    }
}

Ejemplo de configuración para Doctrine ORM

El siguiente paso es configurar el archivo security.yml de nuestra aplicación

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: security.csrf.token_manager
            logout:       true
            anonymous:    true

    access_control:
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, role: ROLE_ADMIN }

Se ha establecido la codificación en sha512 , un algoritmo de codificación de 512 Bits.

El rol definido con el nombre ROLE_ADMIN , contiene ROLE_USER . El role ROLE_SUPER_ADMIN contiene ROLE_ADMIN , por tanto contiene todos los roles definidos en ROLE_ADMIN .

Para que quede más claro, la aplicación final va a tener 3 tipos de usuario con sus permisos correspondientes:

  1. Usuario anónimo: puede ver posts.
  2. ROLE_ADMIN: puede ver y comentar posts.
  3. ROLE_SUPER_ADMIN: puede gestionar todas las entidades de la aplicación.

El firewall main ha sido modificado para establecer la propiedad form_login , que indica a Symfony que cualquier petición realizada bajo este firewall requiere autenticación.

logout y anonymous tienen como valor true , para permitir el cierre de sessión y el acceso a rutas sin protección, como por ejemplo, la pantalla que contiene el formulario de login.

En access_control la única ruta protegida es ^/admin/ . Las demás permiten el acceso anónimo para login, registro de usuario y recuperación de contraseña.

Ahora debemos indicar la configuración y enrutamiento del bundle

# app/config/config.yml
fos_user:
    db_driver: orm
    firewall_name: main
    user_class: AppBundle\Entity\User
# app/config/routing.yml
fos_user_security:
    resource: "@FOSUserBundle/Resources/config/routing/security.xml"

fos_user_profile:
    resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
    prefix: /profile

fos_user_register:
    resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
    prefix: /register

fos_user_resetting:
    resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
    prefix: /resetting

fos_user_change_password:
    resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
    prefix: /profile

Si actualizamos el esquema de la base de datos se creará una nueva tabla fos_user .

php app/console doctrine:schema:update --force

Creación y gestión de usuarios

Este bundle incluye una serie de comandos para poder realizar acciones sobre los usuarios de la aplicación. Aquí puedes encontrarlos todos.

En nuestro caso, necesitamos crear un usuario y asignarle el rol de administrador de la aplicación.

php app/console fos:user:create admin admin@myblog.com adminpass

php app/console fos:user:promote admin ROLE_SUPER_ADMIN

FOSUserBundle manager

Este bundle provee de un gestor de usuarios para facilitar su manejo dentro de la aplicacion. Es similar al EntityManager de Doctrine, pero propio de FOSUserBundle. Se obtiene de la siguiente forma desde el contenedor de servicios:

<?php

$userManager = $container->get('fos_user.user_manager');

La documentación para conocer todas las opciones de las que dispone se encuentra aquí .

Por supuesto, puedes seguir manejando las entidades de FOSUserBundle con EntityManager, al igual que con cualquier otra entidad, pero el UserManager es más eficiente en este caso.

Personalizar vistas de usuario

Para integrar las vistas de FOSUserBundle en nuestra aplicación tenemos que sobrescribirlas utilizando la herencia de plantillas, como vimos en el capítulo 3 .

En este caso, hay que sobrescribir la plantilla layout.html.twig de FOSUserBundle.

app/Resources/FOSUserBundle/views/layout.html.twig.

El bloque fos_user_content es el que contiene las diferentes vistas de cada una de las acciones que se muestran por pantalla: login, registro, etc.

{% block content %}
    {% block fos_user_content %}{% endblock %}
{% endblock %}

layout.html.twig es la plantilla base de la que heredan todas las demás de FOSUerBundle. Puedes también personalizar todas las vistas de acciones concretas:

  • Login
  • Registro
  • Registro confirmado
  • Solicitar recuperación de contraseña
  • Establecer nueva contraseña
  • Email de confirmación enviado.
  • La contraseña ya ha sido solicitada
  • Editar perfil de usuario
  • Mostrar perfil de usuario

Envío de emails

FOSUserBundle también provee un soporte para el envío de email en dos posibles casos.

Confirmación de registro

Se puede añadir una configuración para obligar al usuario registrado que confirme su dirección de email. En el archivo app/config/config.yml

fos_user:
    # ...
    registration:
        confirmation:
            enabled: true

Recuperación de contraseña

Si un usuario no recuerda su contraseña, se le puede redirigir a una pantalla de recuperación con un proceso en 2 pasos:

  1. Mediante un formulario, el usuario introduce el email correspondiente a su cuenta en la aplicación.
  2. La aplicación envía un email de connfirmación, que contiene una url con un token autogenerado.

Al pinchar en el enlace, el usuario es redirigido a otra página con un formulario para introducir su nueva contraseña y confirmarla.

FOSUserBundle utiliza la librería SwiftMailer internamente para el envío de emails. De forma sencilla se puede configurar la aplicación para que, estando en el entorno de desarrollo, siempre envíe los email a la misma dirección, independietemenete de lo que hayamos configurado en los controladores, con el objetivo de hacer pruebas de funcionamiento. En app/config/config_dev.yml

swiftmailer:
    delivery_address: sergio@sopinet.com

Más opciones

Éstas son sólo algunas de las características que podemos encontrar en este bundle, para seguir aprendiendo sobre FOSUserBundle visita la documentación oficial para configuraciones avanzadas .