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