Laravel nested route group inverse middleware - php

I have a fairly complex application which makes use of custom authentication middleware. I have a route group like this:
Route::group(['prefix' => 'auth', 'middleware' => 'auth'], function() {
Route::get('/', function() {
echo 'private';
});
Route::group(['prefix' => 'public'], function() {
Route::get('/', function() {
echo 'public';
});
})
});
Now the auth middleware will redirect all requests which are not authenticated. The main group with the auth prefix is authenticated. However, I want the group public to be accessible even if the user is not authenticated.
So:
http://example.com/auth < must be authenticated
http://example.com/auth/some-sub-page < must be authenticated
http://example.com/auth/public < no need for authentication
So is there a way to add something like 'remove-middleware' => 'auth' to the nested group with the public prefix? Or would I have to restructure my route groups?

Why not just wrap the auth middleware around the non-public routes?
Route::group(['prefix' => 'auth'], function() {
// routes requiring auth
Route::group(['middleware' => 'auth']) {
Route::get('/', function() {
echo 'private';
});
}
// other routes
Route::group(['prefix' => 'public'], function() {
Route::get('/', function() {
echo 'public';
});
});
});
There may be a way to do a 'remove-middleware' type middleware, but that could get messy. This seems like the cleanest solution.

you can use withoutMiddleware method on your route.
Route::get('/example')->withoutMiddleware('auth')
You can also use withoutMiddleware on Route::group

Related

Laravel 5.6 get user in Routes issue

How to get an id of the user?
app/routes/web.php
Route::group(['middleware' => 'auth'], function()
{
var_dump(Auth::user());
}
It returns null.
Simple things made difficult.. Also there is no reliable explanation
How to handle this?
You have not defined any route, try this instead:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
dd(Auth::user());
});
});
Change the '/' to what ever you like, does that work for you?

Laravel 5.3 - set clear cache on middle not working

I want to prevent the user from clicking back the browsers button. Whenever user logged in and click browser's back button the page redirect back to login which is wrong. I create middleware and register it to the kernel and use it in my route as group but its not working. Here's the code
MIDDLEWARE
<?php
namespace App\Http\Middleware;
use Closure;
class ClearCache
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set("Cache-Control", "no-cache,no-store, must-revalidate");
return $response;
}
}
KERNEL
protected $routeMiddleware = [
....
// CUSTOM MIDDLEWARE GOES HERE
'clear.cache' => \App\Http\Middleware\ClearCache::class,
];
ROUTES
<?php
Route::group(['middleware' => 'guest'], function() {
Route::get('/', function () {
return view('welcome');
});
});
Auth::routes();
Route::group(['middleware' => 'auth'], function() {
Route::group(['middleware' => 'clear.cache'], function() {
Route::get('/home', 'HomeController#index');
});
});
After logging in when user clicks back button it redirects back on login page. Logged out is fine. Any help? :(
You can define multiple middleware for one group :
Route::group(['middleware' => ['auth', 'cache.clear']], function() {
But by default Laravel redirects users to $redirectTo defined in your Auth controllers. I don't understand why you are trying to avoid back click.

Laravel multiple midleware for some route

I am developing web application with laravel 5.2.
What i need is i have some off account that distinguished by role. and i have to role that can access 1 route but other role cannot access. i have browsing and i have done everything that i found like
Route::group(['prefix' => '/', 'middleware' => ['role:user_a','role:user_b']], function(){someroute}
Route::group(['prefix' => '/', 'middleware' => ['role:user_a|role:user_b']], function(){someroute}
Route::group(['prefix' => '/', 'middleware' => ['role:user_a,role:user_b']], function(){someroute}
no one work. i dont know how to make my single route can be accessed by 2 role but disable for other role
You can create a middleware named role, read more about middleware in docs here
The handle method of middleware will be as:
public function handle($request, Closure $next)
{
if (auth()->user()->role('b')) {
return redirect('home');
}
// else users of other roles can visit the page
return $next($request);
}
Then you can use it in your route file as:
Route::group(['middleware' => 'role'], function () {
// someroute
});
i think you cant do this, but you can use this way.
Route::group(['prefix'=>'/', 'middleware' =>['role:user_a','role:user_b']],function(){
Route::group(['prefix'=>'userAorB', 'middleware' =>['role:user_a|role:user_b']],function(){ Routes });
Route::group(['prefix'=>'userAANDB', 'middleware' =>['role:user_a,role:user_b']],function(){ Routes });
})

Laravel 5.3: localhost redirected you too many times

I have 2 user roles which is superadmin and admin
I don't want admin to access of Settings Page.
I am not sure if this is the proper way.
So, here's my SettingsController.php
class SettingsController extends Controller {
public function index() {
if(Auth::user()->roles == 0) {
return redirect(url()->previous());
} else {
return view('settings.index');
}
}
}
As you can see if the roles is 0. I redirect the user to the last page they're in. I also tried to use return back();
web.php (routes)
<?php
Route::get('/', ['uses' => 'UsersController#index']);
Route::post('login', ['uses' => 'UsersController#login']);
Route::group(['middleware' => ['auth']], function() {
Route::get('logout', ['uses' => 'UsersController#destroy']);
Route::get('upline', ['uses' => 'UplinesController#index']);
Route::get('upline/create', ['uses' => 'UplinesController#create']);
Route::post('upline', ['uses' => 'UplinesController#store']);
Route::delete('upline/destroy/{id}', ['uses' => 'UplinesController#destroy']);
Route::put('upline/update/{id}', ['uses' => 'UplinesController#update']);
Route::get('upline/getdownlines/{id}', ['uses' => 'UplinesController#getDownlines']);
Route::get('downline', ['uses' => 'DownlinesController#index']);
Route::post('downline', ['uses' => 'DownlinesController#store']);
Route::delete('upline/destroy/{id}', ['uses' => 'DownlinesController#destroy']);
Route::put('downline/update/{id}', ['uses' => 'DownlinesController#update']);
Route::get('bonus', ['uses' => 'BonusController#index']);
Route::post('bonus/csv', ['uses' => 'BonusController#fileUpload']);
Route::get('settings', ['uses' => 'SettingsController#index']);
});
I have a 2nd question. Can I limit admin using middleware? If yes, how?
Any help would be appreciated.
Maybe the second option, "Limiting admin with middleware".
So you can try something like;
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function () {
Route::get('/', 'DownlinesController#update');
});
Then
Route::group(['prefix' => 'super', 'middleware' => 'auth'], function () {
Route::get('/', 'UplinesController#index');
});
As #michael s answer suggests use middleware, his answer fails to demonstrate on how to do it (mine too, I just added more text).
Note: Laravel is big because of its documentation, USE IT!
You have 2 (or more options):
parameterized middleware
2 distinctive middlewares (one for admin, another for superadmin)
Note: use artisan to generate middleware from stubs, $ php artisan make:middleware MyNewShinyMiddleware
parametrized middleware (my pick)
Head to documentation and check out this.
Example shows exactly your problem.
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) { //implement hasRole in User Model
// Redirect...
// (use named routes to redirect or do 401 (unauthorized) because thats what is going on!
// abort(401) // create view in /views/errors/401.blade.php
// return redirect()->route('home');
}
//success user has role $role, do nothing here just go to another "onion" layer
return $next($request);
}
2 distinctive middlewares
simply create two middlewares and hardcode your checking routine of roles
(same as you do in your controller sample) except use $request->user()...
(routes) web.php
Route::group(['middleware' => 'role:admin'], function () {...} //parametrized
Route::group(['middleware' => 'checkRoleAdmin'], function () {...}
Route::group(['middleware' => 'checkRoleSuper'], function () {...}
Note: role, checkRoleAdmin and checkRoleSuper are "named" middlewares and you need to register them in kernel.php
Another way is yo use gates or policies which make the best sense, since you are trying to limit user. Read more here.
I use middleware based ACL for really simple projects (like one admin and no real users).
I use gates based ACL for medium projects (1-2 roles).
I use policies based ACL for "huge" projects (many roles, many users).
Also consider looking at https://github.com/Zizaco/entrust

Laravel redirect to route

I'm using Laravel 5.1 and wanted to know if there is a better way to do routing redirection.
Route::get('user/login', 'UserController#login');
Route::get('login', function() {
return redirect()->to('user/login');
});
So basically, whenever a user goes to http://example.com/login, they will be redirect to http://example.com/user/login.
Is there a better way or other ways to do this or am I doing it correctly already? Thanks!
That's about as simple as it gets
You could also do redirect('user/login') to save a few characters
If you had multiple redirects like this you could handle them all at once
Route::pattern('user_path', '(login|logout)');
Route::get('{user_path}', function($user_path) {
return redirect('user/' . $user_path);
});
Route::get('new/create_view','CreateController#create_view');
Route::post('new/create_view','CreateController#insert_view');
Route::get('new/create_table','CreateController#create_table');
Route::post('new/create_table','CreateController#insert_table');
Route::get('new/create_package','CreateController#create_package');
Route::post('new/create_package','CreateController#insert_package');
This is the way i am using the route. Simple method. when the time of GET, am calling a controller function and inside that particular controller function, i have written the logical codes. In the POST also, doing the same thing.
Another way is there,GROUP Routing
Route::group(['namespace' => 'Admin'], function()
{
// Controllers Within The "App\Http\Controllers\Admin" Namespace
Route::group(['namespace' => 'User'], function()
{
// Controllers Within The "App\Http\Controllers\Admin\User" Namespace
});
});
eg:
Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function()
{
Route::resource('pages', 'PagesController', array('only' => array('index', 'store', 'show', 'update', 'destroy')));
Route::resource('users', 'UsersController');
});

Categories