Initial commit

This commit is contained in:
root
2026-05-09 17:28:23 +02:00
commit 9d73f82529
5575 changed files with 281989 additions and 0 deletions
+596
View File
@@ -0,0 +1,596 @@
<?php
namespace App\Services;
class SystemFixService
{
private array $results = [];
public function checkAndFixAll(): array
{
$this->results = [];
// 1. Check PHP extensions
$this->checkAndFixPhpExtensions();
// 2. Check Git
$this->checkAndFixGit();
// 3. Check Maven
$this->checkAndFixMaven();
// 4. Check Node.js
$this->checkAndFixNode();
// 5. Check MySQL connection
$this->checkDatabase();
// 6. Fix permissions
$this->fixPermissions();
// 7. Fix open_basedir
$this->fixOpenBaseDir();
// 8. Configure emulator database from .env
$this->configureEmulatorDatabase();
// 9. Create missing directories
$this->createMissingDirectories();
// 10. Fix storage permissions
$this->fixStoragePermissions();
// 11. Check disk space
$this->checkDiskSpace();
// 12. Clear old caches
$this->clearOldCaches();
// 13. Fix git safe directories
$this->fixGitSafeDirectories();
// 14. Create .m2 directory for Maven
$this->fixMavenDirectory();
// 15. Check and install Java (needed for Maven)
$this->checkAndFixJava();
return $this->results;
}
private function checkAndFixPhpExtensions(): void
{
$requiredExtensions = ['pdo_mysql', 'curl', 'json', 'mbstring', 'xml', 'zip', 'bcmath'];
$missing = [];
foreach ($requiredExtensions as $ext) {
if (! extension_loaded($ext)) {
$missing[] = $ext;
}
}
if ($missing === []) {
$this->results[] = ['item' => 'PHP Extensions', 'status' => 'ok', 'message' => 'Alle vereiste extensies geïnstalleerd'];
} else {
$this->results[] = ['item' => 'PHP Extensions', 'status' => 'warning', 'message' => 'Ontbrekend: ' . implode(', ', $missing)];
}
}
private function checkAndFixGit(): void
{
$result = shell_exec('which git 2>/dev/null || echo ""');
if (! in_array(trim($result ?? ''), ['', '0'], true)) {
$this->results[] = ['item' => 'Git', 'status' => 'ok', 'message' => trim($result)];
} else {
// Install Git
shell_exec('sudo apt-get update && sudo apt-get install -y git 2>&1');
$result = shell_exec('which git 2>/dev/null || echo ""');
if (! in_array(trim($result ?? ''), ['', '0'], true)) {
$this->results[] = ['item' => 'Git', 'status' => 'fixed', 'message' => 'Automatisch geïnstalleerd'];
} else {
$this->results[] = ['item' => 'Git', 'status' => 'error', 'message' => 'Installatie mislukt'];
}
}
}
private function checkAndFixMaven(): void
{
$result = shell_exec('which mvn 2>/dev/null || echo ""');
if (! in_array(trim($result ?? ''), ['', '0'], true)) {
$this->results[] = ['item' => 'Maven', 'status' => 'ok', 'message' => trim($result)];
} else {
// Install Maven
shell_exec('sudo apt-get update && sudo apt-get install -y maven 2>&1');
// Fix Maven repository permissions
shell_exec('sudo mkdir -p /var/www/.m2/repository && sudo chown -R www-data:www-data /var/www/.m2');
$result = shell_exec('which mvn 2>/dev/null || echo ""');
if (! in_array(trim($result ?? ''), ['', '0'], true)) {
$this->results[] = ['item' => 'Maven', 'status' => 'fixed', 'message' => 'Automatisch geïnstalleerd'];
} else {
$this->results[] = ['item' => 'Maven', 'status' => 'error', 'message' => 'Installatie mislukt'];
}
}
}
private function checkAndFixNode(): void
{
// Use shell command to check for node (bypasses open_basedir)
$nodeResult = shell_exec('which node 2>/dev/null || echo ""');
$nodePath = trim($nodeResult ?? '');
if ($nodePath !== '' && $nodePath !== '0') {
$version = shell_exec("{$nodePath} --version 2>/dev/null || echo ''");
$versionNum = trim($version ?? '');
// Check if version is 24.x
if (str_starts_with($versionNum, 'v24')) {
$this->results[] = ['item' => 'Node.js', 'status' => 'ok', 'message' => $versionNum];
} else {
// Upgrade to Node.js 24
$this->installNode24();
}
} else {
// Install Node.js 24
$this->installNode24();
}
}
private function installNode24(): void
{
// Install Node.js 24 via NodeSource
$commands = [
'curl -fsSL https://deb.nodesource.com/setup_24.x | sudo bash - 2>&1',
'sudo apt-get install -y nodejs 2>&1',
];
$success = true;
foreach ($commands as $cmd) {
$result = shell_exec($cmd);
if (str_contains($result ?? '', 'E:')) {
$success = false;
break;
}
}
// Verify installation
$version = shell_exec('node --version 2>/dev/null || echo ""');
$versionNum = trim($version ?? '');
if ($versionNum !== '' && $versionNum !== '0' && str_starts_with($versionNum, 'v24')) {
$this->results[] = ['item' => 'Node.js', 'status' => 'fixed', 'message' => "Geïnstalleerd: {$versionNum}"];
} else {
$this->results[] = ['item' => 'Node.js', 'status' => 'error', 'message' => 'Installatie mislukt'];
}
}
private function checkDatabase(): void
{
try {
$host = setting('emulator_database_host', '127.0.0.1');
$port = setting('emulator_database_port', '3306');
$name = setting('emulator_database_name', config('database.connections.mysql.database', ''));
$username = setting('emulator_database_username', config('database.connections.mysql.username', ''));
$password = setting('emulator_database_password', config('database.connections.mysql.password', ''));
if (empty($name) || empty($username)) {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'warning', 'message' => 'Niet geconfigureerd'];
$this->autoFixEmulatorDatabase();
return;
}
// Validate inputs
$validationErrors = $this->validateDatabaseInputs($host, $port, $name, $username);
if ($validationErrors !== []) {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => implode(', ', $validationErrors)];
$this->autoFixEmulatorDatabase();
return;
}
// Try connection
try {
$pdo = new \PDO(
"mysql:host={$host};port={$port};charset=utf8mb4",
$username,
$password,
[\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_TIMEOUT => 5],
);
// Test with database
$pdo->exec("USE `{$name}`");
$pdo->query('SELECT 1');
$this->results[] = ['item' => 'Emulator Database', 'status' => 'ok', 'message' => "Verbonden met {$name}"];
} catch (\PDOException $e) {
$errorMsg = $e->getMessage();
if (str_contains($errorMsg, 'Unknown database')) {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => "Database '{$name}' bestaat niet"];
$this->autoFixEmulatorDatabase();
} elseif (str_contains($errorMsg, 'Access denied')) {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => 'Verkeerde gebruikersnaam/wachtwoord'];
$this->autoFixEmulatorDatabase();
} elseif (str_contains($errorMsg, 'Connection refused')) {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => "Kan niet verbinden met {$host}:{$port}"];
} else {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => $errorMsg];
}
}
} catch (\Exception $e) {
$this->results[] = ['item' => 'Emulator Database', 'status' => 'error', 'message' => $e->getMessage()];
$this->autoFixEmulatorDatabase();
}
}
private function validateDatabaseInputs(string $host, string $port, string $name, string $username): array
{
$errors = [];
// Validate host
if ($host === '' || $host === '0') {
$errors[] = 'Host is leeg';
} elseif (! filter_var($host, FILTER_VALIDATE_IP) && ! preg_match('/^[a-zA-Z0-9.-]+$/', $host)) {
$errors[] = 'Ongeldige host: ' . $host;
}
// Validate port
if ($port === '' || $port === '0') {
$errors[] = 'Port is leeg';
} elseif (! is_numeric($port) || $port < 1 || $port > 65535) {
$errors[] = 'Ongeldige port: ' . $port;
}
// Validate database name
if ($name === '' || $name === '0') {
$errors[] = 'Database naam is leeg';
} elseif (! preg_match('/^\w+$/', $name)) {
$errors[] = 'Ongeldige database naam: ' . $name;
}
// Validate username
if ($username === '' || $username === '0') {
$errors[] = 'Gebruikersnaam is leeg';
} elseif (! preg_match('/^\w+$/', $username)) {
$errors[] = 'Ongeldige gebruikersnaam: ' . $username;
}
return $errors;
}
private function autoFixEmulatorDatabase(): void
{
// Try to get correct values from .env / config
$host = config('database.connections.mysql.host', '127.0.0.1');
$port = config('database.connections.mysql.port', '3306');
$name = config('database.connections.mysql.database', '');
$username = config('database.connections.mysql.username', '');
$password = config('database.connections.mysql.password', '');
if (empty($name) || empty($username)) {
// Try to detect from MySQL process list or common names
$detected = $this->detectDatabaseFromMysql();
if ($detected) {
$name = $detected['name'];
$host = $detected['host'] ?? $host;
$username = $detected['username'] ?? $username;
$password = $detected['password'] ?? $password;
} else {
$this->results[] = ['item' => 'Emulator Database Fix', 'status' => 'warning', 'message' => 'Kon geen geldige database vinden'];
return;
}
}
$settings = app(SettingsService::class);
$settings->set('emulator_database_host', $host);
$settings->set('emulator_database_port', (string) $port);
$settings->set('emulator_database_name', $name);
$settings->set('emulator_database_username', $username);
$settings->set('emulator_database_password', $password);
$this->results[] = ['item' => 'Emulator Database Fix', 'status' => 'fixed', 'message' => "Automatisch gefixt: {$name}@{$host}"];
}
private function detectDatabaseFromMysql(): ?array
{
// Common database names for hotel emulators
$commonNames = ['habbo', 'hotel', 'retro', 'emulator', 'game', 'server', 'arcturus', 'fusion'];
// Get CMS database credentials that work
$cmsHost = config('database.connections.mysql.host', '127.0.0.1');
$cmsPort = config('database.connections.mysql.port', '3306');
$cmsUser = config('database.connections.mysql.username', '');
$cmsPass = config('database.connections.mysql.password', '');
$cmsDb = config('database.connections.mysql.database', '');
if (empty($cmsUser)) {
return null;
}
try {
$pdo = new \PDO(
"mysql:host={$cmsHost};port={$cmsPort};charset=utf8mb4",
$cmsUser,
$cmsPass,
[\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_TIMEOUT => 5],
);
// Get all databases the user can access
$stmt = $pdo->query('SHOW DATABASES');
$databases = $stmt->fetchAll(\PDO::FETCH_COLUMN);
// Check for common names
foreach ($commonNames as $name) {
if (in_array($name, $databases)) {
return [
'name' => $name,
'host' => $cmsHost,
'username' => $cmsUser,
'password' => $cmsPass,
];
}
}
// If CMS database exists and works, use that
if (! empty($cmsDb) && in_array($cmsDb, $databases)) {
return [
'name' => $cmsDb,
'host' => $cmsHost,
'username' => $cmsUser,
'password' => $cmsPass,
];
}
// Return first database that's not system db
foreach ($databases as $db) {
if (! in_array($db, ['information_schema', 'performance_schema', 'mysql', 'sys'])) {
return [
'name' => $db,
'host' => $cmsHost,
'username' => $cmsUser,
'password' => $cmsPass,
];
}
}
} catch (\Exception) {
// Could not detect
}
return null;
}
private function fixPermissions(): void
{
$directories = [
'/var/www/emulator-source',
'/var/www/nitro-client',
'/var/www/nitro-renderer',
'/var/www/Client',
'/var/www/atomcms/storage',
'/var/www/atomcms/bootstrap/cache',
'/var/www/atomcms/app',
];
$fixed = false;
foreach ($directories as $dir) {
if (is_dir($dir)) {
// Check if already owned by www-data
$owner = shell_exec("stat -c '%U' {$dir} 2>/dev/null || echo ''");
if (trim($owner ?? '') !== 'www-data') {
shell_exec("sudo chown -R www-data:www-data {$dir} 2>/dev/null || true");
$fixed = true;
}
}
}
// Always fix app directory permissions (new files might have wrong owner)
shell_exec("sudo find /var/www/atomcms/app -type f -name '*.php' ! -user www-data -exec chown www-data:www-data {} \\; 2>/dev/null || true");
$this->results[] = ['item' => 'Permissions', 'status' => $fixed ? 'fixed' : 'ok', 'message' => $fixed ? 'Directories eigendom gefixt' : 'Al correct geconfigureerd'];
}
private function fixOpenBaseDir(): void
{
$openBaseDir = ini_get('open_basedir');
if (in_array($openBaseDir, ['', '0', false], true)) {
$this->results[] = ['item' => 'open_basedir', 'status' => 'ok', 'message' => 'Geen restrictie'];
return;
}
// Check if all required paths are in open_basedir
$requiredPaths = ['/var/www', '/tmp', '/root'];
$missing = [];
foreach ($requiredPaths as $path) {
if (! str_contains($openBaseDir, $path)) {
$missing[] = $path;
}
}
if ($missing === []) {
$this->results[] = ['item' => 'open_basedir', 'status' => 'ok', 'message' => 'Alle paden toegestaan'];
} else {
$this->results[] = ['item' => 'open_basedir', 'status' => 'warning', 'message' => 'Ontbrekende paden: ' . implode(', ', $missing)];
}
}
private function configureEmulatorDatabase(): void
{
// Only configure if not already set
$currentHost = setting('emulator_database_host', '');
if (! empty($currentHost)) {
$this->results[] = ['item' => 'Emulator Database Config', 'status' => 'ok', 'message' => 'Al geconfigureerd'];
return;
}
// Get from .env
$host = config('database.connections.mysql.host', '127.0.0.1');
$port = config('database.connections.mysql.port', '3306');
$name = config('database.connections.mysql.database', '');
$username = config('database.connections.mysql.username', '');
$password = config('database.connections.mysql.password', '');
if (empty($name) || empty($username)) {
$this->results[] = ['item' => 'Emulator Database Config', 'status' => 'warning', 'message' => 'Geen database gevonden in .env'];
return;
}
$settings = app(SettingsService::class);
$settings->set('emulator_database_host', $host);
$settings->set('emulator_database_port', $port);
$settings->set('emulator_database_name', $name);
$settings->set('emulator_database_username', $username);
$settings->set('emulator_database_password', $password);
$this->results[] = ['item' => 'Emulator Database Config', 'status' => 'fixed', 'message' => "Automatisch geconfigureerd: {$name}@{$host}"];
}
private function createMissingDirectories(): void
{
$directories = [
'/var/www/emulator-source',
'/var/www/nitro-client',
'/var/www/nitro-client/dist',
'/var/www/nitro-renderer',
'/var/www/Client',
'/var/www/Client/gamedata',
'/var/www/Gamedata',
'/root/emulator',
];
$created = [];
foreach ($directories as $dir) {
if (! is_dir($dir)) {
shell_exec("sudo mkdir -p {$dir} 2>/dev/null && sudo chown www-data:www-data {$dir} 2>/dev/null");
$created[] = basename($dir);
}
}
if ($created !== []) {
$this->results[] = ['item' => 'Directories', 'status' => 'fixed', 'message' => 'Aangemaakt: ' . implode(', ', $created)];
} else {
$this->results[] = ['item' => 'Directories', 'status' => 'ok', 'message' => 'Alle directories bestaan'];
}
}
private function fixStoragePermissions(): void
{
$storageDirs = [
'/var/www/atomcms/storage',
'/var/www/atomcms/storage/logs',
'/var/www/atomcms/storage/framework',
'/var/www/atomcms/storage/framework/cache',
'/var/www/atomcms/storage/framework/sessions',
'/var/www/atomcms/storage/framework/views',
'/var/www/atomcms/bootstrap/cache',
];
$fixed = false;
foreach ($storageDirs as $dir) {
if (is_dir($dir)) {
$owner = shell_exec("stat -c '%U' {$dir} 2>/dev/null || echo ''");
if (trim($owner ?? '') !== 'www-data') {
shell_exec("sudo chown -R www-data:www-data {$dir} 2>/dev/null");
$fixed = true;
}
} else {
shell_exec("sudo mkdir -p {$dir} && sudo chown www-data:www-data {$dir} 2>/dev/null");
$fixed = true;
}
}
// Make storage writable
shell_exec('sudo chmod -R 775 /var/www/atomcms/storage 2>/dev/null');
shell_exec('sudo chmod -R 775 /var/www/atomcms/bootstrap/cache 2>/dev/null');
$this->results[] = ['item' => 'Storage Permissions', 'status' => $fixed ? 'fixed' : 'ok', 'message' => $fixed ? 'Gefixt' : 'Al correct'];
}
private function checkDiskSpace(): void
{
$result = shell_exec("df -h /var/www 2>/dev/null | tail -1 | awk '{print $5}'");
$usage = trim($result ?? '0%');
$usageNum = (int) str_replace('%', '', $usage);
if ($usageNum >= 90) {
$this->results[] = ['item' => 'Disk Space', 'status' => 'error', 'message' => "Disk {$usage} vol!"];
} elseif ($usageNum >= 75) {
$this->results[] = ['item' => 'Disk Space', 'status' => 'warning', 'message' => "Disk {$usage} gebruikt"];
} else {
$this->results[] = ['item' => 'Disk Space', 'status' => 'ok', 'message' => "Disk {$usage} gebruikt"];
}
}
private function clearOldCaches(): void
{
// Clear old temp files
shell_exec("find /tmp -name 'emulator-update-*' -mtime +1 -exec rm -rf {} \\; 2>/dev/null");
shell_exec("find /tmp -name 'nitro_*' -mtime +1 -exec rm -rf {} \\; 2>/dev/null");
shell_exec("find /tmp -name '*.lock' -mtime +1 -delete 2>/dev/null");
// Clear Laravel caches
shell_exec('cd /var/www/atomcms && php artisan cache:clear 2>/dev/null');
shell_exec('cd /var/www/atomcms && php artisan view:clear 2>/dev/null');
$this->results[] = ['item' => 'Cache Cleanup', 'status' => 'fixed', 'message' => 'Oude caches opgeruimd'];
}
private function fixGitSafeDirectories(): void
{
$directories = [
'/var/www/atomcms',
'/var/www/emulator-source',
'/var/www/emulator-source/Emulator',
'/var/www/nitro-client',
'/var/www/nitro-renderer',
'/var/www/Client',
'/root',
'/root/emulator',
'/var/www',
];
foreach ($directories as $dir) {
shell_exec("git config --global --add safe.directory {$dir} 2>/dev/null || true");
}
$this->results[] = ['item' => 'Git Safe Directories', 'status' => 'fixed', 'message' => 'Alle directories toegevoegd'];
}
private function fixMavenDirectory(): void
{
$mavenDir = '/var/www/.m2';
if (! is_dir($mavenDir)) {
shell_exec("sudo mkdir -p {$mavenDir}/repository && sudo chown -R www-data:www-data {$mavenDir}");
$this->results[] = ['item' => 'Maven Directory', 'status' => 'fixed', 'message' => 'Aangemaakt'];
} else {
$owner = shell_exec("stat -c '%U' {$mavenDir} 2>/dev/null || echo ''");
if (trim($owner ?? '') !== 'www-data') {
shell_exec("sudo chown -R www-data:www-data {$mavenDir}");
$this->results[] = ['item' => 'Maven Directory', 'status' => 'fixed', 'message' => 'Permissions gefixt'];
} else {
$this->results[] = ['item' => 'Maven Directory', 'status' => 'ok', 'message' => 'Al correct'];
}
}
}
private function checkAndFixJava(): void
{
$result = shell_exec('which java 2>/dev/null || echo ""');
if (! in_array(trim($result ?? ''), ['', '0'], true)) {
$version = shell_exec('java -version 2>&1 | head -1');
$this->results[] = ['item' => 'Java', 'status' => 'ok', 'message' => trim($version ?? '')];
} else {
// Install Java
shell_exec('sudo apt-get update && sudo apt-get install -y default-jdk 2>&1');
$result = shell_exec('which java 2>/dev/null || echo ""');
if (! in_array(trim($result ?? ''), ['', '0'], true)) {
$this->results[] = ['item' => 'Java', 'status' => 'fixed', 'message' => 'Automatisch geïnstalleerd'];
} else {
$this->results[] = ['item' => 'Java', 'status' => 'error', 'message' => 'Installatie mislukt'];
}
}
}
}