How do I protect routes and functions of a controller with custom middleware in laravel 5.3?

0

I have% custom middleware for routes and for CRUD functions.

The one with the routes works perfectly for me, but the one with the functions does not.

Constructor of each controller, this ej is the one of Users:

public function __construct(Guard $auth){
        $this->auth = $auth;
        $this->middleware('auth');
        $this->middleware('ruta:Usuarios');
        $this->middleware('funciones:Usuarios,crear',['only'=>['crear']]);
        $this->middleware('funciones:Usuarios,editar',['only'=>['editar']]);
        $this->middleware('funciones:Usuarios,eliminar',['only'=>['eliminar']]);
        $this->middleware('funciones:Usuarios,estado',['only'=>['estado']]);
}

I pass as a parameter the controller in which it is, in this case it is the one of Users.

The middleware of the routes:

namespace App\Http\Middleware;

use Illuminate\Contracts\Auth\Guard;
use Closure;
use Auth;
use Session;
use Redirect;
use DB;
use Debugbar;

class Ruta{

    protected $auth;

    public function __construct(Guard $auth){
        $this->auth = $auth;
    }
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $ruta){
        $results = DB::select('select exists(select * FROM perfiles_funciones AS pf INNER JOIN funciones AS f ON f.id = pf.id_funciones INNER JOIN perfiles AS p ON p.id = pf.id_perfiles WHERE pf.id_perfiles = :id AND f.titulo = :ruta) as "exists"', 
            [
            'id' => ($this->auth->user()->id_perfiles),
            'ruta'=>($ruta)
            ]);
        if(!$results){
            session()->set('message','No tiene permisos para acceder a la opción de '.$ruta);
            return redirect('/');
        }
        return $next($request);
    }
}

The middleware of the functions:


namespace App\Http\Middleware;

use Illuminate\Contracts\Auth\Guard;
use Closure;
use Auth;
use Session;
use Redirect;
use DB;
use Debugbar;

class Funciones{

    protected $auth;

    public function __construct(Guard $auth){
        $this->auth = $auth;
    }
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $ruta, $func){
        if($func=='crear'){
            $results = DB::select("select exists(select * FROM perfiles_funciones AS pf INNER JOIN funciones AS f ON f.id = pf.id_funciones INNER JOIN perfiles AS p ON p.id = pf.id_perfiles WHERE pf.id_perfiles = :id AND f.titulo = :ruta AND pf.crear = 't')",
                [
                'id' => ($this->auth->user()->id_perfiles),
                'ruta'=>($ruta)
                ]);
            if($results){
                return $next($request);
            }
        }
        if($func=='editar'){
            $results = DB::select("select exists(select * FROM perfiles_funciones AS pf INNER JOIN funciones AS f ON f.id = pf.id_funciones INNER JOIN perfiles AS p ON p.id = pf.id_perfiles WHERE pf.id_perfiles = :id AND f.titulo = :ruta AND pf.editar = 't')",
                [
                'id' => ($this->auth->user()->id_perfiles),
                'ruta'=>($ruta)
                ]);
            if($results){
                return $next($request);
            }
        }
        if($func=='eliminar'){
            $results = DB::select("select exists(select * FROM perfiles_funciones AS pf INNER JOIN funciones AS f ON f.id = pf.id_funciones INNER JOIN perfiles AS p ON p.id = pf.id_perfiles WHERE pf.id_perfiles = :id AND f.titulo = :ruta AND pf.eliminar = 't')",
                [
                'id' => ($this->auth->user()->id_perfiles),
                'ruta'=>($ruta)
                ]);
            if($results){
                return $next($request);
            }
        }
        if($func=='estado'){
            $results = DB::select("select exists(select * FROM perfiles_funciones AS pf INNER JOIN funciones AS f ON f.id = pf.id_funciones INNER JOIN perfiles AS p ON p.id = pf.id_perfiles WHERE pf.id_perfiles = :id AND f.titulo = :ruta AND pf.estado = 't')",
                [
                'id' => ($this->auth->user()->id_perfiles),
                'ruta'=>($ruta)
                ]);
            if($results){
                return $next($request);
            }
        }
    }
}

Kernel file where I define the middleware:

    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'ruta' => \App\Http\Middleware\Ruta::class,
        'funciones' => \App\Http\Middleware\Funciones::class,
    ];

I check with debugbar the result of sql and it is the expected result but it does not block the action at url as it will enter the condition.

Update 1 modify the query I perform in the middleware as follows:

namespace App\Http\Middleware;

use Illuminate\Contracts\Auth\Guard;
use Closure;
use Auth;
use Session;
use Redirect;
use DB;
use Debugbar;

class Funciones{

    protected $auth;

    public function __construct(Guard $auth){
        $this->auth = $auth;
    }
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $ruta, $func){
        if($func=='crear'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.crear', 't')
                        ->exists();
            if($results){
                return $next($request);
            }
        }
        if($func=='editar'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.editar', 't')
                        ->exists();
            if($results){
                return $next($request);
            }
        }
        if($func=='eliminar'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.eliminar', 't')
                        ->exists();
            Debugbar::error($results);
            if($results){
                return $next($request);
            }
        }
        if($func=='estado'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.estado', 't')
                        ->exists();
            if($results){
                return $next($request);
            }
        }
    }
}

but now it throws me the following error:

ErrorException in VerifyCsrfToken.php line 136: Trying to get property of non-object
    
asked by Pablo Contreras 09.01.2017 в 08:02
source

2 answers

1

The way laravel does it is to launch an axception at the end, in case you do not call return $next($request); In the file app/Exceptions/Handler.php you place the error in the array

protected $dontReport = [
    \Illuminate\Auth\AuthenticationException::class,
    \Illuminate\Auth\Access\AuthorizationException::class,
    \Symfony\Component\HttpKernel\Exception\HttpException::class,
    \Illuminate\Database\Eloquent\ModelNotFoundException::class,
    \Illuminate\Session\TokenMismatchException::class,
    \Illuminate\Validation\ValidationException::class,
    \App\Exceptions\FunctionException::class // error sobre tu midleware
];

In render you must place

public function render($request, Exception $exception)
{
    if ($e instanceof FunctionException) {
        return $e->errorEnFunciones();
    }
    return parent::render($request, $exception);
}

you place a function errorEnFunciones

protected function unauthenticated($request, FunctionException $exception){......}

where you can do a redirect, like this in the function unauthenticated

Claro importaas

use App\Exceptions\FunctionException;

That something should be like this

app / Exceptions / FunctionException.php

namespace App\Exceptions;

use Exception;

class FunctionException extends Exception
{

    protected $guards;


    public function __construct($message = 'Error en funciones.', array $guards = [])
    {
        parent::__construct($message);

        $this->guards = $guards;
    }


    public function guards()
    {
        return $this->guards;
    }
}

and about your midleware at the end of the flame

throw new FunctionException('Error en funciones.', $guards);
    
answered by 09.01.2017 / 17:35
source
0

Fixed: in the first update I show an error that the middleware gave me, I simply remove the return $next($request); of the condition and the condition I invested it.

namespace App\Http\Middleware;

use Illuminate\Contracts\Auth\Guard;
use Closure;
use Auth;
use Session;
use Redirect;
use DB;
use Debugbar;

class Funciones{

    protected $auth;

    public function __construct(Guard $auth){
        $this->auth = $auth;
    }
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next, $ruta, $func){
        if($func=='crear'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.crear', 't')
                        ->exists();
            if(!$results){
                $ruta = strtolower($ruta);
                return redirect('/'.$ruta);
            }
            return $next($request);
        }
        if($func=='editar'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.editar', 't')
                        ->exists();
            if(!$results){
                $ruta = strtolower($ruta);
                return redirect('/'.$ruta);
            }
            return $next($request);
        }
        if($func=='eliminar'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.eliminar', 't')
                        ->exists();
            Debugbar::error($results);
            if(!$results){
                $ruta = strtolower($ruta);
                return redirect('/'.$ruta);
            }
            return $next($request);
        }
        if($func=='estado'){
            $results = DB::table('perfiles_funciones AS pf')
                        ->join('funciones AS f','pf.id_funciones','=','f.id')
                        ->join('perfiles AS p','pf.id_perfiles','=','p.id')
                        ->where('pf.id_perfiles', ($this->auth->user()->id_perfiles))
                        ->where('f.titulo', ($ruta))
                        ->where('pf.estado', 't')
                        ->exists();
            if(!$results){
                $ruta = strtolower($ruta);
                return redirect('/'.$ruta);
            }
            return $next($request);
        }
    }
}
    
answered by 09.01.2017 в 17:24