How to use middleware on routes in laravel? - laravel

I need to implement a little functionality for my application.
I have a form for editing and only admin must have access to it.
I can't figure out how to arrange the routes correctly, because I get
"The site has redirected too many times."
middleware:
class AdminMiddleware
{
public function handle($request, Closure $next)
{
$user = new User();
if ($user->role_id !==1) {
return redirect('/');
}
return $next($request);
}
}
route:
Route::post('/product', 'IndexController#store');
Route::get('/product', 'IndexController#index');
Route::get('/product/create', 'IndexController#create');
Route::put('/product/{product}', 'IndexController#update');
Route::get('/product/{product}/edit', 'IndexController#edit')->middleware('admin');
This route should be available only for admin
'/product/{product}/edit'
What am I doing wrong?

Related

Custom Auth Middleware not redirecting properly for unauthorized user

I have created a custom auth controller for recognising unauthorized user and redirect them to login path. If logged in the middlewre is working absolutely fine, but showing error if not logged in. Here is my code
Middleware:
class CheckUserAuthenticated
{
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user_id = auth()->user()->id;
define('authenticated_user_id' ,$user_id);
return $next($request);
}
return redirect('login'); // this code is not working
}
}
Error:
try this hope it help
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user_id = auth()->user()->id;
define('authenticated_user_id' ,$user_id);
return $next($request);
}
return redirect('/login'); OR return redirect(route('login'));
}
class CheckUserAuthenticated
{
public function handle($request, Closure $next)
{
if(auth()->check()) {
$user_id = auth()->user()->id;
define('authenticated_user_id' ,$user_id);
return $next($request);
}
// return redirect('login'); // this code is not working
return redirect()->guest('/login');
}
}
redirect()->guest() will redirect if there is no authenticated user.
Example: If an authenticated user is logged in, it won't redirect them as they aren't a guest. If a user isn't logged in, the redirect will happen.
The issue is in circular routing, you are calling from one route, and then return to the same route from the middleware, so your request never reaches the endpoint.
if you call middleware on the...
Route::get('login')->middleware('auth);
...then middleware can not route to 'login' on the fail...
return redirect('login');
... because it will create the loop that never ends. The middleware should reroute to something else, or be placed on other route like 'admin'...
You probably have the middleware on the 'login', that creates the loop, just remove it.

Conditionally set a URL to redirect to after authentication

In my app, a post author can set an otherwise public post to private. If an unauthenticated user tries to visit that post, they will be prompted to login.
After they authenticate, I want to redirect them back to the original post URL, so they can read that private post.
This behavior is normally handled by Laravel's default auth middleware. However, because the posts are often public, I can't use that in this case.
Here's my current, non-functioning middleware:
public function handle($request, Closure $next)
{
$post = $request->route('post');
if ($post->isPrivate()) {
$request->session()->setPreviousUrl($request->url());
return redirect()->guest('login');
}
return $next($request);
}
My hope is that I can set a custom URL to redirect to (/posts/{id}). However, when I try to login, I'm redirected to my default $redirectTo property (/dashboard).
Is this something that's feasible? Am I even thinking about this in the correct way?
#adam, thanks for the assist!
For anyone else looking, here's my final code:
Middleware:
public function handle($request, Closure $next)
{
if (auth()->check()) {
return $next($request);
}
$post = $request->route('post');
if ($post->isPrivate()) {
$request->session()->setPreviousUrl($request->path());
return redirect()->guest('login');
}
return $next($request);
}
LoginController:
protected function authenticated(Request $request, $user)
{
if ($request->session()->has('url.intended')) {
return redirect($request->session()->get('url.intended'));
}
}

Role-based routing in LoginController (Auth)

In my Laravel 5.3 setup, I am using Bouncer package, and I defined two roles, admin and customer. When logged in, customers are redirected to /home, as specified in protected $redirectTo = '/home'; under App\Http\Controllers\Auth\LoginController.php. Now, if a user with the role of an admin logs in, he is also redirected to /home because $redirectTo does not make any distinction between user roles. My goal here is to redirect admin users to /admin/home instead.
What is the best solution to handle this? Here is my attempt.
In web.php routes, outside of any middleware groups:
Route::get('/home', function(Illuminate\Http\Request $request) { // http://myapp.dev/home
if (Auth::user()->isA('customer')) // -> goto HomeController#index
return app()->make('\App\Http\Controllers\HomeController')->index($request);
else if (Auth::user()->isAn('admin')) // -> redirect
return redirect('/admin/home');
else
abort(403);
})->middleware('auth');
Route::group(['prefix' => 'admin','middleware' => 'auth'], function () {
Route::get('/home', 'Admin\HomeController#index');
});
Alternatively, this can can be done in a middleware, as well:
Route::get('/home', 'HomeController#index')->middleware('auth', 'role');
// in VerifyRole.php middleware...
public function handle($request, Closure $next, $guard = null)
{
if (Auth::user()->isAn('admin')) {
return redirect('/admin/home');
}
return $next($request);
}
This would work, but it's not scalable if more roles are added. I am sure there must be an elegant built-in way to accomplish this. So the question is, how do I route users to their proper dashboard (i.e. home) based on their role?
You can override the authenticated() method in your class App\Http\Controllers\Auth\LoginController as:
protected function authenticated(Request $request, $user)
{
if ($user->isA('customer'))
return redirect('/home');
else if ($user->isAn('admin'))
return redirect('/admin/home');
}
Or
You can override the redirectPath() method as:
public function redirectPath()
{
if (auth()->user()->isA('customer'))
return '/home';
else if (auth()->user()->isAn('admin'))
return '/admin/home';
}
In Laravel 5.3, you can override sendLoginResponse() method in AuthController.php to be able to redirect users to a different routes after login.

Laravel 5 restrict access to pages using middleware

I am working on a laravel project and i need to restrict access to some pages such that only authenticated users can view that page.
To do this, created a middleware: php artisan make:middleware OnlyRegisteredUser
and registered it in the $routemiddleware inside App\Http\kernel.php as
'onlyregistereduser' => \App\Http\Middleware\OnlyRegisteredUser::class,
and this is the class. it redirects user to auth/login if not logged in
public function handle($request, Closure $next, $right=null)
{
$user = $request->user();
if ($user && $user->onlyregistereduser()) {
return $next($request);
}
return redirect('auth/login');
}
Here is my route:
Route::get('admin/poem', ['middleware' => 'onlyregistereduser:admin', 'uses'=>'PoemsController#poem']);
admin is a parameter passed to my middleware. It is taken from my user model which has an `enum' column as follows:
public function up()
{
Schema::create('users', function (Blueprint $table) {
//...
$table->enum('rights', ['admin', 'guest'])->nullable();
// ...
});
}
Now to restrict access to some of my controller methods, e.g create, i added a constructor to my PoemsController as shown:
public function __construct()
{
$this->middleware('onlyregistereduser');
}
My problem now is that this caused every single route to the PoemsController to redirect me to the login page. And again after login in, it doesn't take me to the page i intended to visit. it takes me instead to the home page. What i want is to restrict access to only some of the controller methods and not all of them and to be able to redirect to the intended page after user login.
I hope you understand my problem.
Any help will be greatly appreciated.
Remove the middleware from constructor, you don't have to add middleware to both route and costructor. That should solve your ". What i want is to restrict access to only some of the controller methods and not all of them" issue.
For othe issue modify your middleware like this
public function handle($request, Closure $next, $right=null)
{
$user = $request->user();
if ($user && $user->onlyregistereduser()) {
return $next($request);
}
$request_url = $request->path();
session()->put('login_refferrer', $request_url);
return redirect('auth/login');
}
and before redirect user after login
if(session()->has('login_refferrer')){
$url = session()->pull('login_refferrer');
return redirect($url);
}

Laravel 5.2 Redirect admin page after login as admin

Laravel 5.2 has been out for some time now. Yes, it has new auth function which is very good. Specially for beginners.
My question,
How to check if user is admin and then redirect safely to admin/dashboard properly? I know one way is to use admin flag in database but can any of you show some example?
go to AuthController.php and add this method
where role is the user role as defined in the database.
protected function authenticated($request,$user){
if($user->role === 'admin'){
return redirect()->intended('admin'); //redirect to admin panel
}
return redirect()->intended('/'); //redirect to standard user homepage
}
As in Laravel 5.3 / 5.4
Add following line to create_users_table migration.
$table->boolean('is_admin');
Add following method to LoginController.
protected function authenticated(Request $request, $user)
{
if ( $user->is_admin ) {
return redirect('/admin/home');
}
return redirect('/home');
}
Additional note don't forget to add the following lines to RedirectIfAuthenticated middleware:
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
// the following 3 lines
if (Auth::user()->is_admin) {
return redirect('/admin/home');
}
return redirect('/home');
}
return $next($request);
}
Otherwise if you e.g. type yourdomain/login and your logged in as admin it would be redirected to home instead of admin/home.
AuthController extends the AuthenticatesAndRegistersUsers trait, which has a public method named redirectPath. In my case I would extend that method on the AuthController and I'd put my logic there:
public function redirectPath()
{
if (Auth::user->myMethodToCheckIfUserHasAnAdminRoleLikeAnEmailOrSomethingLikeThat()) {
redirect('admin/dashboard');
}
redirect('home');
}
in Auth/LoginController there is protected $redirectTo = '/home';
change '/home' to '/loginin' for example, and create a new controller and in the controller get the information of the user and check if he is a admin or not and then redirect him to the proper page

Resources