In laravel I've simply done this:
Route::group(["middleware" => "admin"], function() {
Route::get("/", "UserController#index")->name("user_index");
});
Route::group(["middleware" => "user", "as" => "User::"], function() {
Route::get("/", "DocumentController#index")->name("user_index");
});
The problem is when I am logged in as my Admin auth middleware, when going to "/" my browser returns too many redirects and stops. I'm guessing because the second route is removing this as when I print out php artisan route:list there is only one result for "/" and that's with the user middle's parameters so it's defo overriding the previous route.
What I don't understand is why would it do this is both have a separate middleware?
Both middlewares are extremely simple. Below is my admin
public function handle($request, Closure $next)
{
if ( Auth::check() && Auth::user()->hasRole("customer_service") )
{
return $next($request);
}
return redirect("/");
}
And my user's middleware is exactly alike except the role is different
This is probably wrong but this is what I did to fix this particular issue with the above.
public function index() {
return \Auth::user()->hasRole("trainer") ? \App::call("App\Http\Controllers\Trainer\UserController#index")
: \App::call("App\Http\Controllers\User\UserController#index");
}
Related
I´m trying to return another route because in my case login it´s a modal page, and when the session has expired, return to this route but it does not exist. I don´t know how I would do this.
I can see this in web: if(Auth::check()){ return route('/')} but i don´t know where i´m putting this code.
Also i can see this: in 'App\Exception\Handler' put this:
if ($exception instanceof AuthenticationException) {
return redirect('/');
}
How I would can to do this?
Thanks for helping me
You can create a route to check sessions, every minute it will check session exists or not.
You can use like this:
Blade part:
#if (Auth::user())
<script>
$(function() {
setInterval(function checkSession() {
$.get('/is-logged-in', function(data) {
// if session was expired
if (!data.isLoggedIn) {
// redirect to login page
// or, may be better, just reload page
location.reload();
}
});
}, 60000); // You can change it
});
</script>
#endif
Route:
Route::get('is-logged-in', 'Auth\AuthController#checkSession');
Controller:
public function checkSession()
{
return Response::json(['isLoggedIn' => Auth::check()]);
}
Laravel probably already has what you need. Take a look at the App\Http\Middleware\Authenticate class. This is a middleware that will redirect user to 'login' named route (by default), if the session has expired.
By default none of the routes you put in routes/web.php are protected by this middleware, but you can change this.
Method 1: Add a auth middleware in your controller's constructor:
public function __construct()
{
$this->middleware('auth');
}
Method 2: Add a auth middleware for one of your routes:
Route::get('profile', function () {
// Only authenticated users may enter...
})->middleware('auth');
Method 3: Adding all protected routes into group:
Route::group(['middleware' => ['auth']], function () {
// All your protected routes go here
});
Then you can easily change the URL which will be used for redirecting users with expired session (not authenticated). Just edit the App\Http\Middleware\Authenticate::redirectTo() method and return your URL, for example:
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('yourLoginRouteName');
}
}
I have a post route inside a middleware that checks whether a user performing a request belongs to a specific role. I have 4 roles in total. And I have found it silly to write tests like :
testRole2CanNotDoAction
testRole3CanNotDoAction
testRole4CanNotDoAction
every time I want to test some action. So it would be really nice if I can just write 1 test
testMiddlewareWasCalled
to assure that route is placed in right place. How can I do it? To give you the context lets assume I have the following middleware:
class MustBeRole1
{
public function handle($request, Closure $next)
{
$user = $request->user();
if ($user && $user->isRole1()) {
return $next($request);
}
abort(403, 'You are not an role1!');
}
}
and following routes:
Route::group(['middleware' => ['isRole1']], function () {
Route::post('/testAction', ['as' => 'testAction', 'uses' => 'testActionController#test']);
}
How should my test look like?
I’m currently building my first larval app.
I’ve got two user types: buyers and sellers. However, they both have access to the same routes, but they need to be served up different templates and data. For example, both would have access to /home, but see something completely different.
I know I can use an if statement within the route, but that’s getting messy. To try and fix this, I’ve made two separate middlewares using two different route groups. Each middleware checks the user for permission, and logs them out if they don't have it, like so:
if ( Auth::user()->role !== 'buyer' ) {
return redirect( 'login' );
}
My goal:
If the user 'isBuyer', it only reads that middleware route group.
If the user 'isSeller', it only reads that middleware group.
I was hoping to use both in tandem:
// this will be triggered if they have the role 'buyer'
Route::group(['middleware' => 'isBuyer'], function () {
Route::get( '/', function ( ) {
return view( '/home-seller' );
});
});
//this will be triggered if they have the role 'seller'
Route::group(['middleware' => 'isSeller'], function () {
Route::get( '/', function ( ) {
return view( '/home-buyer' );
});
});
But it never reads the second group. It logs me out as a result of failing the auth test on the first group.
I assume this is because it's applying the middleware filter before it finishes reading the routes.php file. What's the best to deal with using the same routes for different user types?
You can use something like this:-
$middleware = '';
if ( Auth::user()->role == 'buyer' ) {
$middleware = 'isBuyer';
}
elseif(Auth::user()->role == 'seller') {
$middleware = 'isSeller';
}
else{
return redirect( 'login' );
}
Route::group(['middleware' => $middleware], function () {
Route::get( '/', function ( ) {
return view( '/home-seller' );
});
});
How about use a single route and render from the controller (returning a view) depending the role using "if blocks" for each role. Can you try that.
For this requirement, I think you should check the user role in your app controller/parent controller and depending on that role, redirect the user to their respective actions.
I've started learning Laravel 5.1 and so far I'm liking it! But there is one thing I don't get yet..
In my previous project I had 2 specific controllers (eg: "normal", "extended") which , after a successfull login, were called based on the Users user_group from the database.
If "Foo.Bar" enters his valid credentials and has the group normal he is redirected to NormalControler. Since I wasn't using any framework I restricted access to the other group by setting a $_SESSION with the group and checking it. So if another group tried to access that controller he got redirected.
How would this be achievable in Laravel 5? So far I have a controller which is callable without an Authentication and one restricted by this code in routes.php :
// All routes in the group are protected, only authed user are allowed to access them
Route::group(array('before' => 'auth'), function() {
// TO-DO : Seperate Controller access
});
And the login looks like this :
public function performLogin()
{
$logindata = array(
'username' => Input::get('user_name'),
'password' => Input::get('user_pass')
);
if( Auth::attempt( $logindata ) ){
// return \Redirect::to( check group and access this controller based on it);
}
else {
// TO-DO : Redirect back and show error message
dd('Login failed!');
}
}
----- EDIT -----
I've run the artisan command and made this middleware as you suggested :
namespace App\Http\Middleware;
use Closure;
use Request;
class GroupPermissions
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $group)
{
// Check User Group Permissions
if( $request->user()->group === $group ){
// Continue the request
return $next($request);
}
// Redirect
return redirect('restricted');
}
}
and edited this line into Kernel.php into $routeMiddleware :
'group.perm' => \App\Http\Middleware\GroupPermissions::class
I think this is done right so far, correct me if I'm wrong! Could I then do something like this to restrict the controllers?
Route::group(array('before' => 'auth'), function() {
Route::group( ['middleware' => 'group.perm', 'group' => 'normal'], function(){
Route::get('/normal/index', 'DummyNormalController#index');
});
Route::group( ['middleware' => 'group.perm', 'group' => 'extended'], function(){
Route::get('/extended/index', 'DummyExtendedController#index');
});
});
Ok, here is what you might do. Once user is logged in, you would check his credentials, get his user_group and decide what controller he should be redirected to.
if( Auth::attempt( $logindata ) ){
$user = Auth::user();
if ($user->inGroup('normal')) {
return redirect()->route('normal_controllers_named_route');
}
return redirect()->route('extended_controllers_named_route');
}
return redirect()->back()->withFlashMessage('don\'t get me wrong');
This will handle right routing after logging in.
The next portion where you need to protect you routes from unwanted user groups may be achieved with middlewares.
do an artisan command php artisan make:middleware ShouldBeInGroup
go to app/http/Kernel.php and add your new middleware to the routeMiddleware array. Key of the item might be anything you like. Let's call in inGroup. So: 'inGroup' => 'App\Http\Middleware\ShouldBeInGroup'
Now, in your controller, in constructor, you are able to call this middleware
$this->middleware('inGroup:extended'); //we also passing the name of the group
at lastly, work on the our middleware. Open newly created ShouldBeInGroup class and edit the handle method.
public function handle($request, Closure $next, $groupName)
{
if (Auth::check() && Auth::user()->inGroup($groupName)) {
return $next($request);
}
return redirect('/');
}
And finally you should work on inGroup method, that should return true of false. I assume that you have user_group field your users table. Then in your User eloquent model add the method
public function inGroup($groupName) {
return $this->user_group == $groupName;
}
Edit
if you want to use this middleware in your routes, you can do the following
Route::group(array('before' => 'auth'), function() {
Route::get('/normal/index', ['middleware' => 'group.perm:normal', 'uses' =>'DummyNormalController#index']);
}
But generally it's better to put all your middlewares into your Controller's constructor
public function __construct(){
$this->middleware('group.perm:normal'); // you can also pass in second argument to limit the methods this middleware is applied to : ['only' => ['store', 'update']];
}
And also on this note, Laravel provides built in auth middleware that you can use
public function __construct(){
$this->middleware('auth');
$this->middleware('group.perm:normal');
}
so then your routes would become much cleaner, just:
Route::get('normal/index', 'DummyNormalController#index');
I think the best way to do that is using middlewares. See the doc here
You can easily create a middleware using the following artisan command:
php artisan make:middleware ExtendedMiddleware
If you can't or don't want to use artisan, you need to create a class in The App/Http/Middleware folder.
In this class you'll need the following method to handle the request. In the method you can check for the user group.
public function handle($request, Closure $next)
{
// check user group
if( user_group_ok )
return $next($request); // Continue the request
return redirect('restricted'); // Redidrect
}
You can then use this middleware in your route.php file:
Route::group(['middleware' => 'auth'], function()
{
// Logged-in user with the extended group
Route::group(['middleware' => 'extended'], function()
{
// Restricted routes here
});
// Normal routes here
});
You can create a Middleware called : PermissionFilter
In PermissionFilter, you check if requesting user is in the group or not.
I can't provide a demo for now, but if you want I can make a demo later.
L5 middleware: http://laravel.com/docs/5.1/middleware
Please tell me how to restrict the page using laravel,
i have 3 users.
1. admin, 2. client, 3. partner
i want if admin is logged in then open only- admin.index page
and if client logged in then open only- client.index page
i used in route.php following code-
Route::group(array('before' => 'role'), function(){
Route::resource('admin','AdminController#index');
Route::resource('client','clientController#index');
Route::resource('partner','partnerController#index');
});
using above code this if no any user login then it's coming properly,
and suppose if admin logged in, then page redirect to AdminController but,
if i hard coded (url) hit clientController or partnerController like http://localhost/laravel-login/public/client then client page is coming.
so please tell me how to avoid these
sorry for my english..
thanks
You may use different route filters for each route and create individual filters, for example:
Route::group(array('before' => 'auth'), function() {
Route::resource('admin','AdminController#index');
Route::resource('client','clientController#index');
Route::resource('partner','partnerController#index');
});
In each controller create a __construct method and add filter like:
public function __construct()
{
// In your AdminController
$this->beforeFilter(function() {
if(Auth::user()->role->name != 'admin') return redirect::to('/'); // home
});
}
Same way declare other filters in other controllers:
public function __construct()
{
// In your clientController
$this->beforeFilter(function() {
if(Auth::user()->role->name != 'client') return redirect::to('/'); // home
});
}
And so on. Check more on Laravel website about controller filtering.
The best way to restrict controllers to make new middleware , where you can define rules before the request. example :
I have a admin controller only register users with admin role can access it .
to do so when you define the route include the middleware .
// namespace = indicate where my controller is (sub folder )
// middleware = indicate what restriction i want for my controller you can pass one middleware or array of midlewares
Route::group([ 'namespace' => 'Admin','middleware' => ['auth' , 'IsAdmin'] ], function()
{
Route::resource('admin/posts', 'PostsController');
});
to create the middle ware and register it follow the documentation
look this is my middleware after
<?php
namespace App\Http\Middleware;
use Closure;
class IsAdmin
{
public function handle($request, Closure $next)
{
if($request->user()->is_admin == false ){
return redirect('/');
}
return $next($request);
}
}