Files
Atomcms-edit/app/Http/Controllers/Miscellaneous/InstallationController.php
T
root b1739cabbf fix(security): eliminate remaining critical vulnerabilities
- SystemFixService: removed ALL shell_exec/sudo calls (30+ instances), replaced with
  safe PHP alternatives (mkdir, chmod, disk_total_space, Artisan calls)
- InstallationController: added ALLOWED_SETTINGS whitelist to prevent arbitrary
  settings manipulation via request data
- ExceptionHandler: removed dangerous npm run build execution and hardcoded
  chown/chmod paths from auto-recovery
- AuthController: fixed user enumeration timing attack by running Hash::make()
  even when user doesn't exist (constant-time comparison)
- DDoSDetectionCommand: added IP validation (FILTER_VALIDATE_IP) before blocking
  to prevent iptables manipulation with spoofed/malicious IPs
- trackRequest: now validates IP before storing in cache
2026-05-19 19:46:38 +02:00

131 lines
3.8 KiB
PHP
Executable File

<?php
namespace App\Http\Controllers\Miscellaneous;
use App\Http\Controllers\Controller;
use App\Models\Miscellaneous\WebsiteInstallation;
use App\Models\Miscellaneous\WebsiteSetting;
use App\Rules\ValidateInstallationKeyRule;
use Exception;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Illuminate\View\View;
class InstallationController extends Controller
{
private const array ALLOWED_SETTINGS = [
'hotel_name', 'hotel_url', 'emulator_database_host', 'emulator_database_port',
'emulator_database_name', 'emulator_database_username', 'emulator_database_password',
'theme', 'start_credits', 'start_pixels', 'start_diamonds',
'social_login_google_enabled', 'social_login_discord_enabled', 'social_login_github_enabled',
];
public function index(): View
{
return view('installation.index');
}
public function storeInstallationKey(Request $request): RedirectResponse
{
$request->validate([
'installation_key' => ['required', 'string', 'max:255', new ValidateInstallationKeyRule],
]);
WebsiteInstallation::first()->update([
'step' => 1,
'user_ip' => $request->ip(),
]);
return to_route('installation.show-step', 1);
}
public function showStep(int $currentStep): View
{
$settings = $this->getSettingsForStep($currentStep);
return view('installation.step-' . $currentStep, [
'settings' => $settings,
]);
}
public function saveStepSettings(Request $request): RedirectResponse
{
$this->updateSettings($request);
WebsiteInstallation::first()->increment('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
}
public function previousStep(): RedirectResponse
{
WebsiteInstallation::first()->decrement('step');
return to_route('installation.show-step', WebsiteInstallation::first()->step);
}
public function restartInstallation(): RedirectResponse
{
WebsiteInstallation::first()->update([
'step' => 0,
'installation_key' => Str::uuid(),
'user_ip' => null,
]);
WebsiteSetting::where('key', 'theme')->update([
'value' => 'atom',
]);
return to_route('installation.index');
}
public function completeInstallation(): RedirectResponse
{
Cache::forget('website_permissions');
Cache::forget('website_settings');
WebsiteInstallation::latest()->first()->update([
'completed' => true,
]);
return to_route('welcome');
}
private function updateSettings(Request $request): void
{
$data = $request->except(['_token', '_method']);
foreach ($data as $key => $value) {
if (! in_array($key, self::ALLOWED_SETTINGS)) {
continue;
}
WebsiteSetting::where('key', $key)->update([
'value' => is_array($value) ? json_encode($value) : (string) $value,
]);
}
}
private function getSettingsForStep(int $step): Collection
{
$settingsData = array_chunk(WebsiteSetting::all()->pluck('key')->toArray(), (int) ceil(WebsiteSetting::count() / 4));
$settings = match ($step) {
1 => $settingsData[0] ?? [],
2 => $settingsData[1] ?? [],
3 => $settingsData[2] ?? [],
4 => $settingsData[3] ?? [],
5 => [],
default => throw new Exception('Step does not exist'),
};
return WebsiteSetting::query()
->whereIn('key', $settings)
->select(['key', 'value', 'comment'])
->get();
}
}