I'm configuring maintenance mode in Laravel. I'm trying to add in an IP whitelist.
When I run this code:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckForMaintenanceMode
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance() &&
!in_array($request->getClientIP(), ['127.0.0.1']))
{
return response('Be right back!', 503);
}
return $next($request);
}
}
I get this error:
Undefined property: App\Http\Middleware\CheckForMaintenanceMode::$app
Can someone tell me what's the problem is?
Update
As of Laravel 5.6.21, this functionality is now built into Laravel. The php artisan down command now takes --allow parameters which lets you specify the IP addresses to allow to access the site.
So, instead of making any customizations, you'd just need to run php artisan down --allow=127.0.0.1.
Original
You're using $this->app, but your class doesn't have an $app property. You can either just use the app() helper method, you can inject the Application into your middleware, or you can extend Laravel's CheckForMaintenanceMode class, which will take care of all that for you.
Extend Laravel:
class CheckForMaintenanceMode extends \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode
Dependency Injection:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Foundation\Application;
class CheckForMaintenanceMode
{
/**
* The application implementation.
*
* #var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Foundation\Application $app
* #return void
*/
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance() &&
!in_array($request->getClientIP(), ['127.0.0.1']))
{
return response('Be right back!', 503);
}
return $next($request);
}
}
app() Helper
public function handle($request, Closure $next)
{
if (app()->isDownForMaintenance() &&
!in_array($request->getClientIP(), ['127.0.0.1']))
{
return response('Be right back!', 503);
}
return $next($request);
}
Related
I want to implement Impersonate functionality into Laravel-8 without using any package.
Only super-admin can use this functionality.
I used laravel sanctum to authenticate.
to access impersonate functionality user should be super-admin. (is_admin(boolean) flag is set into users table).
Here is my middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ImpersonateUser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
$impersonateId = $request->cookie('x-impersonate-id');
if($request->user()->is_admin && $impersonateId) {
$user = User::findOrFail($impersonateId);
if($user->is_admin) {
return response()->json(["message" => trans("You cannot impersonate an admin account.")], 400);
}
Auth::setUser($user);
}
return $next($request);
}
}
My route file:
// Impersonate routes.
Route::middleware(['auth:sanctum', 'impersonate'])->group(function () {
// checklist routes
Route::get('checklists', [ChecklistController::class, "index"]);
});
Whether use Auth::setUser($user) is safe or I have to use Auth::onceUsingId($userId); ?
Auth::onceUsingId($userId); not working with auth::sanctum middleware. So Auth::setUser($user) is safe or not?
I used laravel to develop backend API only.(SPA)
They should be the same in terms of safety. OnceUsingId() calls setUser() in the background.
From the Illuminate\Auth\SessionGuard class
/**
* Log the given user ID into the application without sessions or cookies.
*
* #param mixed $id
* #return \Illuminate\Contracts\Auth\Authenticatable|false
*/
public function onceUsingId($id)
{
if (! is_null($user = $this->provider->retrieveById($id))) {
$this->setUser($user);
return $user;
}
return false;
}
/**
* Set the current user.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #return $this
*/
public function setUser(AuthenticatableContract $user)
{
$this->user = $user;
$this->loggedOut = false;
$this->fireAuthenticatedEvent($user);
return $this;
}
Both of these methods come from the SessionGuard though. I don't know if Sanctum implements its own version.
So i've got some middleware here:
namespace App\Http\Middleware;
use Closure;
use App\ChatLog;
use App\Http\Services;
class LogChat
{
protected $chatLogService;
public function __construct(ChatLogService $chatLogService)
{
$this->chatLogService = $chatLogService;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$chatLog = new ChatLog;
$chatLog->companyid = '5';
$chatLog->type = 'REQUEST';
$chatLog->ipaddress = '1';
$chatLog->name = 'bob';
$chatLog->message = 'testmessage';
$chatLog->action = 'click';
$chatLog->timeTaken = '1';
$chatLog->fullLog = 'all the log';
$this->chatLogService->store($chatLog);
return $next($request);
}
}
which calls this service here:
namespace App\Http\Services;
use App\ChatLog;
use Illuminate\Support\Facades\DB;
class ChatLogService
{
/**
* Display a listing of the resource.
*
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \App\ChatLog $chatLog
*/
public function store(ChatLog $chatLog)
{
$chatLog->save();
}
/**
* Display the specified resource.
*
* #param \App\ChatLog $chatLog
*/
public function show(ChatLog $chatLog)
{
//
}
}
which is injected in here:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(ChatLogService::class, function ($app) {
return new ChatLogService();
});
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
But this gives me the following exception: ReflectionException
Class App\Http\Middleware\ChatLogService does not exist
What i want to do is call the "store" method in a nicely abstracted way and i feel this solution is very close - however, I can't seem to get around this error. I'm not sure if it's something simple that i'm missing, or if the approach is fundamentally wrong!
I can't see what's wrong!
Ta :)
Many of the processes inside lumen use the "closure" class. I know what a closure is, but still I'd like to know what it looks like in Lumen. Therefore, I need to find the file where the class is defined.
For example, my authenticate.php middleware uses "Closure", you can see it in the top of the code:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Factory as Auth;
class Authenticate
{
/**
* The authentication guard factory instance.
*
* #var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #return void
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if ($this->auth->guard($guard)->guest()) {
return response('Unauthorized.', 401);
}
return $next($request);
}
}
But unlike any other class in Lumen, this one doesn't provide any path to the location of the class in the source code. I've looked up the root directory, and it's not there.
So where is it?
You can scan in the documentation in PHP Closure Class. It was added in PHP 5.3 it is built in PHP not under Lumen Framework or Laravel.
I'm new to laravel and I'm trying to use laravel basic auth for android application login. I can login without any problem to my website but using the same username and password in postman basic auth , I got the message "sorry, you are not authorized". I'm completely confused, can anyone help me please?
The basic auth middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
class BasicAuth
{
protected $auth;
/**
* Create a new middleware instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #return void
*/
public function __construct(AuthFactory $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $this->auth->basic('phone') ?: $next($request);
}
}
The route that I call in postman is:
Route::middleware('basic.auth')->get('/user', function (Request $request) {
return $request->user();
});
Postman
My goal is to pass User Context like email or ID into Sentry so I can see which users broke something.
I've configured a piece of Global Middleware to add user context to my Sentry errors. Here is the class:
class AddUserToSentry
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::user())
{
//dd(Auth::user()->email);
app('sentry')->user_context(array(
'email' => Auth::user()->email
));
}
return $next($request);
}
}
In my Handler.php I have:
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* #param \Exception $e
* #return void
*/
public function report(Exception $e)
{
if ($this->shouldReport($e)) {
app('sentry')->captureException($e);
}
parent::report($e);
}
What am I missing to make this work? All I get for user context is the IP address, which is not very helpful in my case.
Thank you very much,
Josh
Here is a complete example, the source is from the official Sentry documentation. To avoid having to add use Auth; you can simply use the auth() helper function.
namespace App\Http\Middleware;
use Closure;
class SentryContext
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
*
* #return mixed
*/
public function handle($request, Closure $next)
{
if (app()->bound('sentry')) {
/** #var \Raven_Client $sentry */
$sentry = app('sentry');
// Add user context
if (auth()->check()) {
$sentry->user_context(['id' => auth()->user()->id, 'email' => auth()->user()->email]);
}
// Add tags context
// $sentry->tags_context(['foo' => 'bar']);
}
return $next($request);
}
}
You need to provide access to Laravel's Auth Facade in your controller like so:
Use Auth;