Laravel ComposerServiceProvider redirect - php

On my app, I'm trying to make it so that if a user has a certain condition, he will ALWAYS be redirected to a certain page, no matter which route he tries to access. In this case, it's if he doesn't have a username (long story).
ComposerServiceProvider.php :
public function boot() {
View::composer('templates.default', function ($view) {
if(Auth::user()) {
if (Auth::user()->username == null || Auth::user()->username == "") {
return redirect()->route('auth.chooseUsername');
}
So I figured the place to do this would be
ComposerServiceProvider.php.
However, I'm noticing that my redirect don't work in ComposerServiceProvider.php. And laravel.log doesn't give me an error or reason why.
The if condition is being met. If I replace return redirect()->route('auth.chooseUsername'); with dd('test');, sure enough all my pages return 'test'.
Why is this happening?

Try this steps:
You can use middleware for this scenario like below:
Create middleware php artisan make:middleware CheckPoint
Inside App\Http\Middleware\CheckPoint.php File
use Closure;
class CheckPoint
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if($request->user()) {
if ($request->user()->username == null || $request->user()->username == "") {
return redirect()->route('auth.chooseUsername');
}
}
return $next($request);
}
}
2. Add the middleware inside the app\Http\kernel.php
protected $routeMiddleware = [
'checkPoint' => \App\Http\Middleware\CheckPoint::class,
];
Then you can use it inside your route file and controller like below
Route::get(...)->middleware('checkPoint');
Route::middleware('checkPoint')->group(function() {
//Group of routes
.....
});
More About Middleware
controller middleware

In App\Http\Middleware create a new middleware:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckYourCondition
{
public function handle($request, Closure $next)
{
if (! $request->user()->yourCondition()) {
return redirect('your_target_routre');
}
return $next($request);
}
}
Register your middleware by adding it to protected $routeMiddleware in App\Http\Kernel.
and assing it to the 'web' middleware group in protected $middlewareGroups.
For details see
The ComposerServiceProvider has a different purpose. It is used to register View Composers.
View composers are callbacks or class methods that are called when a
view is rendered. If you have data that you want to be bound to a view
each time that view is rendered, a view composer can help you organize
that logic into a single location.
See View Composers.

Related

Laravel, first user is only user

I am building a Laravel site for personal use and I would like to make the first user to register on the site be the only user. So with a fresh Laravel install with the ui installed, migration sorted and no users registered, I would like the register route to be reachable. But if there is a registered user, block the register route and only allow the login route to be reachable.
I could do something like this in the web.php
Route:get('/register', function () {...})->auth();
But I would have to do that after I first create a user. I'd rather do it in a more controllable fashion.
Edit
I don't doubt that #yves-kipondo's answer is the more correct option if I were to create this for someone else.
The solution I went with is a simple one. In my register controller I just add a check in the constructor, if there already is a user return a 404.
public function __construct() {
if (!User::all()) {
$this->middleware('guest');
} else {
abort(404);
}
}
You can create a Middleware which will be register on the register route
<?php
namespace App\Http\Middleware;
use Closure;
class RegisterOnce
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (User::count() !== 0) {
// you can redirect wherever you want
return redirect('home');
}
return $next($request);
}
}
After that you can register the middleware in the app/Http/Kernel.php by adding this line after all registered routes middleware like this
protected $routeMiddleware = [
\\ ... previous registered middleware
'once' => App\Http\Middleware\RegisterOnce::class,
];
and you can customize the register route like this in the routes/web.php file
which wille replace the default set by Auth::routes();
Route::get('register', [App\Controllers\Auth\RegisterController::class, 'showRegistrationForm'])
->name('register')
->middleware('once');

Restricting Pages to Admins - Laravel

I am having a tutorial on how to restrict pages to admins. In my RedirectIfAuthenticated.php, this is how my code looks like
public function handle($request, Closure $next, $guard = null)
{
if (!Auth::guard($guard)->check()) {
// return redirect('/login');
} else {
$user = Auth::user();
if($user->hasRole('manager')) {
return redirect('admin/home');
} else {
return redirect('/home');
}
}
return $next($request);
}
After i login, i am routed to the respective pages but the issue is, i can still route to the admin page even tho i login as a member and not manager. When i place localhost/admin/home, i am still routed to that page although i am not a manager. What am i missing out?
You are able to access the manager url after login because your code only redirects each user to their appropriate url's but does'nt do any other check after the users are logged in. You can accomplish this by creating a middleware to check for each user type and redirect them to their appropriate pages and attach this middleware to your desired routes.
In your terminal, run php artisan make:middleware AdminMiddleware to create a middleware Note: the AdminMiddleware is a name of my choosing and can be changed.
This creates a middleware in the app\Middlewares directory. edit the contents to look like this..
<?php
namespace App\Http\Middleware;
use Closure;
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Auth::user();
if(!$user->hasRole('manager'))
{
//you can throw a 401 unauthorized error here instead of redirecting back
return redirect()->back(); //this redirects all non-admins back to their previous url's
}
return $next($request);
}
}
Then go to the app/Http/Kernel.php file and add the following to the $routeMiddleware array.
'admin' => \App\Http\Middleware\AdminMiddleware::class,
Now you can attach the admin middleware to any route which you would like only managers to access.

How to add custom middleware inside a Route group in laravel

I have a Route group in laravel which has middleware of auth
Route::group(['middleware'=>'auth', function()
{
//Routes
});
Now these routes are only available to logged in users. I have a situation that logged in users have privileges. I have some routes that are only to be visited by logged in users AND if they have privilege of OWNER
In function I have started a session and stored privilege value.
I did something like this
Route::group(['middleware'=>'auth', function()
{
//Routes
if(session::get('privilege')
{
//Routes
}
});
This isn't working neither it's appropriate method. Can anyone tell me how add middleware inside a middleware?
There should be no logic inside your routes file(s) - these should simply define routes and nothing else. What you should do is define middleware which verifies privileges/roles your user has, you can specify parameters which are passed to the middleware like this:
Route::group(['middleware' => 'auth', function() {
Route::get('/my-route', 'Controller#method')->middleware('role:some_role');
Route::get('/my-other-route', 'Controller#otherMethod')->middleware('role:some_other_role');
});
Then in your middleware, you can access that parameter via a third argument in the handle method. With that value, you could verify the privileged/role the user has and then decide if the user should access that route:
public function handle($request, Closure $next, $role)
{
// Do something with $role
return $next($request);
}
If you're unsure about defining your own custom middleware, check out the docs here: https://laravel.com/docs/middleware
You will need to create a custom middleware called OWNER
php artisan make:middleware Owner
Will create a middleware file for you.
Then in the public function called handle u can do something like
if (Auth::user()->privilege == "OWNER") {
return $next($request);
}
return redirect('home');
So at the end your custom middleware will look something like this:
<?php
namespace App\Http\Middleware;
use Closure;
class Owner
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::user()->privilege == "OWNER") {
return $next($request);
}
return redirect('home');
}
}
More about Laravel Middelware here

Maintenance mode in public page not in admin page [Laravel]

Now i'm working on laravel web project, there is the feature on admin page to set web as maintenance mode, but this maintenance just stop proceed the request which come in public page, I tried to make middleware so all route or controller which handle public page will stop if setting is set on maintenance mode. (settings are saved in database that has value 'online' or 'maintenance')
public function handle($request, Closure $next, $guard = null){
// retrieve setting from database and turn into key value array
if($site_settings['status'] == 'maintenance'){
return response()->view('errors.500', [], 500);
}
return $next($request);
}
what my approach is incorrect?
Have you registered your middleware in Kernel.php?
You need to add it to app/Http/Kernel.php, under the Global middleware comment:
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\YourMiddlewareClass::class, // add it here
];
And create a middleware class in app/Http/Middleware with a public function handle
<?php
namespace App\Http\Middleware;
class YourMiddlewareClass
{
public function handle($request, Closure $next, $guard = null){
if ( $site_settings['status'] == 'maintenance' && !$request->is('admin/*') ){
return response()->view('errors.500', [], 500);
}
return $next($request);
}
}
This will force error 500 on anything that doesn't start with admin/ in the URL.

How to change default redirect URL of Laravel 5 Auth filter?

By default if I am not logged and I try visit this in browser:
http://localhost:8000/home
It redirect me to http://localhost:8000/auth/login
How can I change to redirect me to http://localhost:8000/login
I wanted to do the same thing in Laravel 5.5. Handling authentication has moved to Illuminate\Auth\Middleware\Authenticate which throws an Illuminate\Auth\AuthenticationException.
That exception is handled in Illuminate\Foundation\Exceptions\Hander.php, but you don't want to change the original vendor files, so you can overwrite it with your own project files by adding it to App\Exceptions\Handler.php.
To do this, add the following to the top of the Handler class in App\Exceptions\Handler.php:
use Illuminate\Auth\AuthenticationException;
And then add the following method, editing as necessary:
/**
* Convert an authentication exception into an unauthenticated response.
*
* #param \Illuminate\Http\Request $request
* #param \Illuminate\Auth\AuthenticationException $exception
* #return \Illuminate\Http\Response
*/
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
return redirect()->guest('login'); //<----- Change this
}
Just change return redirect()->guest('login'); to return redirect()->guest(route('auth.login')); or anything else.
I wanted to write this down because it took me more than 5 minutes to figure it out. Please drop me a line if you happened to find this in the docs because I couldn't.
Just to extend #ultimate's answer:
You need to modify App\Http\Middleware\Authenticate::handle() method and change auth/login to /login.
Than you need to add $loginPath property to your \App\Http\Controllers\Auth\AuthController class. Why? See Laravel source.
In result you'll have this in your middleware:
namespace App\Http\Middleware;
class Authenticate {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
return redirect()->guest('/login'); // <--- note this
}
}
return $next($request);
}
}
And this in your AuthController:
namespace App\Http\Controllers\Auth;
class AuthController extends Controller
{
protected $loginPath = '/login'; // <--- note this
// ... other properties, constructor, traits, etc
}
This is Laravel 5.4 Solution:
There is a new unauthenticated() method in app/Exceptions/Handler.php which handles unauthenticated users and redirects to login path.
So change
return redirect()->guest('login');
to
return redirect()->guest('auth/login');
Authentication checks are made using middleware in Laravel 5.
And the middleware for auth is App\Http\Middleware\Authenticate.
So, you can change it in handle method of the middleware.
In Laravel 5.6, go to app/Exceptions folder and open the Handler.php, add a new method that overrides the unauthenticated method like so:
protected function unauthenticated($request, AuthenticationException $exception)
{
if($request->ajax())
{
return response([
"message" => "Unauthenticated.",
"data" => [],
],401);
}
return redirect()->to('/');
}
This method is triggered when you access a protected route using the built-in "auth" middleware. Now you will have full control where to redirect or the response sent.
EDIT: On Laravel 5.1, simply add protected $redirectPath = '/url/you/want'; to AuthController would do the trick.
REFER : http://laravel.com/docs/5.1/authentication#included-authenticating
On Laravel 5.1, it is completely moved to another middleware named RedirectIfAuthenticated.php under App\Http\Middleware
public function handle($request, Closure $next)
{
if ($this->auth->check()) {
return redirect('/'); //change this part to anywhere you wish to be redirected to
}
return $next($request);
}
Hope it helps.
could you please outputs php artisan route:list please
You are right you can set the following attributes:
protected $loginPath = 'xxx';
protected $redirectPath = 'xxx';
protected $redirectAfterLogout = 'xxx';
Set this attribute to you AuthController.php
Since your other question was marked as duplicate..I will try to answer it here..
First you need to change your route like
<?php
Route::get(config('constants.cms_path') . '/login', [
'as' => 'login',
'uses' => 'Auth\AuthController#getLogin'
]);
In your blade..make sure you use named route in the Login url link like
{{ route('login') }}
In Middleware/Authenticate.php change the redirect guest to
return redirect()->guest(config('constants.cms_path') . '/login');
To change the redirection after the login, you only have to go to app/Http/Controllers/Auth/LoginController.php and add that inside the class LoginController:
protected $redirectTo = '/redirect-url-here';
Same for redirection after a new users register, but in that case, on AuthController.php
For Laravel 5.4 You can set protected $redirectTo = '/'; in LoginController.php FILE.
Or in RegistersUsers.php file you can
protected function registered(Request $request, $user)
{
return redirect('tosomeRoute');
//Note: This code will run when
//The user has been registered
}

Categories