The only reason I want to apply middleware options to my routes and not the controllers themselves is because I would like to build route groups from the same routes PHP file like the following, and I would like to do something like so:
Route::prefix('api')
->middleware('api')
->middleware('auth:api', ['only' => ['store', 'edit', 'delete']])
->middleware('auth:api', ['except' => ['index', 'show']])
->namespace($this->namespace)
->group(base_path('routes/api.php'));
Route::prefix('web')
->middleware('api')
->middleware('auth', ['only' => ['store', 'edit', 'delete']])
->middleware('auth', ['except' => ['index', 'show']])
->namespace($this->namespace)
->group(base_path('routes/api.php'));
However, obviously, the official documentation listed you can have multiple middlewares with this method in routes:
route->middleware('middleware1', 'middleware2')
Is there anyway to apply the "only these methods" and "except these methods" to route groups? If no, is there another way to go around this problem within my controllers, so that they know which route group the request is from and use different middlewares accordingly?
If I understand your question correctly, route groups (as suggested in the comments) are the "official" way to do what you're describing, particularly if you nest them.
Nested groups attempt to intelligently "merge" attributes with their parent group. Middleware and where conditions are merged while names, namespaces, and prefixes are appended. Namespace delimiters and slashes in URI prefixes are automatically added where appropriate.
You can also supply an array of options to the group method:
// routes/api.php
$namespaces = [
'namespace1',
'namespace2',
'namespace3',
...
];
foreach ($namespaces as $namespace) {
Route::group(['namespace' => $namespace], function() {
Route::group([
'prefix' => 'api',
'middleware' => [
'api',
['auth:api', ['only' => ['store', 'edit', 'delete']]],
['auth:api', ['except' => ['index', 'show']]]
],
], function() {
// api controller methods here
});
Route::group([
'prefix' => 'web',
'middleware' => [
'api',
['auth', ['only' => ['store', 'edit', 'delete']]],
['auth', ['except' => ['index', 'show']]]
],
], function() {
// web controller methods here
});
});
}
Note however that you may need to rearrange the array order to get the desired effect:
Middleware are executed in the order they are listed in the array
Related
I use Laravel 5.6.33. I would like the user can have an access to the 'dashboard' page only when he/she has signed In/Up. When I use the 'guest' middleware, the user can't access the page at all and when I use the 'auth' middleware, the user always have an access to the page. What shall I do?
Route::group(['middleware' => ['web']], function (){
Route::get('/dashboard', [
'uses' => 'UserController#getDashboard',
'as' => 'dashboard',
'middleware' => 'auth'
]);
});
I have also added $this->middleware('auth'); in the getDashboard function or in the constructor of the UserController but it doesn't work. What shall I do?
In the Kernel.php the auth address is as follows:
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
If you are using Laravel 5.6 you don't need to wrap your routes with web middleware as long as you put them inside your routes\web.php file. Laravel makes this for you in the RouteServiceProvider.php.
For your purpose the auth middleware should work. Try this instead of what you have:
Route::middleware('auth')->group(function() {
Route::get('/dashboard', [
'uses' => 'UserController#getDashboard',
'as' => 'dashboard'
]);
});
you have to do nothing.
just add the following code.
Route::group(['middleware'=>'auth'],function () {
//you can create the list of the url or the resource here to block the unath users.
Route::resource('brands', 'BrandController');
Route::resource('products', 'ProductController');
});
Or use the construct function on the controller which you want to block.
public function __construct()
{
$this->middleware('auth');
}
it will block all the function on that controller like index, create, store, update, delete. only auth can use those functions.
So in the documentation says (http://jwt-auth.readthedocs.io/en/develop/) to change defaults to api, like this:
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
]
But then my web routes doesn't work.
Literally apply the next set of instructions.
You need to group your routes inside the API middleware.
So you'll need to do the same in your routes/web.php file.
If you don't they will use the wrong middleware.
Route::group([
'middleware' => 'api',
'prefix' => 'auth'
], function ($router) {
Route::post('login', 'AuthController#login');
Route::post('logout', 'AuthController#logout');
Route::post('refresh', 'AuthController#refresh');
Route::post('me', 'AuthController#me');
});
http://jwt-auth.readthedocs.io/en/develop/quick-start/
just some weeks ago I started with Laravel and I made some good progress in these weeks with my project.
3 days ago I decided to implement some roles for my users in the system.
I created a middleware via artisan and wrote the code for it.
The problem I have is to assign my middleware to a specific route.
First I added this line to the $routeMiddleware-array in the Kernel.php: 'role' => \App\Http\Middleware\RolesMiddleware::class,.
my routes/web.php-file looks like this on:
// Member area
Route::group(['prefix' => 'member', 'middleware' => ['auth', 'role']], function() {
Route::get('dashboard', ['as' => 'dashboard', 'uses' => function () {
return view('member.dashboard');
}]);
Route::group(['prefix' => 'user'], function() {
Route::get('showUsers',[
'uses' => 'UserController#showUsers',
'as' => 'manageUsers',
'roles' => 'manageUsers'
]);
});
});
First I had only the 'auth' middleware in the first group and I wanted to add my 'role' middleware as additional action directly on my get-route like middleware => 'role:manageUsers'. In this case my middleware was ignored totally and did not get called in any case.
After is put the middleware in the array like in the code above it got called at least.
Now I tried to add a custom action 'roles' with the value 'managerUsers' to my get-route. The middleware still gets called and if output the actions via var_dump(request->route()->getAction()); I see the actions 'uses' and 'as' but not my custom action 'roles'.
I have srsly no clue whats wrong. Does anyone know if it isn't possible to add custom actions or an additional middleware to a specific route?
Best regards.
EDIT 1 (17.07.2017)
My \app\Http\Middleware\RolesMiddleware.php looks like this:
namespace App\Http\Middleware;
use Closure;
class RolesMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param \string[] ...$roles
* #return mixed
*/
public function handle($request, Closure $next, string ...$roles)
{
var_dump($roles);
die('middleware reachted');
}
}
My \app\Http\Kernel.php looks like this:
...
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,
'role' => \App\Http\Middleware\RolesMiddleware::class,
];
...
And my \routes\web.php look like this:
...
Route::group(['prefix' => 'member', 'middleware' => ['auth', 'role']], function() {
...
Route::group(['prefix' => 'user'], function() {
Route::get('showUsers',[
'uses' => 'UserController#showUsers',
'as' => 'manageUsers'
]);
});
});
...
If I do assign my middleware as an array together with the "auth" middleware, my one will be called. The point is, that I want to define a role the user has to have with a specific route. (In this case with the Route::get(...))
If I do assign my middleware not together with the "auth" middleware (e.g. in the group with prefix "user"), it will be totally ignored. The same if I do assign my middleware with the get-route directly.
Route::group(['prefix'=>'user', 'middleware'=>'role:manageUsers'], function() {
Route::get('/showUsers',[
'uses' => 'UserController#showUsers',
'as' => 'manageUsers'
]);
});
Your RolesMiddleware.php:
class RolesMiddleware{
public function handle($request, Closure $next, ...$roles){
// sent arguments are stored in $roles array
print_r($roles); // Array ( [0] => manageUsers )
}
}
Have you registered your middleware in your kernel.php?
Best regards...
As usual the problem was in front of the PC.
I copied some more routes for later usage and forgot to change the value for 'as' in the action-array.
Because I'm using the value of the 'as' key for my template to find the correct page I got redirected by another route than expected. Sadly this one pointed to the same controller and action and I didn't noticed the wrong URL in my browsers adress bar.
My role-middleware worked as expected but I just accessed the wrong page.
so I have to make this system for transport management. The user can log in create/update/edit all his trips. But the admin can do the same for all users. I have divided user and admin in to route prefixes:
Route::group(['prefix' => 'admin/', 'middleware' => ['auth','admin']], function(){
Route::resource('trips', 'TripsController',
array('except' => array('show')));}
Route::group(['prefix' => 'user/', 'middleware' => ['auth', 'user']], function(){
Route::resource('trips', 'TripsController',
array('except' => array('show')));
}
The problem is in every method of the TripController I have to pass route variable with the correct url (the admin request will have a 'admin' prefix, and the users will have 'user' prefix)
return View('trips.index', compact('users', 'route'));
The question is there a way to do this nicely or should I just pull the trips Route::resource out of the both groups so that it wouldn't have any groups? What is the correct approach here?
I use this approach:
Route::group(['namespace' => 'Admin', 'as' => 'admin::', 'prefix' => 'admin'], function() {
// For Other middlewares
Route::group(['middleware' => 'IsNotAuthenticated'], function(){
// "admin::login"
// http://localhost:8000/admin/login
Route::get('login', ['as' => 'login', 'uses' => 'AdminController#index']);
});
// For admin middlewares
Route::group(['middleware' => 'admin'], function(){
// "admin::admin.area.index"
// http://localhost:8000/admin/area/{area}
Route::resource('Area', 'AreaController');
// "admin::dashboard"
// http://localhost:8000/admin/
Route::get('/', ['as' => 'dashboard', 'uses' => 'AdminController#dashboard']);
});
});
Whenever I need to access url in blade templates I simply use route helper method.
// For resourceful routes
{{ route('admin::admin.city.index') }}
or
//For regular get/post routes
{{ route('admin::dashboard') }}
Or simply run artisan command to list route names.
php artisan route:list
I did it with this:
//Admin Group&NameSpace
Route::namespace('Admin')->prefix('admin')->group(function () {
Route::get('/dashboard', 'DashboardController#index')->name('dashboard')->middleware('auth');
});
Even you can customize the ->middleware('auth'); with a custom middleware role based.
I am trying to group all the routes for our admin section to access model resources. So far I've come with this:
Route::group(['middleware' => 'auth', 'prefix' => 'admin', 'as' => 'admin::'], function() {
Route::get('dashboard', ['as' => 'dashboard', function() {
return view('pages.dashboard');
}]);
Route::resource('user', 'UserController', ['as' => 'user']);
Route::resource('plan', 'PlanController', ['as' => 'plan']);
Route::resource('answer', 'AnswerController', ['as' => 'answer']);
Route::resource('question', 'QuestionController', ['as' => 'question']);
Route::resource('retailer', 'RetailerController', ['as' => 'retailer']);
Route::resource('restriction', 'RestrictionController', ['as' => 'restriction']);
});
I want to name these routes to access them in a much easier manner by calling their names. However it breaks and says "Route [admin::user] not defined." I want to use the route naming feature to use route('admin::user'). I am having problem with the resource routes. The dashboard one works fine - route('admin::dashboard')
I take from this post that naming resource routes should work (Laravel named route for resource controller)
Resources are given route names automatically run php artisan route:list to list the routes out:
Route::group(['middleware' => 'auth', 'prefix' => 'admin', 'as' => 'admin::'], function() {
Route::get('dashboard', ['as' => 'dashboard', function() {
return view('pages.dashboard');
}]);
Route::resource('user', 'UserController');
});
Resulting Routes
admin::dashboard
admin::admin.user.store
admin::admin.user.index
admin::admin.user.create
admin::admin.user.destroy
admin::admin.user.show
admin::admin.user.update
admin::admin.user.edit