From 0e4cec86cce83f7a450fb2dd2adaf72df33339b6 Mon Sep 17 00:00:00 2001 From: Graphictoria Date: Thu, 21 Apr 2022 22:37:18 -0400 Subject: [PATCH] Reworked maintenance system. Also had to rework a few HTTP error related things because the 404 page wasn't being run through middleware. --- web/app/Exceptions/Handler.php | 5 +- web/app/Http/Kernel.php | 15 +- .../Middleware/Exception/WebException.php | 19 +++ .../PreventRequestsDuringMaintenance.php | 148 +++--------------- .../Providers/MaintenanceServiceProvider.php | 42 +++++ web/app/Providers/RouteServiceProvider.php | 26 +-- web/config/app.php | 2 +- web/resources/views/errors/500.blade.php | 8 +- web/resources/views/layouts/footer.blade.php | 26 +-- web/resources/views/layouts/nav.blade.php | 98 +++++++----- web/routes/web.php | 5 + 11 files changed, 185 insertions(+), 209 deletions(-) create mode 100644 web/app/Http/Middleware/Exception/WebException.php create mode 100644 web/app/Providers/MaintenanceServiceProvider.php diff --git a/web/app/Exceptions/Handler.php b/web/app/Exceptions/Handler.php index 8a53c32..edc7d26 100644 --- a/web/app/Exceptions/Handler.php +++ b/web/app/Exceptions/Handler.php @@ -50,12 +50,15 @@ class Handler extends ExceptionHandler return response()->view('errors.403', [], 403); }); + /* + // Moved to route fallback $this->renderable(function (NotFoundHttpException $e, $request) { return response()->view('errors.404', [], 404); }); + // Moved to middleware $this->renderable(function (\ErrorException $e, $request) { return response()->view('errors.500', ['stack' => $e->getTraceAsString()], 500); - }); + });*/ } } diff --git a/web/app/Http/Kernel.php b/web/app/Http/Kernel.php index 3c37488..c056a06 100644 --- a/web/app/Http/Kernel.php +++ b/web/app/Http/Kernel.php @@ -20,7 +20,7 @@ class Kernel extends HttpKernel \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, - \Illuminate\Session\Middleware\StartSession::class + \Illuminate\Session\Middleware\StartSession::class, ]; /** @@ -30,6 +30,7 @@ class Kernel extends HttpKernel */ protected $middlewareGroups = [ 'web' => [ + \App\Http\Middleware\Exception\WebException::class, \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, @@ -39,22 +40,12 @@ class Kernel extends HttpKernel \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, ], - - 'admin' => [ - \App\Http\Middleware\EncryptCookies::class, - \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, - \Illuminate\Session\Middleware\StartSession::class, - // \Illuminate\Session\Middleware\AuthenticateSession::class, - \Illuminate\View\Middleware\ShareErrorsFromSession::class, - \App\Http\Middleware\VerifyCsrfToken::class, - \Illuminate\Routing\Middleware\SubstituteBindings::class, - ], 'api' => [ // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, - \App\Http\Middleware\PreventRequestsDuringMaintenance::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, ], ]; diff --git a/web/app/Http/Middleware/Exception/WebException.php b/web/app/Http/Middleware/Exception/WebException.php new file mode 100644 index 0000000..33e68d7 --- /dev/null +++ b/web/app/Http/Middleware/Exception/WebException.php @@ -0,0 +1,19 @@ +exception) { + return response()->view('errors.500', ['stack' => $response->exception->getTraceAsString()], 500); + } + + return $response; + } +} diff --git a/web/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/web/app/Http/Middleware/PreventRequestsDuringMaintenance.php index 1b7d639..cfab088 100644 --- a/web/app/Http/Middleware/PreventRequestsDuringMaintenance.php +++ b/web/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -3,139 +3,33 @@ namespace App\Http\Middleware; use Closure; +use Illuminate\Support\Facades\Route; use Illuminate\Contracts\Foundation\Application; -use Illuminate\Foundation\Http\MaintenanceModeBypassCookie; -use Symfony\Component\HttpKernel\Exception\HttpException; class PreventRequestsDuringMaintenance { - /** - * The application implementation. - * - * @var \Illuminate\Contracts\Foundation\Application - */ - protected $app; - - /** - * The URIs that should be accessible while maintenance mode is enabled. - * - * @var array - */ - protected $except = ['maintenance', 'maintenance/bypass']; - - /** - * Create a new middleware instance. - * - * @param \Illuminate\Contracts\Foundation\Application $app - * @return void - */ - public function __construct(Application $app) + protected $app; + public function __construct(Application $app) { $this->app = $app; } - - /** - * Handle an incoming request. - * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @return mixed - * - * @throws \Symfony\Component\HttpKernel\Exception\HttpException - */ - public function handle($request, Closure $next) - { - if ($this->app->isDownForMaintenance()) { - $data = json_decode(file_get_contents($this->app->storagePath().'/framework/down'), true); - - if ($this->hasValidBypassCookie($request, $data) || - $this->inExceptArray($request)) { - return $next($request); - } - return response('{"errors":[{"code":503,"message":"ServiceUnavailable"}]}', 503) - ->header('Cache-Control', 'private') - ->header('Content-Type', 'application/json; charset=utf-8'); - } - - return $next($request); - } - - /** - * Determine if the incoming request has a maintenance mode bypass cookie. - * - * @param \Illuminate\Http\Request $request - * @param array $data - * @return bool - */ - protected function hasValidBypassCookie($request, array $data) - { - return isset($data['secret']) && - $request->cookie('gt_constraint') && - MaintenanceModeBypassCookie::isValid( - $request->cookie('gt_constraint'), - $data['secret'] - ); - } - - /** - * Determine if the request has a URI that should be accessible in maintenance mode. - * - * @param \Illuminate\Http\Request $request - * @return bool - */ - protected function inExceptArray($request) - { - foreach ($this->except as $except) { - if ($except !== '/') { - $except = trim($except, '/'); - } - - if ($request->fullUrlIs($except) || $request->is($except)) { - return true; - } - } - - return false; - } - - /** - * Redirect the user back to the root of the application with a maintenance mode bypass cookie. - * - * @param string $secret - * @return \Illuminate\Http\RedirectResponse - */ - protected function bypassResponse(string $secret) - { - return redirect('/')->withCookie( - MaintenanceModeBypassCookie::create($secret) - ); - } - - /** - * Get the headers that should be sent with the response. - * - * @param array $data - * @return array - */ - protected function getHeaders($data) - { - $headers = isset($data['retry']) ? ['Retry-After' => $data['retry']] : []; - - if (isset($data['refresh'])) { - $headers['Refresh'] = $data['refresh']; - } - - return $headers; - } - - /** - * Get the URIs that should be accessible even when maintenance mode is enabled. - * - * @return array - */ - public function getExcludedPaths() - { - return $this->except; - } + public function handle($request, Closure $next) + { + if($this->app->isDownForMaintenance()) { + if(in_array('web', $request->route()->middleware())) + { + if($request->route()->uri() != 'maintenance') + return redirect('/maintenance?ReturnUrl=' . urlencode(url()->full())); + } + else + { + return response(['errors' => [['code' => 503, 'message' => 'ServiceUnavailable']]], 503) + ->header('Cache-Control', 'private') + ->header('Content-Type', 'application/json; charset=utf-8'); + } + } + + return $next($request); + } } diff --git a/web/app/Providers/MaintenanceServiceProvider.php b/web/app/Providers/MaintenanceServiceProvider.php new file mode 100644 index 0000000..d068827 --- /dev/null +++ b/web/app/Providers/MaintenanceServiceProvider.php @@ -0,0 +1,42 @@ +app = $app; + } + + /** + * Register any application services. + * + * @return void + */ + public function register() + { + // + } + + /** + * Bootstrap any application services. + * + * @return void + */ + public function boot() + { + Blade::directive('live', function() { + return 'isDownForMaintenance()): ?>'; + }); + + Blade::directive('endlive', function() { + return ''; + }); + } +} diff --git a/web/app/Providers/RouteServiceProvider.php b/web/app/Providers/RouteServiceProvider.php index 8af2212..3f1d593 100644 --- a/web/app/Providers/RouteServiceProvider.php +++ b/web/app/Providers/RouteServiceProvider.php @@ -37,7 +37,7 @@ class RouteServiceProvider extends ServiceProvider */ public function boot() { - $this->configureRateLimiting(); + //$this->configureRateLimiting(); $this->routes(function () { Route::domain('apis.' . env('APP_URL')) @@ -66,7 +66,7 @@ class RouteServiceProvider extends ServiceProvider ->group(base_path('routes/versioncompatibility.php')); Route::domain('impulse.' . env('APP_URL')) - ->middleware('admin') + ->middleware('web') ->namespace($this->namespace) ->group(base_path('routes/admin.php')); @@ -82,15 +82,15 @@ class RouteServiceProvider extends ServiceProvider }); } - /** - * Configure the rate limiters for the application. - * - * @return void - */ - protected function configureRateLimiting() - { - RateLimiter::for('api', function (Request $request) { - return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip()); - }); - } +// /** +// * Configure the rate limiters for the application. +// * +// * @return void +// */ +// protected function configureRateLimiting() +// { +// RateLimiter::for('api', function (Request $request) { +// return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip()); +// }); +// } } diff --git a/web/config/app.php b/web/config/app.php index 168b732..572228d 100644 --- a/web/config/app.php +++ b/web/config/app.php @@ -139,7 +139,7 @@ return [ /* * Laravel Framework Service Providers... */ - Illuminate\Auth\AuthServiceProvider::class, + App\Providers\MaintenanceServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, diff --git a/web/resources/views/errors/500.blade.php b/web/resources/views/errors/500.blade.php index cff76b6..f9df3f3 100644 --- a/web/resources/views/errors/500.blade.php +++ b/web/resources/views/errors/500.blade.php @@ -4,10 +4,13 @@ @section('content')
+ @env(['staging', 'local']) +
+ @endenv Oops, we ran into an issue while trying to process your request, please try again later in a few minutes. If the issue persists after a few minutes, please contact us at support@gtoria.net. - @env(['production', 'staging']) + @env(['staging', 'local']) @if(isset($stack))
@@ -24,5 +27,8 @@
+ @env(['staging', 'local']) +
+ @endenv
@endsection diff --git a/web/resources/views/layouts/footer.blade.php b/web/resources/views/layouts/footer.blade.php index 110987b..ee6b617 100644 --- a/web/resources/views/layouts/footer.blade.php +++ b/web/resources/views/layouts/footer.blade.php @@ -31,18 +31,20 @@