Implementar Entrust usando Middleware's [ Laravel 5 ]


En nuestro post anterior ENTRUST [ Laravel5 ], hablamos de la instalación, configuración y aplicación del paquete.
Ahora vamos a ver como implementarlo en nuestro proyecto usando Middleware's.

Para este tutorial eh usado los siguientes paquetes:

  1. laravel-ide-helper - Paquete de autocompletado de código en IDE's | Enlace
  2. laravel-debugbar - Paquete util al momento de testear nuestro proyecto | Enlace

En el anterior post creamos un usuario, roles, permisos y los asignamos o relacionamos respectivamente.

Creamos una ruta para testear nuestro usuario:

get('test', function () {
    return \App\User::find(4)->load([
        'roles' => function ($q) {
            $q->with('perms');
        }
    ]);
});
Y el front nos retorna:
{
    "id": "4",
    "name": "John Doe",
    "email": "johndoe@doe.com",
    "created_at": "2015-05-25 15:51:42",
    "updated_at": "2015-05-25 15:51:42",
    "roles": [
        {
            "id": "1",
            "name": "admin",
            "display_name": "Administrador de usuarios",
            "description": "Se permite al usuario gestionar y editar otros usuarios",
            "created_at": "2015-05-22 20:40:48",
            "updated_at": "2015-05-22 20:40:48",
            "pivot": {
                "user_id": "4",
                "role_id": "1"
            },
            "perms": [
                {
                    "id": "1",
                    "name": "create-post",
                    "display_name": "Crear Entradas",
                    "description": "crear nuevas entradas del blog",
                    "created_at": "2015-05-25 15:53:47",
                    "updated_at": "2015-05-25 15:53:47",
                    "pivot": {
                        "role_id": "1",
                        "permission_id": "1"
                    }
                },
                {
                    "id": "2",
                    "name": "edit-user",
                    "display_name": "Editar Usuarios",
                    "description": "editar los usuarios existentes",
                    "created_at": "2015-05-25 15:53:47",
                    "updated_at": "2015-05-25 15:53:47",
                    "pivot": {
                        "role_id": "1",
                        "permission_id": "2"
                    }
                }
            ]
        }
    ]
}
Como vemos el Usuario tiene asignado el rol admin el cual tiene 2 permisos: create-post y edit-user; Para usar esta información vamos a crear nuestro middleware.
En nuestra terminal tipeamos:
php artisan make:middleware EntrustMiddleware
Agregamos nuestro Middleware al Kernel del proyecto app/Http/Kernel.php, en el arreglo $routeMiddleware agregamos:
'entrust' => 'App\Http\Middleware\EntrustMiddleware'

Ahora abrimos nuestro archivo app/Http/Middleware/EntrustMiddleware.php:

<?php namespace App\Http\Middleware;

use Closure;

class EntrustMiddleware {

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }

}
En el constructor de esta clase vamos a inyectar Illuminate\Contracts\Auth\Guard(Usuario autentificado) e Illuminate\Routing\Route(Ruta actual con todas sus caracteristicas) y lo siguiente sera analizar los requerimientos de la ruta:


public function __construct(Guard $auth, Route $route)
{
    /**
     * Información del usuario autentificado
     */
    $this->auth = $auth;

    /**
     * Si en la ruta definimos que necesita roles
     * get('uri',['roles'=>'admin'])
     */
    if(isset($route->getAction()['roles']))
    {
        $this->requireRole = true;
        $this->roles = $route->getAction()['roles'];
    }
    /**
     * Si en la ruta definimos perms
     * get('uri',['perms'=>'create-post'])
     */
    if(isset($route->getAction()['perms']))
    {
        $this->needsPerms = true;
        $this->permissions = $route->getAction()['perms'];
    }
}
Yo cree 2 funciones donde se verifica/analiza si el usuario autentificado cumple los requerimientos de la ruta:


/**
 * Analiza si el usuario autentificado 
 * tiene el(los) rol(es) solicitado(s) en la ruta
 * 
 * @param \Illuminate\Http\Request $request
 * @param \Closure $next
 * @return \Illuminate\Http\RedirectResponse
 */
protected function analiceWithRole($request, $next)
{
    if($this->auth->user()->hasRole($this->roles))
    {
        if($this->needsPerms)
        {
            return $this->analiceWithPerms($request, $next);
        }

        return $next($request);
    }
    else
    {
        Flash::warning('No Tiene permisos suficientes para acceder a este recurso.');

        return redirect()->back(302);
    }
}

/**
 * Analiza si el usuario autentificado
 * tiene los permisos solicitados en la ruta
 * 
 * @param \Illuminate\Http\Request $request
 * @param \Closure $next
 * @return \Illuminate\Http\RedirectResponse
 */
protected function analiceWithPerms($request, $next)
{
    if($this->auth->user()->can($this->permissions))
    {
        return $next($request);
    }
    else
    {
        Flash::warning('No Tiene acceso a este recurso.');

        return redirect()->back(302);
    }
}
Ahora nuestro middleware completo quedaría de esta manera:


<?php namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Routing\Route;
use Laracasts\Flash\Flash;

class EntrustMiddleware
{

    protected $requireRole = false;
    protected $needsPerms = false;

    public function __construct(Guard $auth, Route $route)
    {
        /**
         * Información del usuario autentificado
         */
        $this->auth = $auth;

        /**
         * Si en la ruta definimos que necesita roles
         * get('uri',['roles'=>'admin'])
         */
        if(isset($route->getAction()['roles']))
        {
            $this->requireRole = true;
            $this->roles = $route->getAction()['roles'];
        }

        /**
         * Si en la ruta definimos perms
         * get('uri',['perms'=>'create-post'])
         */
        if(isset($route->getAction()['perms']))
        {
            $this->needsPerms = true;
            $this->permissions = $route->getAction()['perms'];
        }
    }

    /**
     * Handle an incoming request.
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if($this->requireRole)
        {
            return $this->analiceWithRole($request, $next);
        }
        elseif($this->needsPerms)
        {
            return $this->analiceWithPerms($request, $next);
        }
        else
        {
            return $next($request);
        }
    }

    /**
     * Analiza si el usuario autentificado
     * tiene el rol(es) solicitado en la ruta
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return \Illuminate\Http\RedirectResponse
     */
    protected function analiceWithRole($request, $next)
    {
        if($this->auth->user()->hasRole($this->roles))
        {
            if($this->needsPerms)
            {
                return $this->analiceWithPerms($request, $next);
            }

            return $next($request);
        }
        else
        {
            Flash::warning('No Tiene permisos suficientes para acceder a este recurso.');

            return redirect()->back(302);
        }
    }

    /**
     * Analiza si el usuario autentificado
     * tiene los permisos solicitados
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return \Illuminate\Http\RedirectResponse
     */
    protected function analiceWithPerms($request, $next)
    {
        if($this->auth->user()->can($this->permissions))
        {
            return $next($request);
        }
        else
        {
            Flash::warning('No Tiene acceso a este recurso.');

            return redirect()->back(302);
        }
    }
}
Con esto tenemos nuestro middleware creado y yo creo que es muy bonito :3 :).
Ahora vamos a usarlo, en nuestro archivo app/Http/routes.php vamos a definir unas cuantas rutas para testear nuestro middelware:


Route::group(['middleware' => ['entrust', 'auth'], 'roles' => 'admin', 'perms' => 'create-post'], function ()
{
    get('dashboardAdmin', function ()
    {
        return "El usuario autentificado tiene el rol de Administrador y tiene permisos para crear post's";
    });
});

Bueno y así de simple resulta la implementación de este paquete a nuestro Front, claro que este es solamente un punto de vista. Seguramente hay mejores programadores que en conjunto podrían crear algo mucho mejor.

Si te perdiste en alguna de la entrada, puedes descargar el código fuente del proyecto en GitHub | Enlace |
No olviden que después de descargar el código deben tipear:
composer install

Espero que les sea de utilidad,
Saludos y hasta la próxima.

PD: No se olviden de dejar algún comentario y también son libres de modificar a su gusto el código

1 comentario:

  1. Excelente gracias. Animo con nuevos tutoriales

    ResponderEliminar