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

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.

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');

Laravel 7 : Redirect to different logins on different guards

i'm using the auth middleware and creating and admin guard for controlling the admin access. Im having some problems when im trying to access to the admin routes, i would like to redirect the unathenticated trafict associated to the admins routes to an /admin/login page, but instead of that, it redirect me to the /login page.
I don't know how to get the guards associated to a route in the class Authenticate.
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}
that's the code, i would like to be something like :
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
if(Auth::guard('admin'))
return route('admin.login);
else
return route(login);
}
}
}
but it doesn't work, 'cos the only parameter that i have is the $request.
Those are my routes...
//Admin Routes
Route::middleware(['auth:admin'])->group(function () {
Route::get('/admin', 'AdminController#index')->name('admin');
Route::get('/newDoncente', 'AdminController#addDocenteView')->name('newDocente');
//Docentes Routes
Route::get('/docentes', 'Docente\DocenteController#getDocentesView')->name('getDocentesView');
Route::get('/editDocente/{id}', 'Docente\DocenteController#editDocenteView')->name('editDocentesView');
Route::get('/docentesTables', 'Docente\DocenteController#getDocentesDatatables')->name('getDocentesTables');
Route::get('/docente/{id}', 'Docente\DocenteController#getDocenteView')->name('getDocenteView');
Thanks.
go to the app/Exception/Handler.php
use this class
use Illuminate\Auth\AuthenticationException;
and add this function in the class
protected function unauthenticated($request, AuthenticationException $exception)
{
if (request()->expectsJson()) {
return Response()->json(['error' => 'UnAuthorized'], 401); //exeption for api
}
$guard = data_get($exception->guards(), 0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}
I've been looking for a guard based answer, where I was looking to check the guard than redirects based on the guard type. However I couldn't find a solution.
However, I found another solution that gets the job done but it isn't as dynamic as the answer I'm looking for. However, it's working fine for me
in
App\Http\Middleware\Authinticate.php
class, add the following code:
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
if($request->is('admin') || $request->is('admin/*'))
return route('admin.login');
return route('login');
}
}
Also, don't forget to prefix all admin routes with admin/ .
Hope this answer helps you.
I'm not sure if this is the right way , I overrode the handle method so I can get the guards from it as follows:
protected $guards = [];
public function handle($request, Closure $next, ...$guards)
{
$this->guards = $guards;
return parent::handle($request, $next, ...$guards);
}
protected function redirectTo($request)
{
if (in_array("admin", $this->guards)) {
return "admin/login";
}
}
Ok, i've resolve it, i guess that's quite a good approach. I create a middleware and i asked for the auth guard on the middleware.
First I create the middleware
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::guard('admin')->check())
return $next($request);
else
return redirect('/admin/login');
}
}
Then I put the middleware in the Kernel file
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'isAdmin' => \App\Http\Middleware\IsAdmin::class,
Last, i change the middleware for the routes
Route::get('/admin', 'AdminController#index')->name('admin');
Now it's working fine, but if you have a better solution, i really wanted to know it.

Laravel ComposerServiceProvider redirect

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.

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 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