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.
Related
Context, I'm bumping an old version of laravel into a newer version.
I have been able to fix several leaky holes, however, there is one, in particular, that is getting hard to find a solution for and that is this:
Route::when('admin/*', 'isAdmin');
It seems like the ::when thing no longer works.
Keep in mind I'm not a PHP developer, hell this is actually the first time I'm using PHP at all.
Here's the routing page (web.php)).
<?php
use Illuminate\Support\Facades\Route;
use App\Models\User;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::resource('admin/dashboard', 'App\Http\Controllers\DashboardController', array('only' => array('index')));
Route::resource('admin/companies', 'App\Http\Controllers\CompaniesController');
Route::resource('admin/users', 'App\Http\Controllers\UsersController');
Route::resource('admin/public_polls', 'App\Http\Controllers\PublicPollsController');
Route::resource('admin/public_polls.public_poll_options', 'App\Http\Controllers\PublicPollsOptionsController',array('except' => array('index')));
/** Define filter to all admin actions **/
Route::when('admin/*', 'isAdmin');
/** Login/Register Routes **/
Route::get('/', array(
'uses' => 'App\Http\Controllers\loginController#index',
'as' => 'home'
));
Route::post('/', array(
'uses' => 'App\Http\Controllers\loginController#login',
'as' => 'home'
));
Route::post('register', array(
'uses' => 'App\Http\Controllers\loginController#register',
'as' => 'register'
));
Route::get('register', array(
'uses' => 'App\Http\Controllers\loginController#index',
'as' => 'register'
));
/*Route::get('logout', array(
'uses' => 'loginController#logout',
'as' => 'logout'
))->before('auth');
*/
Route::get('welcome', function() {
if ( User::isAdmin(Auth::user()->id) ) {
return Redirect::to('admin/dashboard');
}
return View::make('welcome');
});
/*
Route::get('teste', function() {
return 'Ecrã de teste';
dd(User::isAdmin(Auth::user()->id));
});*/
/** Email Routes **/
Route::get('email', function() {
$data['name'] = 'Random_Name';
// Mail::pretend();
Mail::send('emails.auth.accountActivation', $data, function($message){
$message->to('random_email#email.com')->subject('Welcome');
});
return 'Email sent!';
});
/*
Event::Listen('laravel.query', function(){
var_dump($sql);
});*/
Nevermind fellows, found the solution, it was as easy as doing a Route::group() and moving the resources with /admin inside the group.
Route::group([
'prefix' => '/admin',
'as' => 'admin.',
], function () {
Route::resource('/dashboard', 'App\Http\Controllers\DashboardController', array('only' => array('index')));
Route::resource('/companies', 'App\Http\Controllers\CompaniesController');
Route::resource('/users', 'App\Http\Controllers\UsersController');
Route::resource('/public_polls', 'App\Http\Controllers\PublicPollsController');
Route::resource('/public_polls.public_poll_options', 'App\Http\Controllers\PublicPollsOptionsController',array('except' => array('index')));
});
/** Define filter to all admin actions **/
//Route::when('admin/*', 'isAdmin');
This way it also generates the stuff like admin.companies.create and admin.users.create
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.
I have middleware that redirects the user if it it not logged in. The user is not prevented from filling in the form, only when he submits the data my middleware comes in to check if he is authenticated. It seems like it is not passing throught the middleware at all when the submit button is clicked.
My route
Route::group(['middleware' => 'allow.access'], function(){
Route::post('houses', [ //I wonder if I defined this
'as' => 'houses.store', //route correctly because
'uses' => 'HousesController#store' //it seems Laravel is ignoring it
]);
Route::get('houses/{id}/edit', [
'as' => 'houses.edit',
'uses' => 'HousesController#edit'
]);
});
My middleware works if I use this route inside the group:
Route::get('houses/create/{zip}', [
'as' => 'houses.create',
'uses' => 'HousesController#create'
]);
my middleware
public function handle($request, Closure $next)
{
if(!$request->session()->has('loginInfo'))
{
return redirect()->route('register.login');
}
return $next($request);
}
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
I want to let only authenticated users access a certain page in my application. After reading the documentation I found out this can be done using middleware. I assigned the auth middleware to the route which I want to protect, but I can still access it even if I am not authenticated.
Route::get("add","Clubs#add",['middleware' => 'auth', function () {}]);
I think you're looking for this syntax.
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'ProfileController#show'
]);
So for your case, it should look like this.
Route::get('add', [
'middleware' => 'auth',
'uses' => 'Clubs#add'
]);