Working on the maintenance page. TODO: fix the stupid cookie error

This commit is contained in:
Graphictoria 2022-04-22 22:48:51 -04:00
parent 2c7842b3fa
commit 23f75ea803
10 changed files with 63 additions and 43 deletions

View File

@ -0,0 +1,31 @@
<?php
/*
Graphictoria 2022
Maintenance helper
*/
namespace App\Helpers;
use Illuminate\Http\Request;
use Illuminate\Foundation\Http\MaintenanceModeBypassCookie;
class MaintenanceHelper
{
public static function isDown(Request $request)
{
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
return (app()->isDownForMaintenance() && !MaintenanceHelper::hasValidBypassCookie($request, $data));
}
protected static function hasValidBypassCookie(Request $request, array $data)
{
return isset($data['secret']) &&
$request->cookie('gt_constraint') &&
MaintenanceModeBypassCookie::isValid(
$request->cookie('gt_constraint'),
$data['secret']
);
}
}

View File

@ -10,8 +10,11 @@ use App\Models\WebsiteConfiguration;
class MaintenanceController extends Controller class MaintenanceController extends Controller
{ {
public function showPage() { public function showPage()
return view('maintenance'); {
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
return view('maintenance', ['hideLogin' => !isset($data['secret'])]);
} }
/** /**
@ -25,8 +28,7 @@ class MaintenanceController extends Controller
$buttons = $request->input('buttons'); $buttons = $request->input('buttons');
if(!$password || !$buttons) { if(!$password || !$buttons) {
return response('{"errors":[{"code":400,"message":"BadRequest"}]}') return response('{"errors":[{"code":400,"message":"BadRequest"}]}', 400)
->setStatusCode(400)
->header('Cache-Control', 'private') ->header('Cache-Control', 'private')
->header('Content-Type', 'application/json; charset=utf-8'); ->header('Content-Type', 'application/json; charset=utf-8');
} }
@ -43,7 +45,7 @@ class MaintenanceController extends Controller
if(isset($data['secret']) && $btns === $mtconf->combination) if(isset($data['secret']) && $btns === $mtconf->combination)
{ {
$trustedHosts = explode(',', env('TRUSTED_HOSTS')); $trustedHosts = explode(',', env('TRUSTED_HOSTS'));
$origin = parse_url($request->headers->get('origin'), PHP_URL_HOST); $origin = join('.', array_slice(explode('.', $request->headers->get('origin')), -2));
$passCheck = false; $passCheck = false;
foreach($trustedHosts as &$host) foreach($trustedHosts as &$host)
@ -52,11 +54,14 @@ class MaintenanceController extends Controller
$passCheck = true; $passCheck = true;
} }
$expiresAt = Carbon::now()->addHours(24); $expiresAt = Carbon::now()->addHours(24);
$bypassCookie = new Cookie('gt_constraint', base64_encode(json_encode([ $bypassCookie = new Cookie('gt_constraint', base64_encode(json_encode([
'expires_at' => $expiresAt->getTimestamp(), 'expires_at' => $expiresAt->getTimestamp(),
'mac' => hash_hmac('SHA256', $expiresAt->getTimestamp(), $data['secret']), 'mac' => hash_hmac('SHA256', $expiresAt->getTimestamp(), $data['secret']),
])), $expiresAt); ])), $expiresAt);
$bypassCookie = $bypassCookie->withSecure(false);
//$bypassCookie = $bypassCookie->withSameSite('none');
if($passCheck) if($passCheck)
$bypassCookie = $bypassCookie->withDomain('.' . $origin); $bypassCookie = $bypassCookie->withDomain('.' . $origin);
@ -66,7 +71,6 @@ class MaintenanceController extends Controller
} }
} }
return response('') return response('', 403);
->setStatusCode(403);
} }
} }

View File

@ -43,7 +43,6 @@ class Kernel extends HttpKernel
'api' => [ 'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
], ],

View File

@ -2,14 +2,17 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Helpers\MaintenanceHelper;
use Closure; use Closure;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
class PreventRequestsDuringMaintenance class PreventRequestsDuringMaintenance
{ {
public function handle($request, Closure $next) public function handle(Request $request, Closure $next)
{ {
if(app()->isDownForMaintenance()) { if(MaintenanceHelper::isDown($request)) {
if(in_array('web', $request->route()->middleware())) if(in_array('web', $request->route()->middleware()))
{ {
if($request->route()->uri() != 'maintenance') if($request->route()->uri() != 'maintenance')
@ -17,6 +20,9 @@ class PreventRequestsDuringMaintenance
} }
else else
{ {
if(in_array('api', $request->route()->middleware()) && str_starts_with($request->route()->uri(), 'v1/maintenance'))
return $next($request);
return response(['errors' => [['code' => 503, 'message' => 'ServiceUnavailable']]], 503) return response(['errors' => [['code' => 503, 'message' => 'ServiceUnavailable']]], 503)
->header('Cache-Control', 'private') ->header('Cache-Control', 'private')
->header('Content-Type', 'application/json; charset=utf-8'); ->header('Content-Type', 'application/json; charset=utf-8');

View File

@ -32,7 +32,7 @@ class MaintenanceServiceProvider extends ServiceProvider
public function boot() public function boot()
{ {
Blade::directive('live', function() { Blade::directive('live', function() {
return '<?php if(!app()->isDownForMaintenance()): ?>'; return '<?php if(!\App\Helpers\MaintenanceHelper::isDown(request())): ?>';
}); });
Blade::directive('endlive', function() { Blade::directive('endlive', function() {

View File

@ -2,10 +2,8 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider class RouteServiceProvider extends ServiceProvider
@ -21,15 +19,6 @@ class RouteServiceProvider extends ServiceProvider
protected $namespace = 'App\Http\Controllers'; protected $namespace = 'App\Http\Controllers';
/**
* The controller namespace for the application.
*
* When present, controller route declarations will automatically be prefixed with this namespace.
*
* @var string|null
*/
// protected $namespace = 'App\\Http\\Controllers';
/** /**
* Define your route model bindings, pattern filters, etc. * Define your route model bindings, pattern filters, etc.
* *
@ -81,16 +70,4 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/web.php')); ->group(base_path('routes/web.php'));
}); });
} }
// /**
// * 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());
// });
// }
} }

View File

@ -1,5 +1,5 @@
{ {
"/js/app.js": "/js/app.js?id=cd2fb1cee326ab151ccc", "/js/app.js": "/js/app.js?id=cd2fb1cee326ab151ccc",
"/js/pages/maintenance.js": "/js/pages/maintenance.js?id=8b2854bc9146fb6d6d92", "/js/pages/maintenance.js": "/js/pages/maintenance.js?id=48c6a431110c9ea51807",
"/css/graphictoria.css": "/css/graphictoria.css?id=569f8477631683f9ea96" "/css/graphictoria.css": "/css/graphictoria.css?id=569f8477631683f9ea96"
} }

View File

@ -4,7 +4,7 @@
const urlObject = new URL(document.location.href); const urlObject = new URL(document.location.href);
export function getCurrentDomain() { export function getCurrentDomain() {
return urlObject.hostname.replace(/^[^.]+\./g, ''); return urlObject.hostname.split('.').slice(-2).join('.');
}; };
export function getProtocol() { export function getProtocol() {

View File

@ -5,7 +5,8 @@
<div class="container graphictoria-center-vh my-auto text-center text-white"> <div class="container graphictoria-center-vh my-auto text-center text-white">
<div class="mb-4 graphictoria-home-shadow"> <div class="mb-4 graphictoria-home-shadow">
<h1 class="graphictoria-homepage-header">Graphictoria</h1> <h1 class="graphictoria-homepage-header">Graphictoria</h1>
<h5 class="mb-0">Graphictoria aims to revive the classic Roblox experience. Join <b>8k+</b> other users and relive your childhood!</h5> {{-- TODO: make the user count automatic via a model --}}
<h5 class="mb-0">Graphictoria aims to revive the classic Roblox experience. Join <b>9k+</b> other users and relive your childhood!</h5>
<p class="graphictoria-homepage-fine-print fst-italic">* Graphictoria is not affiliated with, endorsed by, or sponsored by Roblox Corporation.</p> <p class="graphictoria-homepage-fine-print fst-italic">* Graphictoria is not affiliated with, endorsed by, or sponsored by Roblox Corporation.</p>
</div> </div>
<a href="{{ url('/register') }}" class="btn btn-success">Create your account<i class="ps-2 graphictoria-small-aligned-text fas fa-chevron-right"></i></a> <a href="{{ url('/register') }}" class="btn btn-success">Create your account<i class="ps-2 graphictoria-small-aligned-text fas fa-chevron-right"></i></a>

View File

@ -19,11 +19,13 @@ $buttons = str_split('Graphictoria')
<div class="text-center m-auto container gtoria-maintenance-form"> <div class="text-center m-auto container gtoria-maintenance-form">
<h1>Graphictoria is currently under maintenance.</h1> <h1>Graphictoria is currently under maintenance.</h1>
<h4>Our cyborg team of highly trained code-monkes are working to make Graphictoria better. We'll be back soon!</h4> <h4>Our cyborg team of highly trained code-monkes are working to make Graphictoria better. We'll be back soon!</h4>
<div class="input-group mt-5 d-none d-md-flex" id="gt_mt_buttons"> @if(!$hideLogin)
<input type="password" class="form-control" placeholder="Password" autoComplete="off" /> <div class="input-group mt-5 d-none d-md-flex" id="gt_mt_buttons">
@foreach($buttons as $index => $button) <input type="password" class="form-control" placeholder="Password" autoComplete="off" />
<button class="btn btn-secondary" type="button" name="gt_mtbtn{{ $index }}">{{ $button }}</button> @foreach($buttons as $index => $button)
@endforeach <button class="btn btn-secondary" type="button" name="gt_mtbtn{{ $index }}">{{ $button }}</button>
</div> @endforeach
</div>
@endif
</div> </div>
@endsection @endsection