diff --git a/.dockerignore b/.dockerignore index 3a0ec49f7..2eba3cb46 100644 --- a/.dockerignore +++ b/.dockerignore @@ -23,3 +23,4 @@ yarn-error.log .rnd /.ssh .ignition.json +.env.dusk.local diff --git a/.github/workflows/coolify-production-build.yml b/.github/workflows/coolify-production-build.yml index 771687d4b..7017b4897 100644 --- a/.github/workflows/coolify-production-build.yml +++ b/.github/workflows/coolify-production-build.yml @@ -53,8 +53,6 @@ jobs: tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} - labels: | - coolify.managed=true aarch64: runs-on: [self-hosted, arm64] @@ -90,8 +88,6 @@ jobs: tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 - labels: | - coolify.managed=true merge-manifest: runs-on: ubuntu-latest diff --git a/.github/workflows/coolify-staging-build.yml b/.github/workflows/coolify-staging-build.yml index dd5e6ebd6..6e4d4adc3 100644 --- a/.github/workflows/coolify-staging-build.yml +++ b/.github/workflows/coolify-staging-build.yml @@ -48,8 +48,6 @@ jobs: tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }} ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }} - labels: | - coolify.managed=true aarch64: runs-on: [self-hosted, arm64] @@ -83,8 +81,6 @@ jobs: tags: | ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 - labels: | - coolify.managed=true merge-manifest: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 09504afee..1a021ab3e 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ _ide_helper_models.php /.ssh scripts/load-test/* .ignition.json +.env.dusk.local diff --git a/app/Actions/Application/GenerateConfig.php b/app/Actions/Application/GenerateConfig.php index d38f9c28b..991146b48 100644 --- a/app/Actions/Application/GenerateConfig.php +++ b/app/Actions/Application/GenerateConfig.php @@ -11,8 +11,6 @@ class GenerateConfig public function handle(Application $application, bool $is_json = false) { - ray()->clearAll(); - return $application->generateConfig(is_json: $is_json); } } diff --git a/app/Actions/Application/StopApplication.php b/app/Actions/Application/StopApplication.php index 61005845b..cab7e45f0 100644 --- a/app/Actions/Application/StopApplication.php +++ b/app/Actions/Application/StopApplication.php @@ -17,7 +17,6 @@ class StopApplication if (! $server->isFunctional()) { return 'Server is not functional'; } - ray('Stopping application: '.$application->name); if ($server->isSwarm()) { instant_remote_process(["docker stack rm {$application->uuid}"], $server); @@ -36,8 +35,6 @@ class StopApplication CleanupDocker::dispatch($server, true); } } catch (\Exception $e) { - ray($e->getMessage()); - return $e->getMessage(); } } diff --git a/app/Actions/Application/StopApplicationOneServer.php b/app/Actions/Application/StopApplicationOneServer.php index da8c700fe..b13b10efd 100644 --- a/app/Actions/Application/StopApplicationOneServer.php +++ b/app/Actions/Application/StopApplicationOneServer.php @@ -32,8 +32,6 @@ class StopApplicationOneServer } } } catch (\Exception $e) { - ray($e->getMessage()); - return $e->getMessage(); } } diff --git a/app/Actions/CoolifyTask/PrepareCoolifyTask.php b/app/Actions/CoolifyTask/PrepareCoolifyTask.php index 686b60780..6676b7937 100644 --- a/app/Actions/CoolifyTask/PrepareCoolifyTask.php +++ b/app/Actions/CoolifyTask/PrepareCoolifyTask.php @@ -48,7 +48,6 @@ class PrepareCoolifyTask call_event_data: $this->remoteProcessArgs->call_event_data, ); if ($this->remoteProcessArgs->type === ActivityTypes::COMMAND->value) { - ray('Dispatching a high priority job'); dispatch($job)->onQueue('high'); } else { dispatch($job); diff --git a/app/Actions/CoolifyTask/RunRemoteProcess.php b/app/Actions/CoolifyTask/RunRemoteProcess.php index c691f52c0..c75a30ae8 100644 --- a/app/Actions/CoolifyTask/RunRemoteProcess.php +++ b/app/Actions/CoolifyTask/RunRemoteProcess.php @@ -125,7 +125,6 @@ class RunRemoteProcess ])); } } catch (\Throwable $e) { - ray($e); } } diff --git a/app/Actions/Database/StartDatabase.php b/app/Actions/Database/StartDatabase.php index 323c52ff9..73b2f9ac0 100644 --- a/app/Actions/Database/StartDatabase.php +++ b/app/Actions/Database/StartDatabase.php @@ -23,28 +23,28 @@ class StartDatabase return 'Server is not functional'; } switch ($database->getMorphClass()) { - case 'App\Models\StandalonePostgresql': + case \App\Models\StandalonePostgresql::class: $activity = StartPostgresql::run($database); break; - case 'App\Models\StandaloneRedis': + case \App\Models\StandaloneRedis::class: $activity = StartRedis::run($database); break; - case 'App\Models\StandaloneMongodb': + case \App\Models\StandaloneMongodb::class: $activity = StartMongodb::run($database); break; - case 'App\Models\StandaloneMysql': + case \App\Models\StandaloneMysql::class: $activity = StartMysql::run($database); break; - case 'App\Models\StandaloneMariadb': + case \App\Models\StandaloneMariadb::class: $activity = StartMariadb::run($database); break; - case 'App\Models\StandaloneKeydb': + case \App\Models\StandaloneKeydb::class: $activity = StartKeydb::run($database); break; - case 'App\Models\StandaloneDragonfly': + case \App\Models\StandaloneDragonfly::class: $activity = StartDragonfly::run($database); break; - case 'App\Models\StandaloneClickhouse': + case \App\Models\StandaloneClickhouse::class: $activity = StartClickhouse::run($database); break; } diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index a514c51b4..d7a3bc697 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -26,7 +26,7 @@ class StartDatabaseProxy $server = data_get($database, 'destination.server'); $containerName = data_get($database, 'uuid'); $proxyContainerName = "{$database->uuid}-proxy"; - if ($database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) { $databaseType = $database->databaseType(); // $connectPredefined = data_get($database, 'service.connect_to_docker_network'); $network = $database->service->uuid; @@ -34,54 +34,54 @@ class StartDatabaseProxy $proxyContainerName = "{$database->service->uuid}-proxy"; switch ($databaseType) { case 'standalone-mariadb': - $type = 'App\Models\StandaloneMariadb'; + $type = \App\Models\StandaloneMariadb::class; $containerName = "mariadb-{$database->service->uuid}"; break; case 'standalone-mongodb': - $type = 'App\Models\StandaloneMongodb'; + $type = \App\Models\StandaloneMongodb::class; $containerName = "mongodb-{$database->service->uuid}"; break; case 'standalone-mysql': - $type = 'App\Models\StandaloneMysql'; + $type = \App\Models\StandaloneMysql::class; $containerName = "mysql-{$database->service->uuid}"; break; case 'standalone-postgresql': - $type = 'App\Models\StandalonePostgresql'; + $type = \App\Models\StandalonePostgresql::class; $containerName = "postgresql-{$database->service->uuid}"; break; case 'standalone-redis': - $type = 'App\Models\StandaloneRedis'; + $type = \App\Models\StandaloneRedis::class; $containerName = "redis-{$database->service->uuid}"; break; case 'standalone-keydb': - $type = 'App\Models\StandaloneKeydb'; + $type = \App\Models\StandaloneKeydb::class; $containerName = "keydb-{$database->service->uuid}"; break; case 'standalone-dragonfly': - $type = 'App\Models\StandaloneDragonfly'; + $type = \App\Models\StandaloneDragonfly::class; $containerName = "dragonfly-{$database->service->uuid}"; break; case 'standalone-clickhouse': - $type = 'App\Models\StandaloneClickhouse'; + $type = \App\Models\StandaloneClickhouse::class; $containerName = "clickhouse-{$database->service->uuid}"; break; } } - if ($type === 'App\Models\StandaloneRedis') { + if ($type === \App\Models\StandaloneRedis::class) { $internalPort = 6379; - } elseif ($type === 'App\Models\StandalonePostgresql') { + } elseif ($type === \App\Models\StandalonePostgresql::class) { $internalPort = 5432; - } elseif ($type === 'App\Models\StandaloneMongodb') { + } elseif ($type === \App\Models\StandaloneMongodb::class) { $internalPort = 27017; - } elseif ($type === 'App\Models\StandaloneMysql') { + } elseif ($type === \App\Models\StandaloneMysql::class) { $internalPort = 3306; - } elseif ($type === 'App\Models\StandaloneMariadb') { + } elseif ($type === \App\Models\StandaloneMariadb::class) { $internalPort = 3306; - } elseif ($type === 'App\Models\StandaloneKeydb') { + } elseif ($type === \App\Models\StandaloneKeydb::class) { $internalPort = 6379; - } elseif ($type === 'App\Models\StandaloneDragonfly') { + } elseif ($type === \App\Models\StandaloneDragonfly::class) { $internalPort = 6379; - } elseif ($type === 'App\Models\StandaloneClickhouse') { + } elseif ($type === \App\Models\StandaloneClickhouse::class) { $internalPort = 9000; } $configuration_dir = database_proxy_dir($database->uuid); diff --git a/app/Actions/Database/StopDatabaseProxy.php b/app/Actions/Database/StopDatabaseProxy.php index b2092e2ef..9e9a62170 100644 --- a/app/Actions/Database/StopDatabaseProxy.php +++ b/app/Actions/Database/StopDatabaseProxy.php @@ -22,7 +22,7 @@ class StopDatabaseProxy { $server = data_get($database, 'destination.server'); $uuid = $database->uuid; - if ($database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) { $uuid = $database->service->uuid; $server = data_get($database, 'service.server'); } diff --git a/app/Actions/Fortify/CreateNewUser.php b/app/Actions/Fortify/CreateNewUser.php index 481757162..9f97dd0d4 100644 --- a/app/Actions/Fortify/CreateNewUser.php +++ b/app/Actions/Fortify/CreateNewUser.php @@ -6,12 +6,11 @@ use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\Rule; +use Illuminate\Validation\Rules\Password; use Laravel\Fortify\Contracts\CreatesNewUsers; class CreateNewUser implements CreatesNewUsers { - use PasswordValidationRules; - /** * Validate and create a newly registered user. * @@ -32,7 +31,7 @@ class CreateNewUser implements CreatesNewUsers 'max:255', Rule::unique(User::class), ], - 'password' => $this->passwordRules(), + 'password' => ['required', Password::defaults(), 'confirmed'], ])->validate(); if (User::count() == 0) { diff --git a/app/Actions/Fortify/PasswordValidationRules.php b/app/Actions/Fortify/PasswordValidationRules.php deleted file mode 100644 index 92fcc7532..000000000 --- a/app/Actions/Fortify/PasswordValidationRules.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ - protected function passwordRules(): array - { - return ['required', 'string', new Password, 'confirmed']; - } -} diff --git a/app/Actions/Fortify/ResetUserPassword.php b/app/Actions/Fortify/ResetUserPassword.php index 7a57c5037..d3727a52c 100644 --- a/app/Actions/Fortify/ResetUserPassword.php +++ b/app/Actions/Fortify/ResetUserPassword.php @@ -5,12 +5,11 @@ namespace App\Actions\Fortify; use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\Rules\Password; use Laravel\Fortify\Contracts\ResetsUserPasswords; class ResetUserPassword implements ResetsUserPasswords { - use PasswordValidationRules; - /** * Validate and reset the user's forgotten password. * @@ -19,7 +18,7 @@ class ResetUserPassword implements ResetsUserPasswords public function reset(User $user, array $input): void { Validator::make($input, [ - 'password' => $this->passwordRules(), + 'password' => ['required', Password::defaults(), 'confirmed'], ])->validate(); $user->forceFill([ diff --git a/app/Actions/Fortify/UpdateUserPassword.php b/app/Actions/Fortify/UpdateUserPassword.php index 700563905..0c51ec56d 100644 --- a/app/Actions/Fortify/UpdateUserPassword.php +++ b/app/Actions/Fortify/UpdateUserPassword.php @@ -5,12 +5,11 @@ namespace App\Actions\Fortify; use App\Models\User; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\Rules\Password; use Laravel\Fortify\Contracts\UpdatesUserPasswords; class UpdateUserPassword implements UpdatesUserPasswords { - use PasswordValidationRules; - /** * Validate and update the user's password. * @@ -20,7 +19,7 @@ class UpdateUserPassword implements UpdatesUserPasswords { Validator::make($input, [ 'current_password' => ['required', 'string', 'current_password:web'], - 'password' => $this->passwordRules(), + 'password' => ['required', Password::defaults(), 'confirmed'], ], [ 'current_password.current_password' => __('The provided password does not match your current password.'), ])->validateWithBag('updatePassword'); diff --git a/app/Actions/License/CheckResaleLicense.php b/app/Actions/License/CheckResaleLicense.php index 55af1a8c0..26a1ff7bf 100644 --- a/app/Actions/License/CheckResaleLicense.php +++ b/app/Actions/License/CheckResaleLicense.php @@ -25,8 +25,6 @@ class CheckResaleLicense // } $base_url = config('coolify.license_url'); $instance_id = config('app.id'); - - ray("Checking license key against $base_url/lemon/validate"); $data = Http::withHeaders([ 'Accept' => 'application/json', ])->get("$base_url/lemon/validate", [ @@ -34,7 +32,6 @@ class CheckResaleLicense 'instance_id' => $instance_id, ])->json(); if (data_get($data, 'valid') === true && data_get($data, 'license_key.status') === 'active') { - ray('Valid & active license key'); $settings->update([ 'is_resale_license_active' => true, ]); @@ -48,7 +45,6 @@ class CheckResaleLicense 'instance_id' => $instance_id, ])->json(); if (data_get($data, 'activated') === true) { - ray('Activated license key'); $settings->update([ 'is_resale_license_active' => true, ]); @@ -60,7 +56,6 @@ class CheckResaleLicense } throw new \Exception('Cannot activate license key.'); } catch (\Throwable $e) { - ray($e); $settings->update([ 'resale_license' => null, 'is_resale_license_active' => false, diff --git a/app/Actions/Proxy/CheckProxy.php b/app/Actions/Proxy/CheckProxy.php index 03a0beddf..d64804758 100644 --- a/app/Actions/Proxy/CheckProxy.php +++ b/app/Actions/Proxy/CheckProxy.php @@ -88,7 +88,6 @@ class CheckProxy $portsToCheck = []; } } catch (\Exception $e) { - ray($e->getMessage()); } if (count($portsToCheck) === 0) { return false; diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index f20c10123..2a6ec7d03 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -13,67 +13,63 @@ class StartProxy public function handle(Server $server, bool $async = true, bool $force = false): string|Activity { - try { - $proxyType = $server->proxyType(); - if ((is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop || $server->isBuildServer()) && $force === false) { - return 'OK'; - } - $commands = collect([]); - $proxy_path = $server->proxyPath(); - $configuration = CheckConfiguration::run($server); - if (! $configuration) { - throw new \Exception('Configuration is not synced'); - } - SaveConfiguration::run($server, $configuration); - $docker_compose_yml_base64 = base64_encode($configuration); - $server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value(); - $server->save(); - if ($server->isSwarm()) { - $commands = $commands->merge([ - "mkdir -p $proxy_path/dynamic", - "cd $proxy_path", - "echo 'Creating required Docker Compose file.'", - "echo 'Starting coolify-proxy.'", - 'docker stack deploy -c docker-compose.yml coolify-proxy', - "echo 'Successfully started coolify-proxy.'", - ]); - } else { - $caddfile = 'import /dynamic/*.caddy'; - $commands = $commands->merge([ - "mkdir -p $proxy_path/dynamic", - "cd $proxy_path", - "echo '$caddfile' > $proxy_path/dynamic/Caddyfile", - "echo 'Creating required Docker Compose file.'", - "echo 'Pulling docker image.'", - 'docker compose pull', - 'if docker ps -a --format "{{.Names}}" | grep -q "^coolify-proxy$"; then', - " echo 'Stopping and removing existing coolify-proxy.'", - ' docker rm -f coolify-proxy || true', - " echo 'Successfully stopped and removed existing coolify-proxy.'", - 'fi', - "echo 'Starting coolify-proxy.'", - 'docker compose up -d --remove-orphans', - "echo 'Successfully started coolify-proxy.'", - ]); - $commands = $commands->merge(connectProxyToNetworks($server)); - } - - if ($async) { - $activity = remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server); - - return $activity; - } else { - instant_remote_process($commands, $server); - $server->proxy->set('status', 'running'); - $server->proxy->set('type', $proxyType); - $server->save(); - ProxyStarted::dispatch($server); - - return 'OK'; - } - } catch (\Throwable $e) { - ray($e); - throw $e; + $proxyType = $server->proxyType(); + if ((is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop || $server->isBuildServer()) && $force === false) { + return 'OK'; } + $commands = collect([]); + $proxy_path = $server->proxyPath(); + $configuration = CheckConfiguration::run($server); + if (! $configuration) { + throw new \Exception('Configuration is not synced'); + } + SaveConfiguration::run($server, $configuration); + $docker_compose_yml_base64 = base64_encode($configuration); + $server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value(); + $server->save(); + if ($server->isSwarm()) { + $commands = $commands->merge([ + "mkdir -p $proxy_path/dynamic", + "cd $proxy_path", + "echo 'Creating required Docker Compose file.'", + "echo 'Starting coolify-proxy.'", + 'docker stack deploy -c docker-compose.yml coolify-proxy', + "echo 'Successfully started coolify-proxy.'", + ]); + } else { + $caddfile = 'import /dynamic/*.caddy'; + $commands = $commands->merge([ + "mkdir -p $proxy_path/dynamic", + "cd $proxy_path", + "echo '$caddfile' > $proxy_path/dynamic/Caddyfile", + "echo 'Creating required Docker Compose file.'", + "echo 'Pulling docker image.'", + 'docker compose pull', + 'if docker ps -a --format "{{.Names}}" | grep -q "^coolify-proxy$"; then', + " echo 'Stopping and removing existing coolify-proxy.'", + ' docker rm -f coolify-proxy || true', + " echo 'Successfully stopped and removed existing coolify-proxy.'", + 'fi', + "echo 'Starting coolify-proxy.'", + 'docker compose up -d --remove-orphans', + "echo 'Successfully started coolify-proxy.'", + ]); + $commands = $commands->merge(connectProxyToNetworks($server)); + } + + if ($async) { + $activity = remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server); + + return $activity; + } else { + instant_remote_process($commands, $server); + $server->proxy->set('status', 'running'); + $server->proxy->set('type', $proxyType); + $server->save(); + ProxyStarted::dispatch($server); + + return 'OK'; + } + } } diff --git a/app/Actions/Server/ConfigureCloudflared.php b/app/Actions/Server/ConfigureCloudflared.php index 0d36e8863..0819da07a 100644 --- a/app/Actions/Server/ConfigureCloudflared.php +++ b/app/Actions/Server/ConfigureCloudflared.php @@ -40,7 +40,6 @@ class ConfigureCloudflared ]); instant_remote_process($commands, $server); } catch (\Throwable $e) { - ray($e); $server->settings->is_cloudflare_tunnel = false; $server->settings->save(); throw $e; diff --git a/app/Actions/Server/InstallDocker.php b/app/Actions/Server/InstallDocker.php index 2e1df8185..fd4dd150c 100644 --- a/app/Actions/Server/InstallDocker.php +++ b/app/Actions/Server/InstallDocker.php @@ -16,7 +16,6 @@ class InstallDocker if (! $supported_os_type) { throw new \Exception('Server OS type is not supported for automated installation. Please install Docker manually before continuing: documentation.'); } - ray('Installing Docker on server: '.$server->name.' ('.$server->ip.')'.' with OS type: '.$supported_os_type); $dockerVersion = '26.0'; $config = base64_encode('{ "log-driver": "json-file", diff --git a/app/Actions/Server/RestartContainer.php b/app/Actions/Server/RestartContainer.php new file mode 100644 index 000000000..63361d8b7 --- /dev/null +++ b/app/Actions/Server/RestartContainer.php @@ -0,0 +1,16 @@ +restartContainer($containerName); + } +} diff --git a/app/Actions/Server/InstallLogDrain.php b/app/Actions/Server/StartLogDrain.php similarity index 96% rename from app/Actions/Server/InstallLogDrain.php rename to app/Actions/Server/StartLogDrain.php index 43376efe5..0e8036cd9 100644 --- a/app/Actions/Server/InstallLogDrain.php +++ b/app/Actions/Server/StartLogDrain.php @@ -5,7 +5,7 @@ namespace App\Actions\Server; use App\Models\Server; use Lorisleiva\Actions\Concerns\AsAction; -class InstallLogDrain +class StartLogDrain { use AsAction; @@ -13,12 +13,16 @@ class InstallLogDrain { if ($server->settings->is_logdrain_newrelic_enabled) { $type = 'newrelic'; + StopLogDrain::run($server); } elseif ($server->settings->is_logdrain_highlight_enabled) { $type = 'highlight'; + StopLogDrain::run($server); } elseif ($server->settings->is_logdrain_axiom_enabled) { $type = 'axiom'; + StopLogDrain::run($server); } elseif ($server->settings->is_logdrain_custom_enabled) { $type = 'custom'; + StopLogDrain::run($server); } else { $type = 'none'; } @@ -151,6 +155,8 @@ services: - ./parsers.conf:/parsers.conf ports: - 127.0.0.1:24224:24224 + labels: + - coolify.managed=true restart: unless-stopped '); $readme = base64_encode('# New Relic Log Drain @@ -202,15 +208,11 @@ Files: throw new \Exception('Unknown log drain type.'); } $restart_command = [ - "echo 'Stopping old Fluent Bit'", - "cd $config_path && docker compose down --remove-orphans || true", "echo 'Starting Fluent Bit'", - "cd $config_path && docker compose up -d --remove-orphans", + "cd $config_path && docker compose up -d", ]; $command = array_merge($command, $add_envs_command, $restart_command); - StopLogDrain::run($server); - return instant_remote_process($command, $server); } catch (\Throwable $e) { return handleError($e); diff --git a/app/Actions/Server/StartSentinel.php b/app/Actions/Server/StartSentinel.php index aef7282e3..587ac4a8d 100644 --- a/app/Actions/Server/StartSentinel.php +++ b/app/Actions/Server/StartSentinel.php @@ -23,6 +23,7 @@ class StartSentinel $pushInterval = data_get($server, 'settings.sentinel_push_interval_seconds'); $token = data_get($server, 'settings.sentinel_token'); $endpoint = data_get($server, 'settings.sentinel_custom_url'); + $debug = data_get($server, 'settings.is_sentinel_debug_enabled'); $mountDir = '/data/coolify/sentinel'; $image = "ghcr.io/coollabsio/sentinel:$version"; if (! $endpoint) { @@ -30,6 +31,7 @@ class StartSentinel } $environments = [ 'TOKEN' => $token, + 'DEBUG' => $debug ? 'true' : 'false', 'PUSH_ENDPOINT' => $endpoint, 'PUSH_INTERVAL_SECONDS' => $pushInterval, 'COLLECTOR_ENABLED' => $server->isMetricsEnabled() ? 'true' : 'false', diff --git a/app/Actions/Server/StopLogDrain.php b/app/Actions/Server/StopLogDrain.php index a5bce94a5..96c2466de 100644 --- a/app/Actions/Server/StopLogDrain.php +++ b/app/Actions/Server/StopLogDrain.php @@ -12,7 +12,7 @@ class StopLogDrain public function handle(Server $server) { try { - return instant_remote_process(['docker rm -f coolify-log-drain || true'], $server); + return instant_remote_process(['docker rm -f coolify-log-drain'], $server, false); } catch (\Throwable $e) { return handleError($e); } diff --git a/app/Actions/Server/UpdateCoolify.php b/app/Actions/Server/UpdateCoolify.php index 30664df26..3185c22b7 100644 --- a/app/Actions/Server/UpdateCoolify.php +++ b/app/Actions/Server/UpdateCoolify.php @@ -18,32 +18,28 @@ class UpdateCoolify public function handle($manual_update = false) { - try { - $settings = instanceSettings(); - $this->server = Server::find(0); - if (! $this->server) { + $settings = instanceSettings(); + $this->server = Server::find(0); + if (! $this->server) { + return; + } + CleanupDocker::dispatch($this->server)->onQueue('high'); + $this->latestVersion = get_latest_version_of_coolify(); + $this->currentVersion = config('version'); + if (! $manual_update) { + if (! $settings->is_auto_update_enabled) { return; } - CleanupDocker::dispatch($this->server)->onQueue('high'); - $this->latestVersion = get_latest_version_of_coolify(); - $this->currentVersion = config('version'); - if (! $manual_update) { - if (! $settings->is_auto_update_enabled) { - return; - } - if ($this->latestVersion === $this->currentVersion) { - return; - } - if (version_compare($this->latestVersion, $this->currentVersion, '<')) { - return; - } + if ($this->latestVersion === $this->currentVersion) { + return; + } + if (version_compare($this->latestVersion, $this->currentVersion, '<')) { + return; } - $this->update(); - $settings->new_version_available = false; - $settings->save(); - } catch (\Throwable $e) { - throw $e; } + $this->update(); + $settings->new_version_available = false; + $settings->save(); } private function update() diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index f28e5490e..9c4b0349c 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -40,7 +40,6 @@ class DeleteService foreach ($commands as $command) { $result = instant_remote_process([$command], $server, false); if ($result !== 0) { - ray("Failed to execute: $command"); } } } diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php index 06d2e0efb..5b8279221 100644 --- a/app/Actions/Service/StartService.php +++ b/app/Actions/Service/StartService.php @@ -12,7 +12,6 @@ class StartService public function handle(Service $service) { - ray('Starting service: '.$service->name); $service->saveComposeConfigs(); $commands[] = 'cd '.$service->workdir(); $commands[] = "echo 'Saved configuration files to {$service->workdir()}.'"; diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 5c7bbc2aa..046d94ced 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -28,8 +28,6 @@ class StopService } } } catch (\Exception $e) { - ray($e->getMessage()); - return $e->getMessage(); } } diff --git a/app/Console/Commands/CleanupStuckedResources.php b/app/Console/Commands/CleanupStuckedResources.php index 66c25ec27..da757c99f 100644 --- a/app/Console/Commands/CleanupStuckedResources.php +++ b/app/Console/Commands/CleanupStuckedResources.php @@ -30,7 +30,6 @@ class CleanupStuckedResources extends Command public function handle() { - ray('Running cleanup stucked resources.'); echo "Running cleanup stucked resources.\n"; $this->cleanup_stucked_resources(); } diff --git a/app/Console/Commands/CloudCleanupSubscriptions.php b/app/Console/Commands/CloudCleanupSubscriptions.php index d220aa00b..5054d125c 100644 --- a/app/Console/Commands/CloudCleanupSubscriptions.php +++ b/app/Console/Commands/CloudCleanupSubscriptions.php @@ -19,7 +19,6 @@ class CloudCleanupSubscriptions extends Command return; } - ray()->clearAll(); $this->info('Cleaning up subcriptions teams'); $stripe = new \Stripe\StripeClient(config('subscription.stripe_api_key')); diff --git a/app/Console/Commands/Emails.php b/app/Console/Commands/Emails.php index ded729114..cda4ca84f 100644 --- a/app/Console/Commands/Emails.php +++ b/app/Console/Commands/Emails.php @@ -124,7 +124,6 @@ class Emails extends Command $applications = Application::all(); foreach ($applications as $application) { $deployments = $application->get_last_days_deployments(); - ray($deployments); if ($deployments->isEmpty()) { continue; } diff --git a/app/Console/Commands/Init.php b/app/Console/Commands/Init.php index ad7bff86d..8f68966a5 100644 --- a/app/Console/Commands/Init.php +++ b/app/Console/Commands/Init.php @@ -180,7 +180,7 @@ class Init extends Command 'save_s3' => false, 'frequency' => '0 0 * * *', 'database_id' => $database->id, - 'database_type' => 'App\Models\StandalonePostgresql', + 'database_type' => \App\Models\StandalonePostgresql::class, 'team_id' => 0, ]); } @@ -219,7 +219,6 @@ class Init extends Command } $queued_inprogress_deployments = ApplicationDeploymentQueue::whereIn('status', [ApplicationDeploymentStatus::IN_PROGRESS->value, ApplicationDeploymentStatus::QUEUED->value])->get(); foreach ($queued_inprogress_deployments as $deployment) { - ray($deployment->id, $deployment->status); echo "Cleaning up deployment: {$deployment->id}\n"; $deployment->status = ApplicationDeploymentStatus::FAILED->value; $deployment->save(); diff --git a/app/Console/Commands/NotifyDemo.php b/app/Console/Commands/NotifyDemo.php index 81333b868..f0131b7b2 100644 --- a/app/Console/Commands/NotifyDemo.php +++ b/app/Console/Commands/NotifyDemo.php @@ -36,8 +36,6 @@ class NotifyDemo extends Command return; } - - ray($channel); } private function showHelp() diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 1e55aa57f..cd560eee3 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -12,6 +12,7 @@ use App\Jobs\DockerCleanupJob; use App\Jobs\PullTemplatesFromCDN; use App\Jobs\ScheduledTaskJob; use App\Jobs\ServerCheckJob; +use App\Jobs\ServerCleanupMux; use App\Jobs\UpdateCoolifyJob; use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledTask; @@ -120,6 +121,15 @@ class Kernel extends ConsoleKernel } else { $schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->timezone($serverTimezone)->onOneServer(); } + // Cleanup multiplexed connections every hour + $schedule->job(new ServerCleanupMux($server))->hourly()->onOneServer(); + + // Temporary solution until we have better memory management for Sentinel + if ($server->isSentinelEnabled()) { + $schedule->job(function () use ($server) { + $server->restartContainer('coolify-sentinel'); + })->daily()->onOneServer(); + } } } @@ -134,7 +144,6 @@ class Kernel extends ConsoleKernel continue; } if (is_null(data_get($scheduled_backup, 'database'))) { - ray('database not found'); $scheduled_backup->delete(); continue; @@ -170,7 +179,6 @@ class Kernel extends ConsoleKernel $application = $scheduled_task->application; if (! $application && ! $service) { - ray('application/service attached to scheduled task does not exist'); $scheduled_task->delete(); continue; diff --git a/app/Enums/Role.php b/app/Enums/Role.php new file mode 100644 index 000000000..a37a5076c --- /dev/null +++ b/app/Enums/Role.php @@ -0,0 +1,37 @@ + 1, + self::ADMIN => 2, + self::OWNER => 3, + }; + } + + public function lt(Role|string $role): bool + { + if (is_string($role)) { + $role = Role::from($role); + } + + return $this->rank() < $role->rank(); + } + + public function gt(Role|string $role): bool + { + if (is_string($role)) { + $role = Role::from($role); + } + + return $this->rank() > $role->rank(); + } +} diff --git a/app/Events/FileStorageChanged.php b/app/Events/FileStorageChanged.php index 27fdc6b5c..57004cf4c 100644 --- a/app/Events/FileStorageChanged.php +++ b/app/Events/FileStorageChanged.php @@ -16,7 +16,6 @@ class FileStorageChanged implements ShouldBroadcast public function __construct($teamId = null) { - ray($teamId); if (is_null($teamId)) { throw new \Exception('Team id is null'); } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 63fbfc862..8c89bb07f 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -84,7 +84,6 @@ class Handler extends ExceptionHandler if (str($e->getMessage())->contains('No space left on device')) { return; } - ray('reporting to sentry'); Integration::captureUnhandledException($e); }); } diff --git a/app/Http/Controllers/Api/DeployController.php b/app/Http/Controllers/Api/DeployController.php index d1c8f5ea6..666dc55a5 100644 --- a/app/Http/Controllers/Api/DeployController.php +++ b/app/Http/Controllers/Api/DeployController.php @@ -292,7 +292,7 @@ class DeployController extends Controller return ['message' => "Resource ($resource) not found.", 'deployment_uuid' => $deployment_uuid]; } switch ($resource?->getMorphClass()) { - case 'App\Models\Application': + case \App\Models\Application::class: $deployment_uuid = new Cuid2; queue_application_deployment( application: $resource, @@ -301,7 +301,7 @@ class DeployController extends Controller ); $message = "Application {$resource->name} deployment queued."; break; - case 'App\Models\Service': + case \App\Models\Service::class: StartService::run($resource); $message = "Service {$resource->name} started. It could take a while, be patient."; break; diff --git a/app/Http/Controllers/Api/ResourcesController.php b/app/Http/Controllers/Api/ResourcesController.php index 1fd5792e0..4180cef9a 100644 --- a/app/Http/Controllers/Api/ResourcesController.php +++ b/app/Http/Controllers/Api/ResourcesController.php @@ -53,7 +53,7 @@ class ResourcesController extends Controller $resources = $resources->flatten(); $resources = $resources->map(function ($resource) { $payload = $resource->toArray(); - if ($resource->getMorphClass() === 'App\Models\Service') { + if ($resource->getMorphClass() === \App\Models\Service::class) { $payload['status'] = $resource->status(); } else { $payload['status'] = $resource->status; diff --git a/app/Http/Controllers/Api/ServersController.php b/app/Http/Controllers/Api/ServersController.php index 540069f85..af4e008ef 100644 --- a/app/Http/Controllers/Api/ServersController.php +++ b/app/Http/Controllers/Api/ServersController.php @@ -249,7 +249,6 @@ class ServersController extends Controller return $payload; }); $server = $this->removeSensitiveData($server); - ray($server); return response()->json(serializeApiResponse(data_get($server, 'resources'))); } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 38d9e2272..581118e16 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -112,57 +112,48 @@ class Controller extends BaseController public function accept_invitation() { - try { - $resetPassword = request()->query('reset-password'); - $invitationUuid = request()->route('uuid'); - $invitation = TeamInvitation::whereUuid($invitationUuid)->firstOrFail(); - $user = User::whereEmail($invitation->email)->firstOrFail(); - $invitationValid = $invitation->isValid(); - if ($invitationValid) { - if ($resetPassword) { - $user->update([ - 'password' => Hash::make($invitationUuid), - 'force_password_reset' => true, - ]); - } - if ($user->teams()->where('team_id', $invitation->team->id)->exists()) { - $invitation->delete(); - - return redirect()->route('team.index'); - } - $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); + $resetPassword = request()->query('reset-password'); + $invitationUuid = request()->route('uuid'); + $invitation = TeamInvitation::whereUuid($invitationUuid)->firstOrFail(); + $user = User::whereEmail($invitation->email)->firstOrFail(); + $invitationValid = $invitation->isValid(); + if ($invitationValid) { + if ($resetPassword) { + $user->update([ + 'password' => Hash::make($invitationUuid), + 'force_password_reset' => true, + ]); + } + if ($user->teams()->where('team_id', $invitation->team->id)->exists()) { $invitation->delete(); - if (auth()->user()?->id !== $user->id) { - return redirect()->route('login'); - } - refreshSession($invitation->team); return redirect()->route('team.index'); - } else { - abort(401); } - } catch (\Throwable $e) { - ray($e->getMessage()); - throw $e; + $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); + $invitation->delete(); + if (auth()->user()?->id !== $user->id) { + return redirect()->route('login'); + } + refreshSession($invitation->team); + + return redirect()->route('team.index'); + } else { + abort(401); } } public function revoke_invitation() { - try { - $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); - $user = User::whereEmail($invitation->email)->firstOrFail(); - if (is_null(auth()->user())) { - return redirect()->route('login'); - } - if (auth()->user()->id !== $user->id) { - abort(401); - } - $invitation->delete(); - - return redirect()->route('team.index'); - } catch (\Throwable $e) { - throw $e; + $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); + $user = User::whereEmail($invitation->email)->firstOrFail(); + if (is_null(auth()->user())) { + return redirect()->route('login'); } + if (auth()->user()->id !== $user->id) { + abort(401); + } + $invitation->delete(); + + return redirect()->route('team.index'); } } diff --git a/app/Http/Controllers/OauthController.php b/app/Http/Controllers/OauthController.php index 630d01045..3a3f18c9c 100644 --- a/app/Http/Controllers/OauthController.php +++ b/app/Http/Controllers/OauthController.php @@ -35,8 +35,6 @@ class OauthController extends Controller return redirect('/'); } catch (\Exception $e) { - ray($e->getMessage()); - $errorCode = $e instanceof HttpException ? 'auth.failed' : 'auth.failed.callback'; return redirect()->route('login')->withErrors([__($errorCode)]); diff --git a/app/Http/Controllers/Webhook/Bitbucket.php b/app/Http/Controllers/Webhook/Bitbucket.php index ef85d59e3..8c74f95e5 100644 --- a/app/Http/Controllers/Webhook/Bitbucket.php +++ b/app/Http/Controllers/Webhook/Bitbucket.php @@ -16,7 +16,6 @@ class Bitbucket extends Controller { try { if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $data = [ 'attributes' => $request->attributes->all(), @@ -55,7 +54,6 @@ class Bitbucket extends Controller 'message' => 'Nothing to do. No branch found in the request.', ]); } - ray('Manual webhook bitbucket push event with branch: '.$branch); } if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') { $branch = data_get($payload, 'pullrequest.destination.branch.name'); @@ -85,7 +83,6 @@ class Bitbucket extends Controller 'status' => 'failed', 'message' => 'Invalid signature.', ]); - ray('Invalid signature'); continue; } @@ -96,13 +93,11 @@ class Bitbucket extends Controller 'status' => 'failed', 'message' => 'Server is not functional.', ]); - ray('Server is not functional: '.$application->destination->server->name); continue; } if ($x_bitbucket_event === 'repo:push') { if ($application->isDeployable()) { - ray('Deploying '.$application->name.' with branch '.$branch); $deployment_uuid = new Cuid2; queue_application_deployment( application: $application, @@ -126,7 +121,6 @@ class Bitbucket extends Controller } if ($x_bitbucket_event === 'pullrequest:created') { if ($application->isPRDeployable()) { - ray('Deploying preview for '.$application->name.' with branch '.$branch.' and base branch '.$base_branch.' and pull request id '.$pull_request_id); $deployment_uuid = new Cuid2; $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if (! $found) { @@ -171,7 +165,6 @@ class Bitbucket extends Controller } } if ($x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') { - ray('Pull request rejected'); $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); if ($found) { $found->delete(); @@ -191,12 +184,9 @@ class Bitbucket extends Controller } } } - ray($return_payloads); return response($return_payloads); } catch (Exception $e) { - ray($e); - return handleError($e); } } diff --git a/app/Http/Controllers/Webhook/Gitea.php b/app/Http/Controllers/Webhook/Gitea.php index e042b74c9..3689ca7b3 100644 --- a/app/Http/Controllers/Webhook/Gitea.php +++ b/app/Http/Controllers/Webhook/Gitea.php @@ -19,15 +19,12 @@ class Gitea extends Controller $return_payloads = collect([]); $x_gitea_delivery = request()->header('X-Gitea-Delivery'); if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $files = Storage::disk('webhooks-during-maintenance')->files(); $gitea_delivery_found = collect($files)->filter(function ($file) use ($x_gitea_delivery) { return Str::contains($file, $x_gitea_delivery); })->first(); if ($gitea_delivery_found) { - ray('Webhook already found'); - return; } $data = [ @@ -67,8 +64,6 @@ class Gitea extends Controller $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); - ray($changed_files); - ray('Manual Webhook Gitea Push Event with branch: '.$branch); } if ($x_gitea_event === 'pull_request') { $action = data_get($payload, 'action'); @@ -77,7 +72,6 @@ class Gitea extends Controller $pull_request_html_url = data_get($payload, 'pull_request.html_url'); $branch = data_get($payload, 'pull_request.head.ref'); $base_branch = data_get($payload, 'pull_request.base.ref'); - ray('Webhook Gitea Pull Request Event with branch: '.$branch.' and base branch: '.$base_branch.' and pull request id: '.$pull_request_id); } if (! $branch) { return response('Nothing to do. No branch found in the request.'); @@ -99,7 +93,6 @@ class Gitea extends Controller $webhook_secret = data_get($application, 'manual_webhook_secret_gitea'); $hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret); if (! hash_equals($x_hub_signature_256, $hmac) && ! isDev()) { - ray('Invalid signature'); $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', @@ -122,7 +115,6 @@ class Gitea extends Controller if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || is_null($application->watch_paths)) { - ray('Deploying '.$application->name.' with branch '.$branch); $deployment_uuid = new Cuid2; queue_application_deployment( application: $application, @@ -228,12 +220,9 @@ class Gitea extends Controller } } } - ray($return_payloads); return response($return_payloads); } catch (Exception $e) { - ray($e->getMessage()); - return handleError($e); } } diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php index 5f3ba933b..3683adaa8 100644 --- a/app/Http/Controllers/Webhook/Github.php +++ b/app/Http/Controllers/Webhook/Github.php @@ -25,15 +25,12 @@ class Github extends Controller $return_payloads = collect([]); $x_github_delivery = request()->header('X-GitHub-Delivery'); if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $files = Storage::disk('webhooks-during-maintenance')->files(); $github_delivery_found = collect($files)->filter(function ($file) use ($x_github_delivery) { return Str::contains($file, $x_github_delivery); })->first(); if ($github_delivery_found) { - ray('Webhook already found'); - return; } $data = [ @@ -73,7 +70,6 @@ class Github extends Controller $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); - ray('Manual Webhook GitHub Push Event with branch: '.$branch); } if ($x_github_event === 'pull_request') { $action = data_get($payload, 'action'); @@ -82,7 +78,6 @@ class Github extends Controller $pull_request_html_url = data_get($payload, 'pull_request.html_url'); $branch = data_get($payload, 'pull_request.head.ref'); $base_branch = data_get($payload, 'pull_request.base.ref'); - ray('Webhook GitHub Pull Request Event with branch: '.$branch.' and base branch: '.$base_branch.' and pull request id: '.$pull_request_id); } if (! $branch) { return response('Nothing to do. No branch found in the request.'); @@ -104,7 +99,6 @@ class Github extends Controller $webhook_secret = data_get($application, 'manual_webhook_secret_github'); $hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret); if (! hash_equals($x_hub_signature_256, $hmac) && ! isDev()) { - ray('Invalid signature'); $return_payloads->push([ 'application' => $application->name, 'status' => 'failed', @@ -127,7 +121,6 @@ class Github extends Controller if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || is_null($application->watch_paths)) { - ray('Deploying '.$application->name.' with branch '.$branch); $deployment_uuid = new Cuid2; queue_application_deployment( application: $application, @@ -232,12 +225,9 @@ class Github extends Controller } } } - ray($return_payloads); return response($return_payloads); } catch (Exception $e) { - ray($e->getMessage()); - return handleError($e); } } @@ -249,15 +239,12 @@ class Github extends Controller $id = null; $x_github_delivery = $request->header('X-GitHub-Delivery'); if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $files = Storage::disk('webhooks-during-maintenance')->files(); $github_delivery_found = collect($files)->filter(function ($file) use ($x_github_delivery) { return Str::contains($file, $x_github_delivery); })->first(); if ($github_delivery_found) { - ray('Webhook already found'); - return; } $data = [ @@ -313,7 +300,6 @@ class Github extends Controller $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); - ray('Webhook GitHub Push Event: '.$id.' with branch: '.$branch); } if ($x_github_event === 'pull_request') { $action = data_get($payload, 'action'); @@ -322,7 +308,6 @@ class Github extends Controller $pull_request_html_url = data_get($payload, 'pull_request.html_url'); $branch = data_get($payload, 'pull_request.head.ref'); $base_branch = data_get($payload, 'pull_request.base.ref'); - ray('Webhook GitHub Pull Request Event: '.$id.' with branch: '.$branch.' and base branch: '.$base_branch.' and pull request id: '.$pull_request_id); } if (! $id || ! $branch) { return response('Nothing to do. No id or branch found.'); @@ -356,7 +341,6 @@ class Github extends Controller if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || is_null($application->watch_paths)) { - ray('Deploying '.$application->name.' with branch '.$branch); $deployment_uuid = new Cuid2; queue_application_deployment( application: $application, @@ -460,8 +444,6 @@ class Github extends Controller return response($return_payloads); } catch (Exception $e) { - ray($e->getMessage()); - return handleError($e); } } @@ -505,7 +487,6 @@ class Github extends Controller try { $installation_id = $request->get('installation_id'); if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $data = [ 'attributes' => $request->attributes->all(), diff --git a/app/Http/Controllers/Webhook/Gitlab.php b/app/Http/Controllers/Webhook/Gitlab.php index ec7f51a0d..f56711bad 100644 --- a/app/Http/Controllers/Webhook/Gitlab.php +++ b/app/Http/Controllers/Webhook/Gitlab.php @@ -17,7 +17,6 @@ class Gitlab extends Controller { try { if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $data = [ 'attributes' => $request->attributes->all(), @@ -67,7 +66,6 @@ class Gitlab extends Controller $removed_files = data_get($payload, 'commits.*.removed'); $modified_files = data_get($payload, 'commits.*.modified'); $changed_files = collect($added_files)->concat($removed_files)->concat($modified_files)->unique()->flatten(); - ray('Manual Webhook GitLab Push Event with branch: '.$branch); } if ($x_gitlab_event === 'merge_request') { $action = data_get($payload, 'object_attributes.action'); @@ -84,7 +82,6 @@ class Gitlab extends Controller return response($return_payloads); } - ray('Webhook GitHub Pull Request Event with branch: '.$branch.' and base branch: '.$base_branch.' and pull request id: '.$pull_request_id); } $applications = Application::where('git_repository', 'like', "%$full_name%"); if ($x_gitlab_event === 'push') { @@ -117,7 +114,6 @@ class Gitlab extends Controller 'status' => 'failed', 'message' => 'Invalid signature.', ]); - ray('Invalid signature'); continue; } @@ -128,7 +124,6 @@ class Gitlab extends Controller 'status' => 'failed', 'message' => 'Server is not functional', ]); - ray('Server is not functional: '.$application->destination->server->name); continue; } @@ -136,7 +131,6 @@ class Gitlab extends Controller if ($application->isDeployable()) { $is_watch_path_triggered = $application->isWatchPathsTriggered($changed_files); if ($is_watch_path_triggered || is_null($application->watch_paths)) { - ray('Deploying '.$application->name.' with branch '.$branch); $deployment_uuid = new Cuid2; queue_application_deployment( application: $application, @@ -171,7 +165,6 @@ class Gitlab extends Controller 'application_uuid' => $application->uuid, 'application_name' => $application->name, ]); - ray('Deployments disabled for '.$application->name); } } if ($x_gitlab_event === 'merge_request') { @@ -207,7 +200,6 @@ class Gitlab extends Controller is_webhook: true, git_type: 'gitlab' ); - ray('Deploying preview for '.$application->name.' with branch '.$branch.' and base branch '.$base_branch.' and pull request id '.$pull_request_id); $return_payloads->push([ 'application' => $application->name, 'status' => 'success', @@ -219,7 +211,6 @@ class Gitlab extends Controller 'status' => 'failed', 'message' => 'Preview deployments disabled', ]); - ray('Preview deployments disabled for '.$application->name); } } elseif ($action === 'closed' || $action === 'close' || $action === 'merge') { $found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first(); @@ -253,8 +244,6 @@ class Gitlab extends Controller return response($return_payloads); } catch (Exception $e) { - ray($e->getMessage()); - return handleError($e); } } diff --git a/app/Http/Controllers/Webhook/Stripe.php b/app/Http/Controllers/Webhook/Stripe.php index 164322586..55c94a618 100644 --- a/app/Http/Controllers/Webhook/Stripe.php +++ b/app/Http/Controllers/Webhook/Stripe.php @@ -22,7 +22,6 @@ class Stripe extends Controller { try { if (app()->isDownForMaintenance()) { - ray('Maintenance mode is on'); $epoch = now()->valueOf(); $data = [ 'attributes' => $request->attributes->all(), diff --git a/app/Http/Controllers/Webhook/Waitlist.php b/app/Http/Controllers/Webhook/Waitlist.php index ea635836c..dec8ca72d 100644 --- a/app/Http/Controllers/Webhook/Waitlist.php +++ b/app/Http/Controllers/Webhook/Waitlist.php @@ -13,7 +13,6 @@ class Waitlist extends Controller { $email = request()->get('email'); $confirmation_code = request()->get('confirmation_code'); - ray($email, $confirmation_code); try { $found = ModelsWaitlist::where('uuid', $confirmation_code)->where('email', $email)->first(); if ($found) { @@ -36,7 +35,6 @@ class Waitlist extends Controller return redirect()->route('dashboard'); } catch (Exception $e) { send_internal_notification('Waitlist confirmation failed: '.$e->getMessage()); - ray($e->getMessage()); return redirect()->route('dashboard'); } @@ -58,7 +56,6 @@ class Waitlist extends Controller return redirect()->route('dashboard'); } catch (Exception $e) { send_internal_notification('Waitlist cancellation failed: '.$e->getMessage()); - ray($e->getMessage()); return redirect()->route('dashboard'); } diff --git a/app/Http/Middleware/ApiAllowed.php b/app/Http/Middleware/ApiAllowed.php index 471e6d602..dc6be5da3 100644 --- a/app/Http/Middleware/ApiAllowed.php +++ b/app/Http/Middleware/ApiAllowed.php @@ -10,7 +10,6 @@ class ApiAllowed { public function handle(Request $request, Closure $next): Response { - ray()->clearAll(); if (isCloud()) { return $next($request); } diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 9ae383a9f..c80b4a7db 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -208,7 +208,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $this->container_name = "{$this->application->settings->custom_internal_name}-pr-{$this->pull_request_id}"; } } - ray('New container name: ', $this->container_name)->green(); $this->saved_outputs = collect(); @@ -298,7 +297,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue if ($this->pull_request_id !== 0 && $this->application->is_github_based()) { ApplicationPullRequestUpdateJob::dispatch(application: $this->application, preview: $this->preview, deployment_uuid: $this->deployment_uuid, status: ProcessStatus::ERROR); } - ray($e); $this->fail($e); throw $e; } finally { @@ -389,7 +387,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue } else { $this->dockerImageTag = $this->application->docker_registry_image_tag; } - ray("echo 'Starting deployment of {$this->dockerImage}:{$this->dockerImageTag} to {$this->server->name}.'"); $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->dockerImage}:{$this->dockerImageTag} to {$this->server->name}."); $this->generate_image_names(); $this->prepare_builder_image(); @@ -712,38 +709,26 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue { $forceFail = true; if (str($this->application->docker_registry_image_name)->isEmpty()) { - ray('empty docker_registry_image_name'); - return; } if ($this->restart_only) { - ray('restart_only'); - return; } if ($this->application->build_pack === 'dockerimage') { - ray('dockerimage'); - return; } if ($this->use_build_server) { - ray('use_build_server'); $forceFail = true; } if ($this->server->isSwarm() && $this->build_pack !== 'dockerimage') { - ray('isSwarm'); $forceFail = true; } if ($this->application->additional_servers->count() > 0) { - ray('additional_servers'); $forceFail = true; } if ($this->is_this_additional_server) { - ray('this is an additional_servers, no pushy pushy'); - return; } - ray('push_to_docker_registry noww: '.$this->production_image_name); try { instant_remote_process(["docker images --format '{{json .}}' {$this->production_image_name}"], $this->server); $this->application_deployment_queue->addLogEntry('----------------------------------------'); @@ -775,7 +760,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue if ($forceFail) { throw new RuntimeException($e->getMessage(), 69420); } - ray($e); } } @@ -1386,8 +1370,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue return; } if ($destination_ids->contains($this->destination->id)) { - ray('Same destination found in additional destinations. Skipping.'); - return; } foreach ($destination_ids as $destination_id) { @@ -2449,7 +2431,6 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); if ($this->application->build_pack !== 'dockercompose') { $code = $exception->getCode(); - ray($code); if ($code !== 69420) { // 69420 means failed to push the image to the registry, so we don't need to remove the new version as it is the currently running one if ($this->application->settings->is_consistent_container_name_enabled || str($this->application->settings->custom_internal_name)->isNotEmpty()) { diff --git a/app/Jobs/ApplicationPullRequestUpdateJob.php b/app/Jobs/ApplicationPullRequestUpdateJob.php index 6120d1cba..2eefc4dd2 100755 --- a/app/Jobs/ApplicationPullRequestUpdateJob.php +++ b/app/Jobs/ApplicationPullRequestUpdateJob.php @@ -31,8 +31,6 @@ class ApplicationPullRequestUpdateJob implements ShouldBeEncrypted, ShouldQueue { try { if ($this->application->is_public_repository()) { - ray('Public repository. Skipping comment update.'); - return; } if ($this->status === ProcessStatus::CLOSED) { @@ -53,16 +51,12 @@ class ApplicationPullRequestUpdateJob implements ShouldBeEncrypted, ShouldQueue $this->body .= '[Open Build Logs]('.$this->build_logs_url.")\n\n\n"; $this->body .= 'Last updated at: '.now()->toDateTimeString().' CET'; - - ray('Updating comment', $this->body); if ($this->preview->pull_request_issue_comment_id) { $this->update_comment(); } else { $this->create_comment(); } } catch (\Throwable $e) { - ray($e); - return $e; } } @@ -73,7 +67,6 @@ class ApplicationPullRequestUpdateJob implements ShouldBeEncrypted, ShouldQueue 'body' => $this->body, ], throwError: false); if (data_get($data, 'message') === 'Not Found') { - ray('Comment not found. Creating new one.'); $this->create_comment(); } } diff --git a/app/Jobs/CheckAndStartSentinelJob.php b/app/Jobs/CheckAndStartSentinelJob.php index 8fbeee663..788db89ea 100644 --- a/app/Jobs/CheckAndStartSentinelJob.php +++ b/app/Jobs/CheckAndStartSentinelJob.php @@ -21,36 +21,32 @@ class CheckAndStartSentinelJob implements ShouldBeEncrypted, ShouldQueue public function handle(): void { - try { - $latestVersion = get_latest_sentinel_version(); + $latestVersion = get_latest_sentinel_version(); - // Check if sentinel is running - $sentinelFound = instant_remote_process(['docker inspect coolify-sentinel'], $this->server, false); - $sentinelFoundJson = json_decode($sentinelFound, true); - $sentinelStatus = data_get($sentinelFoundJson, '0.State.Status', 'exited'); - if ($sentinelStatus !== 'running') { + // Check if sentinel is running + $sentinelFound = instant_remote_process(['docker inspect coolify-sentinel'], $this->server, false); + $sentinelFoundJson = json_decode($sentinelFound, true); + $sentinelStatus = data_get($sentinelFoundJson, '0.State.Status', 'exited'); + if ($sentinelStatus !== 'running') { + StartSentinel::run(server: $this->server, restart: true, latestVersion: $latestVersion); + + return; + } + // If sentinel is running, check if it needs an update + $runningVersion = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false); + if (empty($runningVersion)) { + $runningVersion = '0.0.0'; + } + if ($latestVersion === '0.0.0' && $runningVersion === '0.0.0') { + StartSentinel::run(server: $this->server, restart: true, latestVersion: 'latest'); + + return; + } else { + if (version_compare($runningVersion, $latestVersion, '<')) { StartSentinel::run(server: $this->server, restart: true, latestVersion: $latestVersion); return; } - // If sentinel is running, check if it needs an update - $runningVersion = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false); - if (empty($runningVersion)) { - $runningVersion = '0.0.0'; - } - if ($latestVersion === '0.0.0' && $runningVersion === '0.0.0') { - StartSentinel::run(server: $this->server, restart: true, latestVersion: 'latest'); - - return; - } else { - if (version_compare($runningVersion, $latestVersion, '<')) { - StartSentinel::run(server: $this->server, restart: true, latestVersion: $latestVersion); - - return; - } - } - } catch (\Throwable $e) { - throw $e; } } } diff --git a/app/Jobs/CheckResaleLicenseJob.php b/app/Jobs/CheckResaleLicenseJob.php index b55ae9967..7479867b6 100644 --- a/app/Jobs/CheckResaleLicenseJob.php +++ b/app/Jobs/CheckResaleLicenseJob.php @@ -22,7 +22,6 @@ class CheckResaleLicenseJob implements ShouldBeEncrypted, ShouldQueue CheckResaleLicense::run(); } catch (\Throwable $e) { send_internal_notification('CheckResaleLicenseJob failed with: '.$e->getMessage()); - ray($e); throw $e; } } diff --git a/app/Jobs/CleanupHelperContainersJob.php b/app/Jobs/CleanupHelperContainersJob.php index b8ca8b7ed..f185ab781 100644 --- a/app/Jobs/CleanupHelperContainersJob.php +++ b/app/Jobs/CleanupHelperContainersJob.php @@ -20,18 +20,15 @@ class CleanupHelperContainersJob implements ShouldBeEncrypted, ShouldBeUnique, S public function handle(): void { try { - ray('Cleaning up helper containers on '.$this->server->name); $containers = instant_remote_process(['docker container ps --format \'{{json .}}\' | jq -s \'map(select(.Image | contains("ghcr.io/coollabsio/coolify-helper")))\''], $this->server, false); $containerIds = collect(json_decode($containers))->pluck('ID'); if ($containerIds->count() > 0) { foreach ($containerIds as $containerId) { - ray('Removing container '.$containerId); instant_remote_process(['docker container rm -f '.$containerId], $this->server, false); } } } catch (\Throwable $e) { send_internal_notification('CleanupHelperContainersJob failed with error: '.$e->getMessage()); - ray($e->getMessage()); } } } diff --git a/app/Jobs/CleanupInstanceStuffsJob.php b/app/Jobs/CleanupInstanceStuffsJob.php index d9de3f6fe..acbe82338 100644 --- a/app/Jobs/CleanupInstanceStuffsJob.php +++ b/app/Jobs/CleanupInstanceStuffsJob.php @@ -29,13 +29,11 @@ class CleanupInstanceStuffsJob implements ShouldBeEncrypted, ShouldBeUnique, Sho // $this->cleanup_waitlist(); } catch (\Throwable $e) { send_internal_notification('CleanupInstanceStuffsJob failed with error: '.$e->getMessage()); - ray($e->getMessage()); } try { $this->cleanup_invitation_link(); } catch (\Throwable $e) { send_internal_notification('CleanupInstanceStuffsJob failed with error: '.$e->getMessage()); - ray($e->getMessage()); } } diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 41f4daa4b..196af2a83 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -72,7 +72,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue return; } - if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') { + if (data_get($this->backup, 'database_type') === \App\Models\ServiceDatabase::class) { $this->database = data_get($this->backup, 'database'); $this->server = $this->database->service->server; $this->s3 = $this->backup->s3; @@ -92,11 +92,9 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue $status = str(data_get($this->database, 'status')); if (! $status->startsWith('running') && $this->database->id !== 0) { - ray('database not running'); - return; } - if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') { + if (data_get($this->backup, 'database_type') === \App\Models\ServiceDatabase::class) { $databaseType = $this->database->databaseType(); $serviceUuid = $this->database->service->uuid; $serviceName = str($this->database->service->name)->slug(); @@ -222,7 +220,6 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue // Format: db1:collection1,collection2|db2:collection3,collection4 $databasesToBackup = explode('|', $databasesToBackup); $databasesToBackup = array_map('trim', $databasesToBackup); - ray($databasesToBackup); } elseif (str($databaseType)->contains('mysql')) { // Format: db1,db2,db3 $databasesToBackup = explode(',', $databasesToBackup); @@ -244,7 +241,6 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue } foreach ($databasesToBackup as $database) { $size = 0; - ray('Backing up '.$database); try { if (str($databaseType)->contains('postgres')) { $this->backup_file = "/pg-dump-$database-".Carbon::now()->timestamp.'.dmp'; @@ -377,10 +373,8 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue if ($this->backup_output === '') { $this->backup_output = null; } - ray('Backup done for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location); } catch (\Throwable $e) { $this->add_to_backup_output($e->getMessage()); - ray('Backup failed for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location.'\n\nError:'.$e->getMessage()); throw $e; } } @@ -400,16 +394,13 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue } $commands[] = $backupCommand; - ray($commands); $this->backup_output = instant_remote_process($commands, $this->server); $this->backup_output = trim($this->backup_output); if ($this->backup_output === '') { $this->backup_output = null; } - ray('Backup done for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location); } catch (\Throwable $e) { $this->add_to_backup_output($e->getMessage()); - ray('Backup failed for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location.'\n\nError:'.$e->getMessage()); throw $e; } } @@ -428,10 +419,8 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue if ($this->backup_output === '') { $this->backup_output = null; } - ray('Backup done for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location); } catch (\Throwable $e) { $this->add_to_backup_output($e->getMessage()); - ray('Backup failed for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location.'\n\nError:'.$e->getMessage()); throw $e; } } @@ -445,16 +434,13 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue } else { $commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location"; } - ray($commands); $this->backup_output = instant_remote_process($commands, $this->server); $this->backup_output = trim($this->backup_output); if ($this->backup_output === '') { $this->backup_output = null; } - ray('Backup done for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location); } catch (\Throwable $e) { $this->add_to_backup_output($e->getMessage()); - ray('Backup failed for '.$this->container_name.' at '.$this->server->name.':'.$this->backup_location.'\n\nError:'.$e->getMessage()); throw $e; } } @@ -498,7 +484,7 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue $bucket = $this->s3->bucket; $endpoint = $this->s3->endpoint; $this->s3->testConnection(shouldSave: true); - if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') { + if (data_get($this->backup, 'database_type') === \App\Models\ServiceDatabase::class) { $network = $this->database->service->destination->network; } else { $network = $this->database->destination->network; diff --git a/app/Jobs/GithubAppPermissionJob.php b/app/Jobs/GithubAppPermissionJob.php index 9c0a2b55b..d483fe4c2 100644 --- a/app/Jobs/GithubAppPermissionJob.php +++ b/app/Jobs/GithubAppPermissionJob.php @@ -42,7 +42,6 @@ class GithubAppPermissionJob implements ShouldBeEncrypted, ShouldQueue $this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret'); } catch (\Throwable $e) { send_internal_notification('GithubAppPermissionJob failed with: '.$e->getMessage()); - ray($e->getMessage()); throw $e; } } diff --git a/app/Jobs/PullHelperImageJob.php b/app/Jobs/PullHelperImageJob.php index 0cc2be84d..a92e44c6b 100644 --- a/app/Jobs/PullHelperImageJob.php +++ b/app/Jobs/PullHelperImageJob.php @@ -20,12 +20,8 @@ class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue public function handle(): void { - try { - $helperImage = config('coolify.helper_image'); - $latest_version = instanceSettings()->helper_version; - instant_remote_process(["docker pull -q {$helperImage}:{$latest_version}"], $this->server, false); - } catch (\Throwable $e) { - throw $e; - } + $helperImage = config('coolify.helper_image'); + $latest_version = instanceSettings()->helper_version; + instant_remote_process(["docker pull -q {$helperImage}:{$latest_version}"], $this->server, false); } } diff --git a/app/Jobs/PullTemplatesFromCDN.php b/app/Jobs/PullTemplatesFromCDN.php index 72c971033..bde5e6c7a 100644 --- a/app/Jobs/PullTemplatesFromCDN.php +++ b/app/Jobs/PullTemplatesFromCDN.php @@ -25,7 +25,6 @@ class PullTemplatesFromCDN implements ShouldBeEncrypted, ShouldQueue if (isDev() || isCloud()) { return; } - ray('PullTemplatesAndVersions service-templates'); $response = Http::retry(3, 1000)->get(config('constants.services.official')); if ($response->successful()) { $services = $response->json(); @@ -35,7 +34,6 @@ class PullTemplatesFromCDN implements ShouldBeEncrypted, ShouldQueue } } catch (\Throwable $e) { send_internal_notification('PullTemplatesAndVersions failed with: '.$e->getMessage()); - ray($e->getMessage()); } } } diff --git a/app/Jobs/PullVersionsFromCDN.php b/app/Jobs/PullVersionsFromCDN.php deleted file mode 100644 index 79ebad7a8..000000000 --- a/app/Jobs/PullVersionsFromCDN.php +++ /dev/null @@ -1,39 +0,0 @@ -get('https://cdn.coollabs.io/coolify/versions.json'); - if ($response->successful()) { - $versions = $response->json(); - File::put(base_path('versions.json'), json_encode($versions, JSON_PRETTY_PRINT)); - } else { - send_internal_notification('PullTemplatesAndVersions failed with: '.$response->status().' '.$response->body()); - } - } - } catch (\Throwable $e) { - throw $e; - } - } -} diff --git a/app/Jobs/PushServerUpdateJob.php b/app/Jobs/PushServerUpdateJob.php index 62f059129..74ab8fa40 100644 --- a/app/Jobs/PushServerUpdateJob.php +++ b/app/Jobs/PushServerUpdateJob.php @@ -6,7 +6,7 @@ use App\Actions\Database\StartDatabaseProxy; use App\Actions\Database\StopDatabaseProxy; use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; -use App\Actions\Server\InstallLogDrain; +use App\Actions\Server\StartLogDrain; use App\Actions\Shared\ComplexStatusCheck; use App\Models\Application; use App\Models\ApplicationPreview; @@ -91,123 +91,113 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue public function handle() { // TODO: Swarm is not supported yet - try { - if (! $this->data) { - throw new \Exception('No data provided'); - } - $data = collect($this->data); + if (! $this->data) { + throw new \Exception('No data provided'); + } + $data = collect($this->data); - $this->server->sentinelHeartbeat(); + $this->server->sentinelHeartbeat(); - $this->containers = collect(data_get($data, 'containers')); + $this->containers = collect(data_get($data, 'containers')); - $filesystemUsageRoot = data_get($data, 'filesystem_usage_root.used_percentage'); - ServerStorageCheckJob::dispatch($this->server, $filesystemUsageRoot); + $filesystemUsageRoot = data_get($data, 'filesystem_usage_root.used_percentage'); + ServerStorageCheckJob::dispatch($this->server, $filesystemUsageRoot); - if ($this->containers->isEmpty()) { - return; - } - $this->applications = $this->server->applications(); - $this->databases = $this->server->databases(); - $this->previews = $this->server->previews(); - $this->services = $this->server->services()->get(); - $this->allApplicationIds = $this->applications->filter(function ($application) { - return $application->additional_servers->count() === 0; - })->pluck('id'); - $this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) { - return $application->additional_servers->count() > 0; + if ($this->containers->isEmpty()) { + return; + } + $this->applications = $this->server->applications(); + $this->databases = $this->server->databases(); + $this->previews = $this->server->previews(); + $this->services = $this->server->services()->get(); + $this->allApplicationIds = $this->applications->filter(function ($application) { + return $application->additional_servers->count() === 0; + })->pluck('id'); + $this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) { + return $application->additional_servers->count() > 0; + }); + $this->allApplicationPreviewsIds = $this->previews->pluck('id'); + $this->allDatabaseUuids = $this->databases->pluck('uuid'); + $this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid'); + $this->services->each(function ($service) { + $service->applications()->pluck('id')->each(function ($applicationId) { + $this->allServiceApplicationIds->push($applicationId); }); - $this->allApplicationPreviewsIds = $this->previews->pluck('id'); - $this->allDatabaseUuids = $this->databases->pluck('uuid'); - $this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid'); - $this->services->each(function ($service) { - $service->applications()->pluck('id')->each(function ($applicationId) { - $this->allServiceApplicationIds->push($applicationId); - }); - $service->databases()->pluck('id')->each(function ($databaseId) { - $this->allServiceDatabaseIds->push($databaseId); - }); + $service->databases()->pluck('id')->each(function ($databaseId) { + $this->allServiceDatabaseIds->push($databaseId); }); + }); - ray('allServiceApplicationIds', ['allServiceApplicationIds' => $this->allServiceApplicationIds]); - - foreach ($this->containers as $container) { - $containerStatus = data_get($container, 'state', 'exited'); - $containerHealth = data_get($container, 'health_status', 'unhealthy'); - $containerStatus = "$containerStatus ($containerHealth)"; - $labels = collect(data_get($container, 'labels')); - $coolify_managed = $labels->has('coolify.managed'); - if ($coolify_managed) { - $name = data_get($container, 'name'); - if ($name === 'coolify-log-drain' && $this->isRunning($containerStatus)) { - $this->foundLogDrainContainer = true; - } - if ($labels->has('coolify.applicationId')) { - $applicationId = $labels->get('coolify.applicationId'); - $pullRequestId = data_get($labels, 'coolify.pullRequestId', '0'); - try { - if ($pullRequestId === '0') { - if ($this->allApplicationIds->contains($applicationId) && $this->isRunning($containerStatus)) { - $this->foundApplicationIds->push($applicationId); - } - $this->updateApplicationStatus($applicationId, $containerStatus); - } else { - if ($this->allApplicationPreviewsIds->contains($applicationId) && $this->isRunning($containerStatus)) { - $this->foundApplicationPreviewsIds->push($applicationId); - } - $this->updateApplicationPreviewStatus($applicationId, $containerStatus); + foreach ($this->containers as $container) { + $containerStatus = data_get($container, 'state', 'exited'); + $containerHealth = data_get($container, 'health_status', 'unhealthy'); + $containerStatus = "$containerStatus ($containerHealth)"; + $labels = collect(data_get($container, 'labels')); + $coolify_managed = $labels->has('coolify.managed'); + if ($coolify_managed) { + $name = data_get($container, 'name'); + if ($name === 'coolify-log-drain' && $this->isRunning($containerStatus)) { + $this->foundLogDrainContainer = true; + } + if ($labels->has('coolify.applicationId')) { + $applicationId = $labels->get('coolify.applicationId'); + $pullRequestId = data_get($labels, 'coolify.pullRequestId', '0'); + try { + if ($pullRequestId === '0') { + if ($this->allApplicationIds->contains($applicationId) && $this->isRunning($containerStatus)) { + $this->foundApplicationIds->push($applicationId); } - } catch (\Exception $e) { - ray()->error($e); - } - } elseif ($labels->has('coolify.serviceId')) { - $serviceId = $labels->get('coolify.serviceId'); - $subType = $labels->get('coolify.service.subType'); - $subId = $labels->get('coolify.service.subId'); - if ($subType === 'application' && $this->isRunning($containerStatus)) { - $this->foundServiceApplicationIds->push($subId); - $this->updateServiceSubStatus($serviceId, $subType, $subId, $containerStatus); - } elseif ($subType === 'database' && $this->isRunning($containerStatus)) { - $this->foundServiceDatabaseIds->push($subId); - $this->updateServiceSubStatus($serviceId, $subType, $subId, $containerStatus); - } - - } else { - $uuid = $labels->get('com.docker.compose.service'); - $type = $labels->get('coolify.type'); - if ($name === 'coolify-proxy' && $this->isRunning($containerStatus)) { - $this->foundProxy = true; - } elseif ($type === 'service' && $this->isRunning($containerStatus)) { - ray("Service: $uuid, $containerStatus"); + $this->updateApplicationStatus($applicationId, $containerStatus); } else { - if ($this->allDatabaseUuids->contains($uuid) && $this->isRunning($containerStatus)) { - $this->foundDatabaseUuids->push($uuid); - if ($this->allTcpProxyUuids->contains($uuid) && $this->isRunning($containerStatus)) { - $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: true); - } else { - $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: false); - } + if ($this->allApplicationPreviewsIds->contains($applicationId) && $this->isRunning($containerStatus)) { + $this->foundApplicationPreviewsIds->push($applicationId); + } + $this->updateApplicationPreviewStatus($applicationId, $containerStatus); + } + } catch (\Exception $e) { + } + } elseif ($labels->has('coolify.serviceId')) { + $serviceId = $labels->get('coolify.serviceId'); + $subType = $labels->get('coolify.service.subType'); + $subId = $labels->get('coolify.service.subId'); + if ($subType === 'application' && $this->isRunning($containerStatus)) { + $this->foundServiceApplicationIds->push($subId); + $this->updateServiceSubStatus($serviceId, $subType, $subId, $containerStatus); + } elseif ($subType === 'database' && $this->isRunning($containerStatus)) { + $this->foundServiceDatabaseIds->push($subId); + $this->updateServiceSubStatus($serviceId, $subType, $subId, $containerStatus); + } + + } else { + $uuid = $labels->get('com.docker.compose.service'); + $type = $labels->get('coolify.type'); + if ($name === 'coolify-proxy' && $this->isRunning($containerStatus)) { + $this->foundProxy = true; + } elseif ($type === 'service' && $this->isRunning($containerStatus)) { + } else { + if ($this->allDatabaseUuids->contains($uuid) && $this->isRunning($containerStatus)) { + $this->foundDatabaseUuids->push($uuid); + if ($this->allTcpProxyUuids->contains($uuid) && $this->isRunning($containerStatus)) { + $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: true); + } else { + $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: false); } } } } } - - $this->updateProxyStatus(); - - $this->updateNotFoundApplicationStatus(); - $this->updateNotFoundApplicationPreviewStatus(); - $this->updateNotFoundDatabaseStatus(); - $this->updateNotFoundServiceStatus(); - - $this->updateAdditionalServersStatus(); - - $this->checkLogDrainContainer(); - - } catch (\Exception $e) { - throw $e; } + $this->updateProxyStatus(); + + $this->updateNotFoundApplicationStatus(); + $this->updateNotFoundApplicationPreviewStatus(); + $this->updateNotFoundDatabaseStatus(); + $this->updateNotFoundServiceStatus(); + + $this->updateAdditionalServersStatus(); + + $this->checkLogDrainContainer(); } private function updateApplicationStatus(string $applicationId, string $containerStatus) @@ -218,7 +208,6 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue } $application->status = $containerStatus; $application->save(); - ray('Application updated', ['application_id' => $applicationId, 'status' => $containerStatus]); } private function updateApplicationPreviewStatus(string $applicationId, string $containerStatus) @@ -229,21 +218,17 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue } $application->status = $containerStatus; $application->save(); - ray('Application preview updated', ['application_id' => $applicationId, 'status' => $containerStatus]); } private function updateNotFoundApplicationStatus() { $notFoundApplicationIds = $this->allApplicationIds->diff($this->foundApplicationIds); if ($notFoundApplicationIds->isNotEmpty()) { - ray('Not found application ids', ['application_ids' => $notFoundApplicationIds]); $notFoundApplicationIds->each(function ($applicationId) { - ray('Updating application status', ['application_id' => $applicationId, 'status' => 'exited']); $application = Application::find($applicationId); if ($application) { $application->status = 'exited'; $application->save(); - ray('Application status updated', ['application_id' => $applicationId, 'status' => 'exited']); } }); } @@ -253,14 +238,11 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue { $notFoundApplicationPreviewsIds = $this->allApplicationPreviewsIds->diff($this->foundApplicationPreviewsIds); if ($notFoundApplicationPreviewsIds->isNotEmpty()) { - ray('Not found application previews ids', ['application_previews_ids' => $notFoundApplicationPreviewsIds]); $notFoundApplicationPreviewsIds->each(function ($applicationPreviewId) { - ray('Updating application preview status', ['application_preview_id' => $applicationPreviewId, 'status' => 'exited']); $applicationPreview = ApplicationPreview::find($applicationPreviewId); if ($applicationPreview) { $applicationPreview->status = 'exited'; $applicationPreview->save(); - ray('Application preview status updated', ['application_preview_id' => $applicationPreviewId, 'status' => 'exited']); } }); } @@ -294,17 +276,14 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue } $database->status = $containerStatus; $database->save(); - ray('Database status updated', ['database_uuid' => $databaseUuid, 'status' => $containerStatus]); if ($this->isRunning($containerStatus) && $tcpProxy) { $tcpProxyContainerFound = $this->containers->filter(function ($value, $key) use ($databaseUuid) { return data_get($value, 'name') === "$databaseUuid-proxy" && data_get($value, 'state') === 'running'; })->first(); if (! $tcpProxyContainerFound) { - ray('Starting TCP proxy for database', ['database_uuid' => $databaseUuid]); StartDatabaseProxy::dispatch($database); $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$database->name}", $this->server)); } else { - ray('TCP proxy for database found in containers', ['database_uuid' => $databaseUuid]); } } } @@ -313,17 +292,12 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue { $notFoundDatabaseUuids = $this->allDatabaseUuids->diff($this->foundDatabaseUuids); if ($notFoundDatabaseUuids->isNotEmpty()) { - ray('Not found database uuids', ['database_uuids' => $notFoundDatabaseUuids]); $notFoundDatabaseUuids->each(function ($databaseUuid) { - ray('Updating database status', ['database_uuid' => $databaseUuid, 'status' => 'exited']); $database = $this->databases->where('uuid', $databaseUuid)->first(); if ($database) { $database->status = 'exited'; $database->save(); - ray('Database status updated', ['database_uuid' => $databaseUuid, 'status' => 'exited']); - ray('Database is public', ['database_uuid' => $databaseUuid, 'is_public' => $database->is_public]); if ($database->is_public) { - ray('Stopping TCP proxy for database', ['database_uuid' => $databaseUuid]); StopDatabaseProxy::dispatch($database); } } @@ -341,14 +315,11 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $application = $service->applications()->where('id', $subId)->first(); $application->status = $containerStatus; $application->save(); - ray('Service application updated', ['service_id' => $serviceId, 'sub_type' => $subType, 'sub_id' => $subId, 'status' => $containerStatus]); } elseif ($subType === 'database') { $database = $service->databases()->where('id', $subId)->first(); $database->status = $containerStatus; $database->save(); - ray('Service database updated', ['service_id' => $serviceId, 'sub_type' => $subType, 'sub_id' => $subId, 'status' => $containerStatus]); } else { - ray()->warning('Unknown sub type', ['service_id' => $serviceId, 'sub_type' => $subType, 'sub_id' => $subId, 'status' => $containerStatus]); } } @@ -357,26 +328,20 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue $notFoundServiceApplicationIds = $this->allServiceApplicationIds->diff($this->foundServiceApplicationIds); $notFoundServiceDatabaseIds = $this->allServiceDatabaseIds->diff($this->foundServiceDatabaseIds); if ($notFoundServiceApplicationIds->isNotEmpty()) { - ray('Not found service application ids', ['service_application_ids' => $notFoundServiceApplicationIds]); $notFoundServiceApplicationIds->each(function ($serviceApplicationId) { - ray('Updating service application status', ['service_application_id' => $serviceApplicationId, 'status' => 'exited']); $application = ServiceApplication::find($serviceApplicationId); if ($application) { $application->status = 'exited'; $application->save(); - ray('Service application status updated', ['service_application_id' => $serviceApplicationId, 'status' => 'exited']); } }); } if ($notFoundServiceDatabaseIds->isNotEmpty()) { - ray('Not found service database ids', ['service_database_ids' => $notFoundServiceDatabaseIds]); $notFoundServiceDatabaseIds->each(function ($serviceDatabaseId) { - ray('Updating service database status', ['service_database_id' => $serviceDatabaseId, 'status' => 'exited']); $database = ServiceDatabase::find($serviceDatabaseId); if ($database) { $database->status = 'exited'; $database->save(); - ray('Service database status updated', ['service_database_id' => $serviceDatabaseId, 'status' => 'exited']); } }); } @@ -385,7 +350,6 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue private function updateAdditionalServersStatus() { $this->allApplicationsWithAdditionalServers->each(function ($application) { - ray('Updating additional servers status for application', ['application_id' => $application->id]); ComplexStatusCheck::run($application); }); } @@ -398,7 +362,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue private function checkLogDrainContainer() { if ($this->server->isLogDrainEnabled() && $this->foundLogDrainContainer === false) { - InstallLogDrain::dispatch($this->server); + StartLogDrain::dispatch($this->server); } } } diff --git a/app/Jobs/SendConfirmationForWaitlistJob.php b/app/Jobs/SendConfirmationForWaitlistJob.php index 070598e71..7af8205fc 100755 --- a/app/Jobs/SendConfirmationForWaitlistJob.php +++ b/app/Jobs/SendConfirmationForWaitlistJob.php @@ -31,7 +31,6 @@ class SendConfirmationForWaitlistJob implements ShouldBeEncrypted, ShouldQueue send_user_an_email($mail, $this->email); } catch (\Throwable $e) { send_internal_notification("SendConfirmationForWaitlistJob failed for {$this->email} with error: ".$e->getMessage()); - ray($e->getMessage()); throw $e; } } diff --git a/app/Jobs/ServerCheckJob.php b/app/Jobs/ServerCheckJob.php index 5ac98e954..553796e87 100644 --- a/app/Jobs/ServerCheckJob.php +++ b/app/Jobs/ServerCheckJob.php @@ -5,7 +5,7 @@ namespace App\Jobs; use App\Actions\Docker\GetContainersStatus; use App\Actions\Proxy\CheckProxy; use App\Actions\Proxy\StartProxy; -use App\Actions\Server\InstallLogDrain; +use App\Actions\Server\StartLogDrain; use App\Models\Server; use App\Notifications\Container\ContainerRestarted; use Illuminate\Bus\Queueable; @@ -85,7 +85,6 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue $this->server->team?->notify(new ContainerRestarted('coolify-proxy', $this->server)); } } catch (\Throwable $e) { - ray($e); } } else { $this->server->proxy->status = data_get($foundProxyContainer, 'State.Status'); @@ -97,8 +96,6 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue } } catch (\Throwable $e) { - ray($e->getMessage()); - return handleError($e); } @@ -112,10 +109,10 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue if ($foundLogDrainContainer) { $status = data_get($foundLogDrainContainer, 'State.Status'); if ($status !== 'running') { - InstallLogDrain::dispatch($this->server); + StartLogDrain::dispatch($this->server); } } else { - InstallLogDrain::dispatch($this->server); + StartLogDrain::dispatch($this->server); } } } diff --git a/app/Jobs/ServerCleanupMux.php b/app/Jobs/ServerCleanupMux.php new file mode 100644 index 000000000..70ea59752 --- /dev/null +++ b/app/Jobs/ServerCleanupMux.php @@ -0,0 +1,42 @@ +server->serverStatus() === false) { + return 'Server is not reachable or not ready.'; + } + SshMultiplexingHelper::removeMuxFile($this->server); + + } catch (\Throwable $e) { + return handleError($e); + } + + } +} diff --git a/app/Jobs/ServerLimitCheckJob.php b/app/Jobs/ServerLimitCheckJob.php index 1f09d5a3b..084b6bf81 100644 --- a/app/Jobs/ServerLimitCheckJob.php +++ b/app/Jobs/ServerLimitCheckJob.php @@ -32,9 +32,7 @@ class ServerLimitCheckJob implements ShouldBeEncrypted, ShouldQueue $servers_count = $servers->count(); $limit = data_get($this->team->limits, 'serverLimit', 2); $number_of_servers_to_disable = $servers_count - $limit; - ray('ServerLimitCheckJob', $this->team->uuid, $servers_count, $limit, $number_of_servers_to_disable); if ($number_of_servers_to_disable > 0) { - ray('Disabling servers'); $servers = $servers->sortbyDesc('created_at'); $servers_to_disable = $servers->take($number_of_servers_to_disable); $servers_to_disable->each(function ($server) { @@ -51,7 +49,6 @@ class ServerLimitCheckJob implements ShouldBeEncrypted, ShouldQueue } } catch (\Throwable $e) { send_internal_notification('ServerLimitCheckJob failed with: '.$e->getMessage()); - ray($e->getMessage()); return handleError($e); } diff --git a/app/Jobs/ServerStorageCheckJob.php b/app/Jobs/ServerStorageCheckJob.php index c646f77eb..32737cc47 100644 --- a/app/Jobs/ServerStorageCheckJob.php +++ b/app/Jobs/ServerStorageCheckJob.php @@ -38,7 +38,6 @@ class ServerStorageCheckJob implements ShouldBeEncrypted, ShouldQueue if (is_null($this->percentage)) { $this->percentage = $this->server->storageCheck(); - loggy('Server storage check percentage: '.$this->percentage); } if (! $this->percentage) { return 'No percentage could be retrieved.'; diff --git a/app/Jobs/SubscriptionInvoiceFailedJob.php b/app/Jobs/SubscriptionInvoiceFailedJob.php index b4ef7baa0..aabeecef5 100755 --- a/app/Jobs/SubscriptionInvoiceFailedJob.php +++ b/app/Jobs/SubscriptionInvoiceFailedJob.php @@ -27,14 +27,12 @@ class SubscriptionInvoiceFailedJob implements ShouldBeEncrypted, ShouldQueue ]); $mail->subject('Your last payment was failed for Coolify Cloud.'); $this->team->members()->each(function ($member) use ($mail) { - ray($member); if ($member->isAdmin()) { send_user_an_email($mail, $member->email); } }); } catch (\Throwable $e) { send_internal_notification('SubscriptionInvoiceFailedJob failed with: '.$e->getMessage()); - ray($e->getMessage()); throw $e; } } diff --git a/app/Jobs/SubscriptionTrialEndedJob.php b/app/Jobs/SubscriptionTrialEndedJob.php index 8635b439c..88a5e06be 100755 --- a/app/Jobs/SubscriptionTrialEndedJob.php +++ b/app/Jobs/SubscriptionTrialEndedJob.php @@ -30,14 +30,12 @@ class SubscriptionTrialEndedJob implements ShouldBeEncrypted, ShouldQueue ]); $this->team->members()->each(function ($member) use ($mail) { if ($member->isAdmin()) { - ray('Sending trial ended email to '.$member->email); send_user_an_email($mail, $member->email); send_internal_notification('Trial reminder email sent to '.$member->email); } }); } catch (\Throwable $e) { send_internal_notification('SubscriptionTrialEndsSoonJob failed with: '.$e->getMessage()); - ray($e->getMessage()); throw $e; } } diff --git a/app/Jobs/SubscriptionTrialEndsSoonJob.php b/app/Jobs/SubscriptionTrialEndsSoonJob.php index 244624749..2a76a1097 100755 --- a/app/Jobs/SubscriptionTrialEndsSoonJob.php +++ b/app/Jobs/SubscriptionTrialEndsSoonJob.php @@ -30,14 +30,12 @@ class SubscriptionTrialEndsSoonJob implements ShouldBeEncrypted, ShouldQueue ]); $this->team->members()->each(function ($member) use ($mail) { if ($member->isAdmin()) { - ray('Sending trial ending email to '.$member->email); send_user_an_email($mail, $member->email); send_internal_notification('Trial reminder email sent to '.$member->email); } }); } catch (\Throwable $e) { send_internal_notification('SubscriptionTrialEndsSoonJob failed with: '.$e->getMessage()); - ray($e->getMessage()); throw $e; } } diff --git a/app/Listeners/MaintenanceModeDisabledNotification.php b/app/Listeners/MaintenanceModeDisabledNotification.php index c7cd1bcde..6c3ab83d8 100644 --- a/app/Listeners/MaintenanceModeDisabledNotification.php +++ b/app/Listeners/MaintenanceModeDisabledNotification.php @@ -13,7 +13,6 @@ class MaintenanceModeDisabledNotification public function handle(EventsMaintenanceModeDisabled $event): void { - ray('Maintenance mode disabled!'); $files = Storage::disk('webhooks-during-maintenance')->files(); $files = collect($files); $files = $files->sort(); @@ -41,7 +40,6 @@ class MaintenanceModeDisabledNotification $instance = new $class; $instance->$method($request); } catch (\Throwable $th) { - ray($th); } finally { Storage::disk('webhooks-during-maintenance')->delete($file); } diff --git a/app/Listeners/MaintenanceModeEnabledNotification.php b/app/Listeners/MaintenanceModeEnabledNotification.php index b2cd8c738..5aab248ea 100644 --- a/app/Listeners/MaintenanceModeEnabledNotification.php +++ b/app/Listeners/MaintenanceModeEnabledNotification.php @@ -17,8 +17,5 @@ class MaintenanceModeEnabledNotification /** * Handle the event. */ - public function handle(EventsMaintenanceModeEnabled $event): void - { - ray('Maintenance mode enabled!'); - } + public function handle(EventsMaintenanceModeEnabled $event): void {} } diff --git a/app/Livewire/Boarding/Index.php b/app/Livewire/Boarding/Index.php index 52d4674ee..c9c3092b3 100644 --- a/app/Livewire/Boarding/Index.php +++ b/app/Livewire/Boarding/Index.php @@ -73,8 +73,6 @@ class Index extends Component } $this->privateKeyName = generate_random_name(); $this->remoteServerName = generate_random_name(); - $this->remoteServerPort = $this->remoteServerPort; - $this->remoteServerUser = $this->remoteServerUser; if (isDev()) { $this->privateKey = '-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW @@ -87,26 +85,6 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== $this->remoteServerDescription = 'Created by Coolify'; $this->remoteServerHost = 'coolify-testing-host'; } - // if ($this->currentState === 'create-project') { - // $this->getProjects(); - // } - // if ($this->currentState === 'create-resource') { - // $this->selectExistingServer(); - // $this->selectExistingProject(); - // } - // if ($this->currentState === 'private-key') { - // $this->setServerType('remote'); - // } - // if ($this->currentState === 'create-server') { - // $this->selectExistingPrivateKey(); - // } - // if ($this->currentState === 'validate-server') { - // $this->selectExistingServer(); - // } - // if ($this->currentState === 'select-existing-server') { - // $this->selectExistingServer(); - // } - } public function explanation() diff --git a/app/Livewire/Destination/Form.php b/app/Livewire/Destination/Form.php index 87ae83931..a1a0a7b94 100644 --- a/app/Livewire/Destination/Form.php +++ b/app/Livewire/Destination/Form.php @@ -29,7 +29,7 @@ class Form extends Component public function delete() { try { - if ($this->destination->getMorphClass() === 'App\Models\StandaloneDocker') { + if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) { if ($this->destination->attachedTo()) { return $this->dispatch('error', 'You must delete all resources before deleting this destination.'); } diff --git a/app/Livewire/ForcePasswordReset.php b/app/Livewire/ForcePasswordReset.php index a732ef1c9..61a2a20e9 100644 --- a/app/Livewire/ForcePasswordReset.php +++ b/app/Livewire/ForcePasswordReset.php @@ -4,6 +4,7 @@ namespace App\Livewire; use DanHarrin\LivewireRateLimiting\WithRateLimiting; use Illuminate\Support\Facades\Hash; +use Illuminate\Validation\Rules\Password; use Livewire\Component; class ForcePasswordReset extends Component @@ -16,14 +17,19 @@ class ForcePasswordReset extends Component public string $password_confirmation; - protected $rules = [ - 'email' => 'required|email', - 'password' => 'required|min:8', - 'password_confirmation' => 'required|same:password', - ]; + public function rules(): array + { + return [ + 'email' => ['required', 'email'], + 'password' => ['required', Password::defaults(), 'confirmed'], + ]; + } public function mount() { + if (auth()->user()->force_password_reset === false) { + return redirect()->route('dashboard'); + } $this->email = auth()->user()->email; } @@ -34,6 +40,10 @@ class ForcePasswordReset extends Component public function submit() { + if (auth()->user()->force_password_reset === false) { + return redirect()->route('dashboard'); + } + try { $this->rateLimit(10); $this->validate(); diff --git a/app/Livewire/NewActivityMonitor.php b/app/Livewire/NewActivityMonitor.php index 10dbb9ce7..a9334e710 100644 --- a/app/Livewire/NewActivityMonitor.php +++ b/app/Livewire/NewActivityMonitor.php @@ -68,7 +68,6 @@ class NewActivityMonitor extends Component } else { $this->dispatch($this->eventToDispatch); } - ray('Dispatched event: '.$this->eventToDispatch.' with data: '.$this->eventData); } } } diff --git a/app/Livewire/Notifications/Discord.php b/app/Livewire/Notifications/Discord.php index 49666dabd..01ba8ffe1 100644 --- a/app/Livewire/Notifications/Discord.php +++ b/app/Livewire/Notifications/Discord.php @@ -35,7 +35,6 @@ class Discord extends Component try { $this->submit(); } catch (\Throwable $e) { - ray($e->getMessage()); $this->team->discord_enabled = false; $this->validate(); } diff --git a/app/Livewire/Notifications/Telegram.php b/app/Livewire/Notifications/Telegram.php index a035df71c..09a0f1c3c 100644 --- a/app/Livewire/Notifications/Telegram.php +++ b/app/Livewire/Notifications/Telegram.php @@ -42,7 +42,6 @@ class Telegram extends Component try { $this->submit(); } catch (\Throwable $e) { - ray($e->getMessage()); $this->team->telegram_enabled = false; $this->validate(); } diff --git a/app/Livewire/Profile/Index.php b/app/Livewire/Profile/Index.php index 3be1b05ce..483f68cf8 100644 --- a/app/Livewire/Profile/Index.php +++ b/app/Livewire/Profile/Index.php @@ -3,6 +3,7 @@ namespace App\Livewire\Profile; use Illuminate\Support\Facades\Hash; +use Illuminate\Validation\Rules\Password; use Livewire\Attributes\Validate; use Livewire\Component; @@ -48,9 +49,8 @@ class Index extends Component { try { $this->validate([ - 'current_password' => 'required', - 'new_password' => 'required|min:8', - 'new_password_confirmation' => 'required|min:8|same:new_password', + 'current_password' => ['required'], + 'new_password' => ['required', Password::defaults(), 'confirmed'], ]); if (! Hash::check($this->current_password, auth()->user()->password)) { $this->dispatch('error', 'Current password is incorrect.'); diff --git a/app/Livewire/Project/Application/DeploymentNavbar.php b/app/Livewire/Project/Application/DeploymentNavbar.php index 5fccce792..6a6fa2482 100644 --- a/app/Livewire/Project/Application/DeploymentNavbar.php +++ b/app/Livewire/Project/Application/DeploymentNavbar.php @@ -46,8 +46,6 @@ class DeploymentNavbar extends Component try { force_start_deployment($this->application_deployment_queue); } catch (\Throwable $e) { - ray($e); - return handleError($e, $this); } } @@ -81,8 +79,6 @@ class DeploymentNavbar extends Component } instant_remote_process([$kill_command], $server); } catch (\Throwable $e) { - ray($e); - return handleError($e, $this); } finally { $this->application_deployment_queue->update([ diff --git a/app/Livewire/Project/Database/Backup/Index.php b/app/Livewire/Project/Database/Backup/Index.php index d9a4b623d..9ff2f48d5 100644 --- a/app/Livewire/Project/Database/Backup/Index.php +++ b/app/Livewire/Project/Database/Backup/Index.php @@ -24,10 +24,10 @@ class Index extends Component } // No backups if ( - $database->getMorphClass() === 'App\Models\StandaloneRedis' || - $database->getMorphClass() === 'App\Models\StandaloneKeydb' || - $database->getMorphClass() === 'App\Models\StandaloneDragonfly' || - $database->getMorphClass() === 'App\Models\StandaloneClickhouse' + $database->getMorphClass() === \App\Models\StandaloneRedis::class || + $database->getMorphClass() === \App\Models\StandaloneKeydb::class || + $database->getMorphClass() === \App\Models\StandaloneDragonfly::class || + $database->getMorphClass() === \App\Models\StandaloneClickhouse::class ) { return redirect()->route('project.database.configuration', [ 'project_uuid' => $project->uuid, diff --git a/app/Livewire/Project/Database/BackupEdit.php b/app/Livewire/Project/Database/BackupEdit.php index 016218b78..8d838ed3b 100644 --- a/app/Livewire/Project/Database/BackupEdit.php +++ b/app/Livewire/Project/Database/BackupEdit.php @@ -77,7 +77,7 @@ class BackupEdit extends Component $this->backup->delete(); - if ($this->backup->database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($this->backup->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $previousUrl = url()->previous(); $url = Url::fromString($previousUrl); $url = $url->withoutQueryParameter('selectedBackupId'); @@ -138,7 +138,7 @@ class BackupEdit extends Component $backupFolder = null; foreach ($executions as $execution) { - if ($this->backup->database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($this->backup->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $server = $this->backup->database->service->destination->server; } else { $server = $this->backup->database->destination->server; diff --git a/app/Livewire/Project/Database/BackupExecutions.php b/app/Livewire/Project/Database/BackupExecutions.php index d7ac18097..45c7c30e2 100644 --- a/app/Livewire/Project/Database/BackupExecutions.php +++ b/app/Livewire/Project/Database/BackupExecutions.php @@ -57,7 +57,7 @@ class BackupExecutions extends Component return; } - if ($execution->scheduledDatabaseBackup->database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($execution->scheduledDatabaseBackup->database->getMorphClass() === \App\Models\ServiceDatabase::class) { delete_backup_locally($execution->filename, $execution->scheduledDatabaseBackup->database->service->destination->server); } else { delete_backup_locally($execution->filename, $execution->scheduledDatabaseBackup->database->destination->server); diff --git a/app/Livewire/Project/Database/CreateScheduledBackup.php b/app/Livewire/Project/Database/CreateScheduledBackup.php index 5ed74a6c3..52bced44f 100644 --- a/app/Livewire/Project/Database/CreateScheduledBackup.php +++ b/app/Livewire/Project/Database/CreateScheduledBackup.php @@ -66,7 +66,7 @@ class CreateScheduledBackup extends Component } $databaseBackup = ScheduledDatabaseBackup::create($payload); - if ($this->database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($this->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $this->dispatch('refreshScheduledBackups', $databaseBackup->id); } else { $this->dispatch('refreshScheduledBackups'); diff --git a/app/Livewire/Project/Database/Import.php b/app/Livewire/Project/Database/Import.php index dfaa4461b..cd9818b41 100644 --- a/app/Livewire/Project/Database/Import.php +++ b/app/Livewire/Project/Database/Import.php @@ -77,10 +77,10 @@ class Import extends Component } if ( - $this->resource->getMorphClass() == 'App\Models\StandaloneRedis' || - $this->resource->getMorphClass() == 'App\Models\StandaloneKeydb' || - $this->resource->getMorphClass() == 'App\Models\StandaloneDragonfly' || - $this->resource->getMorphClass() == 'App\Models\StandaloneClickhouse' + $this->resource->getMorphClass() == \App\Models\StandaloneRedis::class || + $this->resource->getMorphClass() == \App\Models\StandaloneKeydb::class || + $this->resource->getMorphClass() == \App\Models\StandaloneDragonfly::class || + $this->resource->getMorphClass() == \App\Models\StandaloneClickhouse::class ) { $this->unsupported = true; } @@ -108,19 +108,19 @@ class Import extends Component $this->importCommands[] = "docker cp {$tmpPath} {$this->container}:{$tmpPath}"; switch ($this->resource->getMorphClass()) { - case 'App\Models\StandaloneMariadb': + case \App\Models\StandaloneMariadb::class: $this->importCommands[] = "docker exec {$this->container} sh -c '{$this->mariadbRestoreCommand} < {$tmpPath}'"; $this->importCommands[] = "rm {$tmpPath}"; break; - case 'App\Models\StandaloneMysql': + case \App\Models\StandaloneMysql::class: $this->importCommands[] = "docker exec {$this->container} sh -c '{$this->mysqlRestoreCommand} < {$tmpPath}'"; $this->importCommands[] = "rm {$tmpPath}"; break; - case 'App\Models\StandalonePostgresql': + case \App\Models\StandalonePostgresql::class: $this->importCommands[] = "docker exec {$this->container} sh -c '{$this->postgresqlRestoreCommand} {$tmpPath}'"; $this->importCommands[] = "rm {$tmpPath}"; break; - case 'App\Models\StandaloneMongodb': + case \App\Models\StandaloneMongodb::class: $this->importCommands[] = "docker exec {$this->container} sh -c '{$this->mongodbRestoreCommand}{$tmpPath}'"; $this->importCommands[] = "rm {$tmpPath}"; break; diff --git a/app/Livewire/Project/Database/ScheduledBackups.php b/app/Livewire/Project/Database/ScheduledBackups.php index 8021e25d3..412240bd4 100644 --- a/app/Livewire/Project/Database/ScheduledBackups.php +++ b/app/Livewire/Project/Database/ScheduledBackups.php @@ -29,7 +29,7 @@ class ScheduledBackups extends Component $this->setSelectedBackup($this->selectedBackupId, true); } $this->parameters = get_route_parameters(); - if ($this->database->getMorphClass() === 'App\Models\ServiceDatabase') { + if ($this->database->getMorphClass() === \App\Models\ServiceDatabase::class) { $this->type = 'service-database'; } else { $this->type = 'database'; diff --git a/app/Livewire/Project/New/DockerImage.php b/app/Livewire/Project/New/DockerImage.php index d3f5b5261..417fb2ea0 100644 --- a/app/Livewire/Project/New/DockerImage.php +++ b/app/Livewire/Project/New/DockerImage.php @@ -46,7 +46,6 @@ class DockerImage extends Component $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first(); - ray($image, $tag); $application = Application::create([ 'name' => 'docker-image-'.new Cuid2, 'repository_project_id' => 0, diff --git a/app/Livewire/Project/New/GithubPrivateRepository.php b/app/Livewire/Project/New/GithubPrivateRepository.php index fbeb5601f..2f4f5a25c 100644 --- a/app/Livewire/Project/New/GithubPrivateRepository.php +++ b/app/Livewire/Project/New/GithubPrivateRepository.php @@ -153,7 +153,6 @@ class GithubPrivateRepository extends Component protected function loadBranchByPage() { - ray('Loading page '.$this->page); $response = Http::withToken($this->token)->get("{$this->github_app->api_url}/repos/{$this->selected_repository_owner}/{$this->selected_repository_repo}/branches?per_page=100&page={$this->page}"); $json = $response->json(); if ($response->status() !== 200) { diff --git a/app/Livewire/Project/New/PublicGitRepository.php b/app/Livewire/Project/New/PublicGitRepository.php index a6601a898..55eb5c77d 100644 --- a/app/Livewire/Project/New/PublicGitRepository.php +++ b/app/Livewire/Project/New/PublicGitRepository.php @@ -213,7 +213,7 @@ class PublicGitRepository extends Component return; } - if ($this->git_source->getMorphClass() === 'App\Models\GithubApp') { + if ($this->git_source->getMorphClass() === \App\Models\GithubApp::class) { ['rate_limit_remaining' => $this->rate_limit_remaining, 'rate_limit_reset' => $this->rate_limit_reset] = githubApi(source: $this->git_source, endpoint: "/repos/{$this->git_repository}/branches/{$this->git_branch}"); $this->rate_limit_reset = Carbon::parse((int) $this->rate_limit_reset)->format('Y-M-d H:i:s'); $this->branchFound = true; diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index 9804fb5ba..f95075de6 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -96,7 +96,6 @@ class Database extends Component updateCompose($this->database); $this->dispatch('success', 'Database saved.'); } catch (\Throwable $e) { - ray($e); } finally { $this->dispatch('generateDockerCompose'); } diff --git a/app/Livewire/Project/Service/Navbar.php b/app/Livewire/Project/Service/Navbar.php index 7db6d9834..2c5198387 100644 --- a/app/Livewire/Project/Service/Navbar.php +++ b/app/Livewire/Project/Service/Navbar.php @@ -27,7 +27,6 @@ class Navbar extends Component public function mount() { if (str($this->service->status())->contains('running') && is_null($this->service->config_hash)) { - ray('isConfigurationChanged init'); $this->service->isConfigurationChanged(true); $this->dispatch('configurationChanged'); } diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Livewire/Project/Shared/EnvironmentVariable/All.php index 5a711259b..787d33a69 100644 --- a/app/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -35,7 +35,7 @@ class All extends Component public function mount() { $this->resourceClass = get_class($this->resource); - $resourceWithPreviews = ['App\Models\Application']; + $resourceWithPreviews = [\App\Models\Application::class]; $simpleDockerfile = ! is_null(data_get($this->resource, 'dockerfile')); if (str($this->resourceClass)->contains($resourceWithPreviews) && ! $simpleDockerfile) { $this->showPreview = true; diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/Show.php b/app/Livewire/Project/Shared/EnvironmentVariable/Show.php index 53c4374df..e71cd9f42 100644 --- a/app/Livewire/Project/Shared/EnvironmentVariable/Show.php +++ b/app/Livewire/Project/Shared/EnvironmentVariable/Show.php @@ -58,7 +58,7 @@ class Show extends Component public function mount() { - if ($this->env->getMorphClass() === 'App\Models\SharedEnvironmentVariable') { + if ($this->env->getMorphClass() === \App\Models\SharedEnvironmentVariable::class) { $this->isSharedVariable = true; } $this->modalId = new Cuid2; @@ -80,7 +80,7 @@ class Show extends Component public function serialize() { data_forget($this->env, 'real_value'); - if ($this->env->getMorphClass() === 'App\Models\SharedEnvironmentVariable') { + if ($this->env->getMorphClass() === \App\Models\SharedEnvironmentVariable::class) { data_forget($this->env, 'is_build_time'); } } diff --git a/app/Livewire/Project/Shared/GetLogs.php b/app/Livewire/Project/Shared/GetLogs.php index f3d9da07d..43fd97c34 100644 --- a/app/Livewire/Project/Shared/GetLogs.php +++ b/app/Livewire/Project/Shared/GetLogs.php @@ -44,7 +44,7 @@ class GetLogs extends Component public function mount() { if (! is_null($this->resource)) { - if ($this->resource->getMorphClass() === 'App\Models\Application') { + if ($this->resource->getMorphClass() === \App\Models\Application::class) { $this->showTimeStamps = $this->resource->settings->is_include_timestamps; } else { if ($this->servicesubtype) { @@ -53,7 +53,7 @@ class GetLogs extends Component $this->showTimeStamps = $this->resource->is_include_timestamps; } } - if ($this->resource?->getMorphClass() === 'App\Models\Application') { + if ($this->resource?->getMorphClass() === \App\Models\Application::class) { if (str($this->container)->contains('-pr-')) { $this->pull_request = 'Pull Request: '.str($this->container)->afterLast('-pr-')->beforeLast('_')->value(); } @@ -69,11 +69,11 @@ class GetLogs extends Component public function instantSave() { if (! is_null($this->resource)) { - if ($this->resource->getMorphClass() === 'App\Models\Application') { + if ($this->resource->getMorphClass() === \App\Models\Application::class) { $this->resource->settings->is_include_timestamps = $this->showTimeStamps; $this->resource->settings->save(); } - if ($this->resource->getMorphClass() === 'App\Models\Service') { + if ($this->resource->getMorphClass() === \App\Models\Service::class) { $serviceName = str($this->container)->beforeLast('-')->value(); $subType = $this->resource->applications()->where('name', $serviceName)->first(); if ($subType) { @@ -95,7 +95,7 @@ class GetLogs extends Component if (! $this->server->isFunctional()) { return; } - if (! $refresh && ($this->resource?->getMorphClass() === 'App\Models\Service' || str($this->container)->contains('-pr-'))) { + if (! $refresh && ($this->resource?->getMorphClass() === \App\Models\Service::class || str($this->container)->contains('-pr-'))) { return; } if ($this->numberOfLines <= 0 || is_null($this->numberOfLines)) { diff --git a/app/Livewire/Project/Shared/Logs.php b/app/Livewire/Project/Shared/Logs.php index 5af0a6a50..e2b57aab3 100644 --- a/app/Livewire/Project/Shared/Logs.php +++ b/app/Livewire/Project/Shared/Logs.php @@ -109,7 +109,6 @@ class Logs extends Component $this->containers = $this->containers->filter(function ($container) { return str_contains($container, $this->query['pull_request_id']); }); - ray($this->containers); } diff --git a/app/Livewire/Project/Shared/ResourceOperations.php b/app/Livewire/Project/Shared/ResourceOperations.php index ec09eb80f..414ebba03 100644 --- a/app/Livewire/Project/Shared/ResourceOperations.php +++ b/app/Livewire/Project/Shared/ResourceOperations.php @@ -41,7 +41,7 @@ class ResourceOperations extends Component } $uuid = (string) new Cuid2; $server = $new_destination->server; - if ($this->resource->getMorphClass() === 'App\Models\Application') { + if ($this->resource->getMorphClass() === \App\Models\Application::class) { $new_resource = $this->resource->replicate()->fill([ 'uuid' => $uuid, 'name' => $this->resource->name.'-clone-'.$uuid, @@ -78,14 +78,14 @@ class ResourceOperations extends Component return redirect()->to($route); } elseif ( - $this->resource->getMorphClass() === 'App\Models\StandalonePostgresql' || - $this->resource->getMorphClass() === 'App\Models\StandaloneMongodb' || - $this->resource->getMorphClass() === 'App\Models\StandaloneMysql' || - $this->resource->getMorphClass() === 'App\Models\StandaloneMariadb' || - $this->resource->getMorphClass() === 'App\Models\StandaloneRedis' || - $this->resource->getMorphClass() === 'App\Models\StandaloneKeydb' || - $this->resource->getMorphClass() === 'App\Models\StandaloneDragonfly' || - $this->resource->getMorphClass() === 'App\Models\StandaloneClickhouse' + $this->resource->getMorphClass() === \App\Models\StandalonePostgresql::class || + $this->resource->getMorphClass() === \App\Models\StandaloneMongodb::class || + $this->resource->getMorphClass() === \App\Models\StandaloneMysql::class || + $this->resource->getMorphClass() === \App\Models\StandaloneMariadb::class || + $this->resource->getMorphClass() === \App\Models\StandaloneRedis::class || + $this->resource->getMorphClass() === \App\Models\StandaloneKeydb::class || + $this->resource->getMorphClass() === \App\Models\StandaloneDragonfly::class || + $this->resource->getMorphClass() === \App\Models\StandaloneClickhouse::class ) { $uuid = (string) new Cuid2; $new_resource = $this->resource->replicate()->fill([ diff --git a/app/Livewire/Project/Shared/Storages/Add.php b/app/Livewire/Project/Shared/Storages/Add.php index 27e0c6e44..afa27a6bd 100644 --- a/app/Livewire/Project/Shared/Storages/Add.php +++ b/app/Livewire/Project/Shared/Storages/Add.php @@ -83,7 +83,7 @@ class Add extends Component ]); $this->file_storage_path = trim($this->file_storage_path); $this->file_storage_path = str($this->file_storage_path)->start('/')->value(); - if ($this->resource->getMorphClass() === 'App\Models\Application') { + if ($this->resource->getMorphClass() === \App\Models\Application::class) { $fs_path = application_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path; } LocalFileVolume::create( diff --git a/app/Livewire/Server/Advanced.php b/app/Livewire/Server/Advanced.php index 4d2d777d4..87b42cf3c 100644 --- a/app/Livewire/Server/Advanced.php +++ b/app/Livewire/Server/Advanced.php @@ -4,45 +4,82 @@ namespace App\Livewire\Server; use App\Jobs\DockerCleanupJob; use App\Models\Server; +use Livewire\Attributes\Rule; use Livewire\Component; class Advanced extends Component { public Server $server; - protected $rules = [ - 'server.settings.concurrent_builds' => 'required|integer|min:1', - 'server.settings.dynamic_timeout' => 'required|integer|min:1', - 'server.settings.force_docker_cleanup' => 'required|boolean', - 'server.settings.docker_cleanup_frequency' => 'required_if:server.settings.force_docker_cleanup,true|string', - 'server.settings.docker_cleanup_threshold' => 'required_if:server.settings.force_docker_cleanup,false|integer|min:1|max:100', - 'server.settings.server_disk_usage_notification_threshold' => 'required|integer|min:50|max:100', - 'server.settings.delete_unused_volumes' => 'boolean', - 'server.settings.delete_unused_networks' => 'boolean', - ]; + public array $parameters = []; - protected $validationAttributes = [ + #[Rule(['integer', 'min:1'])] + public int $concurrentBuilds = 1; - 'server.settings.concurrent_builds' => 'Concurrent Builds', - 'server.settings.dynamic_timeout' => 'Dynamic Timeout', - 'server.settings.force_docker_cleanup' => 'Force Docker Cleanup', - 'server.settings.docker_cleanup_frequency' => 'Docker Cleanup Frequency', - 'server.settings.docker_cleanup_threshold' => 'Docker Cleanup Threshold', - 'server.settings.server_disk_usage_notification_threshold' => 'Server Disk Usage Notification Threshold', - 'server.settings.delete_unused_volumes' => 'Delete Unused Volumes', - 'server.settings.delete_unused_networks' => 'Delete Unused Networks', - ]; + #[Rule(['integer', 'min:1'])] + public int $dynamicTimeout = 1; + + #[Rule('boolean')] + public bool $forceDockerCleanup = false; + + #[Rule('string')] + public string $dockerCleanupFrequency = '*/10 * * * *'; + + #[Rule(['integer', 'min:1', 'max:99'])] + public int $dockerCleanupThreshold = 10; + + #[Rule(['integer', 'min:1', 'max:99'])] + public int $serverDiskUsageNotificationThreshold = 50; + + #[Rule('boolean')] + public bool $deleteUnusedVolumes = false; + + #[Rule('boolean')] + public bool $deleteUnusedNetworks = false; + + public function mount(string $server_uuid) + { + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->parameters = get_route_parameters(); + $this->syncData(); + } catch (\Throwable $e) { + return redirect()->route('server.show'); + } + } + + public function syncData(bool $toModel = false) + { + if ($toModel) { + $this->validate(); + $this->server->settings->concurrent_builds = $this->concurrentBuilds; + $this->server->settings->dynamic_timeout = $this->dynamicTimeout; + $this->server->settings->force_docker_cleanup = $this->forceDockerCleanup; + $this->server->settings->docker_cleanup_frequency = $this->dockerCleanupFrequency; + $this->server->settings->docker_cleanup_threshold = $this->dockerCleanupThreshold; + $this->server->settings->server_disk_usage_notification_threshold = $this->serverDiskUsageNotificationThreshold; + $this->server->settings->delete_unused_volumes = $this->deleteUnusedVolumes; + $this->server->settings->delete_unused_networks = $this->deleteUnusedNetworks; + $this->server->settings->save(); + } else { + $this->concurrentBuilds = $this->server->settings->concurrent_builds; + $this->dynamicTimeout = $this->server->settings->dynamic_timeout; + $this->forceDockerCleanup = $this->server->settings->force_docker_cleanup; + $this->dockerCleanupFrequency = $this->server->settings->docker_cleanup_frequency; + $this->dockerCleanupThreshold = $this->server->settings->docker_cleanup_threshold; + $this->serverDiskUsageNotificationThreshold = $this->server->settings->server_disk_usage_notification_threshold; + $this->deleteUnusedVolumes = $this->server->settings->delete_unused_volumes; + $this->deleteUnusedNetworks = $this->server->settings->delete_unused_networks; + } + } public function instantSave() { try { - $this->validate(); - $this->server->settings->save(); + $this->syncData(true); $this->dispatch('success', 'Server updated.'); - $this->dispatch('refreshServerShow'); + // $this->dispatch('refreshServerShow'); } catch (\Throwable $e) { - $this->server->settings->refresh(); - return handleError($e, $this); } } @@ -60,12 +97,11 @@ class Advanced extends Component public function submit() { try { - $frequency = $this->server->settings->docker_cleanup_frequency; - if (empty($frequency) || ! validate_cron_expression($frequency)) { - $this->server->settings->docker_cleanup_frequency = '*/10 * * * *'; - throw new \Exception('Invalid Cron / Human expression for Docker Cleanup Frequency. Resetting to default 10 minutes.'); + if (! validate_cron_expression($this->dockerCleanupFrequency)) { + $this->dockerCleanupFrequency = $this->server->settings->getOriginal('docker_cleanup_frequency'); + throw new \Exception('Invalid Cron / Human expression for Docker Cleanup Frequency.'); } - $this->server->settings->save(); + $this->syncData(true); $this->dispatch('success', 'Server updated.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Server/Charts.php b/app/Livewire/Server/Charts.php index 20f8dd9ed..d879de65d 100644 --- a/app/Livewire/Server/Charts.php +++ b/app/Livewire/Server/Charts.php @@ -19,6 +19,15 @@ class Charts extends Component public bool $poll = true; + public function mount(string $server_uuid) + { + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function pollData() { if ($this->poll || $this->interval <= 10) { diff --git a/app/Livewire/Server/CloudflareTunnels.php b/app/Livewire/Server/CloudflareTunnels.php index 82bc789db..f16962bca 100644 --- a/app/Livewire/Server/CloudflareTunnels.php +++ b/app/Livewire/Server/CloudflareTunnels.php @@ -3,27 +3,33 @@ namespace App\Livewire\Server; use App\Models\Server; +use Livewire\Attributes\Rule; use Livewire\Component; class CloudflareTunnels extends Component { public Server $server; - protected $rules = [ - 'server.settings.is_cloudflare_tunnel' => 'required|boolean', - ]; + #[Rule(['required', 'boolean'])] + public bool $isCloudflareTunnelsEnabled; - protected $validationAttributes = [ - 'server.settings.is_cloudflare_tunnel' => 'Cloudflare Tunnel', - ]; + public function mount(string $server_uuid) + { + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel; + } catch (\Throwable $e) { + return handleError($e, $this); + } + } public function instantSave() { try { $this->validate(); + $this->server->settings->is_cloudflare_tunnel = $this->isCloudflareTunnelsEnabled; $this->server->settings->save(); $this->dispatch('success', 'Server updated.'); - $this->dispatch('refreshServerShow'); } catch (\Throwable $e) { return handleError($e, $this); } @@ -31,6 +37,7 @@ class CloudflareTunnels extends Component public function manualCloudflareConfig() { + $this->isCloudflareTunnelsEnabled = true; $this->server->settings->is_cloudflare_tunnel = true; $this->server->settings->save(); $this->server->refresh(); diff --git a/app/Livewire/Server/Delete.php b/app/Livewire/Server/Delete.php index cc2b335e1..b9e3944b5 100644 --- a/app/Livewire/Server/Delete.php +++ b/app/Livewire/Server/Delete.php @@ -4,6 +4,7 @@ namespace App\Livewire\Server; use App\Actions\Server\DeleteServer; use App\Models\InstanceSettings; +use App\Models\Server; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; @@ -13,7 +14,16 @@ class Delete extends Component { use AuthorizesRequests; - public $server; + public Server $server; + + public function mount(string $server_uuid) + { + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } public function delete($password) { diff --git a/app/Livewire/Server/Destination/Show.php b/app/Livewire/Server/Destination/Show.php index 986e16cbf..71c051a74 100644 --- a/app/Livewire/Server/Destination/Show.php +++ b/app/Livewire/Server/Destination/Show.php @@ -3,27 +3,87 @@ namespace App\Livewire\Server\Destination; use App\Models\Server; +use App\Models\StandaloneDocker; +use App\Models\SwarmDocker; +use Illuminate\Support\Collection; use Livewire\Component; class Show extends Component { - public ?Server $server = null; + public Server $server; - public $parameters = []; + public Collection $networks; - public function mount() + public function mount(string $server_uuid) { - $this->parameters = get_route_parameters(); try { - $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); - if (is_null($this->server)) { - return redirect()->route('server.index'); - } + $this->networks = collect(); + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + loggy($this->server); } catch (\Throwable $e) { return handleError($e, $this); } } + private function createNetworkAndAttachToProxy() + { + $connectProxyToDockerNetworks = connectProxyToNetworks($this->server); + instant_remote_process($connectProxyToDockerNetworks, $this->server, false); + } + + public function add($name) + { + if ($this->server->isSwarm()) { + $found = $this->server->swarmDockers()->where('network', $name)->first(); + if ($found) { + $this->dispatch('error', 'Network already added to this server.'); + + return; + } else { + SwarmDocker::create([ + 'name' => $this->server->name.'-'.$name, + 'network' => $this->name, + 'server_id' => $this->server->id, + ]); + } + } else { + $found = $this->server->standaloneDockers()->where('network', $name)->first(); + if ($found) { + $this->dispatch('error', 'Network already added to this server.'); + + return; + } else { + StandaloneDocker::create([ + 'name' => $this->server->name.'-'.$name, + 'network' => $name, + 'server_id' => $this->server->id, + ]); + } + $this->createNetworkAndAttachToProxy(); + } + } + + public function scan() + { + if ($this->server->isSwarm()) { + $alreadyAddedNetworks = $this->server->swarmDockers; + } else { + $alreadyAddedNetworks = $this->server->standaloneDockers; + } + $networks = instant_remote_process(['docker network ls --format "{{json .}}"'], $this->server, false); + $this->networks = format_docker_command_output_to_json($networks)->filter(function ($network) { + return $network['Name'] !== 'bridge' && $network['Name'] !== 'host' && $network['Name'] !== 'none'; + })->filter(function ($network) use ($alreadyAddedNetworks) { + return ! $alreadyAddedNetworks->contains('network', $network['Name']); + }); + if ($this->networks->count() === 0) { + $this->dispatch('success', 'No new destinations found on this server.'); + + return; + } + $this->dispatch('success', 'Scan done.'); + } + public function render() { return view('livewire.server.destination.show'); diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 82d9f5d8e..697c7b76f 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -56,6 +56,7 @@ class Form extends Component 'server.settings.sentinel_push_interval_seconds' => 'required|integer|min:10', 'server.settings.sentinel_custom_url' => 'nullable|url', 'server.settings.is_sentinel_enabled' => 'required|boolean', + 'server.settings.is_sentinel_debug_enabled' => 'required|boolean', 'server.settings.server_timezone' => 'required|string|timezone', ]; @@ -75,6 +76,7 @@ class Form extends Component 'server.settings.sentinel_metrics_history_days' => 'Metrics History', 'server.settings.sentinel_push_interval_seconds' => 'Push Interval', 'server.settings.is_sentinel_enabled' => 'Server API', + 'server.settings.is_sentinel_debug_enabled' => 'Debug', 'server.settings.sentinel_custom_url' => 'Coolify URL', 'server.settings.server_timezone' => 'Server Timezone', ]; @@ -84,6 +86,7 @@ class Form extends Component $this->server = $server; $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); $this->wildcard_domain = $this->server->settings->wildcard_domain; + } public function checkSyncStatus() @@ -108,7 +111,7 @@ class Form extends Component { if ($field === 'server.settings.docker_cleanup_frequency') { $frequency = $this->server->settings->docker_cleanup_frequency; - if (empty($frequency) || ! validate_cron_expression($frequency)) { + if (! validate_cron_expression($frequency)) { $this->dispatch('error', 'Invalid Cron / Human expression for Docker Cleanup Frequency. Resetting to default 10 minutes.'); $this->server->settings->docker_cleanup_frequency = '*/10 * * * *'; } @@ -158,6 +161,11 @@ class Form extends Component $this->restartSentinel(); } + public function updatedServerSettingsIsSentinelDebugEnabled() + { + $this->restartSentinel(); + } + public function instantSave() { try { diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index 6e09eecdd..2bc24eff8 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -2,84 +2,96 @@ namespace App\Livewire\Server; -use App\Actions\Server\InstallLogDrain; +use App\Actions\Server\StartLogDrain; use App\Actions\Server\StopLogDrain; use App\Models\Server; +use Livewire\Attributes\Rule; use Livewire\Component; class LogDrains extends Component { public Server $server; - public $parameters = []; + #[Rule(['boolean'])] + public bool $isLogDrainNewRelicEnabled = false; - protected $rules = [ - 'server.settings.is_logdrain_newrelic_enabled' => 'required|boolean', - 'server.settings.logdrain_newrelic_license_key' => 'required|string', - 'server.settings.logdrain_newrelic_base_uri' => 'required|string', - 'server.settings.is_logdrain_highlight_enabled' => 'required|boolean', - 'server.settings.logdrain_highlight_project_id' => 'required|string', - 'server.settings.is_logdrain_axiom_enabled' => 'required|boolean', - 'server.settings.logdrain_axiom_dataset_name' => 'required|string', - 'server.settings.logdrain_axiom_api_key' => 'required|string', - 'server.settings.is_logdrain_custom_enabled' => 'required|boolean', - 'server.settings.logdrain_custom_config' => 'required|string', - 'server.settings.logdrain_custom_config_parser' => 'nullable', - ]; + #[Rule(['boolean'])] + public bool $isLogDrainCustomEnabled = false; - protected $validationAttributes = [ - 'server.settings.is_logdrain_newrelic_enabled' => 'New Relic log drain', - 'server.settings.logdrain_newrelic_license_key' => 'New Relic license key', - 'server.settings.logdrain_newrelic_base_uri' => 'New Relic base URI', - 'server.settings.is_logdrain_highlight_enabled' => 'Highlight log drain', - 'server.settings.logdrain_highlight_project_id' => 'Highlight project ID', - 'server.settings.is_logdrain_axiom_enabled' => 'Axiom log drain', - 'server.settings.logdrain_axiom_dataset_name' => 'Axiom dataset name', - 'server.settings.logdrain_axiom_api_key' => 'Axiom API key', - 'server.settings.is_logdrain_custom_enabled' => 'Custom log drain', - 'server.settings.logdrain_custom_config' => 'Custom log drain configuration', - 'server.settings.logdrain_custom_config_parser' => 'Custom log drain configuration parser', - ]; + #[Rule(['boolean'])] + public bool $isLogDrainAxiomEnabled = false; - public function mount() + #[Rule(['string', 'nullable'])] + public ?string $logDrainNewRelicLicenseKey = null; + + #[Rule(['url', 'nullable'])] + public ?string $logDrainNewRelicBaseUri = null; + + #[Rule(['string', 'nullable'])] + public ?string $logDrainAxiomDatasetName = null; + + #[Rule(['string', 'nullable'])] + public ?string $logDrainAxiomApiKey = null; + + #[Rule(['string', 'nullable'])] + public ?string $logDrainCustomConfig = null; + + #[Rule(['string', 'nullable'])] + public ?string $logDrainCustomConfigParser = null; + + public function mount(string $server_uuid) { - $this->parameters = get_route_parameters(); try { - $server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); - if (is_null($server)) { - return redirect()->route('server.index'); - } - $this->server = $server; + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } - public function configureLogDrain() + public function syncData(bool $toModel = false) + { + + if ($toModel) { + $this->validate(); + $this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled; + $this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled; + $this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled; + + $this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey; + $this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri; + $this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName; + $this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey; + $this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig; + $this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser; + + $this->server->settings->save(); + } else { + $this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled; + $this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled; + $this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled; + + $this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key; + $this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri; + $this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name; + $this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key; + $this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config; + $this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser; + } + + } + + public function instantSave() { try { - InstallLogDrain::run($this->server); - if (! $this->server->isLogDrainEnabled()) { - $this->dispatch('serverRefresh'); + $this->syncData(true); + if ($this->server->isLogDrainEnabled()) { + StartLogDrain::run($this->server); + $this->dispatch('success', 'Log drain service started.'); + } else { + StopLogDrain::run($this->server); $this->dispatch('success', 'Log drain service stopped.'); - - return; } - $this->dispatch('serverRefresh'); - $this->dispatch('success', 'Log drain service started.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function instantSave(string $type) - { - try { - $ok = $this->submit($type); - if (! $ok) { - return; - } - $this->configureLogDrain(); } catch (\Throwable $e) { return handleError($e, $this); } @@ -88,79 +100,10 @@ class LogDrains extends Component public function submit(string $type) { try { - $this->resetErrorBag(); - if ($type === 'newrelic') { - $this->validate([ - 'server.settings.is_logdrain_newrelic_enabled' => 'required|boolean', - 'server.settings.logdrain_newrelic_license_key' => 'required|string', - 'server.settings.logdrain_newrelic_base_uri' => 'required|string', - ]); - $this->server->settings->update([ - 'is_logdrain_highlight_enabled' => false, - 'is_logdrain_axiom_enabled' => false, - 'is_logdrain_custom_enabled' => false, - ]); - } elseif ($type === 'highlight') { - $this->validate([ - 'server.settings.is_logdrain_highlight_enabled' => 'required|boolean', - 'server.settings.logdrain_highlight_project_id' => 'required|string', - ]); - $this->server->settings->update([ - 'is_logdrain_newrelic_enabled' => false, - 'is_logdrain_axiom_enabled' => false, - 'is_logdrain_custom_enabled' => false, - ]); - } elseif ($type === 'axiom') { - $this->validate([ - 'server.settings.is_logdrain_axiom_enabled' => 'required|boolean', - 'server.settings.logdrain_axiom_dataset_name' => 'required|string', - 'server.settings.logdrain_axiom_api_key' => 'required|string', - ]); - $this->server->settings->update([ - 'is_logdrain_newrelic_enabled' => false, - 'is_logdrain_highlight_enabled' => false, - 'is_logdrain_custom_enabled' => false, - ]); - } elseif ($type === 'custom') { - $this->validate([ - 'server.settings.is_logdrain_custom_enabled' => 'required|boolean', - 'server.settings.logdrain_custom_config' => 'required|string', - 'server.settings.logdrain_custom_config_parser' => 'nullable', - ]); - $this->server->settings->update([ - 'is_logdrain_newrelic_enabled' => false, - 'is_logdrain_highlight_enabled' => false, - 'is_logdrain_axiom_enabled' => false, - ]); - } - if (! $this->server->isLogDrainEnabled()) { - StopLogDrain::dispatch($this->server); - } - $this->server->settings->save(); + $this->syncData(true); $this->dispatch('success', 'Settings saved.'); - - return true; } catch (\Throwable $e) { - if ($type === 'newrelic') { - $this->server->settings->update([ - 'is_logdrain_newrelic_enabled' => false, - ]); - } elseif ($type === 'highlight') { - $this->server->settings->update([ - 'is_logdrain_highlight_enabled' => false, - ]); - } elseif ($type === 'axiom') { - $this->server->settings->update([ - 'is_logdrain_axiom_enabled' => false, - ]); - } elseif ($type === 'custom') { - $this->server->settings->update([ - 'is_logdrain_custom_enabled' => false, - ]); - } - handleError($e, $this); - - return false; + return handleError($e, $this); } } diff --git a/app/Livewire/Server/PrivateKey/Show.php b/app/Livewire/Server/PrivateKey/Show.php index 0ad820428..64aa1884b 100644 --- a/app/Livewire/Server/PrivateKey/Show.php +++ b/app/Livewire/Server/PrivateKey/Show.php @@ -8,26 +8,63 @@ use Livewire\Component; class Show extends Component { - public ?Server $server = null; + public Server $server; public $privateKeys = []; public $parameters = []; - public function mount() + public function mount(string $server_uuid) { - $this->parameters = get_route_parameters(); try { - $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); - if (is_null($this->server)) { - return redirect()->route('server.index'); - } + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); $this->privateKeys = PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false); } catch (\Throwable $e) { return handleError($e, $this); } } + public function setPrivateKey($privateKeyId) + { + $ownedPrivateKey = PrivateKey::ownedByCurrentTeam()->find($privateKeyId); + if (is_null($ownedPrivateKey)) { + $this->dispatch('error', 'You are not allowed to use this private key.'); + + return; + } + + $originalPrivateKeyId = $this->server->getOriginal('private_key_id'); + try { + $this->server->update(['private_key_id' => $privateKeyId]); + ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(justCheckingNewKey: true); + if ($uptime) { + $this->dispatch('success', 'Private key updated successfully.'); + } else { + throw new \Exception($error); + } + } catch (\Exception $e) { + $this->server->update(['private_key_id' => $originalPrivateKeyId]); + $this->server->validateConnection(); + $this->dispatch('error', $e->getMessage()); + } + } + + public function checkConnection() + { + try { + ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); + if ($uptime) { + $this->dispatch('success', 'Server is reachable.'); + } else { + $this->dispatch('error', 'Server is not reachable.

Check this documentation for further help.

Error: '.$error); + + return; + } + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() { return view('livewire.server.private-key.show'); diff --git a/app/Livewire/Server/Show.php b/app/Livewire/Server/Show.php index 85c5f95f8..afc7682a4 100644 --- a/app/Livewire/Server/Show.php +++ b/app/Livewire/Server/Show.php @@ -3,38 +3,203 @@ namespace App\Livewire\Server; use App\Models\Server; -use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Livewire\Attributes\Rule; use Livewire\Component; class Show extends Component { - use AuthorizesRequests; - public Server $server; - public array $parameters; + #[Rule(['required'])] + public string $name; - protected $listeners = ['refreshServerShow']; + #[Rule(['nullable'])] + public ?string $description; - public function mount() + #[Rule(['required'])] + public string $ip; + + #[Rule(['required'])] + public string $user; + + #[Rule(['required'])] + public string $port; + + #[Rule(['nullable'])] + public ?string $validationLogs = null; + + #[Rule(['nullable', 'url'])] + public ?string $wildcardDomain; + + #[Rule(['required'])] + public bool $isReachable; + + #[Rule(['required'])] + public bool $isUsable; + + #[Rule(['required'])] + public bool $isSwarmManager; + + #[Rule(['required'])] + public bool $isSwarmWorker; + + #[Rule(['required'])] + public bool $isBuildServer; + + #[Rule(['required'])] + public bool $isMetricsEnabled; + + #[Rule(['required'])] + public string $sentinelToken; + + #[Rule(['nullable'])] + public ?string $sentinelUpdatedAt; + + #[Rule(['required', 'integer', 'min:1'])] + public int $sentinelMetricsRefreshRateSeconds; + + #[Rule(['required', 'integer', 'min:1'])] + public int $sentinelMetricsHistoryDays; + + #[Rule(['required', 'integer', 'min:10'])] + public int $sentinelPushIntervalSeconds; + + #[Rule(['nullable', 'url'])] + public ?string $sentinelCustomUrl; + + #[Rule(['required'])] + public bool $isSentinelEnabled; + + #[Rule(['required'])] + public bool $isSentinelDebugEnabled; + + #[Rule(['required'])] + public string $serverTimezone; + + public array $timezones; + + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},CloudflareTunnelConfigured" => '$refresh', + 'refreshServerShow' => '$refresh', + ]; + } + + public function mount(string $server_uuid) { try { - $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail(); - $this->parameters = get_route_parameters(); + $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); + $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } - public function refreshServerShow() + public function syncData(bool $toModel = false) { - $this->server->refresh(); - $this->dispatch('$refresh'); + if ($toModel) { + $this->validate(); + $this->server->name = $this->name; + $this->server->description = $this->description; + $this->server->ip = $this->ip; + $this->server->user = $this->user; + $this->server->port = $this->port; + $this->server->validation_logs = $this->validationLogs; + $this->server->save(); + + $this->server->settings->is_swarm_manager = $this->isSwarmManager; + $this->server->settings->is_swarm_worker = $this->isSwarmWorker; + $this->server->settings->is_build_server = $this->isBuildServer; + $this->server->settings->is_metrics_enabled = $this->isMetricsEnabled; + $this->server->settings->sentinel_token = $this->sentinelToken; + $this->server->settings->sentinel_metrics_refresh_rate_seconds = $this->sentinelMetricsRefreshRateSeconds; + $this->server->settings->sentinel_metrics_history_days = $this->sentinelMetricsHistoryDays; + $this->server->settings->sentinel_push_interval_seconds = $this->sentinelPushIntervalSeconds; + $this->server->settings->sentinel_custom_url = $this->sentinelCustomUrl; + $this->server->settings->is_sentinel_enabled = $this->isSentinelEnabled; + $this->server->settings->is_sentinel_debug_enabled = $this->isSentinelDebugEnabled; + $this->server->settings->server_timezone = $this->serverTimezone; + $this->server->settings->save(); + } else { + $this->name = $this->server->name; + $this->description = $this->server->description; + $this->ip = $this->server->ip; + $this->user = $this->server->user; + $this->port = $this->server->port; + $this->wildcardDomain = $this->server->settings->wildcard_domain; + $this->isReachable = $this->server->settings->is_reachable; + $this->isUsable = $this->server->settings->is_usable; + $this->isSwarmManager = $this->server->settings->is_swarm_manager; + $this->isSwarmWorker = $this->server->settings->is_swarm_worker; + $this->isBuildServer = $this->server->settings->is_build_server; + $this->isMetricsEnabled = $this->server->settings->is_metrics_enabled; + $this->sentinelToken = $this->server->settings->sentinel_token; + $this->sentinelMetricsRefreshRateSeconds = $this->server->settings->sentinel_metrics_refresh_rate_seconds; + $this->sentinelMetricsHistoryDays = $this->server->settings->sentinel_metrics_history_days; + $this->sentinelPushIntervalSeconds = $this->server->settings->sentinel_push_interval_seconds; + $this->sentinelCustomUrl = $this->server->settings->sentinel_custom_url; + $this->isSentinelEnabled = $this->server->settings->is_sentinel_enabled; + $this->isSentinelDebugEnabled = $this->server->settings->is_sentinel_debug_enabled; + $this->sentinelUpdatedAt = $this->server->settings->updated_at; + $this->serverTimezone = $this->server->settings->server_timezone; + } + } + + public function validateServer($install = true) + { + try { + $this->validationLogs = $this->server->validation_logs = null; + $this->server->save(); + $this->dispatch('init', $install); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function checkLocalhostConnection() + { + $this->syncData(true); + ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); + if ($uptime) { + $this->dispatch('success', 'Server is reachable.'); + $this->server->settings->is_reachable = $this->isReachable = true; + $this->server->settings->is_usable = $this->isUsable = true; + $this->server->settings->save(); + $this->dispatch('proxyStatusUpdated'); + } else { + $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.

Check this documentation for further help.

Error: '.$error); + + return; + } + } + + public function regenerateSentinelToken() + { + try { + $this->server->settings->generateSentinelToken(); + $this->dispatch('success', 'Token regenerated & Sentinel restarted.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function instantSave() + { + $this->submit(); } public function submit() { - $this->dispatch('serverRefresh', false); + try { + $this->syncData(true); + $this->dispatch('success', 'Server updated'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function render() diff --git a/app/Livewire/Server/ShowPrivateKey.php b/app/Livewire/Server/ShowPrivateKey.php deleted file mode 100644 index cc77fd611..000000000 --- a/app/Livewire/Server/ShowPrivateKey.php +++ /dev/null @@ -1,68 +0,0 @@ -parameters = get_route_parameters(); - } - - public function setPrivateKey($privateKeyId) - { - $ownedPrivateKey = PrivateKey::ownedByCurrentTeam()->find($privateKeyId); - if (is_null($ownedPrivateKey)) { - $this->dispatch('error', 'You are not allowed to use this private key.'); - - return; - } - - $originalPrivateKeyId = $this->server->getOriginal('private_key_id'); - try { - $this->server->update(['private_key_id' => $privateKeyId]); - ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); - if ($uptime) { - $this->dispatch('success', 'Private key updated successfully.'); - } else { - throw new \Exception('Server is not reachable.

Check this documentation for further help.

Error: '.$error); - } - } catch (\Exception $e) { - $this->server->update(['private_key_id' => $originalPrivateKeyId]); - $this->server->validateConnection(); - $this->dispatch('error', 'Failed to update private key: '.$e->getMessage()); - } finally { - $this->dispatch('refreshServerShow'); - $this->server->refresh(); - } - } - - public function checkConnection() - { - try { - ['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(); - if ($uptime) { - $this->dispatch('success', 'Server is reachable.'); - } else { - $this->dispatch('error', 'Server is not reachable.

Check this documentation for further help.

Error: '.$error); - - return; - } - } catch (\Throwable $e) { - return handleError($e, $this); - } finally { - $this->dispatch('refreshServerShow'); - $this->server->refresh(); - } - } -} diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php index 938d0e548..0a6c5bae6 100644 --- a/app/Livewire/Settings/Index.php +++ b/app/Livewire/Settings/Index.php @@ -7,70 +7,93 @@ use App\Models\InstanceSettings; use App\Models\Server; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; +use Livewire\Attributes\Locked; +use Livewire\Attributes\Rule; use Livewire\Component; class Index extends Component { public InstanceSettings $settings; - public bool $do_not_track; - - public bool $is_auto_update_enabled; - - public bool $is_registration_enabled; - - public bool $is_dns_validation_enabled; - - public bool $is_api_enabled; - - public string $auto_update_frequency; - - public string $update_check_frequency; - - public $timezones; - - public bool $disable_two_step_confirmation; - - protected string $dynamic_config_path = '/data/coolify/proxy/dynamic'; - protected Server $server; - protected $rules = [ - 'settings.fqdn' => 'nullable', - 'settings.resale_license' => 'nullable', - 'settings.public_port_min' => 'required', - 'settings.public_port_max' => 'required', - 'settings.custom_dns_servers' => 'nullable', - 'settings.instance_name' => 'nullable', - 'settings.allowed_ips' => 'nullable', - 'settings.is_auto_update_enabled' => 'boolean', - 'settings.public_ipv4' => 'nullable', - 'settings.public_ipv6' => 'nullable', - 'auto_update_frequency' => 'string', - 'update_check_frequency' => 'string', - 'settings.instance_timezone' => 'required|string|timezone', - ]; + #[Locked] + public $timezones; - protected $validationAttributes = [ - 'settings.fqdn' => 'FQDN', - 'settings.resale_license' => 'Resale License', - 'settings.public_port_min' => 'Public port min', - 'settings.public_port_max' => 'Public port max', - 'settings.custom_dns_servers' => 'Custom DNS servers', - 'settings.allowed_ips' => 'Allowed IPs', - 'settings.is_auto_update_enabled' => 'Auto Update Enabled', - 'settings.public_ipv4' => 'IPv4', - 'settings.public_ipv6' => 'IPv6', - 'auto_update_frequency' => 'Auto Update Frequency', - 'update_check_frequency' => 'Update Check Frequency', - 'settings.instance_timezone' => 'Instance Timezone', - ]; + #[Rule('boolean')] + public bool $is_auto_update_enabled; + + #[Rule('nullable|string|max:255')] + public ?string $fqdn = null; + + #[Rule('nullable|string|max:255')] + public ?string $resale_license = null; + + #[Rule('required|integer|min:1025|max:65535')] + public int $public_port_min; + + #[Rule('required|integer|min:1025|max:65535')] + public int $public_port_max; + + #[Rule('nullable|string')] + public ?string $custom_dns_servers = null; + + #[Rule('nullable|string|max:255')] + public ?string $instance_name = null; + + #[Rule('nullable|string')] + public ?string $allowed_ips = null; + + #[Rule('nullable|string')] + public ?string $public_ipv4 = null; + + #[Rule('nullable|string')] + public ?string $public_ipv6 = null; + + #[Rule('string')] + public string $auto_update_frequency; + + #[Rule('string')] + public string $update_check_frequency; + + #[Rule('required|string|timezone')] + public string $instance_timezone; + + #[Rule('boolean')] + public bool $do_not_track; + + #[Rule('boolean')] + public bool $is_registration_enabled; + + #[Rule('boolean')] + public bool $is_dns_validation_enabled; + + #[Rule('boolean')] + public bool $is_api_enabled; + + #[Rule('boolean')] + public bool $disable_two_step_confirmation; + + public function render() + { + return view('livewire.settings.index'); + } public function mount() { - if (isInstanceAdmin()) { + if (! isInstanceAdmin()) { + return redirect()->route('dashboard'); + } else { $this->settings = instanceSettings(); - loggy($this->settings); + $this->fqdn = $this->settings->fqdn; + $this->resale_license = $this->settings->resale_license; + $this->public_port_min = $this->settings->public_port_min; + $this->public_port_max = $this->settings->public_port_max; + $this->custom_dns_servers = $this->settings->custom_dns_servers; + $this->instance_name = $this->settings->instance_name; + $this->allowed_ips = $this->settings->allowed_ips; + $this->public_ipv4 = $this->settings->public_ipv4; + $this->public_ipv6 = $this->settings->public_ipv6; $this->do_not_track = $this->settings->do_not_track; $this->is_auto_update_enabled = $this->settings->is_auto_update_enabled; $this->is_registration_enabled = $this->settings->is_registration_enabled; @@ -79,14 +102,22 @@ class Index extends Component $this->auto_update_frequency = $this->settings->auto_update_frequency; $this->update_check_frequency = $this->settings->update_check_frequency; $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); + $this->instance_timezone = $this->settings->instance_timezone; $this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation; - } else { - return redirect()->route('dashboard'); } } - public function instantSave() + public function instantSave($isSave = true) { + $this->settings->fqdn = $this->fqdn; + $this->settings->resale_license = $this->resale_license; + $this->settings->public_port_min = $this->public_port_min; + $this->settings->public_port_max = $this->public_port_max; + $this->settings->custom_dns_servers = $this->custom_dns_servers; + $this->settings->instance_name = $this->instance_name; + $this->settings->allowed_ips = $this->allowed_ips; + $this->settings->public_ipv4 = $this->public_ipv4; + $this->settings->public_ipv6 = $this->public_ipv6; $this->settings->do_not_track = $this->do_not_track; $this->settings->is_auto_update_enabled = $this->is_auto_update_enabled; $this->settings->is_registration_enabled = $this->is_registration_enabled; @@ -95,8 +126,11 @@ class Index extends Component $this->settings->auto_update_frequency = $this->auto_update_frequency; $this->settings->update_check_frequency = $this->update_check_frequency; $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation; - $this->settings->save(); - $this->dispatch('success', 'Settings updated!'); + $this->settings->instance_timezone = $this->instance_timezone; + if ($isSave) { + $this->settings->save(); + $this->dispatch('success', 'Settings updated!'); + } } public function submit() @@ -153,13 +187,8 @@ class Index extends Component $this->settings->allowed_ips = $this->settings->allowed_ips->unique(); $this->settings->allowed_ips = $this->settings->allowed_ips->implode(','); - $this->settings->do_not_track = $this->do_not_track; - $this->settings->is_auto_update_enabled = $this->is_auto_update_enabled; - $this->settings->is_registration_enabled = $this->is_registration_enabled; - $this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled; - $this->settings->is_api_enabled = $this->is_api_enabled; - $this->settings->auto_update_frequency = $this->auto_update_frequency; - $this->settings->update_check_frequency = $this->update_check_frequency; + $this->instantSave(isSave: false); + $this->settings->save(); $this->server->setupDynamicProxyConfiguration(); if (! $error_show) { @@ -182,11 +211,6 @@ class Index extends Component } } - public function render() - { - return view('livewire.settings.index'); - } - public function toggleTwoStepConfirmation($password) { if (! Hash::check($password, Auth::user()->password)) { @@ -195,9 +219,8 @@ class Index extends Component return; } - $this->settings->disable_two_step_confirmation = true; + $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true; $this->settings->save(); - $this->disable_two_step_confirmation = true; $this->dispatch('success', 'Two step confirmation has been disabled.'); } } diff --git a/app/Livewire/Settings/License.php b/app/Livewire/Settings/License.php index 8cb7aad8f..79f8269f3 100644 --- a/app/Livewire/Settings/License.php +++ b/app/Livewire/Settings/License.php @@ -50,7 +50,6 @@ class License extends Component $this->dispatch('reloadWindow'); } catch (\Throwable $e) { session()->flash('error', 'Something went wrong. Please contact support.
Error: '.$e->getMessage()); - ray($e->getMessage()); return redirect()->route('settings.license'); } diff --git a/app/Livewire/SettingsBackup.php b/app/Livewire/SettingsBackup.php index 9240aa96d..38f7e548a 100644 --- a/app/Livewire/SettingsBackup.php +++ b/app/Livewire/SettingsBackup.php @@ -2,50 +2,59 @@ namespace App\Livewire; -use App\Jobs\DatabaseBackupJob; use App\Models\InstanceSettings; use App\Models\S3Storage; use App\Models\ScheduledDatabaseBackup; use App\Models\Server; use App\Models\StandalonePostgresql; +use Livewire\Attributes\Locked; +use Livewire\Attributes\Rule; use Livewire\Component; class SettingsBackup extends Component { public InstanceSettings $settings; - public $s3s; - public ?StandalonePostgresql $database = null; public ScheduledDatabaseBackup|null|array $backup = []; + #[Locked] + public $s3s; + + #[Locked] public $executions = []; - protected $rules = [ - 'database.uuid' => 'required', - 'database.name' => 'required', - 'database.description' => 'nullable', - 'database.postgres_user' => 'required', - 'database.postgres_password' => 'required', + #[Rule(['required'])] + public string $uuid; - ]; + #[Rule(['required'])] + public string $name; - protected $validationAttributes = [ - 'database.uuid' => 'uuid', - 'database.name' => 'name', - 'database.description' => 'description', - 'database.postgres_user' => 'postgres user', - 'database.postgres_password' => 'postgres password', - ]; + #[Rule(['nullable'])] + public ?string $description = null; + + #[Rule(['required'])] + public string $postgres_user; + + #[Rule(['required'])] + public string $postgres_password; public function mount() { - if (isInstanceAdmin()) { + if (! isInstanceAdmin()) { + return redirect()->route('dashboard'); + } else { $settings = instanceSettings(); $this->database = StandalonePostgresql::whereName('coolify-db')->first(); $s3s = S3Storage::whereTeamId(0)->get() ?? []; if ($this->database) { + $this->uuid = $this->database->uuid; + $this->name = $this->database->name; + $this->description = $this->database->description; + $this->postgres_user = $this->database->postgres_user; + $this->postgres_password = $this->database->postgres_password; + if ($this->database->status !== 'running') { $this->database->status = 'running'; $this->database->save(); @@ -55,13 +64,10 @@ class SettingsBackup extends Component } $this->settings = $settings; $this->s3s = $s3s; - - } else { - return redirect()->route('dashboard'); } } - public function add_coolify_database() + public function addCoolifyDatabase() { try { $server = Server::findOrFail(0); @@ -78,7 +84,7 @@ class SettingsBackup extends Component 'postgres_password' => $postgres_password, 'postgres_db' => $postgres_db, 'status' => 'running', - 'destination_type' => 'App\Models\StandaloneDocker', + 'destination_type' => \App\Models\StandaloneDocker::class, 'destination_id' => 0, ]); $this->backup = ScheduledDatabaseBackup::create([ @@ -87,7 +93,7 @@ class SettingsBackup extends Component 'save_s3' => false, 'frequency' => '0 0 * * *', 'database_id' => $this->database->id, - 'database_type' => 'App\Models\StandalonePostgresql', + 'database_type' => \App\Models\StandalonePostgresql::class, 'team_id' => currentTeam()->id, ]); $this->database->refresh(); @@ -98,16 +104,14 @@ class SettingsBackup extends Component } } - public function backup_now() - { - dispatch(new DatabaseBackupJob( - backup: $this->backup - )); - $this->dispatch('success', 'Backup queued. It will be available in a few minutes.'); - } - public function submit() { + $this->database->update([ + 'name' => $this->name, + 'description' => $this->description, + 'postgres_user' => $this->postgres_user, + 'postgres_password' => $this->postgres_password, + ]); $this->dispatch('success', 'Backup updated.'); } } diff --git a/app/Livewire/Team/AdminView.php b/app/Livewire/Team/AdminView.php index 700c30f0a..c9dabcb5c 100644 --- a/app/Livewire/Team/AdminView.php +++ b/app/Livewire/Team/AdminView.php @@ -59,20 +59,16 @@ class AdminView extends Component foreach ($servers as $server) { $resources = $server->definedResources(); foreach ($resources as $resource) { - ray('Deleting resource: '.$resource->name); $resource->forceDelete(); } - ray('Deleting server: '.$server->name); $server->forceDelete(); } $projects = $team->projects; foreach ($projects as $project) { - ray('Deleting project: '.$project->name); $project->forceDelete(); } $team->members()->detach($user->id); - ray('Deleting team: '.$team->name); $team->delete(); } @@ -91,29 +87,23 @@ class AdminView extends Component $user = User::find($id); $teams = $user->teams; foreach ($teams as $team) { - ray($team->name); $user_alone_in_team = $team->members->count() === 1; if ($team->id === 0) { if ($user_alone_in_team) { - ray('user is alone in the root team, do nothing'); - return $this->dispatch('error', 'User is alone in the root team, cannot delete'); } } if ($user_alone_in_team) { - ray('user is alone in the team'); $this->finalizeDeletion($user, $team); continue; } - ray('user is not alone in the team'); if ($user->isOwner()) { $found_other_owner_or_admin = $team->members->filter(function ($member) { return $member->pivot->role === 'owner' || $member->pivot->role === 'admin'; })->where('id', '!=', $user->id)->first(); if ($found_other_owner_or_admin) { - ray('found other owner or admin'); $team->members()->detach($user->id); continue; @@ -122,24 +112,19 @@ class AdminView extends Component return $member->pivot->role === 'member'; })->first(); if ($found_other_member_who_is_not_owner) { - ray('found other member who is not owner'); $found_other_member_who_is_not_owner->pivot->role = 'owner'; $found_other_member_who_is_not_owner->pivot->save(); $team->members()->detach($user->id); } else { - // This should never happen as if the user is the only member in the team, the team should be deleted already. - ray('found no other member who is not owner'); $this->finalizeDeletion($user, $team); } continue; } } else { - ray('user is not owner'); $team->members()->detach($user->id); } } - ray('Deleting user: '.$user->name); $user->delete(); $this->getUsers(); } diff --git a/app/Livewire/Team/Member.php b/app/Livewire/Team/Member.php index fa0cf6122..890d640a0 100644 --- a/app/Livewire/Team/Member.php +++ b/app/Livewire/Team/Member.php @@ -2,41 +2,77 @@ namespace App\Livewire\Team; +use App\Enums\Role; use App\Models\User; use Illuminate\Support\Facades\Cache; -use Livewire\Attributes\Locked; use Livewire\Component; class Member extends Component { - #[Locked] public User $member; public function makeAdmin() { - $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'admin']); - $this->dispatch('reloadWindow'); + try { + if (Role::from(auth()->user()->role())->lt(Role::ADMIN) + || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { + throw new \Exception('You are not authorized to perform this action.'); + } + $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => Role::ADMIN->value]); + $this->dispatch('reloadWindow'); + } catch (\Exception $e) { + $this->dispatch('error', $e->getMessage()); + } } public function makeOwner() { - $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'owner']); - $this->dispatch('reloadWindow'); + try { + if (Role::from(auth()->user()->role())->lt(Role::OWNER) + || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { + throw new \Exception('You are not authorized to perform this action.'); + } + $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => Role::OWNER->value]); + $this->dispatch('reloadWindow'); + } catch (\Exception $e) { + $this->dispatch('error', $e->getMessage()); + } } public function makeReadonly() { - $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'member']); - $this->dispatch('reloadWindow'); + try { + if (Role::from(auth()->user()->role())->lt(Role::ADMIN) + || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { + throw new \Exception('You are not authorized to perform this action.'); + } + $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => Role::MEMBER->value]); + $this->dispatch('reloadWindow'); + } catch (\Exception $e) { + $this->dispatch('error', $e->getMessage()); + } } public function remove() { - $this->member->teams()->detach(currentTeam()); - Cache::forget("team:{$this->member->id}"); - Cache::remember('team:'.$this->member->id, 3600, function () { - return $this->member->teams()->first(); - }); - $this->dispatch('reloadWindow'); + try { + if (Role::from(auth()->user()->role())->lt(Role::ADMIN) + || Role::from($this->getMemberRole())->gt(auth()->user()->role())) { + throw new \Exception('You are not authorized to perform this action.'); + } + $this->member->teams()->detach(currentTeam()); + Cache::forget("team:{$this->member->id}"); + Cache::remember('team:'.$this->member->id, 3600, function () { + return $this->member->teams()->first(); + }); + $this->dispatch('reloadWindow'); + } catch (\Exception $e) { + $this->dispatch('error', $e->getMessage()); + } + } + + private function getMemberRole() + { + return $this->member->teams()->where('teams.id', currentTeam()->id)->first()?->pivot?->role; } } diff --git a/app/Livewire/VerifyEmail.php b/app/Livewire/VerifyEmail.php index d1f79c835..9d1fdab98 100644 --- a/app/Livewire/VerifyEmail.php +++ b/app/Livewire/VerifyEmail.php @@ -17,8 +17,6 @@ class VerifyEmail extends Component $this->dispatch('success', 'Email verification link sent!'); } catch (\Exception $e) { - ray($e); - return handleError($e, $this); } } diff --git a/app/Models/Application.php b/app/Models/Application.php index 6ed1aaf03..c747c75c5 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -221,7 +221,6 @@ class Application extends BaseModel { if ($this->build_pack === 'dockercompose') { $server = data_get($this, 'destination.server'); - ray('Deleting volumes'); instant_remote_process(["cd {$this->dirOnServer()} && docker compose down -v"], $server, false); } else { if ($persistentStorages->count() === 0) { @@ -937,7 +936,7 @@ class Application extends BaseModel $source_html_url_host = $url['host']; $source_html_url_scheme = $url['scheme']; - if ($this->source->getMorphClass() == 'App\Models\GithubApp') { + if ($this->source->getMorphClass() == \App\Models\GithubApp::class) { if ($this->source->is_public) { $fullRepoUrl = "{$this->source->html_url}/{$customRepository}"; $git_clone_command = "{$git_clone_command} {$this->source->html_url}/{$customRepository} {$baseDir}"; @@ -1246,13 +1245,11 @@ class Application extends BaseModel return; } if (base64_encode(base64_decode($customLabels, true)) !== $customLabels) { - ray('custom_labels is not base64 encoded'); $this->custom_labels = str($customLabels)->replace(',', "\n"); $this->custom_labels = base64_encode($customLabels); } $customLabels = base64_decode($this->custom_labels); if (mb_detect_encoding($customLabels, 'ASCII', true) === false) { - ray('custom_labels contains non-ascii characters'); $customLabels = str(implode('|coolify|', generateLabelsApplication($this, $preview)))->replace('|coolify|', "\n"); } $this->custom_labels = base64_encode($customLabels); @@ -1481,8 +1478,6 @@ class Application extends BaseModel public function setConfig($config) { - - $config = $config; $validator = Validator::make(['config' => $config], [ 'config' => 'required|json', ]); diff --git a/app/Models/Environment.php b/app/Models/Environment.php index c892d7ba1..d0bb5d2a6 100644 --- a/app/Models/Environment.php +++ b/app/Models/Environment.php @@ -27,7 +27,6 @@ class Environment extends Model static::deleting(function ($environment) { $shared_variables = $environment->environment_variables(); foreach ($shared_variables as $shared_variable) { - ray('Deleting environment shared variable: '.$shared_variable->name); $shared_variable->delete(); } diff --git a/app/Models/GithubApp.php b/app/Models/GithubApp.php index b9564e02c..0b0e93b12 100644 --- a/app/Models/GithubApp.php +++ b/app/Models/GithubApp.php @@ -65,7 +65,7 @@ class GithubApp extends BaseModel { return Attribute::make( get: function () { - if ($this->getMorphClass() === 'App\Models\GithubApp') { + if ($this->getMorphClass() === \App\Models\GithubApp::class) { return 'github'; } }, diff --git a/app/Models/Project.php b/app/Models/Project.php index 5a9dd964a..3a09b0b8f 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -47,7 +47,6 @@ class Project extends BaseModel $project->settings()->delete(); $shared_variables = $project->environment_variables(); foreach ($shared_variables as $shared_variable) { - ray('Deleting project shared variable: '.$shared_variable->name); $shared_variable->delete(); } }); diff --git a/app/Models/Server.php b/app/Models/Server.php index 229f34620..fbd464dc3 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -5,6 +5,7 @@ namespace App\Models; use App\Actions\Server\InstallDocker; use App\Actions\Server\StartSentinel; use App\Enums\ProxyTypes; +use App\Helpers\SshMultiplexingHelper; use App\Jobs\CheckAndStartSentinelJob; use App\Notifications\Server\Reachable; use App\Notifications\Server\Unreachable; @@ -63,7 +64,11 @@ class Server extends BaseModel $payload['ip'] = str($server->ip)->trim(); } $server->forceFill($payload); - + }); + static::saved(function ($server) { + if ($server->privateKey->isDirty()) { + refresh_server_connection($server->privateKey); + } }); static::created(function ($server) { ServerSetting::create([ @@ -1022,7 +1027,6 @@ $schema://$host { $this->refresh(); $unreachableNotificationSent = (bool) $this->unreachable_notification_sent; $isReachable = (bool) $this->settings->is_reachable; - loggy('Server setting is_reachable changed to '.$isReachable.' for server '.$this->id.'. Unreachable notification sent: '.$unreachableNotificationSent); // If the server is reachable, send the reachable notification if it was sent before if ($isReachable === true) { if ($unreachableNotificationSent === true) { @@ -1052,10 +1056,12 @@ $schema://$host { $this->team->notify(new Unreachable($this)); } - public function validateConnection($isManualCheck = true) + public function validateConnection(bool $isManualCheck = true, bool $justCheckingNewKey = false) { config()->set('constants.ssh.mux_enabled', ! $isManualCheck); + SshMultiplexingHelper::removeMuxFile($this); + if ($this->skipServer()) { return ['uptime' => false, 'error' => 'Server skipped.']; } @@ -1072,6 +1078,9 @@ $schema://$host { return ['uptime' => true, 'error' => null]; } catch (\Throwable $e) { + if ($justCheckingNewKey) { + return ['uptime' => false, 'error' => 'This key is not valid for this server.']; + } if ($this->settings->is_reachable === true) { $this->settings->is_reachable = false; $this->settings->save(); @@ -1248,4 +1257,9 @@ $schema://$host { { return base_url().'/server/'.$this->uuid; } + + public function restartContainer(string $containerName) + { + return instant_remote_process(['docker restart '.$containerName], $this, false); + } } diff --git a/app/Models/ServerSetting.php b/app/Models/ServerSetting.php index 7a8e7b8ed..bca16536e 100644 --- a/app/Models/ServerSetting.php +++ b/app/Models/ServerSetting.php @@ -117,7 +117,6 @@ class ServerSetting extends Model $domain = 'http://'.$settings->public_ipv6.':8000'; } $this->sentinel_custom_url = $domain; - loggy('Sentinel URL: '.$domain); if ($save) { $this->save(); } diff --git a/app/Models/Service.php b/app/Models/Service.php index 0af1adf22..c4f4c2d3c 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -366,7 +366,6 @@ class Service extends BaseModel ]); } $password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LANGFUSE')->first(); - ray('password', $password); if ($password) { $data = $data->merge([ 'Admin Password' => [ @@ -1108,7 +1107,6 @@ class Service extends BaseModel foreach ($fields as $field) { $key = data_get($field, 'key'); $value = data_get($field, 'value'); - ray($key, $value); $found = $this->environment_variables()->where('key', $key)->first(); if ($found) { $found->value = $value; diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index ccab7d658..3dd13b633 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -71,7 +71,6 @@ class StandalonePostgresql extends BaseModel } $server = data_get($this, 'destination.server'); foreach ($persistentStorages as $storage) { - ray('Deleting volume: '.$storage->name); instant_remote_process(["docker volume rm -f $storage->name"], $server, false); } } diff --git a/app/Models/Team.php b/app/Models/Team.php index a0f99e5f8..49b019725 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -93,27 +93,22 @@ class Team extends Model implements SendsDiscord, SendsEmail static::deleting(function ($team) { $keys = $team->privateKeys; foreach ($keys as $key) { - ray('Deleting key: '.$key->name); $key->delete(); } $sources = $team->sources(); foreach ($sources as $source) { - ray('Deleting source: '.$source->name); $source->delete(); } $tags = Tag::whereTeamId($team->id)->get(); foreach ($tags as $tag) { - ray('Deleting tag: '.$tag->name); $tag->delete(); } $shared_variables = $team->environment_variables(); foreach ($shared_variables as $shared_variable) { - ray('Deleting team shared variable: '.$shared_variable->name); $shared_variable->delete(); } $s3s = $team->s3s; foreach ($s3s as $s3) { - ray('Deleting s3: '.$s3->name); $s3->delete(); } }); @@ -167,8 +162,12 @@ class Team extends Model implements SendsDiscord, SendsEmail if (currentTeam()->id === 0 && isDev()) { return 9999999; } + $team = Team::find(currentTeam()->id); + if (! $team) { + return 0; + } - return Team::find(currentTeam()->id)->limits['serverLimit']; + return data_get($team, 'limits.serverLimit', 0); } public function limits(): Attribute diff --git a/app/Notifications/Application/DeploymentSuccess.php b/app/Notifications/Application/DeploymentSuccess.php index a2674ad76..946a622ca 100644 --- a/app/Notifications/Application/DeploymentSuccess.php +++ b/app/Notifications/Application/DeploymentSuccess.php @@ -52,7 +52,7 @@ class DeploymentSuccess extends Notification implements ShouldQueue $channels = setNotificationChannels($notifiable, 'deployments'); if (isCloud()) { // TODO: Make batch notifications work with email - $channels = array_diff($channels, ['App\Notifications\Channels\EmailChannel']); + $channels = array_diff($channels, [\App\Notifications\Channels\EmailChannel::class]); } return $channels; diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 413d3de53..af9af978d 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -32,7 +32,6 @@ class EmailChannel if ($error === 'No email settings found.') { throw $e; } - ray($e->getMessage()); $message = "EmailChannel error: {$e->getMessage()}. Failed to send email to:"; if (isset($recipients)) { $message .= implode(', ', $recipients); diff --git a/app/Notifications/Channels/TelegramChannel.php b/app/Notifications/Channels/TelegramChannel.php index b1a607651..4b1fa49dd 100644 --- a/app/Notifications/Channels/TelegramChannel.php +++ b/app/Notifications/Channels/TelegramChannel.php @@ -18,23 +18,23 @@ class TelegramChannel $topicsInstance = get_class($notification); switch ($topicsInstance) { - case 'App\Notifications\Test': + case \App\Notifications\Test::class: $topicId = data_get($notifiable, 'telegram_notifications_test_message_thread_id'); break; - case 'App\Notifications\Application\StatusChanged': - case 'App\Notifications\Container\ContainerRestarted': - case 'App\Notifications\Container\ContainerStopped': + case \App\Notifications\Application\StatusChanged::class: + case \App\Notifications\Container\ContainerRestarted::class: + case \App\Notifications\Container\ContainerStopped::class: $topicId = data_get($notifiable, 'telegram_notifications_status_changes_message_thread_id'); break; - case 'App\Notifications\Application\DeploymentSuccess': - case 'App\Notifications\Application\DeploymentFailed': + case \App\Notifications\Application\DeploymentSuccess::class: + case \App\Notifications\Application\DeploymentFailed::class: $topicId = data_get($notifiable, 'telegram_notifications_deployments_message_thread_id'); break; - case 'App\Notifications\Database\BackupSuccess': - case 'App\Notifications\Database\BackupFailed': + case \App\Notifications\Database\BackupSuccess::class: + case \App\Notifications\Database\BackupFailed::class: $topicId = data_get($notifiable, 'telegram_notifications_database_backups_message_thread_id'); break; - case 'App\Notifications\ScheduledTask\TaskFailed': + case \App\Notifications\ScheduledTask\TaskFailed::class: $topicId = data_get($notifiable, 'telegram_notifications_scheduled_tasks_thread_id'); break; } diff --git a/app/Notifications/Database/BackupSuccess.php b/app/Notifications/Database/BackupSuccess.php index 4bd6b97b8..5128c8ed6 100644 --- a/app/Notifications/Database/BackupSuccess.php +++ b/app/Notifications/Database/BackupSuccess.php @@ -61,7 +61,6 @@ class BackupSuccess extends Notification implements ShouldQueue public function toTelegram(): array { $message = "Coolify: Database backup for {$this->name} (db:{$this->database_name}) with frequency of {$this->frequency} was successful."; - ray($message); return [ 'message' => $message, diff --git a/app/Notifications/Test.php b/app/Notifications/Test.php index 4c069ffd6..a43b1e153 100644 --- a/app/Notifications/Test.php +++ b/app/Notifications/Test.php @@ -25,7 +25,7 @@ class Test extends Notification implements ShouldQueue public function middleware(object $notifiable, string $channel) { return match ($channel) { - 'App\Notifications\Channels\EmailChannel' => [new RateLimited('email')], + \App\Notifications\Channels\EmailChannel::class => [new RateLimited('email')], default => [], }; } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 8b4c2eef2..1fffd0399 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,6 +5,7 @@ namespace App\Providers; use App\Models\PersonalAccessToken; use Illuminate\Support\Facades\Http; use Illuminate\Support\ServiceProvider; +use Illuminate\Validation\Rules\Password; use Laravel\Sanctum\Sanctum; class AppServiceProvider extends ServiceProvider @@ -15,6 +16,14 @@ class AppServiceProvider extends ServiceProvider { Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class); + Password::defaults(function () { + $rule = Password::min(8); + + return $this->app->isProduction() + ? $rule->mixedCase()->letters()->numbers()->symbols() + : $rule; + }); + Http::macro('github', function (string $api_url, ?string $github_access_token = null) { if ($github_access_token) { return Http::withHeaders([ diff --git a/app/Providers/DuskServiceProvider.php b/app/Providers/DuskServiceProvider.php new file mode 100644 index 000000000..07e0e8709 --- /dev/null +++ b/app/Providers/DuskServiceProvider.php @@ -0,0 +1,21 @@ +visit('/login') + ->type('email', 'test@example.com') + ->type('password', 'password') + ->press('Login'); + }); + } +} diff --git a/app/View/Components/Server/Sidebar.php b/app/View/Components/Server/Sidebar.php deleted file mode 100644 index f968b6d0c..000000000 --- a/app/View/Components/Server/Sidebar.php +++ /dev/null @@ -1,27 +0,0 @@ -getMorphClass() === 'App\Models\ServiceApplication') { + if ($resource->getMorphClass() === \App\Models\ServiceApplication::class) { $uuid = data_get($resource, 'uuid'); $server = data_get($resource, 'service.server'); $environment_variables = data_get($resource, 'service.environment_variables'); $type = $resource->serviceType(); - } elseif ($resource->getMorphClass() === 'App\Models\Application') { + } elseif ($resource->getMorphClass() === \App\Models\Application::class) { $uuid = data_get($resource, 'uuid'); $server = data_get($resource, 'destination.server'); $environment_variables = data_get($resource, 'environment_variables'); @@ -279,7 +279,6 @@ function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains, $labels->push("caddy_ingress_network={$network}"); } foreach ($domains as $loop => $domain) { - $loop = $loop; $url = Url::fromString($domain); $host = $url->getHost(); $path = $url->getPath(); diff --git a/bootstrap/helpers/github.php b/bootstrap/helpers/github.php index 97deb0b1c..0b5f7034b 100644 --- a/bootstrap/helpers/github.php +++ b/bootstrap/helpers/github.php @@ -57,7 +57,7 @@ function githubApi(GithubApp|GitlabApp|null $source, string $endpoint, string $m if (is_null($source)) { throw new \Exception('Not implemented yet.'); } - if ($source->getMorphClass() == 'App\Models\GithubApp') { + if ($source->getMorphClass() == \App\Models\GithubApp::class) { if ($source->is_public) { $response = Http::github($source->api_url)->$method($endpoint); } else { diff --git a/bootstrap/helpers/services.php b/bootstrap/helpers/services.php index eba88d000..94c3c5f45 100644 --- a/bootstrap/helpers/services.php +++ b/bootstrap/helpers/services.php @@ -24,7 +24,7 @@ function replaceVariables(string $variable): Stringable function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Application $oneService, bool $isInit = false) { try { - if ($oneService->getMorphClass() === 'App\Models\Application') { + if ($oneService->getMorphClass() === \App\Models\Application::class) { $workdir = $oneService->workdir(); $server = $oneService->destination->server; } else { diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index dbab6861d..89462215c 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -127,7 +127,6 @@ function refreshSession(?Team $team = null): void } function handleError(?Throwable $error = null, ?Livewire\Component $livewire = null, ?string $customErrorMessage = null) { - loggy($error); if ($error instanceof TooManyRequestsException) { if (isset($livewire)) { return $livewire->dispatch('error', "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."); @@ -370,6 +369,9 @@ function translate_cron_expression($expression_to_validate): string } function validate_cron_expression($expression_to_validate): bool { + if (empty($expression_to_validate)) { + return false; + } $isValid = false; $expression = new CronExpression($expression_to_validate); $isValid = $expression->isValid(); @@ -669,7 +671,7 @@ function generateGitManualWebhook($resource, $type) if ($resource->source_id !== 0 && ! is_null($resource->source_id)) { return null; } - if ($resource->getMorphClass() === 'App\Models\Application') { + if ($resource->getMorphClass() === \App\Models\Application::class) { $baseUrl = base_url(); $api = Url::fromString($baseUrl)."/webhooks/source/$type/events/manual"; @@ -685,7 +687,7 @@ function removeAnsiColors($text) function getTopLevelNetworks(Service|Application $resource) { - if ($resource->getMorphClass() === 'App\Models\Service') { + if ($resource->getMorphClass() === \App\Models\Service::class) { if ($resource->docker_compose_raw) { try { $yaml = Yaml::parse($resource->docker_compose_raw); @@ -740,7 +742,7 @@ function getTopLevelNetworks(Service|Application $resource) return $topLevelNetworks->keys(); } - } elseif ($resource->getMorphClass() === 'App\Models\Application') { + } elseif ($resource->getMorphClass() === \App\Models\Application::class) { try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { @@ -1147,7 +1149,7 @@ function checkIfDomainIsAlreadyUsed(Collection|array $domains, ?string $teamId = function check_domain_usage(ServiceApplication|Application|null $resource = null, ?string $domain = null) { if ($resource) { - if ($resource->getMorphClass() === 'App\Models\Application' && $resource->build_pack === 'dockercompose') { + if ($resource->getMorphClass() === \App\Models\Application::class && $resource->build_pack === 'dockercompose') { $domains = data_get(json_decode($resource->docker_compose_domains, true), '*.domain'); $domains = collect($domains); } else { @@ -1411,7 +1413,7 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull if ($source->value() === '/tmp' || $source->value() === '/tmp/') { return $volume; } - if (get_class($resource) === "App\Models\Application") { + if (get_class($resource) === \App\Models\Application::class) { $dir = base_configuration_dir().'/applications/'.$resource->uuid; } else { $dir = base_configuration_dir().'/services/'.$resource->service->uuid; @@ -1451,7 +1453,7 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull } } $slugWithoutUuid = Str::slug($source, '-'); - if (get_class($resource) === "App\Models\Application") { + if (get_class($resource) === \App\Models\Application::class) { $name = "{$resource->uuid}_{$slugWithoutUuid}"; } else { $name = "{$resource->service->uuid}_{$slugWithoutUuid}"; @@ -1494,7 +1496,7 @@ function parseServiceVolumes($serviceVolumes, $resource, $topLevelVolumes, $pull function parseDockerComposeFile(Service|Application $resource, bool $isNew = false, int $pull_request_id = 0, ?int $preview_id = null) { - if ($resource->getMorphClass() === 'App\Models\Service') { + if ($resource->getMorphClass() === \App\Models\Service::class) { if ($resource->docker_compose_raw) { try { $yaml = Yaml::parse($resource->docker_compose_raw); @@ -2208,7 +2210,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } else { return collect([]); } - } elseif ($resource->getMorphClass() === 'App\Models\Application') { + } elseif ($resource->getMorphClass() === \App\Models\Application::class) { try { $yaml = Yaml::parse($resource->docker_compose_raw); } catch (\Exception $e) { @@ -3094,7 +3096,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int } } - if ($value && get_class($value) === 'Illuminate\Support\Stringable' && $value->startsWith('/')) { + if ($value && get_class($value) === \Illuminate\Support\Stringable::class && $value->startsWith('/')) { $path = $value->value(); if ($path !== '/') { $fqdn = "$fqdn$path"; diff --git a/database/migrations/2024_10_29_093927_add_is_sentinel_debug_enabled_to_server_settings.php b/database/migrations/2024_10_29_093927_add_is_sentinel_debug_enabled_to_server_settings.php new file mode 100644 index 000000000..d8ab1313b --- /dev/null +++ b/database/migrations/2024_10_29_093927_add_is_sentinel_debug_enabled_to_server_settings.php @@ -0,0 +1,28 @@ +boolean('is_sentinel_debug_enabled')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('server_settings', function (Blueprint $table) { + $table->dropColumn('is_sentinel_debug_enabled'); + }); + } +}; diff --git a/database/seeders/PopulateSshKeysDirectorySeeder.php b/database/seeders/PopulateSshKeysDirectorySeeder.php index e2543ee02..d528179c0 100644 --- a/database/seeders/PopulateSshKeysDirectorySeeder.php +++ b/database/seeders/PopulateSshKeysDirectorySeeder.php @@ -33,7 +33,6 @@ class PopulateSshKeysDirectorySeeder extends Seeder } } catch (\Throwable $e) { echo "Error: {$e->getMessage()}\n"; - ray($e->getMessage()); } } } diff --git a/public/svgs/coder.svg b/public/svgs/coder.svg new file mode 100644 index 000000000..45b7f795c --- /dev/null +++ b/public/svgs/coder.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 7d615885f..d6c3edf84 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -5,6 +5,13 @@ Coolify
+ @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif
@csrf @@ -27,28 +34,22 @@ {{ __('auth.forgot_password') }}? @endenv - {{ __('auth.login') }} + {{ __('auth.login') }} + + @if (session('error')) +
+ {{ session('error') }} +
+ @endif @if (!$is_registration_enabled)
{{ __('auth.registration_disabled') }}
@endif - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach -
- @endif @if (session('status'))
{{ session('status') }}
@endif - @if (session('error')) -
- {{ session('error') }} -
- @endif
@if ($is_registration_enabled) diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 1d236a6c4..370f75656 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -32,25 +32,19 @@ $email = getOldOrLocal('email', 'test3@example.com'); label="{{ __('input.name') }}" /> -
diff --git a/resources/views/components/forms/checkbox.blade.php b/resources/views/components/forms/checkbox.blade.php index fed6ad77f..f5eb5778a 100644 --- a/resources/views/components/forms/checkbox.blade.php +++ b/resources/views/components/forms/checkbox.blade.php @@ -14,10 +14,7 @@ 'w-full' => $fullWidth, ])> @if (!$hideLabel) -