How to choose a Controller in the routes - php

In Laravel 4.2, I have the following route:
Route::group(array('before' => 'auth'), function() {
Route::post('/account/edit', array(
'as' => 'account-edit',
'uses' => 'UserController#accEdit'
));
});
I have a ClientController and an AdminController for common user and admin, respectively.
Assuming that I know the user type (Auth::getUser()->getType()), how can I replace the UserController with the correct controller without adding extra logic to routes class? Can this be done with filters?
I'm trying to avoid an extra controller between the routes and the final controller.

Actually, it is not necessary to create two user controller. Just use middleware to limit the access rights of clients. By this way, you can keep the original UserController.
You can add IsAdmin.php in the middleware.
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\RedirectResponse;
use Illuminate\Contracts\Auth\Guard;
class IsAdmin {
public function handle($request, Closure $next)
{
if (Auth::getUser()->getType() === 'admin')
{
return $next($request);
}
return new RedirectResponse(url('/'));
}
}
In kernel.php, you need declare your middleware.
protected $routeMiddleware = [
// some other middlewares
'admin' => 'App\Http\Middleware\IsAdmin',
];
Then, add the following statements in public function __construct of the UserController.php
$this->middleware('admin', ['only' => ['OnlyForAdmin1','OnlyForAdmin2']]);
Thus, clients will have no access to the function OnlyForAdmin1 and function OnlyForAdmin2.

Related

Protect Route in Laravel 9 Based on User Column Value

I have a column in my User table named role with 2 possible values--"Admin" and
"Driver".
All my crud routes are protected with Auth middleware, but I'd like to further secure a few of those routes.
For example I'd like to have the "Create" routes only accessible by Users with the role column equalling "Admin". I wasn't sure how to go about this, so I can't provide examples of what I've tried.
web.php
...
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/users', App\Http\Livewire\User\Index::class)->name('users.index');
Route::get('/user/{user}/edit', App\Http\Livewire\User\Edit::class)->name('user.edit');
/* This is the route I want to protect to just "Admin" role */
Route::get('/user/create', App\Http\Livewire\User\Create::class)->name('user.create');
...
You can create a middleware with the artisan command
php artisan make:middleware IsAdminMiddleware
Then add something like this in the handle function of your middleware.
public function handle(Request $request, Closure $next)
{
// This validation assumes you can access role from User Model
if ($request->user()->role != "Admin") {
return response()->json(['error' => 'you are not an admin!'], 403);
}
return $next($request);
}
Finally add the middleware on your Routes
Route::get('/user/create', App\Http\Livewire\User\Create::class)
->middleware(IsAdminMiddleware::class) // <<----
->name('user.create');
For more info refer to middleware the docs at laravel.
You can use authorization in laravel for your case
in laravel you can use gate or policy for further feature
https://laravel.com/docs/9.x/authorization
Gate
define gate in App\Providers\AuthServiceProvider on method boot
use Illuminate\Support\Facades\Gate;
use Illuminate\Auth\Access\Response;
use App\Models\User;
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('create', function (User $user) {
return ($user->role == 'Admin')
? Response::allow()
: Response::deny('You must be an administrator.');
});
}
On your controller
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class CreateController extends Controller
{
public function create(Request $request)
{
$user = Auth::user();
if (Gate::allows('create', $user)) {
//create
}
}
}

How to redirect non-authenticated users to login view

I'm making an application which requires a user and password for access. Every user should face the login view. Currently, writing the URL manually, I can access all the routes without login. What I want is to redirect every unauthenticated user to the login view, so that they can't see anything else until they log in.
LoginController
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
public function redirectTo() {
$isAuth = Auth::check();
if ($isAuth) {
return redirect('dashboard');
} else {
return redirect('login');
}
}
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function logout(Request $request)
{
Auth::logout();
return redirect('/login');
}
}
Routes
<?php
Route::get('/', function () {
return view('home');
});
Route::resource('project','ProjectController');
Route::resource('client','ClientController');
Route::resource('task','TaskController');
Route::resource('people','PeopleController');
Route::get('/login', function () {
return view('login');
});
Route::get('logout', '\App\Http\Controllers\Auth\LoginController#logout');
Auth::routes();
Route::get('/dashboard', 'DashboardController#index');
You should use a middleware for that. To get info on what a middleware is check here laravel.com/docs/master/middleware
Let's see how you can use the default Laravel's auth middleware for this purpose:
First of all get rid of your AdminBaseController and use only AdminController
Then you have to check that the auth middleware is enabled in the file app\Http\Kernel.php
You should have the line:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
This means that the middleware is active and usable for your routes.
Now let's go inside the middleware class in app\Http\Middleware\Authenticate.php to specify the middleware's behaviour :
this method will be triggered before your controller constructor
public function handle($request, Closure $next)
{
//check here if the user is authenticated
if ( ! $this->auth->user() )
{
// here you should redirect to login
}
return $next($request);
}
Now the only thing left to do is to decide for what routes you should apply the middleware. Let's suppose you have two routes that you want to be only accessible from authenticated users, you should specify to use the middleware for these two routes in this way:
Route::group( ['middleware' => 'auth' ], function()
{
Route::get('admin/home', 'AdminController#index');
});
You should move your Auth::routes() before your first route
<?php
Auth::routes()
Route::get('/', function () {
return view('home');
});
And use auth middleware in your controllers where you want only authenticated user.
public function __construct()
{
$this->middleware('auth');
}
Move your Auth:Routes(); right after
Route::get('/', function () {
return view('home');
});
Then all your routes will be auth protected.

Define Laravel 5 route inside subfolder and display it via controller

I have Laravel 5.2.45 app.
I have controller structure like this:
App
Http
Controllers
Admin
AdminController.php
inside AdminController.php I have
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Requests;
class AdminController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('is.admin');
}
public function index()
{
return view('admin.home');
}
}
I have views folder structure like this:
views
admin
home.blade.php
And inside my routes.php I have
Route::get('/admin/home', 'Admin\AdminController#index');
So I'm trying to get that when I type .../admin/home browser displays home.blade.php inside admin folder.
My routes.php:
Route::auth();
Route::get('/', 'FrontController#index');
Route::get('/home', 'FrontController#index');
Route::get('/add_user', 'FrontController#user');
Route::group(['prefix', 'admin', 'namespace' => 'Admin'], function() {
Route::get('home', 'AdminController#index');
});
The prefix is missing in your route definition. Correct it to look like this:
<?php
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function() {
Route::get('/home', 'AdminController#index');
});
Now, try base_url/admin/home in your browser and it should work.
You can use route groups with the namespace and prefix options.
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function() {
Route::get('home', 'AdminController#index');
});
Here, the prefix allows you to specify the beginning of a URL that should always be in the routes inside the group. So any routes you put inside that group should start with admin.
The namespace lets you specifiy a folder/namespace for the controllers you reference. So all the controllers must be in the App\Http\Controllers\Admin namespace and the app/Http/Controllers/Admin folder.
You need to drop the leading forward slash so it becomes:
Route::get('admin/home', 'Admin\AdminController#index');

assign separate middleware to each method of a resource in laravel

I am using Zizaco/entrust laravel package as a ACL Manager for my project.
I know that for limit access to a route group via middlewares and assign a role (or permission) to it, I should do that like this:
Route::group(['prefix' => 'admin', 'middleware' => ['role:admin']], function() {
....
});
But I want to assign separate permission to different routes(methods) of a resource controller.
I know that how can so that for whole resource but I can not implement it for each controller method:
Route::group(['prefix' => 'admin', 'middleware' => ['role:admin']], function() {
Route::resource('/post', ['middleware' => ['permission:manage-posts'], 'uses' => 'PostController']);
});
I want to assing this permission to related method :
'post-create' => public function create ()
'post-edit' => public function edit()
and so on.
You can assign middlewares in your controller's constructor:
class Foo extends Conroller
{
public function __construct() {
$this->middleware('post-create', ['only' => ['create']]);
$this->middleware('post-edit', ['only' => ['edit']]);
}
}
Imagine you have apiResource units-of-measure. You can assign different middlewares to separate endpoints like this:
Route::middleware('role:seller|buyer')->group(function () {
Route::apiResource('units-of-measure', UnitOfMeasureController::class)->only('index');
});
Route::middleware('role:seller')->group(function () {
Route::apiResource('units-of-measure', UnitOfMeasureController::class)->except('index');
});
The index endpoint will be accessible for sellers as well as for buyers. The rest of endpoints are only for sellers.
you can chain the methods, using the only method.
here is an example:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Spatie\Permission\Models\Role;
class UserController extends Controller
{
public function __construct()
{
$this->middleware('permission:read-user')->only('index','show');
$this->middleware('permission:edit-user')->only('edit','update');
$this->middleware('permission:delete-user')->only('delete');
$this->middleware('permission:create-user')->only('create','store');
}

Laravel Add a filter to resourceful route

I'm using Laravel 4.2
I have a ressourceful route like this:
Route::resource('customers', 'CustomersController');
How can I add a filter, let's say 'auth' filter to all corresponding routes and how to target only some of them, let's say I want only to filter access to the named route 'customers.create'.
You can define a filter in your Controller's constructor:
public function __construct()
{
$this->beforeFilter('auth', ['only' => ['update', 'store']]);
}
If you have many resources you can use route groups:
Route::group(['before'=>'auth'], function () {
Route::resource('customers', 'CustomersController');
// ... another resource ...
});
...and specify beforeFilter in each Controller's constructor.
OR:
Use a simple if statement in routes.php:
if (Auth::check()) {
Route::resource('customers', 'CustomersController');
} else {
Route::resource('customers', 'CustomersController', ['except' => ['update', 'store']]);
}
Create a base controller for resources that use the same filter and extend it:
class AuthorizedController extends BaseController {
// ... constructor with beforeFilter definition ...
}
class CustomersController extends AuthorizedController { ... }

Categories