You've already forked Atomcms-edit
181 lines
5.3 KiB
PHP
Executable File
181 lines
5.3 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use App\Models\Miscellaneous\WebsiteInstallation;
|
|
use App\Services\InstallationService;
|
|
use Closure;
|
|
use Exception;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Illuminate\Support\Str;
|
|
|
|
class InstallationMiddleware
|
|
{
|
|
public function handle(Request $request, Closure $next)
|
|
{
|
|
if (str_starts_with($request->path(), 'api/')) {
|
|
return $next($request);
|
|
}
|
|
|
|
if (app(InstallationService::class)->isComplete()) {
|
|
if ($request->is('installation*')) {
|
|
return to_route('welcome');
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
$this->ensureInstallationTableExists();
|
|
|
|
$installation = $this->getInstallation();
|
|
|
|
$isInstallationStepHandled = $this->handleInstallationSteps($request, $installation);
|
|
|
|
if (! $isInstallationStepHandled) {
|
|
return $this->redirectIfNotCompleted($installation);
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
private function ensureInstallationTableExists(): void
|
|
{
|
|
if (! Schema::hasTable('website_installation')) {
|
|
Artisan::call('migrate', ['--path' => 'database/migrations/' . findMigration('website_installation')]);
|
|
|
|
// Migration executed, proceed
|
|
}
|
|
|
|
if (! Schema::hasTable('sessions')) {
|
|
Artisan::call('migrate', ['--path' => 'database/migrations/' . findMigration('sessions')]);
|
|
}
|
|
}
|
|
|
|
private function getInstallation()
|
|
{
|
|
try {
|
|
$cacheKey = 'installation_record';
|
|
|
|
$cachedInstallation = Cache::get($cacheKey);
|
|
|
|
if ($cachedInstallation) {
|
|
$installation = new WebsiteInstallation;
|
|
$installation->fill((array) $cachedInstallation);
|
|
|
|
return $installation;
|
|
}
|
|
|
|
$installation = WebsiteInstallation::query()->first();
|
|
|
|
if (! $installation) {
|
|
$installation = WebsiteInstallation::create([
|
|
'step' => 0,
|
|
'completed' => false,
|
|
'installation_key' => Str::uuid(),
|
|
'user_ip' => request()->ip(),
|
|
]);
|
|
}
|
|
|
|
if ($installation instanceof WebsiteInstallation && $installation->completed) {
|
|
Cache::rememberForever($cacheKey, fn () => $installation->toArray());
|
|
}
|
|
|
|
return $installation;
|
|
} catch (Exception $e) {
|
|
Log::error('Error fetching or creating WebsiteInstallation: ' . $e->getMessage());
|
|
abort(500, 'An error occurred while setting up installation.');
|
|
}
|
|
}
|
|
|
|
private function handleInstallationSteps(Request $request, WebsiteInstallation $installation)
|
|
{
|
|
if ($installation->completed) {
|
|
return true;
|
|
}
|
|
|
|
if ($this->isWelcomeStep($request, $installation)) {
|
|
return true;
|
|
}
|
|
|
|
if ($this->isRedirectToWelcome($request, $installation)) {
|
|
return false;
|
|
}
|
|
|
|
if ($this->isInvalidAccess($request, $installation)) {
|
|
abort(403);
|
|
}
|
|
|
|
if ($this->isInvalidStep($request)) {
|
|
return false;
|
|
}
|
|
|
|
return ! $this->isMismatchedStep($request, $installation);
|
|
}
|
|
|
|
private function isWelcomeStep(Request $request, WebsiteInstallation $installation)
|
|
{
|
|
return $installation->step === 0 && $request->getRequestUri() === '/installation';
|
|
}
|
|
|
|
private function isRedirectToWelcome(Request $request, WebsiteInstallation $installation)
|
|
{
|
|
return $installation->step === 0 && $request->getRequestUri() !== '/installation' && $request->method() !== 'POST';
|
|
}
|
|
|
|
private function isInvalidAccess(Request $request, WebsiteInstallation $installation)
|
|
{
|
|
// Skip IP check during testing
|
|
if (app()->environment('testing')) {
|
|
return false;
|
|
}
|
|
|
|
return $installation->step > 0 && $request->ip() !== $installation->user_ip;
|
|
}
|
|
|
|
private function isInvalidStep(Request $request)
|
|
{
|
|
return ! $this->isValidStep($request) && $this->isNonPostRequest($request);
|
|
}
|
|
|
|
private function isMismatchedStep(Request $request, WebsiteInstallation $installation)
|
|
{
|
|
return $this->getCurrentStep($request) !== $installation->step && $this->isNonPostRequest($request);
|
|
}
|
|
|
|
private function isValidStep(Request $request)
|
|
{
|
|
$step = $this->getCurrentStep($request);
|
|
|
|
return filter_var($step, FILTER_VALIDATE_INT) !== false;
|
|
}
|
|
|
|
private function isNonPostRequest(Request $request)
|
|
{
|
|
return $request->method() !== 'POST' || $request->is('restart-installation');
|
|
}
|
|
|
|
private function getCurrentStep(Request $request)
|
|
{
|
|
return (int) Str::after($request->path(), 'step/');
|
|
}
|
|
|
|
private function redirectToStep(int $step)
|
|
{
|
|
return to_route('installation.show-step', $step);
|
|
}
|
|
|
|
protected function redirectIfNotCompleted(WebsiteInstallation $installation)
|
|
{
|
|
|
|
if ($installation->step === 0) {
|
|
return to_route('installation.index');
|
|
}
|
|
|
|
return $this->redirectToStep($installation->step ?: 1);
|
|
}
|
|
}
|