Merge pull request #2438 from Thijmen/php-codestyle

Add PHP Codestyles
This commit is contained in:
Andras Bacsai 2024-06-11 11:37:17 +02:00 committed by GitHub
commit 5ebbd769e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
432 changed files with 5343 additions and 2841 deletions

View File

@ -0,0 +1,25 @@
name: Fix PHP code style issues
on: [push]
permissions:
contents: write
jobs:
php-code-styling:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: Fix PHP code style issues
uses: aglipanci/laravel-pint-action@2.4
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: Fix styling

View File

@ -3,17 +3,17 @@
namespace App\Actions\Application; namespace App\Actions\Application;
use App\Models\Application; use App\Models\Application;
use App\Models\StandaloneDocker;
use App\Notifications\Application\StatusChanged;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
class StopApplication class StopApplication
{ {
use AsAction; use AsAction;
public function handle(Application $application) public function handle(Application $application)
{ {
if ($application->destination->server->isSwarm()) { if ($application->destination->server->isSwarm()) {
instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server); instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server);
return; return;
} }

View File

@ -9,6 +9,7 @@ use Lorisleiva\Actions\Concerns\AsAction;
class StopApplicationOneServer class StopApplicationOneServer
{ {
use AsAction; use AsAction;
public function handle(Application $application, Server $server) public function handle(Application $application, Server $server)
{ {
if ($application->destination->server->isSwarm()) { if ($application->destination->server->isSwarm()) {
@ -32,6 +33,7 @@ class StopApplicationOneServer
} }
} catch (\Exception $e) { } catch (\Exception $e) {
ray($e->getMessage()); ray($e->getMessage());
return $e->getMessage(); return $e->getMessage();
} }
} }

View File

@ -14,6 +14,7 @@ use Spatie\Activitylog\Models\Activity;
class PrepareCoolifyTask class PrepareCoolifyTask
{ {
protected Activity $activity; protected Activity $activity;
protected CoolifyTaskArgs $remoteProcessArgs; protected CoolifyTaskArgs $remoteProcessArgs;
public function __construct(CoolifyTaskArgs $remoteProcessArgs) public function __construct(CoolifyTaskArgs $remoteProcessArgs)
@ -28,12 +29,12 @@ class PrepareCoolifyTask
->withProperties($properties) ->withProperties($properties)
->performedOn($remoteProcessArgs->model) ->performedOn($remoteProcessArgs->model)
->event($remoteProcessArgs->type) ->event($remoteProcessArgs->type)
->log("[]"); ->log('[]');
} else { } else {
$this->activity = activity() $this->activity = activity()
->withProperties($remoteProcessArgs->toArray()) ->withProperties($remoteProcessArgs->toArray())
->event($remoteProcessArgs->type) ->event($remoteProcessArgs->type)
->log("[]"); ->log('[]');
} }
} }
@ -42,6 +43,7 @@ class PrepareCoolifyTask
$job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish, call_event_data: $this->remoteProcessArgs->call_event_data); $job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish, call_event_data: $this->remoteProcessArgs->call_event_data);
dispatch($job); dispatch($job);
$this->activity->refresh(); $this->activity->refresh();
return $this->activity; return $this->activity;
} }
} }

View File

@ -69,7 +69,7 @@ class RunRemoteProcess
return collect($decoded) return collect($decoded)
->sortBy(fn ($i) => $i['order']) ->sortBy(fn ($i) => $i['order'])
->map(fn ($i) => $i['output']) ->map(fn ($i) => $i['output'])
->implode(""); ->implode('');
} }
public function __invoke(): ProcessResult public function __invoke(): ProcessResult
@ -116,7 +116,7 @@ class RunRemoteProcess
try { try {
if ($this->call_event_data) { if ($this->call_event_data) {
event(resolve("App\\Events\\$this->call_event_on_finish", [ event(resolve("App\\Events\\$this->call_event_on_finish", [
"data" => $this->call_event_data, 'data' => $this->call_event_data,
])); ]));
} else { } else {
event(resolve("App\\Events\\$this->call_event_on_finish", [ event(resolve("App\\Events\\$this->call_event_on_finish", [
@ -127,6 +127,7 @@ class RunRemoteProcess
ray($e); ray($e);
} }
} }
return $processResult; return $processResult;
} }
@ -182,6 +183,7 @@ class RunRemoteProcess
if ($description === null || count($description) === 0) { if ($description === null || count($description) === 0) {
return 1; return 1;
} }
return end($description)['order'] + 1; return end($description)['order'] + 1;
} }

View File

@ -4,22 +4,23 @@ namespace App\Actions\Database;
use App\Models\StandaloneClickhouse; use App\Models\StandaloneClickhouse;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartClickhouse class StartClickhouse
{ {
use AsAction; use AsAction;
public StandaloneClickhouse $database; public StandaloneClickhouse $database;
public array $commands = []; public array $commands = [];
public string $configuration_dir; public string $configuration_dir;
public function handle(StandaloneClickhouse $database) public function handle(StandaloneClickhouse $database)
{ {
$this->database = $database; $this->database = $database;
$container_name = $this->database->uuid; $container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->configuration_dir = database_configuration_dir().'/'.$container_name;
@ -57,7 +58,7 @@ class StartClickhouse
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -65,15 +66,15 @@ class StartClickhouse
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -82,10 +83,10 @@ class StartClickhouse
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -111,6 +112,7 @@ class StartClickhouse
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -125,6 +127,7 @@ class StartClickhouse
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -141,6 +144,7 @@ class StartClickhouse
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }

View File

@ -101,7 +101,7 @@ class StartDatabaseProxy
} }
} }
EOF; EOF;
$dockerfile = <<< EOF $dockerfile = <<< 'EOF'
FROM nginx:stable-alpine FROM nginx:stable-alpine
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf
@ -113,7 +113,7 @@ class StartDatabaseProxy
'context' => $configuration_dir, 'context' => $configuration_dir,
'dockerfile' => 'Dockerfile', 'dockerfile' => 'Dockerfile',
], ],
'image' => "nginx:stable-alpine", 'image' => 'nginx:stable-alpine',
'container_name' => $proxyContainerName, 'container_name' => $proxyContainerName,
'restart' => RESTART_MODE, 'restart' => RESTART_MODE,
'ports' => [ 'ports' => [
@ -130,17 +130,17 @@ class StartDatabaseProxy
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 3, 'retries' => 3,
'start_period' => '1s' 'start_period' => '1s',
],
], ],
]
], ],
'networks' => [ 'networks' => [
$network => [ $network => [
'external' => true, 'external' => true,
'name' => $network, 'name' => $network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
$dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2)); $dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2));
$nginxconf_base64 = base64_encode($nginxconf); $nginxconf_base64 = base64_encode($nginxconf);

View File

@ -3,19 +3,19 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Models\StandaloneDragonfly; use App\Models\StandaloneDragonfly;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartDragonfly class StartDragonfly
{ {
use AsAction; use AsAction;
public StandaloneDragonfly $database; public StandaloneDragonfly $database;
public array $commands = [];
public string $configuration_dir;
public array $commands = [];
public string $configuration_dir;
public function handle(StandaloneDragonfly $database) public function handle(StandaloneDragonfly $database)
{ {
@ -48,7 +48,7 @@ class StartDragonfly
$this->database->destination->network, $this->database->destination->network,
], ],
'ulimits' => [ 'ulimits' => [
'memlock'=> '-1' 'memlock' => '-1',
], ],
'labels' => [ 'labels' => [
'coolify.managed' => 'true', 'coolify.managed' => 'true',
@ -58,7 +58,7 @@ class StartDragonfly
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -66,15 +66,15 @@ class StartDragonfly
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -83,10 +83,10 @@ class StartDragonfly
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -112,6 +112,7 @@ class StartDragonfly
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -126,6 +127,7 @@ class StartDragonfly
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -142,6 +144,7 @@ class StartDragonfly
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }

View File

@ -5,17 +5,18 @@ namespace App\Actions\Database;
use App\Models\StandaloneKeydb; use App\Models\StandaloneKeydb;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartKeydb class StartKeydb
{ {
use AsAction; use AsAction;
public StandaloneKeydb $database; public StandaloneKeydb $database;
public array $commands = [];
public string $configuration_dir;
public array $commands = [];
public string $configuration_dir;
public function handle(StandaloneKeydb $database) public function handle(StandaloneKeydb $database)
{ {
@ -56,7 +57,7 @@ class StartKeydb
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -64,15 +65,15 @@ class StartKeydb
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -81,10 +82,10 @@ class StartKeydb
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -119,6 +120,7 @@ class StartKeydb
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -133,6 +135,7 @@ class StartKeydb
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -149,6 +152,7 @@ class StartKeydb
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
@ -165,6 +169,7 @@ class StartKeydb
return $environment_variables->all(); return $environment_variables->all();
} }
private function add_custom_keydb() private function add_custom_keydb()
{ {
if (is_null($this->database->keydb_conf) || empty($this->database->keydb_conf)) { if (is_null($this->database->keydb_conf) || empty($this->database->keydb_conf)) {

View File

@ -4,15 +4,17 @@ namespace App\Actions\Database;
use App\Models\StandaloneMariadb; use App\Models\StandaloneMariadb;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartMariadb class StartMariadb
{ {
use AsAction; use AsAction;
public StandaloneMariadb $database; public StandaloneMariadb $database;
public array $commands = []; public array $commands = [];
public string $configuration_dir; public string $configuration_dir;
public function handle(StandaloneMariadb $database) public function handle(StandaloneMariadb $database)
@ -46,11 +48,11 @@ class StartMariadb
'coolify.managed' => 'true', 'coolify.managed' => 'true',
], ],
'healthcheck' => [ 'healthcheck' => [
'test' => ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"], 'test' => ['CMD', 'healthcheck.sh', '--connect', '--innodb_initialized'],
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -58,15 +60,15 @@ class StartMariadb
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -75,10 +77,10 @@ class StartMariadb
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -112,6 +114,7 @@ class StartMariadb
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -126,6 +129,7 @@ class StartMariadb
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -142,6 +146,7 @@ class StartMariadb
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
@ -166,8 +171,10 @@ class StartMariadb
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_PASSWORD'))->isEmpty()) {
$environment_variables->push("MARIADB_PASSWORD={$this->database->mariadb_password}"); $environment_variables->push("MARIADB_PASSWORD={$this->database->mariadb_password}");
} }
return $environment_variables->all(); return $environment_variables->all();
} }
private function add_custom_mysql() private function add_custom_mysql()
{ {
if (is_null($this->database->mariadb_conf) || empty($this->database->mariadb_conf)) { if (is_null($this->database->mariadb_conf) || empty($this->database->mariadb_conf)) {

View File

@ -4,22 +4,24 @@ namespace App\Actions\Database;
use App\Models\StandaloneMongodb; use App\Models\StandaloneMongodb;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartMongodb class StartMongodb
{ {
use AsAction; use AsAction;
public StandaloneMongodb $database; public StandaloneMongodb $database;
public array $commands = []; public array $commands = [];
public string $configuration_dir; public string $configuration_dir;
public function handle(StandaloneMongodb $database) public function handle(StandaloneMongodb $database)
{ {
$this->database = $database; $this->database = $database;
$startCommand = "mongod"; $startCommand = 'mongod';
$container_name = $this->database->uuid; $container_name = $this->database->uuid;
$this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->configuration_dir = database_configuration_dir().'/'.$container_name;
@ -51,14 +53,14 @@ class StartMongodb
], ],
'healthcheck' => [ 'healthcheck' => [
'test' => [ 'test' => [
"CMD", 'CMD',
"echo", 'echo',
"ok" 'ok',
], ],
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -66,15 +68,15 @@ class StartMongodb
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -83,10 +85,10 @@ class StartMongodb
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -129,6 +131,7 @@ class StartMongodb
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -143,6 +146,7 @@ class StartMongodb
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -159,6 +163,7 @@ class StartMongodb
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
@ -180,8 +185,10 @@ class StartMongodb
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) {
$environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}"); $environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}");
} }
return $environment_variables->all(); return $environment_variables->all();
} }
private function add_custom_mongo_conf() private function add_custom_mongo_conf()
{ {
if (is_null($this->database->mongo_conf) || empty($this->database->mongo_conf)) { if (is_null($this->database->mongo_conf) || empty($this->database->mongo_conf)) {
@ -192,6 +199,7 @@ class StartMongodb
$content_base64 = base64_encode($content); $content_base64 = base64_encode($content);
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null"; $this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null";
} }
private function add_default_database() private function add_default_database()
{ {
$content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});"; $content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});";

View File

@ -4,15 +4,17 @@ namespace App\Actions\Database;
use App\Models\StandaloneMysql; use App\Models\StandaloneMysql;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartMysql class StartMysql
{ {
use AsAction; use AsAction;
public StandaloneMysql $database; public StandaloneMysql $database;
public array $commands = []; public array $commands = [];
public string $configuration_dir; public string $configuration_dir;
public function handle(StandaloneMysql $database) public function handle(StandaloneMysql $database)
@ -46,11 +48,11 @@ class StartMysql
'coolify.managed' => 'true', 'coolify.managed' => 'true',
], ],
'healthcheck' => [ 'healthcheck' => [
'test' => ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p{$this->database->mysql_root_password}"], 'test' => ['CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', "-p{$this->database->mysql_root_password}"],
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -58,15 +60,15 @@ class StartMysql
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -75,10 +77,10 @@ class StartMysql
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -112,6 +114,7 @@ class StartMysql
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -126,6 +129,7 @@ class StartMysql
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -142,6 +146,7 @@ class StartMysql
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
@ -166,8 +171,10 @@ class StartMysql
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_PASSWORD'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_PASSWORD'))->isEmpty()) {
$environment_variables->push("MYSQL_PASSWORD={$this->database->mysql_password}"); $environment_variables->push("MYSQL_PASSWORD={$this->database->mysql_password}");
} }
return $environment_variables->all(); return $environment_variables->all();
} }
private function add_custom_mysql() private function add_custom_mysql()
{ {
if (is_null($this->database->mysql_conf) || empty($this->database->mysql_conf)) { if (is_null($this->database->mysql_conf) || empty($this->database->mysql_conf)) {

View File

@ -4,16 +4,19 @@ namespace App\Actions\Database;
use App\Models\StandalonePostgresql; use App\Models\StandalonePostgresql;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartPostgresql class StartPostgresql
{ {
use AsAction; use AsAction;
public StandalonePostgresql $database; public StandalonePostgresql $database;
public array $commands = []; public array $commands = [];
public array $init_scripts = []; public array $init_scripts = [];
public string $configuration_dir; public string $configuration_dir;
public function handle(StandalonePostgresql $database) public function handle(StandalonePostgresql $database)
@ -25,7 +28,7 @@ class StartPostgresql
$this->commands = [ $this->commands = [
"echo 'Starting {$database->name}.'", "echo 'Starting {$database->name}.'",
"mkdir -p $this->configuration_dir", "mkdir -p $this->configuration_dir",
"mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d/" "mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d/",
]; ];
$persistent_storages = $this->generate_local_persistent_volumes(); $persistent_storages = $this->generate_local_persistent_volumes();
@ -50,13 +53,13 @@ class StartPostgresql
], ],
'healthcheck' => [ 'healthcheck' => [
'test' => [ 'test' => [
"CMD-SHELL", 'CMD-SHELL',
"psql -U {$this->database->postgres_user} -d {$this->database->postgres_db} -c 'SELECT 1' || exit 1" "psql -U {$this->database->postgres_user} -d {$this->database->postgres_db} -c 'SELECT 1' || exit 1",
], ],
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -64,15 +67,15 @@ class StartPostgresql
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -81,10 +84,10 @@ class StartPostgresql
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -133,6 +136,7 @@ class StartPostgresql
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -147,6 +151,7 @@ class StartPostgresql
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -163,6 +168,7 @@ class StartPostgresql
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
@ -187,6 +193,7 @@ class StartPostgresql
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_DB'))->isEmpty()) { if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_DB'))->isEmpty()) {
$environment_variables->push("POSTGRES_DB={$this->database->postgres_db}"); $environment_variables->push("POSTGRES_DB={$this->database->postgres_db}");
} }
return $environment_variables->all(); return $environment_variables->all();
} }
@ -203,6 +210,7 @@ class StartPostgresql
$this->init_scripts[] = "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}"; $this->init_scripts[] = "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}";
} }
} }
private function add_custom_conf() private function add_custom_conf()
{ {
if (is_null($this->database->postgres_conf) || empty($this->database->postgres_conf)) { if (is_null($this->database->postgres_conf) || empty($this->database->postgres_conf)) {

View File

@ -5,17 +5,18 @@ namespace App\Actions\Database;
use App\Models\StandaloneRedis; use App\Models\StandaloneRedis;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\Yaml\Yaml;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml;
class StartRedis class StartRedis
{ {
use AsAction; use AsAction;
public StandaloneRedis $database; public StandaloneRedis $database;
public array $commands = [];
public string $configuration_dir;
public array $commands = [];
public string $configuration_dir;
public function handle(StandaloneRedis $database) public function handle(StandaloneRedis $database)
{ {
@ -55,12 +56,12 @@ class StartRedis
'test' => [ 'test' => [
'CMD-SHELL', 'CMD-SHELL',
'redis-cli', 'redis-cli',
'ping' 'ping',
], ],
'interval' => '5s', 'interval' => '5s',
'timeout' => '5s', 'timeout' => '5s',
'retries' => 10, 'retries' => 10,
'start_period' => '5s' 'start_period' => '5s',
], ],
'mem_limit' => $this->database->limits_memory, 'mem_limit' => $this->database->limits_memory,
'memswap_limit' => $this->database->limits_memory_swap, 'memswap_limit' => $this->database->limits_memory_swap,
@ -68,15 +69,15 @@ class StartRedis
'mem_reservation' => $this->database->limits_memory_reservation, 'mem_reservation' => $this->database->limits_memory_reservation,
'cpus' => (float) $this->database->limits_cpus, 'cpus' => (float) $this->database->limits_cpus,
'cpu_shares' => $this->database->limits_cpu_shares, 'cpu_shares' => $this->database->limits_cpu_shares,
] ],
], ],
'networks' => [ 'networks' => [
$this->database->destination->network => [ $this->database->destination->network => [
'external' => true, 'external' => true,
'name' => $this->database->destination->network, 'name' => $this->database->destination->network,
'attachable' => true, 'attachable' => true,
] ],
] ],
]; ];
if (! is_null($this->database->limits_cpuset)) { if (! is_null($this->database->limits_cpuset)) {
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
@ -85,10 +86,10 @@ class StartRedis
$docker_compose['services'][$container_name]['logging'] = [ $docker_compose['services'][$container_name]['logging'] = [
'driver' => 'fluentd', 'driver' => 'fluentd',
'options' => [ 'options' => [
'fluentd-address' => "tcp://127.0.0.1:24224", 'fluentd-address' => 'tcp://127.0.0.1:24224',
'fluentd-async' => "true", 'fluentd-async' => 'true',
'fluentd-sub-second-precision' => "true", 'fluentd-sub-second-precision' => 'true',
] ],
]; ];
} }
if (count($this->database->ports_mappings_array) > 0) { if (count($this->database->ports_mappings_array) > 0) {
@ -123,6 +124,7 @@ class StartRedis
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
$this->commands[] = "echo 'Database started.'"; $this->commands[] = "echo 'Database started.'";
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged'); return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
} }
@ -137,6 +139,7 @@ class StartRedis
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path; $local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
} }
} }
return $local_persistent_volumes; return $local_persistent_volumes;
} }
@ -153,6 +156,7 @@ class StartRedis
'external' => false, 'external' => false,
]; ];
} }
return $local_persistent_volumes_names; return $local_persistent_volumes_names;
} }
@ -169,6 +173,7 @@ class StartRedis
return $environment_variables->all(); return $environment_variables->all();
} }
private function add_custom_redis() private function add_custom_redis()
{ {
if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) { if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) {

View File

@ -17,7 +17,9 @@ use Lorisleiva\Actions\Concerns\AsAction;
class GetContainersStatus class GetContainersStatus
{ {
use AsAction; use AsAction;
public $applications; public $applications;
public $server; public $server;
public function handle(Server $server) public function handle(Server $server)
@ -28,7 +30,7 @@ class GetContainersStatus
$this->server = $server; $this->server = $server;
if (! $this->server->isFunctional()) { if (! $this->server->isFunctional()) {
return 'Server is not ready.'; return 'Server is not ready.';
}; }
$this->applications = $this->server->applications(); $this->applications = $this->server->applications();
$skip_these_applications = collect([]); $skip_these_applications = collect([]);
foreach ($this->applications as $application) { foreach ($this->applications as $application) {
@ -239,7 +241,7 @@ class GetContainersStatus
$environmentName = data_get($service, 'environment.name'); $environmentName = data_get($service, 'environment.name');
if ($projectUuid && $serviceUuid && $environmentName) { if ($projectUuid && $serviceUuid && $environmentName) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/service/'.$serviceUuid;
} else { } else {
$url = null; $url = null;
} }
@ -265,7 +267,7 @@ class GetContainersStatus
$environment = data_get($application, 'environment.name'); $environment = data_get($application, 'environment.name');
if ($projectUuid && $applicationUuid && $environment) { if ($projectUuid && $applicationUuid && $environment) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environment.'/application/'.$applicationUuid;
} else { } else {
$url = null; $url = null;
} }
@ -290,7 +292,7 @@ class GetContainersStatus
$applicationUuid = data_get($preview, 'application.uuid'); $applicationUuid = data_get($preview, 'application.uuid');
if ($projectUuid && $applicationUuid && $environmentName) { if ($projectUuid && $applicationUuid && $environmentName) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid;
} else { } else {
$url = null; $url = null;
} }
@ -315,7 +317,7 @@ class GetContainersStatus
$databaseUuid = data_get($database, 'uuid'); $databaseUuid = data_get($database, 'uuid');
if ($projectUuid && $databaseUuid && $environmentName) { if ($projectUuid && $databaseUuid && $environmentName) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid;
} else { } else {
$url = null; $url = null;
} }
@ -351,9 +353,11 @@ class GetContainersStatus
} catch (\Exception $e) { } catch (\Exception $e) {
// send_internal_notification("ContainerStatusJob failed on ({$this->server->id}) with: " . $e->getMessage()); // send_internal_notification("ContainerStatusJob failed on ({$this->server->id}) with: " . $e->getMessage());
ray($e->getMessage()); ray($e->getMessage());
return handleError($e); return handleError($e);
} }
} }
private function old_way() private function old_way()
{ {
if ($this->server->isSwarm()) { if ($this->server->isSwarm()) {
@ -361,7 +365,7 @@ class GetContainersStatus
$containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this->server, false); $containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this->server, false);
} else { } else {
// Precheck for containers // Precheck for containers
$containers = instant_remote_process(["docker container ls -q"], $this->server, false); $containers = instant_remote_process(['docker container ls -q'], $this->server, false);
if (! $containers) { if (! $containers) {
return; return;
} }
@ -390,6 +394,7 @@ class GetContainersStatus
data_set($container, 'State.Health.Status', 'unhealthy'); data_set($container, 'State.Health.Status', 'unhealthy');
} }
} }
return $container; return $container;
}); });
} }
@ -569,7 +574,7 @@ class GetContainersStatus
$environmentName = data_get($service, 'environment.name'); $environmentName = data_get($service, 'environment.name');
if ($projectUuid && $serviceUuid && $environmentName) { if ($projectUuid && $serviceUuid && $environmentName) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/service/'.$serviceUuid;
} else { } else {
$url = null; $url = null;
} }
@ -595,7 +600,7 @@ class GetContainersStatus
$environment = data_get($application, 'environment.name'); $environment = data_get($application, 'environment.name');
if ($projectUuid && $applicationUuid && $environment) { if ($projectUuid && $applicationUuid && $environment) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environment.'/application/'.$applicationUuid;
} else { } else {
$url = null; $url = null;
} }
@ -620,7 +625,7 @@ class GetContainersStatus
$applicationUuid = data_get($preview, 'application.uuid'); $applicationUuid = data_get($preview, 'application.uuid');
if ($projectUuid && $applicationUuid && $environmentName) { if ($projectUuid && $applicationUuid && $environmentName) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid;
} else { } else {
$url = null; $url = null;
} }
@ -645,7 +650,7 @@ class GetContainersStatus
$databaseUuid = data_get($database, 'uuid'); $databaseUuid = data_get($database, 'uuid');
if ($projectUuid && $databaseUuid && $environmentName) { if ($projectUuid && $databaseUuid && $environmentName) {
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid; $url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid;
} else { } else {
$url = null; $url = null;
} }

View File

@ -66,6 +66,7 @@ class CreateNewUser implements CreatesNewUsers
} }
// Set session variable // Set session variable
session(['currentTeam' => $user->currentTeam = $team]); session(['currentTeam' => $user->currentTeam = $team]);
return $user; return $user;
} }
} }

View File

@ -6,10 +6,10 @@ use App\Models\InstanceSettings;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
class CheckResaleLicense class CheckResaleLicense
{ {
use AsAction; use AsAction;
public function handle() public function handle()
{ {
try { try {
@ -18,6 +18,7 @@ class CheckResaleLicense
$settings->update([ $settings->update([
'is_resale_license_active' => true, 'is_resale_license_active' => true,
]); ]);
return; return;
} }
// if (!$settings->resale_license) { // if (!$settings->resale_license) {
@ -38,6 +39,7 @@ class CheckResaleLicense
$settings->update([ $settings->update([
'is_resale_license_active' => true, 'is_resale_license_active' => true,
]); ]);
return; return;
} }
$data = Http::withHeaders([ $data = Http::withHeaders([
@ -51,6 +53,7 @@ class CheckResaleLicense
$settings->update([ $settings->update([
'is_resale_license_active' => true, 'is_resale_license_active' => true,
]); ]);
return; return;
} }
if (data_get($data, 'license_key.status') === 'active') { if (data_get($data, 'license_key.status') === 'active') {

View File

@ -2,13 +2,14 @@
namespace App\Actions\Proxy; namespace App\Actions\Proxy;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Lorisleiva\Actions\Concerns\AsAction;
class CheckConfiguration class CheckConfiguration
{ {
use AsAction; use AsAction;
public function handle(Server $server, bool $reset = false) public function handle(Server $server, bool $reset = false)
{ {
$proxyType = $server->proxyType(); $proxyType = $server->proxyType();
@ -26,8 +27,9 @@ class CheckConfiguration
$proxy_configuration = Str::of(generate_default_proxy_configuration($server))->trim()->value; $proxy_configuration = Str::of(generate_default_proxy_configuration($server))->trim()->value;
} }
if (! $proxy_configuration || is_null($proxy_configuration)) { if (! $proxy_configuration || is_null($proxy_configuration)) {
throw new \Exception("Could not generate proxy configuration"); throw new \Exception('Could not generate proxy configuration');
} }
return $proxy_configuration; return $proxy_configuration;
} }
} }

View File

@ -8,6 +8,7 @@ use Lorisleiva\Actions\Concerns\AsAction;
class CheckProxy class CheckProxy
{ {
use AsAction; use AsAction;
public function handle(Server $server, $fromUI = false) public function handle(Server $server, $fromUI = false)
{ {
if (! $server->isFunctional()) { if (! $server->isFunctional()) {
@ -18,6 +19,7 @@ class CheckProxy
$server->proxy = null; $server->proxy = null;
$server->save(); $server->save();
} }
return false; return false;
} }
$proxyType = $server->proxyType(); $proxyType = $server->proxyType();
@ -30,7 +32,7 @@ class CheckProxy
} }
if (! $server->isProxyShouldRun()) { if (! $server->isProxyShouldRun()) {
if ($fromUI) { if ($fromUI) {
throw new \Exception("Proxy should not run. You selected the Custom Proxy."); throw new \Exception('Proxy should not run. You selected the Custom Proxy.');
} else { } else {
return false; return false;
} }
@ -42,12 +44,14 @@ class CheckProxy
if ($status === 'running') { if ($status === 'running') {
return false; return false;
} }
return true; return true;
} else { } else {
$status = getContainerStatus($server, 'coolify-proxy'); $status = getContainerStatus($server, 'coolify-proxy');
if ($status === 'running') { if ($status === 'running') {
$server->proxy->set('status', 'running'); $server->proxy->set('status', 'running');
$server->save(); $server->save();
return false; return false;
} }
if ($server->settings->is_cloudflare_tunnel) { if ($server->settings->is_cloudflare_tunnel) {
@ -76,6 +80,7 @@ class CheckProxy
return false; return false;
} }
} }
return true; return true;
} }
} }

View File

@ -11,6 +11,7 @@ use Spatie\Activitylog\Models\Activity;
class StartProxy class StartProxy
{ {
use AsAction; use AsAction;
public function handle(Server $server, bool $async = true): string|Activity public function handle(Server $server, bool $async = true): string|Activity
{ {
try { try {
@ -22,7 +23,7 @@ class StartProxy
$proxy_path = $server->proxyPath(); $proxy_path = $server->proxyPath();
$configuration = CheckConfiguration::run($server); $configuration = CheckConfiguration::run($server);
if (! $configuration) { if (! $configuration) {
throw new \Exception("Configuration is not synced"); throw new \Exception('Configuration is not synced');
} }
SaveConfiguration::run($server, $configuration); SaveConfiguration::run($server, $configuration);
$docker_compose_yml_base64 = base64_encode($configuration); $docker_compose_yml_base64 = base64_encode($configuration);
@ -34,11 +35,11 @@ class StartProxy
"cd $proxy_path", "cd $proxy_path",
"echo 'Creating required Docker Compose file.'", "echo 'Creating required Docker Compose file.'",
"echo 'Starting coolify-proxy.'", "echo 'Starting coolify-proxy.'",
"docker stack deploy -c docker-compose.yml coolify-proxy", 'docker stack deploy -c docker-compose.yml coolify-proxy',
"echo 'Proxy started successfully.'" "echo 'Proxy started successfully.'",
]); ]);
} else { } else {
$caddfile = "import /dynamic/*.caddy"; $caddfile = 'import /dynamic/*.caddy';
$commands = $commands->merge([ $commands = $commands->merge([
"mkdir -p $proxy_path/dynamic", "mkdir -p $proxy_path/dynamic",
"cd $proxy_path", "cd $proxy_path",
@ -47,16 +48,17 @@ class StartProxy
"echo 'Pulling docker image.'", "echo 'Pulling docker image.'",
'docker compose pull', 'docker compose pull',
"echo 'Stopping existing coolify-proxy.'", "echo 'Stopping existing coolify-proxy.'",
"docker compose down -v --remove-orphans > /dev/null 2>&1", 'docker compose down -v --remove-orphans > /dev/null 2>&1',
"echo 'Starting coolify-proxy.'", "echo 'Starting coolify-proxy.'",
'docker compose up -d --remove-orphans', 'docker compose up -d --remove-orphans',
"echo 'Proxy started successfully.'" "echo 'Proxy started successfully.'",
]); ]);
$commands = $commands->merge(connectProxyToNetworks($server)); $commands = $commands->merge(connectProxyToNetworks($server));
} }
if ($async) { if ($async) {
$activity = remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server); $activity = remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server);
return $activity; return $activity;
} else { } else {
instant_remote_process($commands, $server); instant_remote_process($commands, $server);
@ -64,6 +66,7 @@ class StartProxy
$server->proxy->set('type', $proxyType); $server->proxy->set('type', $proxyType);
$server->save(); $server->save();
ProxyStarted::dispatch($server); ProxyStarted::dispatch($server);
return 'OK'; return 'OK';
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {

View File

@ -2,12 +2,13 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Server; use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
class CleanupDocker class CleanupDocker
{ {
use AsAction; use AsAction;
public function handle(Server $server, bool $force = true) public function handle(Server $server, bool $force = true)
{ {
if ($force) { if ($force) {

View File

@ -9,18 +9,19 @@ use Symfony\Component\Yaml\Yaml;
class ConfigureCloudflared class ConfigureCloudflared
{ {
use AsAction; use AsAction;
public function handle(Server $server, string $cloudflare_token) public function handle(Server $server, string $cloudflare_token)
{ {
try { try {
$config = [ $config = [
"services" => [ 'services' => [
"coolify-cloudflared" => [ 'coolify-cloudflared' => [
"container_name" => "coolify-cloudflared", 'container_name' => 'coolify-cloudflared',
"image" => "cloudflare/cloudflared:latest", 'image' => 'cloudflare/cloudflared:latest',
"restart" => RESTART_MODE, 'restart' => RESTART_MODE,
"network_mode" => "host", 'network_mode' => 'host',
"command" => "tunnel run", 'command' => 'tunnel run',
"environment" => [ 'environment' => [
"TUNNEL_TOKEN={$cloudflare_token}", "TUNNEL_TOKEN={$cloudflare_token}",
], ],
], ],
@ -29,12 +30,12 @@ class ConfigureCloudflared
$config = Yaml::dump($config, 12, 2); $config = Yaml::dump($config, 12, 2);
$docker_compose_yml_base64 = base64_encode($config); $docker_compose_yml_base64 = base64_encode($config);
$commands = collect([ $commands = collect([
"mkdir -p /tmp/cloudflared", 'mkdir -p /tmp/cloudflared',
"cd /tmp/cloudflared", 'cd /tmp/cloudflared',
"echo '$docker_compose_yml_base64' | base64 -d | tee docker-compose.yml > /dev/null", "echo '$docker_compose_yml_base64' | base64 -d | tee docker-compose.yml > /dev/null",
"docker compose pull", 'docker compose pull',
"docker compose down -v --remove-orphans > /dev/null 2>&1", 'docker compose down -v --remove-orphans > /dev/null 2>&1',
"docker compose up -d --remove-orphans", 'docker compose up -d --remove-orphans',
]); ]);
instant_remote_process($commands, $server); instant_remote_process($commands, $server);
} catch (\Throwable $e) { } catch (\Throwable $e) {
@ -42,7 +43,7 @@ class ConfigureCloudflared
throw $e; throw $e;
} finally { } finally {
$commands = collect([ $commands = collect([
"rm -fr /tmp/cloudflared", 'rm -fr /tmp/cloudflared',
]); ]);
instant_remote_process($commands, $server); instant_remote_process($commands, $server);
} }

View File

@ -2,13 +2,14 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker; use App\Models\StandaloneDocker;
use Lorisleiva\Actions\Concerns\AsAction;
class InstallDocker class InstallDocker
{ {
use AsAction; use AsAction;
public function handle(Server $server) public function handle(Server $server)
{ {
$supported_os_type = $server->validateOS(); $supported_os_type = $server->validateOS();
@ -36,40 +37,41 @@ class InstallDocker
if (isDev() && $server->id === 0) { if (isDev() && $server->id === 0) {
$command = $command->merge([ $command = $command->merge([
"echo 'Installing Prerequisites...'", "echo 'Installing Prerequisites...'",
"sleep 1", 'sleep 1',
"echo 'Installing Docker Engine...'", "echo 'Installing Docker Engine...'",
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'", "echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
"sleep 4", 'sleep 4',
"echo 'Restarting Docker Engine...'", "echo 'Restarting Docker Engine...'",
"ls -l /tmp" 'ls -l /tmp',
]); ]);
return remote_process($command, $server); return remote_process($command, $server);
} else { } else {
if ($supported_os_type->contains('debian')) { if ($supported_os_type->contains('debian')) {
$command = $command->merge([ $command = $command->merge([
"echo 'Installing Prerequisites...'", "echo 'Installing Prerequisites...'",
"apt-get update -y", 'apt-get update -y',
"command -v curl >/dev/null || apt install -y curl", 'command -v curl >/dev/null || apt install -y curl',
"command -v wget >/dev/null || apt install -y wget", 'command -v wget >/dev/null || apt install -y wget',
"command -v git >/dev/null || apt install -y git", 'command -v git >/dev/null || apt install -y git',
"command -v jq >/dev/null || apt install -y jq", 'command -v jq >/dev/null || apt install -y jq',
]); ]);
} elseif ($supported_os_type->contains('rhel')) { } elseif ($supported_os_type->contains('rhel')) {
$command = $command->merge([ $command = $command->merge([
"echo 'Installing Prerequisites...'", "echo 'Installing Prerequisites...'",
"command -v curl >/dev/null || dnf install -y curl", 'command -v curl >/dev/null || dnf install -y curl',
"command -v wget >/dev/null || dnf install -y wget", 'command -v wget >/dev/null || dnf install -y wget',
"command -v git >/dev/null || dnf install -y git", 'command -v git >/dev/null || dnf install -y git',
"command -v jq >/dev/null || dnf install -y jq", 'command -v jq >/dev/null || dnf install -y jq',
]); ]);
} elseif ($supported_os_type->contains('sles')) { } elseif ($supported_os_type->contains('sles')) {
$command = $command->merge([ $command = $command->merge([
"echo 'Installing Prerequisites...'", "echo 'Installing Prerequisites...'",
"zypper update -y", 'zypper update -y',
"command -v curl >/dev/null || zypper install -y curl", 'command -v curl >/dev/null || zypper install -y curl',
"command -v wget >/dev/null || zypper install -y wget", 'command -v wget >/dev/null || zypper install -y wget',
"command -v git >/dev/null || zypper install -y git", 'command -v git >/dev/null || zypper install -y git',
"command -v jq >/dev/null || zypper install -y jq", 'command -v jq >/dev/null || zypper install -y jq',
]); ]);
} else { } else {
throw new \Exception('Unsupported OS'); throw new \Exception('Unsupported OS');
@ -78,29 +80,30 @@ class InstallDocker
"echo 'Installing Docker Engine...'", "echo 'Installing Docker Engine...'",
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}", "curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}",
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'", "echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
"test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json \"/etc/docker/daemon.json.original-$(date +\"%Y%m%d-%H%M%S\")\"", 'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"',
"test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null", "test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null",
"echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null", "echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null",
"jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null", 'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null',
"mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify", 'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify',
"jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null", "jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null",
"mv /etc/docker/daemon.json.appended /etc/docker/daemon.json", 'mv /etc/docker/daemon.json.appended /etc/docker/daemon.json',
"echo 'Restarting Docker Engine...'", "echo 'Restarting Docker Engine...'",
"systemctl enable docker >/dev/null 2>&1 || true", 'systemctl enable docker >/dev/null 2>&1 || true',
"systemctl restart docker", 'systemctl restart docker',
]); ]);
if ($server->isSwarm()) { if ($server->isSwarm()) {
$command = $command->merge([ $command = $command->merge([
"docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true", 'docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true',
]); ]);
} else { } else {
$command = $command->merge([ $command = $command->merge([
"docker network create --attachable coolify >/dev/null 2>&1 || true", 'docker network create --attachable coolify >/dev/null 2>&1 || true',
]); ]);
$command = $command->merge([ $command = $command->merge([
"echo 'Done!'", "echo 'Done!'",
]); ]);
} }
return remote_process($command, $server); return remote_process($command, $server);
} }
} }

View File

@ -2,12 +2,13 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Server; use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
class InstallLogDrain class InstallLogDrain
{ {
use AsAction; use AsAction;
public function handle(Server $server) public function handle(Server $server)
{ {
if ($server->settings->is_logdrain_newrelic_enabled) { if ($server->settings->is_logdrain_newrelic_enabled) {
@ -25,8 +26,9 @@ class InstallLogDrain
if ($type === 'none') { if ($type === 'none') {
$command = [ $command = [
"echo 'Stopping old Fluent Bit'", "echo 'Stopping old Fluent Bit'",
"docker rm -f coolify-log-drain || true", 'docker rm -f coolify-log-drain || true',
]; ];
return instant_remote_process($command, $server); return instant_remote_process($command, $server);
} elseif ($type === 'newrelic') { } elseif ($type === 'newrelic') {
if (! $server->settings->is_logdrain_newrelic_enabled) { if (! $server->settings->is_logdrain_newrelic_enabled) {
@ -63,7 +65,7 @@ class InstallLogDrain
if (! $server->settings->is_logdrain_highlight_enabled) { if (! $server->settings->is_logdrain_highlight_enabled) {
throw new \Exception('Highlight log drain is not enabled.'); throw new \Exception('Highlight log drain is not enabled.');
} }
$config = base64_encode(" $config = base64_encode('
[SERVICE] [SERVICE]
Flush 5 Flush 5
Daemon off Daemon off
@ -71,7 +73,7 @@ class InstallLogDrain
Parsers_File parsers.conf Parsers_File parsers.conf
[INPUT] [INPUT]
Name forward Name forward
tag \${HIGHLIGHT_PROJECT_ID} tag ${HIGHLIGHT_PROJECT_ID}
Buffer_Chunk_Size 1M Buffer_Chunk_Size 1M
Buffer_Max_Size 6M Buffer_Max_Size 6M
[OUTPUT] [OUTPUT]
@ -79,7 +81,7 @@ class InstallLogDrain
Match * Match *
Host otel.highlight.io Host otel.highlight.io
Port 24224 Port 24224
"); ');
} elseif ($type === 'axiom') { } elseif ($type === 'axiom') {
if (! $server->settings->is_logdrain_axiom_enabled) { if (! $server->settings->is_logdrain_axiom_enabled) {
throw new \Exception('Axiom log drain is not enabled.'); throw new \Exception('Axiom log drain is not enabled.');
@ -133,7 +135,7 @@ class InstallLogDrain
Regex /^(?!\s*$).+/ Regex /^(?!\s*$).+/
"); ");
} }
$compose = base64_encode(" $compose = base64_encode('
services: services:
coolify-log-drain: coolify-log-drain:
image: cr.fluentbit.io/fluent/fluent-bit:2.0 image: cr.fluentbit.io/fluent/fluent-bit:2.0
@ -147,7 +149,7 @@ services:
ports: ports:
- 127.0.0.1:24224:24224 - 127.0.0.1:24224:24224
restart: unless-stopped restart: unless-stopped
"); ');
$readme = base64_encode('# New Relic Log Drain $readme = base64_encode('# New Relic Log Drain
This log drain is based on [Fluent Bit](https://fluentbit.io/) and New Relic Log Forwarder. This log drain is based on [Fluent Bit](https://fluentbit.io/) and New Relic Log Forwarder.
@ -191,7 +193,7 @@ Files:
]; ];
} elseif ($type === 'custom') { } elseif ($type === 'custom') {
$add_envs_command = [ $add_envs_command = [
"touch $config_path/.env" "touch $config_path/.env",
]; ];
} else { } else {
throw new \Exception('Unknown log drain type.'); throw new \Exception('Unknown log drain type.');
@ -203,6 +205,7 @@ Files:
"cd $config_path && docker compose up -d --remove-orphans", "cd $config_path && docker compose up -d --remove-orphans",
]; ];
$command = array_merge($command, $add_envs_command, $restart_command); $command = array_merge($command, $add_envs_command, $restart_command);
return instant_remote_process($command, $server); return instant_remote_process($command, $server);
} catch (\Throwable $e) { } catch (\Throwable $e) {
return handleError($e); return handleError($e);

View File

@ -2,12 +2,13 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Server; use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
class StartSentinel class StartSentinel
{ {
use AsAction; use AsAction;
public function handle(Server $server, $version = 'latest', bool $restart = false) public function handle(Server $server, $version = 'latest', bool $restart = false)
{ {
if ($restart) { if ($restart) {
@ -15,8 +16,8 @@ class StartSentinel
} }
instant_remote_process([ instant_remote_process([
"docker run --rm --pull always -d -e \"SCHEDULER=true\" --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v /data/coolify/metrics:/app/metrics -v /data/coolify/logs:/app/logs --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 ghcr.io/coollabsio/sentinel:$version", "docker run --rm --pull always -d -e \"SCHEDULER=true\" --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v /data/coolify/metrics:/app/metrics -v /data/coolify/logs:/app/logs --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 ghcr.io/coollabsio/sentinel:$version",
"chown -R 9999:root /data/coolify/metrics /data/coolify/logs", 'chown -R 9999:root /data/coolify/metrics /data/coolify/logs',
"chmod -R 700 /data/coolify/metrics /data/coolify/logs" 'chmod -R 700 /data/coolify/metrics /data/coolify/logs',
], $server, false); ], $server, false);
} }
} }

View File

@ -2,15 +2,18 @@
namespace App\Actions\Server; namespace App\Actions\Server;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use App\Models\Server; use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
class UpdateCoolify class UpdateCoolify
{ {
use AsAction; use AsAction;
public ?Server $server = null; public ?Server $server = null;
public ?string $latestVersion = null; public ?string $latestVersion = null;
public ?string $currentVersion = null; public ?string $currentVersion = null;
public function handle($manual_update = false) public function handle($manual_update = false)
@ -46,14 +49,15 @@ class UpdateCoolify
{ {
if (isDev()) { if (isDev()) {
remote_process([ remote_process([
"sleep 10" 'sleep 10',
], $this->server); ], $this->server);
return; return;
} }
remote_process([ remote_process([
"curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh", 'curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh',
"bash /data/coolify/source/upgrade.sh $this->latestVersion" "bash /data/coolify/source/upgrade.sh $this->latestVersion",
], $this->server); ], $this->server);
return;
} }
} }

View File

@ -2,12 +2,13 @@
namespace App\Actions\Service; namespace App\Actions\Service;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Service; use App\Models\Service;
use Lorisleiva\Actions\Concerns\AsAction;
class DeleteService class DeleteService
{ {
use AsAction; use AsAction;
public function handle(Service $service) public function handle(Service $service)
{ {
try { try {

View File

@ -2,26 +2,27 @@
namespace App\Actions\Service; namespace App\Actions\Service;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Service; use App\Models\Service;
use Lorisleiva\Actions\Concerns\AsAction;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
class StartService class StartService
{ {
use AsAction; use AsAction;
public function handle(Service $service) public function handle(Service $service)
{ {
ray('Starting service: '.$service->name); ray('Starting service: '.$service->name);
$service->saveComposeConfigs(); $service->saveComposeConfigs();
$commands[] = "cd " . $service->workdir(); $commands[] = 'cd '.$service->workdir();
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'"; $commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
$commands[] = "echo 'Creating Docker network.'"; $commands[] = "echo 'Creating Docker network.'";
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid"; $commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
$commands[] = "echo Starting service."; $commands[] = 'echo Starting service.';
$commands[] = "echo 'Pulling images.'"; $commands[] = "echo 'Pulling images.'";
$commands[] = "docker compose pull"; $commands[] = 'docker compose pull';
$commands[] = "echo 'Starting containers.'"; $commands[] = "echo 'Starting containers.'";
$commands[] = "docker compose up -d --remove-orphans --force-recreate --build"; $commands[] = 'docker compose up -d --remove-orphans --force-recreate --build';
$commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true"; $commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true";
if (data_get($service, 'connect_to_docker_network')) { if (data_get($service, 'connect_to_docker_network')) {
$compose = data_get($service, 'docker_compose', []); $compose = data_get($service, 'docker_compose', []);
@ -32,6 +33,7 @@ class StartService
} }
} }
$activity = remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged'); $activity = remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged');
return $activity; return $activity;
} }
} }

View File

@ -2,12 +2,13 @@
namespace App\Actions\Service; namespace App\Actions\Service;
use Lorisleiva\Actions\Concerns\AsAction;
use App\Models\Service; use App\Models\Service;
use Lorisleiva\Actions\Concerns\AsAction;
class StopService class StopService
{ {
use AsAction; use AsAction;
public function handle(Service $service) public function handle(Service $service)
{ {
try { try {
@ -33,6 +34,7 @@ class StopService
} catch (\Exception $e) { } catch (\Exception $e) {
echo $e->getMessage(); echo $e->getMessage();
ray($e->getMessage()); ray($e->getMessage());
return $e->getMessage(); return $e->getMessage();
} }

View File

@ -8,6 +8,7 @@ use Lorisleiva\Actions\Concerns\AsAction;
class ComplexStatusCheck class ComplexStatusCheck
{ {
use AsAction; use AsAction;
public function handle(Application $application) public function handle(Application $application)
{ {
$servers = $application->additional_servers; $servers = $application->additional_servers;
@ -17,9 +18,11 @@ class ComplexStatusCheck
if (! $server->isFunctional()) { if (! $server->isFunctional()) {
if ($is_main_server) { if ($is_main_server) {
$application->update(['status' => 'exited:unhealthy']); $application->update(['status' => 'exited:unhealthy']);
continue; continue;
} else { } else {
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']); $application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
continue; continue;
} }
} }
@ -44,9 +47,11 @@ class ComplexStatusCheck
} else { } else {
if ($is_main_server) { if ($is_main_server) {
$application->update(['status' => 'exited:unhealthy']); $application->update(['status' => 'exited:unhealthy']);
continue; continue;
} else { } else {
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']); $application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
continue; continue;
} }
} }

View File

@ -8,17 +8,20 @@ use Lorisleiva\Actions\Concerns\AsAction;
class PullImage class PullImage
{ {
use AsAction; use AsAction;
public function handle(Service $resource) public function handle(Service $resource)
{ {
$resource->saveComposeConfigs(); $resource->saveComposeConfigs();
$commands[] = "cd " . $resource->workdir(); $commands[] = 'cd '.$resource->workdir();
$commands[] = "echo 'Saved configuration files to {$resource->workdir()}.'"; $commands[] = "echo 'Saved configuration files to {$resource->workdir()}.'";
$commands[] = "docker compose pull"; $commands[] = 'docker compose pull';
$server = data_get($resource, 'server'); $server = data_get($resource, 'server');
if (!$server) return; if (! $server) {
return;
}
instant_remote_process($commands, $resource->server); instant_remote_process($commands, $resource->server);
} }

View File

@ -2,7 +2,6 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Models\Server;
use App\Models\User; use App\Models\User;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@ -32,6 +31,7 @@ class AdminRemoveUser extends Command
$confirm = $this->confirm('Are you sure you want to remove user with email: '.$email.'?'); $confirm = $this->confirm('Are you sure you want to remove user with email: '.$email.'?');
if (! $confirm) { if (! $confirm) {
$this->info('User removal cancelled.'); $this->info('User removal cancelled.');
return; return;
} }
$this->info("Removing user with email: $email"); $this->info("Removing user with email: $email");
@ -40,6 +40,7 @@ class AdminRemoveUser extends Command
foreach ($teams as $team) { foreach ($teams as $team) {
if ($team->members->count() > 1) { if ($team->members->count() > 1) {
$this->error('User is a member of a team with more than one member. Please remove user from team first.'); $this->error('User is a member of a team with more than one member. Please remove user from team first.');
return; return;
} }
$team->delete(); $team->delete();
@ -48,6 +49,7 @@ class AdminRemoveUser extends Command
} catch (\Exception $e) { } catch (\Exception $e) {
$this->error('Failed to remove user.'); $this->error('Failed to remove user.');
$this->error($e->getMessage()); $this->error($e->getMessage());
return; return;
} }
} }

View File

@ -8,6 +8,7 @@ use Illuminate\Console\Command;
class CleanupApplicationDeploymentQueue extends Command class CleanupApplicationDeploymentQueue extends Command
{ {
protected $signature = 'cleanup:application-deployment-queue {--team-id=}'; protected $signature = 'cleanup:application-deployment-queue {--team-id=}';
protected $description = 'CleanupApplicationDeploymentQueue'; protected $description = 'CleanupApplicationDeploymentQueue';
public function handle() public function handle()
@ -15,7 +16,7 @@ class CleanupApplicationDeploymentQueue extends Command
$team_id = $this->option('team-id'); $team_id = $this->option('team-id');
$servers = \App\Models\Server::where('team_id', $team_id)->get(); $servers = \App\Models\Server::where('team_id', $team_id)->get();
foreach ($servers as $server) { foreach ($servers as $server) {
$deployments = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->where("server_id", $server->id)->get(); $deployments = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->where('server_id', $server->id)->get();
foreach ($deployments as $deployment) { foreach ($deployments as $deployment) {
$deployment->update(['status' => 'failed']); $deployment->update(['status' => 'failed']);
instant_remote_process(['docker rm -f '.$deployment->deployment_uuid], $server, false); instant_remote_process(['docker rm -f '.$deployment->deployment_uuid], $server, false);

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\DB;
class CleanupDatabase extends Command class CleanupDatabase extends Command
{ {
protected $signature = 'cleanup:database {--yes}'; protected $signature = 'cleanup:database {--yes}';
protected $description = 'Cleanup database'; protected $description = 'Cleanup database';
public function handle() public function handle()

View File

@ -8,6 +8,7 @@ use Illuminate\Support\Facades\Redis;
class CleanupQueue extends Command class CleanupQueue extends Command
{ {
protected $signature = 'cleanup:queue'; protected $signature = 'cleanup:queue';
protected $description = 'Cleanup Queue'; protected $description = 'Cleanup Queue';
public function handle() public function handle()

View File

@ -20,6 +20,7 @@ use Illuminate\Console\Command;
class CleanupStuckedResources extends Command class CleanupStuckedResources extends Command
{ {
protected $signature = 'cleanup:stucked-resources'; protected $signature = 'cleanup:stucked-resources';
protected $description = 'Cleanup Stucked Resources'; protected $description = 'Cleanup Stucked Resources';
public function handle() public function handle()
@ -28,6 +29,7 @@ class CleanupStuckedResources extends Command
echo "Running cleanup stucked resources.\n"; echo "Running cleanup stucked resources.\n";
$this->cleanup_stucked_resources(); $this->cleanup_stucked_resources();
} }
private function cleanup_stucked_resources() private function cleanup_stucked_resources()
{ {
@ -158,16 +160,19 @@ class CleanupStuckedResources extends Command
if (! data_get($application, 'environment')) { if (! data_get($application, 'environment')) {
echo 'Application without environment: '.$application->name.'\n'; echo 'Application without environment: '.$application->name.'\n';
$application->forceDelete(); $application->forceDelete();
continue; continue;
} }
if (! $application->destination()) { if (! $application->destination()) {
echo 'Application without destination: '.$application->name.'\n'; echo 'Application without destination: '.$application->name.'\n';
$application->forceDelete(); $application->forceDelete();
continue; continue;
} }
if (! data_get($application, 'destination.server')) { if (! data_get($application, 'destination.server')) {
echo 'Application without server: '.$application->name.'\n'; echo 'Application without server: '.$application->name.'\n';
$application->forceDelete(); $application->forceDelete();
continue; continue;
} }
} }
@ -180,16 +185,19 @@ class CleanupStuckedResources extends Command
if (! data_get($postgresql, 'environment')) { if (! data_get($postgresql, 'environment')) {
echo 'Postgresql without environment: '.$postgresql->name.'\n'; echo 'Postgresql without environment: '.$postgresql->name.'\n';
$postgresql->forceDelete(); $postgresql->forceDelete();
continue; continue;
} }
if (! $postgresql->destination()) { if (! $postgresql->destination()) {
echo 'Postgresql without destination: '.$postgresql->name.'\n'; echo 'Postgresql without destination: '.$postgresql->name.'\n';
$postgresql->forceDelete(); $postgresql->forceDelete();
continue; continue;
} }
if (! data_get($postgresql, 'destination.server')) { if (! data_get($postgresql, 'destination.server')) {
echo 'Postgresql without server: '.$postgresql->name.'\n'; echo 'Postgresql without server: '.$postgresql->name.'\n';
$postgresql->forceDelete(); $postgresql->forceDelete();
continue; continue;
} }
} }
@ -202,16 +210,19 @@ class CleanupStuckedResources extends Command
if (! data_get($redis, 'environment')) { if (! data_get($redis, 'environment')) {
echo 'Redis without environment: '.$redis->name.'\n'; echo 'Redis without environment: '.$redis->name.'\n';
$redis->forceDelete(); $redis->forceDelete();
continue; continue;
} }
if (! $redis->destination()) { if (! $redis->destination()) {
echo 'Redis without destination: '.$redis->name.'\n'; echo 'Redis without destination: '.$redis->name.'\n';
$redis->forceDelete(); $redis->forceDelete();
continue; continue;
} }
if (! data_get($redis, 'destination.server')) { if (! data_get($redis, 'destination.server')) {
echo 'Redis without server: '.$redis->name.'\n'; echo 'Redis without server: '.$redis->name.'\n';
$redis->forceDelete(); $redis->forceDelete();
continue; continue;
} }
} }
@ -225,16 +236,19 @@ class CleanupStuckedResources extends Command
if (! data_get($mongodb, 'environment')) { if (! data_get($mongodb, 'environment')) {
echo 'Mongodb without environment: '.$mongodb->name.'\n'; echo 'Mongodb without environment: '.$mongodb->name.'\n';
$mongodb->forceDelete(); $mongodb->forceDelete();
continue; continue;
} }
if (! $mongodb->destination()) { if (! $mongodb->destination()) {
echo 'Mongodb without destination: '.$mongodb->name.'\n'; echo 'Mongodb without destination: '.$mongodb->name.'\n';
$mongodb->forceDelete(); $mongodb->forceDelete();
continue; continue;
} }
if (! data_get($mongodb, 'destination.server')) { if (! data_get($mongodb, 'destination.server')) {
echo 'Mongodb without server: '.$mongodb->name.'\n'; echo 'Mongodb without server: '.$mongodb->name.'\n';
$mongodb->forceDelete(); $mongodb->forceDelete();
continue; continue;
} }
} }
@ -248,16 +262,19 @@ class CleanupStuckedResources extends Command
if (! data_get($mysql, 'environment')) { if (! data_get($mysql, 'environment')) {
echo 'Mysql without environment: '.$mysql->name.'\n'; echo 'Mysql without environment: '.$mysql->name.'\n';
$mysql->forceDelete(); $mysql->forceDelete();
continue; continue;
} }
if (! $mysql->destination()) { if (! $mysql->destination()) {
echo 'Mysql without destination: '.$mysql->name.'\n'; echo 'Mysql without destination: '.$mysql->name.'\n';
$mysql->forceDelete(); $mysql->forceDelete();
continue; continue;
} }
if (! data_get($mysql, 'destination.server')) { if (! data_get($mysql, 'destination.server')) {
echo 'Mysql without server: '.$mysql->name.'\n'; echo 'Mysql without server: '.$mysql->name.'\n';
$mysql->forceDelete(); $mysql->forceDelete();
continue; continue;
} }
} }
@ -271,16 +288,19 @@ class CleanupStuckedResources extends Command
if (! data_get($mariadb, 'environment')) { if (! data_get($mariadb, 'environment')) {
echo 'Mariadb without environment: '.$mariadb->name.'\n'; echo 'Mariadb without environment: '.$mariadb->name.'\n';
$mariadb->forceDelete(); $mariadb->forceDelete();
continue; continue;
} }
if (! $mariadb->destination()) { if (! $mariadb->destination()) {
echo 'Mariadb without destination: '.$mariadb->name.'\n'; echo 'Mariadb without destination: '.$mariadb->name.'\n';
$mariadb->forceDelete(); $mariadb->forceDelete();
continue; continue;
} }
if (! data_get($mariadb, 'destination.server')) { if (! data_get($mariadb, 'destination.server')) {
echo 'Mariadb without server: '.$mariadb->name.'\n'; echo 'Mariadb without server: '.$mariadb->name.'\n';
$mariadb->forceDelete(); $mariadb->forceDelete();
continue; continue;
} }
} }
@ -294,16 +314,19 @@ class CleanupStuckedResources extends Command
if (! data_get($service, 'environment')) { if (! data_get($service, 'environment')) {
echo 'Service without environment: '.$service->name.'\n'; echo 'Service without environment: '.$service->name.'\n';
$service->forceDelete(); $service->forceDelete();
continue; continue;
} }
if (! $service->destination()) { if (! $service->destination()) {
echo 'Service without destination: '.$service->name.'\n'; echo 'Service without destination: '.$service->name.'\n';
$service->forceDelete(); $service->forceDelete();
continue; continue;
} }
if (! data_get($service, 'server')) { if (! data_get($service, 'server')) {
echo 'Service without server: '.$service->name.'\n'; echo 'Service without server: '.$service->name.'\n';
$service->forceDelete(); $service->forceDelete();
continue; continue;
} }
} }
@ -316,6 +339,7 @@ class CleanupStuckedResources extends Command
if (! data_get($service, 'service')) { if (! data_get($service, 'service')) {
echo 'ServiceApplication without service: '.$service->name.'\n'; echo 'ServiceApplication without service: '.$service->name.'\n';
$service->forceDelete(); $service->forceDelete();
continue; continue;
} }
} }
@ -328,6 +352,7 @@ class CleanupStuckedResources extends Command
if (! data_get($service, 'service')) { if (! data_get($service, 'service')) {
echo 'ServiceDatabase without service: '.$service->name.'\n'; echo 'ServiceDatabase without service: '.$service->name.'\n';
$service->forceDelete(); $service->forceDelete();
continue; continue;
} }
} }

View File

@ -8,6 +8,7 @@ use Illuminate\Console\Command;
class CleanupUnreachableServers extends Command class CleanupUnreachableServers extends Command
{ {
protected $signature = 'cleanup:unreachable-servers'; protected $signature = 'cleanup:unreachable-servers';
protected $description = 'Cleanup Unreachable Servers (7 days)'; protected $description = 'Cleanup Unreachable Servers (7 days)';
public function handle() public function handle()
@ -19,7 +20,7 @@ class CleanupUnreachableServers extends Command
echo "Cleanup unreachable server ($server->id) with name $server->name"; echo "Cleanup unreachable server ($server->id) with name $server->name";
send_internal_notification("Server $server->name is unreachable for 7 days. Cleaning up..."); send_internal_notification("Server $server->name is unreachable for 7 days. Cleaning up...");
$server->update([ $server->update([
'ip' => '1.2.3.4' 'ip' => '1.2.3.4',
]); ]);
} }
} }

View File

@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Process;
class Dev extends Command class Dev extends Command
{ {
protected $signature = 'dev:init'; protected $signature = 'dev:init';
protected $description = 'Init the app in dev mode'; protected $description = 'Init the app in dev mode';
public function handle() public function handle()

View File

@ -2,12 +2,10 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Jobs\DatabaseBackupStatusJob;
use App\Jobs\SendConfirmationForWaitlistJob; use App\Jobs\SendConfirmationForWaitlistJob;
use App\Models\Application; use App\Models\Application;
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Models\ScheduledDatabaseBackupExecution;
use App\Models\Server; use App\Models\Server;
use App\Models\StandalonePostgresql; use App\Models\StandalonePostgresql;
use App\Models\Team; use App\Models\Team;
@ -49,7 +47,9 @@ class Emails extends Command
* Execute the console command. * Execute the console command.
*/ */
private ?MailMessage $mail = null; private ?MailMessage $mail = null;
private ?string $email = null; private ?string $email = null;
public function handle() public function handle()
{ {
$type = select( $type = select(
@ -73,7 +73,7 @@ class Emails extends Command
); );
$emailsGathered = ['realusers-before-trial', 'realusers-server-lost-connection']; $emailsGathered = ['realusers-before-trial', 'realusers-server-lost-connection'];
if (isDev()) { if (isDev()) {
$this->email = "test@example.com"; $this->email = 'test@example.com';
} else { } else {
if (! in_array($type, $emailsGathered)) { if (! in_array($type, $emailsGathered)) {
$this->email = text('Email Address to send to:'); $this->email = text('Email Address to send to:');
@ -82,12 +82,13 @@ class Emails extends Command
set_transanctional_email_settings(); set_transanctional_email_settings();
$this->mail = new MailMessage(); $this->mail = new MailMessage();
$this->mail->subject("Test Email"); $this->mail->subject('Test Email');
switch ($type) { switch ($type) {
case 'updates': case 'updates':
$teams = Team::all(); $teams = Team::all();
if (! $teams || $teams->isEmpty()) { if (! $teams || $teams->isEmpty()) {
echo 'No teams found.'.PHP_EOL; echo 'No teams found.'.PHP_EOL;
return; return;
} }
$emails = []; $emails = [];
@ -99,7 +100,7 @@ class Emails extends Command
} }
} }
$emails = array_unique($emails); $emails = array_unique($emails);
$this->info("Sending to " . count($emails) . " emails."); $this->info('Sending to '.count($emails).' emails.');
foreach ($emails as $email) { foreach ($emails as $email) {
$this->info($email); $this->info($email);
} }
@ -111,7 +112,7 @@ class Emails extends Command
$unsubscribeUrl = route('unsubscribe.marketing.emails', [ $unsubscribeUrl = route('unsubscribe.marketing.emails', [
'token' => encrypt($email), 'token' => encrypt($email),
]); ]);
$this->mail->view('emails.updates', ["unsubscribeUrl" => $unsubscribeUrl]); $this->mail->view('emails.updates', ['unsubscribeUrl' => $unsubscribeUrl]);
$this->sendEmail($email); $this->sendEmail($email);
} }
} }
@ -246,6 +247,7 @@ class Emails extends Command
$teams = Team::doesntHave('subscription')->where('id', '!=', 0)->get(); $teams = Team::doesntHave('subscription')->where('id', '!=', 0)->get();
if (! $teams || $teams->isEmpty()) { if (! $teams || $teams->isEmpty()) {
echo 'No teams found.'.PHP_EOL; echo 'No teams found.'.PHP_EOL;
return; return;
} }
$emails = []; $emails = [];
@ -257,7 +259,7 @@ class Emails extends Command
} }
} }
$emails = array_unique($emails); $emails = array_unique($emails);
$this->info("Sending to " . count($emails) . " emails."); $this->info('Sending to '.count($emails).' emails.');
foreach ($emails as $email) { foreach ($emails as $email) {
$this->info($email); $this->info($email);
} }
@ -296,7 +298,8 @@ class Emails extends Command
break; break;
} }
} }
private function sendEmail(string $email = null)
private function sendEmail(?string $email = null)
{ {
if ($email) { if ($email) {
$this->email = $email; $this->email = $email;

View File

@ -7,7 +7,9 @@ use Illuminate\Console\Command;
class Horizon extends Command class Horizon extends Command
{ {
protected $signature = 'start:horizon'; protected $signature = 'start:horizon';
protected $description = 'Start Horizon'; protected $description = 'Start Horizon';
public function handle() public function handle()
{ {
if (config('coolify.is_horizon_enabled')) { if (config('coolify.is_horizon_enabled')) {

View File

@ -15,6 +15,7 @@ use Illuminate\Support\Facades\Http;
class Init extends Command class Init extends Command
{ {
protected $signature = 'app:init {--full-cleanup} {--cleanup-deployments}'; protected $signature = 'app:init {--full-cleanup} {--cleanup-deployments}';
protected $description = 'Cleanup instance related stuffs'; protected $description = 'Cleanup instance related stuffs';
public function handle() public function handle()
@ -26,6 +27,7 @@ class Init extends Command
if ($cleanup_deployments) { if ($cleanup_deployments) {
echo "Running cleanup deployments.\n"; echo "Running cleanup deployments.\n";
$this->cleanup_in_progress_application_deployments(); $this->cleanup_in_progress_application_deployments();
return; return;
} }
if ($full_cleanup) { if ($full_cleanup) {
@ -52,6 +54,7 @@ class Init extends Command
$settings->update(['is_auto_update_enabled' => false]); $settings->update(['is_auto_update_enabled' => false]);
} }
} }
return; return;
} }
$this->cleanup_stucked_helper_containers(); $this->cleanup_stucked_helper_containers();
@ -82,6 +85,7 @@ class Init extends Command
echo "Error in restoring coolify db backup: {$e->getMessage()}\n"; echo "Error in restoring coolify db backup: {$e->getMessage()}\n";
} }
} }
private function cleanup_stucked_helper_containers() private function cleanup_stucked_helper_containers()
{ {
$servers = Server::all(); $servers = Server::all();
@ -91,6 +95,7 @@ class Init extends Command
} }
} }
} }
private function alive() private function alive()
{ {
$id = config('app.id'); $id = config('app.id');
@ -99,6 +104,7 @@ class Init extends Command
$do_not_track = data_get($settings, 'do_not_track'); $do_not_track = data_get($settings, 'do_not_track');
if ($do_not_track == true) { if ($do_not_track == true) {
echo "Skipping alive as do_not_track is enabled\n"; echo "Skipping alive as do_not_track is enabled\n";
return; return;
} }
try { try {

View File

@ -3,6 +3,7 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use function Termwind\ask; use function Termwind\ask;
use function Termwind\render; use function Termwind\render;
use function Termwind\style; use function Termwind\style;
@ -32,6 +33,7 @@ class NotifyDemo extends Command
if (blank($channel)) { if (blank($channel)) {
$this->showHelp(); $this->showHelp();
return; return;
} }

View File

@ -35,6 +35,7 @@ class RootChangeEmail extends Command
$this->info('Root user\'s email updated successfully.'); $this->info('Root user\'s email updated successfully.');
} catch (\Exception $e) { } catch (\Exception $e) {
$this->error('Failed to update root user\'s email.'); $this->error('Failed to update root user\'s email.');
return; return;
} }
} }

View File

@ -34,6 +34,7 @@ class RootResetPassword extends Command
$passwordAgain = password('Again'); $passwordAgain = password('Again');
if ($password != $passwordAgain) { if ($password != $passwordAgain) {
$this->error('Passwords do not match.'); $this->error('Passwords do not match.');
return; return;
} }
$this->info('Updating root password...'); $this->info('Updating root password...');
@ -42,6 +43,7 @@ class RootResetPassword extends Command
$this->info('Root password updated successfully.'); $this->info('Root password updated successfully.');
} catch (\Exception $e) { } catch (\Exception $e) {
$this->error('Failed to update root password.'); $this->error('Failed to update root password.');
return; return;
} }
} }

View File

@ -7,7 +7,9 @@ use Illuminate\Console\Command;
class Scheduler extends Command class Scheduler extends Command
{ {
protected $signature = 'start:scheduler'; protected $signature = 'start:scheduler';
protected $description = 'Start Scheduler'; protected $description = 'Start Scheduler';
public function handle() public function handle()
{ {
if (config('coolify.is_scheduler_enabled')) { if (config('coolify.is_scheduler_enabled')) {

View File

@ -48,11 +48,13 @@ class ServicesDelete extends Command
$this->deleteServer(); $this->deleteServer();
} }
} }
private function deleteServer() private function deleteServer()
{ {
$servers = Server::all(); $servers = Server::all();
if ($servers->count() === 0) { if ($servers->count() === 0) {
$this->error('There are no applications to delete.'); $this->error('There are no applications to delete.');
return; return;
} }
$serversToDelete = multiselect( $serversToDelete = multiselect(
@ -64,7 +66,7 @@ class ServicesDelete extends Command
$toDelete = $servers->where('id', $server)->first(); $toDelete = $servers->where('id', $server)->first();
if ($toDelete) { if ($toDelete) {
$this->info($toDelete); $this->info($toDelete);
$confirmed = confirm("Are you sure you want to delete all selected resources?"); $confirmed = confirm('Are you sure you want to delete all selected resources?');
if (! $confirmed) { if (! $confirmed) {
break; break;
} }
@ -72,11 +74,13 @@ class ServicesDelete extends Command
} }
} }
} }
private function deleteApplication() private function deleteApplication()
{ {
$applications = Application::all(); $applications = Application::all();
if ($applications->count() === 0) { if ($applications->count() === 0) {
$this->error('There are no applications to delete.'); $this->error('There are no applications to delete.');
return; return;
} }
$applicationsToDelete = multiselect( $applicationsToDelete = multiselect(
@ -88,7 +92,7 @@ class ServicesDelete extends Command
$toDelete = $applications->where('id', $application)->first(); $toDelete = $applications->where('id', $application)->first();
if ($toDelete) { if ($toDelete) {
$this->info($toDelete); $this->info($toDelete);
$confirmed = confirm("Are you sure you want to delete all selected resources? "); $confirmed = confirm('Are you sure you want to delete all selected resources? ');
if (! $confirmed) { if (! $confirmed) {
break; break;
} }
@ -96,11 +100,13 @@ class ServicesDelete extends Command
} }
} }
} }
private function deleteDatabase() private function deleteDatabase()
{ {
$databases = StandalonePostgresql::all(); $databases = StandalonePostgresql::all();
if ($databases->count() === 0) { if ($databases->count() === 0) {
$this->error('There are no databases to delete.'); $this->error('There are no databases to delete.');
return; return;
} }
$databasesToDelete = multiselect( $databasesToDelete = multiselect(
@ -112,7 +118,7 @@ class ServicesDelete extends Command
$toDelete = $databases->where('id', $database)->first(); $toDelete = $databases->where('id', $database)->first();
if ($toDelete) { if ($toDelete) {
$this->info($toDelete); $this->info($toDelete);
$confirmed = confirm("Are you sure you want to delete all selected resources?"); $confirmed = confirm('Are you sure you want to delete all selected resources?');
if (! $confirmed) { if (! $confirmed) {
return; return;
} }
@ -120,11 +126,13 @@ class ServicesDelete extends Command
} }
} }
} }
private function deleteService() private function deleteService()
{ {
$services = Service::all(); $services = Service::all();
if ($services->count() === 0) { if ($services->count() === 0) {
$this->error('There are no services to delete.'); $this->error('There are no services to delete.');
return; return;
} }
$servicesToDelete = multiselect( $servicesToDelete = multiselect(
@ -136,7 +144,7 @@ class ServicesDelete extends Command
$toDelete = $services->where('id', $service)->first(); $toDelete = $services->where('id', $service)->first();
if ($toDelete) { if ($toDelete) {
$this->info($toDelete); $this->info($toDelete);
$confirmed = confirm("Are you sure you want to delete all selected resources?"); $confirmed = confirm('Are you sure you want to delete all selected resources?');
if (! $confirmed) { if (! $confirmed) {
return; return;
} }

View File

@ -56,6 +56,7 @@ class ServicesGenerate extends Command
} }
if ($ignore) { if ($ignore) {
$this->info("Ignoring $file"); $this->info("Ignoring $file");
return; return;
} }
$this->info("Processing $file"); $this->info("Processing $file");
@ -125,6 +126,7 @@ class ServicesGenerate extends Command
$env_file_base64 = base64_encode($env_file_content); $env_file_base64 = base64_encode($env_file_content);
$payload['envs'] = $env_file_base64; $payload['envs'] = $env_file_base64;
} }
return $payload; return $payload;
} }
} }

View File

@ -33,30 +33,31 @@ class SyncBunny extends Command
$that = $this; $that = $this;
$only_template = $this->option('templates'); $only_template = $this->option('templates');
$only_version = $this->option('release'); $only_version = $this->option('release');
$bunny_cdn = "https://cdn.coollabs.io"; $bunny_cdn = 'https://cdn.coollabs.io';
$bunny_cdn_path = "coolify"; $bunny_cdn_path = 'coolify';
$bunny_cdn_storage_name = "coolcdn"; $bunny_cdn_storage_name = 'coolcdn';
$parent_dir = realpath(dirname(__FILE__).'/../../..'); $parent_dir = realpath(dirname(__FILE__).'/../../..');
$compose_file = "docker-compose.yml"; $compose_file = 'docker-compose.yml';
$compose_file_prod = "docker-compose.prod.yml"; $compose_file_prod = 'docker-compose.prod.yml';
$install_script = "install.sh"; $install_script = 'install.sh';
$upgrade_script = "upgrade.sh"; $upgrade_script = 'upgrade.sh';
$production_env = ".env.production"; $production_env = '.env.production';
$service_template = "service-templates.json"; $service_template = 'service-templates.json';
$versions = "versions.json"; $versions = 'versions.json';
PendingRequest::macro('storage', function ($fileName) use ($that) { PendingRequest::macro('storage', function ($fileName) use ($that) {
$headers = [ $headers = [
'AccessKey' => env('BUNNY_STORAGE_API_KEY'), 'AccessKey' => env('BUNNY_STORAGE_API_KEY'),
'Accept' => 'application/json', 'Accept' => 'application/json',
'Content-Type' => 'application/octet-stream' 'Content-Type' => 'application/octet-stream',
]; ];
$fileStream = fopen($fileName, "r"); $fileStream = fopen($fileName, 'r');
$file = fread($fileStream, filesize($fileName)); $file = fread($fileStream, filesize($fileName));
$that->info('Uploading: '.$fileName); $that->info('Uploading: '.$fileName);
return PendingRequest::baseUrl('https://storage.bunnycdn.com')->withHeaders($headers)->withBody($file)->throw(); return PendingRequest::baseUrl('https://storage.bunnycdn.com')->withHeaders($headers)->withBody($file)->throw();
}); });
PendingRequest::macro('purge', function ($url) use ($that) { PendingRequest::macro('purge', function ($url) use ($that) {
@ -65,9 +66,10 @@ class SyncBunny extends Command
'Accept' => 'application/json', 'Accept' => 'application/json',
]; ];
$that->info('Purging: '.$url); $that->info('Purging: '.$url);
return PendingRequest::withHeaders($headers)->get('https://api.bunny.net/purge', [ return PendingRequest::withHeaders($headers)->get('https://api.bunny.net/purge', [
"url" => $url, 'url' => $url,
"async" => false 'async' => false,
]); ]);
}); });
try { try {
@ -76,7 +78,7 @@ class SyncBunny extends Command
} }
if ($only_template) { if ($only_template) {
$this->info('About to sync service-templates.json to BunnyCDN.'); $this->info('About to sync service-templates.json to BunnyCDN.');
$confirmed = confirm("Are you sure you want to sync?"); $confirmed = confirm('Are you sure you want to sync?');
if (! $confirmed) { if (! $confirmed) {
return; return;
} }
@ -85,6 +87,7 @@ class SyncBunny extends Command
$pool->purge("$bunny_cdn/$bunny_cdn_path/$service_template"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$service_template"),
]); ]);
$this->info('Service template uploaded & purged...'); $this->info('Service template uploaded & purged...');
return; return;
} elseif ($only_version) { } elseif ($only_version) {
$this->info('About to sync versions.json to BunnyCDN.'); $this->info('About to sync versions.json to BunnyCDN.');
@ -101,10 +104,10 @@ class SyncBunny extends Command
$pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"),
]); ]);
$this->info('versions.json uploaded & purged...'); $this->info('versions.json uploaded & purged...');
return; return;
} }
Http::pool(fn (Pool $pool) => [ Http::pool(fn (Pool $pool) => [
$pool->storage(fileName: "$parent_dir/$compose_file")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"), $pool->storage(fileName: "$parent_dir/$compose_file")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"),
$pool->storage(fileName: "$parent_dir/$compose_file_prod")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"), $pool->storage(fileName: "$parent_dir/$compose_file_prod")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"),
@ -119,9 +122,9 @@ class SyncBunny extends Command
$pool->purge("$bunny_cdn/$bunny_cdn_path/$upgrade_script"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$upgrade_script"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$install_script"), $pool->purge("$bunny_cdn/$bunny_cdn_path/$install_script"),
]); ]);
$this->info("All files uploaded & purged..."); $this->info('All files uploaded & purged...');
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->error("Error: " . $e->getMessage()); $this->error('Error: '.$e->getMessage());
} }
} }
} }

View File

@ -13,7 +13,9 @@ use Illuminate\Support\Str;
class WaitlistInvite extends Command class WaitlistInvite extends Command
{ {
public Waitlist|User|null $next_patient = null; public Waitlist|User|null $next_patient = null;
public string|null $password = null;
public ?string $password = null;
/** /**
* The name and signature of the console command. * The name and signature of the console command.
* *
@ -38,7 +40,9 @@ class WaitlistInvite extends Command
$this->main(); $this->main();
} }
} }
private function main() {
private function main()
{
if ($this->argument('email')) { if ($this->argument('email')) {
if ($this->option('only-email')) { if ($this->option('only-email')) {
$this->next_patient = User::whereEmail($this->argument('email'))->first(); $this->next_patient = User::whereEmail($this->argument('email'))->first();
@ -52,6 +56,7 @@ class WaitlistInvite extends Command
} }
if (! $this->next_patient) { if (! $this->next_patient) {
$this->error("{$this->argument('email')} not found in the waitlist."); $this->error("{$this->argument('email')} not found in the waitlist.");
return; return;
} }
} else { } else {
@ -60,6 +65,7 @@ class WaitlistInvite extends Command
if ($this->next_patient) { if ($this->next_patient) {
if ($this->option('only-email')) { if ($this->option('only-email')) {
$this->send_email(); $this->send_email();
return; return;
} }
$this->register_user(); $this->register_user();
@ -69,6 +75,7 @@ class WaitlistInvite extends Command
$this->info('No verified user found in the waitlist. 👀'); $this->info('No verified user found in the waitlist. 👀');
} }
} }
private function register_user() private function register_user()
{ {
$already_registered = User::whereEmail($this->next_patient->email)->first(); $already_registered = User::whereEmail($this->next_patient->email)->first();
@ -85,11 +92,13 @@ class WaitlistInvite extends Command
throw new \Exception('User already registered'); throw new \Exception('User already registered');
} }
} }
private function remove_from_waitlist() private function remove_from_waitlist()
{ {
$this->next_patient->delete(); $this->next_patient->delete();
$this->info("User removed from waitlist successfully."); $this->info('User removed from waitlist successfully.');
} }
private function send_email() private function send_email()
{ {
$token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password"); $token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password");
@ -100,6 +109,6 @@ class WaitlistInvite extends Command
]); ]);
$mail->subject('Congratulations! You are invited to join Coolify Cloud.'); $mail->subject('Congratulations! You are invited to join Coolify Cloud.');
send_user_an_email($mail, $this->next_patient->email); send_user_an_email($mail, $this->next_patient->email);
$this->info("Email sent successfully. 📧"); $this->info('Email sent successfully. 📧');
} }
} }

View File

@ -4,13 +4,13 @@ namespace App\Console;
use App\Jobs\CheckLogDrainContainerJob; use App\Jobs\CheckLogDrainContainerJob;
use App\Jobs\CleanupInstanceStuffsJob; use App\Jobs\CleanupInstanceStuffsJob;
use App\Jobs\DatabaseBackupJob;
use App\Jobs\ScheduledTaskJob;
use App\Jobs\ContainerStatusJob; use App\Jobs\ContainerStatusJob;
use App\Jobs\DatabaseBackupJob;
use App\Jobs\PullCoolifyImageJob; use App\Jobs\PullCoolifyImageJob;
use App\Jobs\PullHelperImageJob; use App\Jobs\PullHelperImageJob;
use App\Jobs\PullSentinelImageJob; use App\Jobs\PullSentinelImageJob;
use App\Jobs\PullTemplatesFromCDN; use App\Jobs\PullTemplatesFromCDN;
use App\Jobs\ScheduledTaskJob;
use App\Jobs\ServerStatusJob; use App\Jobs\ServerStatusJob;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Models\ScheduledTask; use App\Models\ScheduledTask;
@ -22,6 +22,7 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel class Kernel extends ConsoleKernel
{ {
private $all_servers; private $all_servers;
protected function schedule(Schedule $schedule): void protected function schedule(Schedule $schedule): void
{ {
$this->all_servers = Server::all(); $this->all_servers = Server::all();
@ -55,6 +56,7 @@ class Kernel extends ConsoleKernel
$schedule->command('uploads:clear')->everyTwoMinutes(); $schedule->command('uploads:clear')->everyTwoMinutes();
} }
} }
private function pull_images($schedule) private function pull_images($schedule)
{ {
$servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4'); $servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4');
@ -65,6 +67,7 @@ class Kernel extends ConsoleKernel
$schedule->job(new PullHelperImageJob($server))->everyFiveMinutes()->onOneServer(); $schedule->job(new PullHelperImageJob($server))->everyFiveMinutes()->onOneServer();
} }
} }
private function check_resources($schedule) private function check_resources($schedule)
{ {
if (isCloud()) { if (isCloud()) {
@ -86,6 +89,7 @@ class Kernel extends ConsoleKernel
$schedule->job(new ServerStatusJob($server))->everyMinute()->onOneServer(); $schedule->job(new ServerStatusJob($server))->everyMinute()->onOneServer();
} }
} }
private function check_scheduled_backups($schedule) private function check_scheduled_backups($schedule)
{ {
$scheduled_backups = ScheduledDatabaseBackup::all(); $scheduled_backups = ScheduledDatabaseBackup::all();
@ -99,6 +103,7 @@ class Kernel extends ConsoleKernel
if (is_null(data_get($scheduled_backup, 'database'))) { if (is_null(data_get($scheduled_backup, 'database'))) {
ray('database not found'); ray('database not found');
$scheduled_backup->delete(); $scheduled_backup->delete();
continue; continue;
} }
@ -127,6 +132,7 @@ class Kernel extends ConsoleKernel
if (! $application && ! $service) { if (! $application && ! $service) {
ray('application/service attached to scheduled task does not exist'); ray('application/service attached to scheduled task does not exist');
$scheduled_task->delete(); $scheduled_task->delete();
continue; continue;
} }
if ($application) { if ($application) {

View File

@ -2,9 +2,7 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
@ -13,14 +11,16 @@ use Illuminate\Queue\SerializesModels;
class ApplicationStatusChanged implements ShouldBroadcast class ApplicationStatusChanged implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamId; public $teamId;
public function __construct($teamId = null) public function __construct($teamId = null)
{ {
if (is_null($teamId)) { if (is_null($teamId)) {
$teamId = auth()->user()->currentTeam()->id ?? null; $teamId = auth()->user()->currentTeam()->id ?? null;
} }
if (is_null($teamId)) { if (is_null($teamId)) {
throw new \Exception("Team id is null"); throw new \Exception('Team id is null');
} }
$this->teamId = $teamId; $this->teamId = $teamId;
} }

View File

@ -2,9 +2,7 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
@ -13,14 +11,16 @@ use Illuminate\Queue\SerializesModels;
class BackupCreated implements ShouldBroadcast class BackupCreated implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamId; public $teamId;
public function __construct($teamId = null) public function __construct($teamId = null)
{ {
if (is_null($teamId)) { if (is_null($teamId)) {
$teamId = auth()->user()->currentTeam()->id ?? null; $teamId = auth()->user()->currentTeam()->id ?? null;
} }
if (is_null($teamId)) { if (is_null($teamId)) {
throw new \Exception("Team id is null"); throw new \Exception('Team id is null');
} }
$this->teamId = $teamId; $this->teamId = $teamId;
} }

View File

@ -2,9 +2,7 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
@ -13,14 +11,16 @@ use Illuminate\Queue\SerializesModels;
class DatabaseStatusChanged implements ShouldBroadcast class DatabaseStatusChanged implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public $userId; public $userId;
public function __construct($userId = null) public function __construct($userId = null)
{ {
if (is_null($userId)) { if (is_null($userId)) {
$userId = auth()->user()->id ?? null; $userId = auth()->user()->id ?? null;
} }
if (is_null($userId)) { if (is_null($userId)) {
throw new \Exception("User id is null"); throw new \Exception('User id is null');
} }
$this->userId = $userId; $this->userId = $userId;
} }

View File

@ -9,6 +9,7 @@ use Illuminate\Queue\SerializesModels;
class ProxyStarted class ProxyStarted
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public $data) public function __construct(public $data)
{ {

View File

@ -2,9 +2,7 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
@ -13,14 +11,16 @@ use Illuminate\Queue\SerializesModels;
class ProxyStatusChanged implements ShouldBroadcast class ProxyStatusChanged implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamId; public $teamId;
public function __construct($teamId = null) public function __construct($teamId = null)
{ {
if (is_null($teamId)) { if (is_null($teamId)) {
$teamId = auth()->user()->currentTeam()->id ?? null; $teamId = auth()->user()->currentTeam()->id ?? null;
} }
if (is_null($teamId)) { if (is_null($teamId)) {
throw new \Exception("Team id is null"); throw new \Exception('Team id is null');
} }
$this->teamId = $teamId; $this->teamId = $teamId;
} }

View File

@ -2,9 +2,7 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
@ -13,14 +11,16 @@ use Illuminate\Queue\SerializesModels;
class ServiceStatusChanged implements ShouldBroadcast class ServiceStatusChanged implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public $userId; public $userId;
public function __construct($userId = null) public function __construct($userId = null)
{ {
if (is_null($userId)) { if (is_null($userId)) {
$userId = auth()->user()->id ?? null; $userId = auth()->user()->id ?? null;
} }
if (is_null($userId)) { if (is_null($userId)) {
throw new \Exception("User id is null"); throw new \Exception('User id is null');
} }
$this->userId = $userId; $this->userId = $userId;
} }

View File

@ -2,9 +2,7 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
@ -13,7 +11,9 @@ use Illuminate\Queue\SerializesModels;
class TestEvent implements ShouldBroadcast class TestEvent implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamId; public $teamId;
public function __construct() public function __construct()
{ {
$this->teamId = auth()->user()->currentTeam()->id; $this->teamId = auth()->user()->currentTeam()->id;

View File

@ -13,7 +13,6 @@ use Throwable;
class Handler extends ExceptionHandler class Handler extends ExceptionHandler
{ {
/** /**
* A list of exception types with their corresponding custom log levels. * A list of exception types with their corresponding custom log levels.
* *
@ -22,14 +21,16 @@ class Handler extends ExceptionHandler
protected $levels = [ protected $levels = [
// //
]; ];
/** /**
* A list of the exception types that are not reported. * A list of the exception types that are not reported.
* *
* @var array<int, class-string<\Throwable>> * @var array<int, class-string<\Throwable>>
*/ */
protected $dontReport = [ protected $dontReport = [
ProcessException::class ProcessException::class,
]; ];
/** /**
* A list of the inputs that are never flashed to the session on validation exceptions. * A list of the inputs that are never flashed to the session on validation exceptions.
* *
@ -40,6 +41,7 @@ class Handler extends ExceptionHandler
'password', 'password',
'password_confirmation', 'password_confirmation',
]; ];
private InstanceSettings $settings; private InstanceSettings $settings;
protected function unauthenticated($request, AuthenticationException $exception) protected function unauthenticated($request, AuthenticationException $exception)
@ -47,8 +49,10 @@ class Handler extends ExceptionHandler
if ($request->is('api/*') || $request->expectsJson() || $this->shouldReturnJson($request, $exception)) { if ($request->is('api/*') || $request->expectsJson() || $this->shouldReturnJson($request, $exception)) {
return response()->json(['message' => $exception->getMessage()], 401); return response()->json(['message' => $exception->getMessage()], 401);
} }
return redirect()->guest($exception->redirectTo() ?? route('login')); return redirect()->guest($exception->redirectTo() ?? route('login'));
} }
/** /**
* Register the exception handling callbacks for the application. * Register the exception handling callbacks for the application.
*/ */
@ -72,7 +76,7 @@ class Handler extends ExceptionHandler
$scope->setUser( $scope->setUser(
[ [
'email' => $email, 'email' => $email,
'instanceAdmin' => $instanceAdmin 'instanceAdmin' => $instanceAdmin,
] ]
); );
} }

View File

@ -6,5 +6,4 @@ use Exception;
class ProcessException extends Exception class ProcessException extends Exception
{ {
} }

View File

@ -27,18 +27,20 @@ class Deploy extends Controller
return invalid_token(); return invalid_token();
} }
$servers = Server::whereTeamId($teamId)->get(); $servers = Server::whereTeamId($teamId)->get();
$deployments_per_server = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->whereIn("server_id", $servers->pluck("id"))->get([ $deployments_per_server = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->whereIn('server_id', $servers->pluck('id'))->get([
"id", 'id',
"application_id", 'application_id',
"application_name", 'application_name',
"deployment_url", 'deployment_url',
"pull_request_id", 'pull_request_id',
"server_name", 'server_name',
"server_id", 'server_id',
"status" 'status',
])->sortBy('id')->toArray(); ])->sortBy('id')->toArray();
return response()->json($deployments_per_server, 200); return response()->json($deployments_per_server, 200);
} }
public function deploy(Request $request) public function deploy(Request $request)
{ {
$teamId = get_team_id_from_token(); $teamId = get_team_id_from_token();
@ -57,8 +59,10 @@ class Deploy extends Controller
} elseif ($uuids) { } elseif ($uuids) {
return $this->by_uuids($uuids, $teamId, $force); return $this->by_uuids($uuids, $teamId, $force);
} }
return response()->json(['error' => 'You must provide uuid or tag.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 400); return response()->json(['error' => 'You must provide uuid or tag.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 400);
} }
private function by_uuids(string $uuid, int $teamId, bool $force = false) private function by_uuids(string $uuid, int $teamId, bool $force = false)
{ {
$uuids = explode(',', $uuid); $uuids = explode(',', $uuid);
@ -82,10 +86,13 @@ class Deploy extends Controller
} }
if ($deployments->count() > 0) { if ($deployments->count() > 0) {
$payload->put('deployments', $deployments->toArray()); $payload->put('deployments', $deployments->toArray());
return response()->json($payload->toArray(), 200); return response()->json($payload->toArray(), 200);
} }
return response()->json(['error' => "No resources found.", 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
return response()->json(['error' => 'No resources found.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
} }
public function by_tags(string $tags, int $team_id, bool $force = false) public function by_tags(string $tags, int $team_id, bool $force = false)
{ {
$tags = explode(',', $tags); $tags = explode(',', $tags);
@ -107,6 +114,7 @@ class Deploy extends Controller
$services = $found_tag->services()->get(); $services = $found_tag->services()->get();
if ($applications->count() === 0 && $services->count() === 0) { if ($applications->count() === 0 && $services->count() === 0) {
$message->push("No resources found for tag {$tag}."); $message->push("No resources found for tag {$tag}.");
continue; continue;
} }
foreach ($applications as $resource) { foreach ($applications as $resource) {
@ -127,11 +135,13 @@ class Deploy extends Controller
if ($deployments->count() > 0) { if ($deployments->count() > 0) {
$payload->put('details', $deployments->toArray()); $payload->put('details', $deployments->toArray());
} }
return response()->json($payload->toArray(), 200); return response()->json($payload->toArray(), 200);
} }
return response()->json(['error' => "No resources found with this tag.", 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404); return response()->json(['error' => 'No resources found with this tag.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
} }
public function deploy_resource($resource, bool $force = false): array public function deploy_resource($resource, bool $force = false): array
{ {
$message = null; $message = null;
@ -200,6 +210,7 @@ class Deploy extends Controller
StartService::run($resource); StartService::run($resource);
$message = "Service {$resource->name} started. It could take a while, be patient."; $message = "Service {$resource->name} started. It could take a while, be patient.";
} }
return ['message' => $message, 'deployment_uuid' => $deployment_uuid]; return ['message' => $message, 'deployment_uuid' => $deployment_uuid];
} }
} }

View File

@ -15,8 +15,10 @@ class Project extends Controller
return invalid_token(); return invalid_token();
} }
$projects = ModelsProject::whereTeamId($teamId)->select('id', 'name', 'uuid')->get(); $projects = ModelsProject::whereTeamId($teamId)->select('id', 'name', 'uuid')->get();
return response()->json($projects); return response()->json($projects);
} }
public function project_by_uuid(Request $request) public function project_by_uuid(Request $request)
{ {
$teamId = get_team_id_from_token(); $teamId = get_team_id_from_token();
@ -24,8 +26,10 @@ class Project extends Controller
return invalid_token(); return invalid_token();
} }
$project = ModelsProject::whereTeamId($teamId)->whereUuid(request()->uuid)->first()->load(['environments']); $project = ModelsProject::whereTeamId($teamId)->whereUuid(request()->uuid)->first()->load(['environments']);
return response()->json($project); return response()->json($project);
} }
public function environment_details(Request $request) public function environment_details(Request $request)
{ {
$teamId = get_team_id_from_token(); $teamId = get_team_id_from_token();
@ -34,6 +38,7 @@ class Project extends Controller
} }
$project = ModelsProject::whereTeamId($teamId)->whereUuid(request()->uuid)->first(); $project = ModelsProject::whereTeamId($teamId)->whereUuid(request()->uuid)->first();
$environment = $project->environments()->whereName(request()->environment_name)->first()->load(['applications', 'postgresqls', 'redis', 'mongodbs', 'mysqls', 'mariadbs', 'services']); $environment = $project->environments()->whereName(request()->environment_name)->first()->load(['applications', 'postgresqls', 'redis', 'mongodbs', 'mysqls', 'mariadbs', 'services']);
return response()->json($environment); return response()->json($environment);
} }
} }

View File

@ -30,9 +30,10 @@ class Resources extends Controller
$payload['status'] = $resource->status; $payload['status'] = $resource->status;
} }
$payload['type'] = $resource->type(); $payload['type'] = $resource->type();
return $payload; return $payload;
}); });
return response()->json($resources); return response()->json($resources);
} }
} }

View File

@ -17,10 +17,13 @@ class Server extends Controller
$servers = ModelsServer::whereTeamId($teamId)->select('id', 'name', 'uuid', 'ip', 'user', 'port')->get()->load(['settings'])->map(function ($server) { $servers = ModelsServer::whereTeamId($teamId)->select('id', 'name', 'uuid', 'ip', 'user', 'port')->get()->load(['settings'])->map(function ($server) {
$server['is_reachable'] = $server->settings->is_reachable; $server['is_reachable'] = $server->settings->is_reachable;
$server['is_usable'] = $server->settings->is_usable; $server['is_usable'] = $server->settings->is_usable;
return $server; return $server;
}); });
return response()->json($servers); return response()->json($servers);
} }
public function server_by_uuid(Request $request) public function server_by_uuid(Request $request)
{ {
$with_resources = $request->query('resources'); $with_resources = $request->query('resources');
@ -47,11 +50,13 @@ class Server extends Controller
} else { } else {
$payload['status'] = $resource->status; $payload['status'] = $resource->status;
} }
return $payload; return $payload;
}); });
} else { } else {
$server->load(['settings']); $server->load(['settings']);
} }
return response()->json($server); return response()->json($server);
} }
} }

View File

@ -14,8 +14,10 @@ class Team extends Controller
return invalid_token(); return invalid_token();
} }
$teams = auth()->user()->teams; $teams = auth()->user()->teams;
return response()->json($teams); return response()->json($teams);
} }
public function team_by_id(Request $request) public function team_by_id(Request $request)
{ {
$id = $request->id; $id = $request->id;
@ -26,10 +28,12 @@ class Team extends Controller
$teams = auth()->user()->teams; $teams = auth()->user()->teams;
$team = $teams->where('id', $id)->first(); $team = $teams->where('id', $id)->first();
if (is_null($team)) { if (is_null($team)) {
return response()->json(['error' => 'Team not found.', "docs" => "https://coolify.io/docs/api-reference/get-team-by-teamid"], 404); return response()->json(['error' => 'Team not found.', 'docs' => 'https://coolify.io/docs/api-reference/get-team-by-teamid'], 404);
} }
return response()->json($team); return response()->json($team);
} }
public function members_by_id(Request $request) public function members_by_id(Request $request)
{ {
$id = $request->id; $id = $request->id;
@ -40,10 +44,12 @@ class Team extends Controller
$teams = auth()->user()->teams; $teams = auth()->user()->teams;
$team = $teams->where('id', $id)->first(); $team = $teams->where('id', $id)->first();
if (is_null($team)) { if (is_null($team)) {
return response()->json(['error' => 'Team not found.', "docs" => "https://coolify.io/docs/api-reference/get-team-by-teamid-members"], 404); return response()->json(['error' => 'Team not found.', 'docs' => 'https://coolify.io/docs/api-reference/get-team-by-teamid-members'], 404);
} }
return response()->json($team->members); return response()->json($team->members);
} }
public function current_team(Request $request) public function current_team(Request $request)
{ {
$teamId = get_team_id_from_token(); $teamId = get_team_id_from_token();
@ -51,8 +57,10 @@ class Team extends Controller
return invalid_token(); return invalid_token();
} }
$team = auth()->user()->currentTeam(); $team = auth()->user()->currentTeam();
return response()->json($team); return response()->json($team);
} }
public function current_team_members(Request $request) public function current_team_members(Request $request)
{ {
$teamId = get_team_id_from_token(); $teamId = get_team_id_from_token();
@ -60,6 +68,7 @@ class Team extends Controller
return invalid_token(); return invalid_token();
} }
$team = auth()->user()->currentTeam(); $team = auth()->user()->currentTeam();
return response()->json($team->members); return response()->json($team->members);
} }
} }

View File

@ -14,33 +14,42 @@ use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\Contracts\FailedPasswordResetLinkRequestResponse; use Laravel\Fortify\Contracts\FailedPasswordResetLinkRequestResponse;
use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse; use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse;
use Illuminate\Support\Facades\Password; use Laravel\Fortify\Fortify;
class Controller extends BaseController class Controller extends BaseController
{ {
use AuthorizesRequests, ValidatesRequests; use AuthorizesRequests, ValidatesRequests;
public function realtime_test() { public function realtime_test()
{
if (auth()->user()?->currentTeam()->id !== 0) { if (auth()->user()?->currentTeam()->id !== 0) {
return redirect(RouteServiceProvider::HOME); return redirect(RouteServiceProvider::HOME);
} }
TestEvent::dispatch(); TestEvent::dispatch();
return 'Look at your other tab.'; return 'Look at your other tab.';
} }
public function verify() {
public function verify()
{
return view('auth.verify-email'); return view('auth.verify-email');
} }
public function email_verify(EmailVerificationRequest $request) {
public function email_verify(EmailVerificationRequest $request)
{
$request->fulfill(); $request->fulfill();
$name = request()->user()?->name; $name = request()->user()?->name;
// send_internal_notification("User {$name} verified their email address."); // send_internal_notification("User {$name} verified their email address.");
return redirect(RouteServiceProvider::HOME); return redirect(RouteServiceProvider::HOME);
} }
public function forgot_password(Request $request) {
public function forgot_password(Request $request)
{
if (is_transactional_emails_active()) { if (is_transactional_emails_active()) {
$arrayOfRequest = $request->only(Fortify::email()); $arrayOfRequest = $request->only(Fortify::email());
$request->merge([ $request->merge([
@ -60,10 +69,13 @@ class Controller extends BaseController
if ($status == Password::RESET_THROTTLED) { if ($status == Password::RESET_THROTTLED) {
return response('Already requested a password reset in the past minutes.', 400); return response('Already requested a password reset in the past minutes.', 400);
} }
return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]); return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]);
} }
return response()->json(['message' => 'Transactional emails are not active'], 400); return response()->json(['message' => 'Transactional emails are not active'], 400);
} }
public function link() public function link()
{ {
$token = request()->get('token'); $token = request()->get('token');
@ -90,9 +102,11 @@ class Controller extends BaseController
} }
Auth::login($user); Auth::login($user);
session(['currentTeam' => $team]); session(['currentTeam' => $team]);
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
} }
return redirect()->route('login')->with('error', 'Invalid credentials.'); return redirect()->route('login')->with('error', 'Invalid credentials.');
} }
@ -108,11 +122,12 @@ class Controller extends BaseController
if ($resetPassword) { if ($resetPassword) {
$user->update([ $user->update([
'password' => Hash::make($invitationUuid), 'password' => Hash::make($invitationUuid),
'force_password_reset' => true 'force_password_reset' => true,
]); ]);
} }
if ($user->teams()->where('team_id', $invitation->team->id)->exists()) { if ($user->teams()->where('team_id', $invitation->team->id)->exists()) {
$invitation->delete(); $invitation->delete();
return redirect()->route('team.index'); return redirect()->route('team.index');
} }
$user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]);
@ -121,6 +136,7 @@ class Controller extends BaseController
return redirect()->route('login'); return redirect()->route('login');
} }
refreshSession($invitation->team); refreshSession($invitation->team);
return redirect()->route('team.index'); return redirect()->route('team.index');
} else { } else {
abort(401); abort(401);
@ -143,6 +159,7 @@ class Controller extends BaseController
abort(401); abort(401);
} }
$invitation->delete(); $invitation->delete();
return redirect()->route('team.index'); return redirect()->route('team.index');
} catch (\Throwable $e) { } catch (\Throwable $e) {
throw $e; throw $e;

View File

@ -12,21 +12,21 @@ class MagicController extends Controller
public function servers() public function servers()
{ {
return response()->json([ return response()->json([
'servers' => Server::isUsable()->get() 'servers' => Server::isUsable()->get(),
]); ]);
} }
public function destinations() public function destinations()
{ {
return response()->json([ return response()->json([
'destinations' => Server::destinationsByServer(request()->query('server_id'))->sortBy('name') 'destinations' => Server::destinationsByServer(request()->query('server_id'))->sortBy('name'),
]); ]);
} }
public function projects() public function projects()
{ {
return response()->json([ return response()->json([
'projects' => Project::ownedByCurrentTeam()->get() 'projects' => Project::ownedByCurrentTeam()->get(),
]); ]);
} }
@ -35,11 +35,12 @@ class MagicController extends Controller
$project = Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->first(); $project = Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->first();
if (! $project) { if (! $project) {
return response()->json([ return response()->json([
'environments' => [] 'environments' => [],
]); ]);
} }
return response()->json([ return response()->json([
'environments' => $project->environments 'environments' => $project->environments,
]); ]);
} }
@ -49,8 +50,9 @@ class MagicController extends Controller
['name' => request()->query('name') ?? generate_random_name()], ['name' => request()->query('name') ?? generate_random_name()],
['team_id' => currentTeam()->id] ['team_id' => currentTeam()->id]
); );
return response()->json([ return response()->json([
'project_uuid' => $project->uuid 'project_uuid' => $project->uuid,
]); ]);
} }
@ -60,6 +62,7 @@ class MagicController extends Controller
['name' => request()->query('name') ?? generate_random_name()], ['name' => request()->query('name') ?? generate_random_name()],
['project_id' => Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->firstOrFail()->id] ['project_id' => Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->firstOrFail()->id]
); );
return response()->json([ return response()->json([
'environment_name' => $environment->name, 'environment_name' => $environment->name,
]); ]);
@ -75,6 +78,7 @@ class MagicController extends Controller
); );
auth()->user()->teams()->attach($team, ['role' => 'admin']); auth()->user()->teams()->attach($team, ['role' => 'admin']);
refreshSession(); refreshSession();
return redirect(request()->header('Referer')); return redirect(request()->header('Referer'));
} }
} }

View File

@ -2,15 +2,15 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
class OauthController extends Controller { class OauthController extends Controller
{
public function redirect(string $provider) public function redirect(string $provider)
{ {
$socialite_provider = get_socialite_provider($provider); $socialite_provider = get_socialite_provider($provider);
return $socialite_provider->redirect(); return $socialite_provider->redirect();
} }
@ -26,9 +26,11 @@ class OauthController extends Controller {
]); ]);
} }
Auth::login($user); Auth::login($user);
return redirect('/'); return redirect('/');
} catch (\Exception $e) { } catch (\Exception $e) {
ray($e->getMessage()); ray($e->getMessage());
return redirect()->route('login')->withErrors([__('auth.failed.callback')]); return redirect()->route('login')->withErrors([__('auth.failed.callback')]);
} }
} }

View File

@ -2,14 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Http\JsonResponse;
use Pion\Laravel\ChunkUpload\Exceptions\UploadFailedException;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile; use Illuminate\Http\UploadedFile;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException; use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
use Pion\Laravel\ChunkUpload\Handler\AbstractHandler;
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory; use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver; use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;
@ -21,7 +18,7 @@ class UploadController extends BaseController
if (is_null($resource)) { if (is_null($resource)) {
return response()->json(['error' => 'You do not have permission for this database'], 500); return response()->json(['error' => 'You do not have permission for this database'], 500);
} }
$receiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request)); $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));
if ($receiver->isUploaded() === false) { if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException(); throw new UploadMissingFileException();
@ -34,9 +31,10 @@ class UploadController extends BaseController
} }
$handler = $save->handler(); $handler = $save->handler();
return response()->json([ return response()->json([
"done" => $handler->getPercentageDone(), 'done' => $handler->getPercentageDone(),
'status' => true 'status' => true,
]); ]);
} }
// protected function saveFileToS3($file) // protected function saveFileToS3($file)
@ -64,19 +62,20 @@ class UploadController extends BaseController
{ {
$mime = str_replace('/', '-', $file->getMimeType()); $mime = str_replace('/', '-', $file->getMimeType());
$filePath = "upload/{$resource->uuid}"; $filePath = "upload/{$resource->uuid}";
$finalPath = storage_path("app/" . $filePath); $finalPath = storage_path('app/'.$filePath);
$file->move($finalPath, 'restore'); $file->move($finalPath, 'restore');
return response()->json([ return response()->json([
'mime_type' => $mime 'mime_type' => $mime,
]); ]);
} }
protected function createFilename(UploadedFile $file) protected function createFilename(UploadedFile $file)
{ {
$extension = $file->getClientOriginalExtension(); $extension = $file->getClientOriginalExtension();
$filename = str_replace("." . $extension, "", $file->getClientOriginalName()); // Filename without extension $filename = str_replace('.'.$extension, '', $file->getClientOriginalName()); // Filename without extension
$filename .= "_" . md5(time()) . "." . $extension; $filename .= '_'.md5(time()).'.'.$extension;
return $filename; return $filename;
} }

View File

@ -30,13 +30,14 @@ class Bitbucket extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Bitbicket::manual_bitbucket", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Bitbicket::manual_bitbucket", $json);
return; return;
} }
$return_payloads = collect([]); $return_payloads = collect([]);
$payload = $request->collect(); $payload = $request->collect();
$headers = $request->headers->all(); $headers = $request->headers->all();
$x_bitbucket_token = data_get($headers, 'x-hub-signature.0', ""); $x_bitbucket_token = data_get($headers, 'x-hub-signature.0', '');
$x_bitbucket_event = data_get($headers, 'x-event-key.0', ""); $x_bitbucket_event = data_get($headers, 'x-event-key.0', '');
$handled_events = collect(['repo:push', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']); $handled_events = collect(['repo:push', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
if (! $handled_events->contains($x_bitbucket_event)) { if (! $handled_events->contains($x_bitbucket_event)) {
return response([ return response([
@ -76,7 +77,7 @@ class Bitbucket extends Controller
$webhook_secret = data_get($application, 'manual_webhook_secret_bitbucket'); $webhook_secret = data_get($application, 'manual_webhook_secret_bitbucket');
$payload = $request->getContent(); $payload = $request->getContent();
list($algo, $hash) = explode('=', $x_bitbucket_token, 2); [$algo, $hash] = explode('=', $x_bitbucket_token, 2);
$payloadHash = hash_hmac($algo, $payload, $webhook_secret); $payloadHash = hash_hmac($algo, $payload, $webhook_secret);
if (! hash_equals($hash, $payloadHash) && ! isDev()) { if (! hash_equals($hash, $payloadHash) && ! isDev()) {
$return_payloads->push([ $return_payloads->push([
@ -85,6 +86,7 @@ class Bitbucket extends Controller
'message' => 'Invalid signature.', 'message' => 'Invalid signature.',
]); ]);
ray('Invalid signature'); ray('Invalid signature');
continue; continue;
} }
$isFunctional = $application->destination->server->isFunctional(); $isFunctional = $application->destination->server->isFunctional();
@ -95,6 +97,7 @@ class Bitbucket extends Controller
'message' => 'Server is not functional.', 'message' => 'Server is not functional.',
]); ]);
ray('Server is not functional: '.$application->destination->server->name); ray('Server is not functional: '.$application->destination->server->name);
continue; continue;
} }
if ($x_bitbucket_event === 'repo:push') { if ($x_bitbucket_event === 'repo:push') {
@ -178,9 +181,11 @@ class Bitbucket extends Controller
} }
} }
ray($return_payloads); ray($return_payloads);
return response($return_payloads); return response($return_payloads);
} catch (Exception $e) { } catch (Exception $e) {
ray($e); ray($e);
return handleError($e); return handleError($e);
} }
} }

View File

@ -27,6 +27,7 @@ class Gitea extends Controller
})->first(); })->first();
if ($gitea_delivery_found) { if ($gitea_delivery_found) {
ray('Webhook already found'); ray('Webhook already found');
return; return;
} }
$data = [ $data = [
@ -41,6 +42,7 @@ class Gitea extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitea::manual_{$x_gitea_delivery}", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitea::manual_{$x_gitea_delivery}", $json);
return; return;
} }
$x_gitea_event = Str::lower($request->header('X-Gitea-Event')); $x_gitea_event = Str::lower($request->header('X-Gitea-Event'));
@ -103,6 +105,7 @@ class Gitea extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Invalid signature.', 'message' => 'Invalid signature.',
]); ]);
continue; continue;
} }
$isFunctional = $application->destination->server->isFunctional(); $isFunctional = $application->destination->server->isFunctional();
@ -112,6 +115,7 @@ class Gitea extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Server is not functional.', 'message' => 'Server is not functional.',
]); ]);
continue; continue;
} }
if ($x_gitea_event === 'push') { if ($x_gitea_event === 'push') {
@ -213,9 +217,11 @@ class Gitea extends Controller
} }
} }
ray($return_payloads); ray($return_payloads);
return response($return_payloads); return response($return_payloads);
} catch (Exception $e) { } catch (Exception $e) {
ray($e->getMessage()); ray($e->getMessage());
return handleError($e); return handleError($e);
} }
} }

View File

@ -33,6 +33,7 @@ class Github extends Controller
})->first(); })->first();
if ($github_delivery_found) { if ($github_delivery_found) {
ray('Webhook already found'); ray('Webhook already found');
return; return;
} }
$data = [ $data = [
@ -47,6 +48,7 @@ class Github extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::manual_{$x_github_delivery}", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::manual_{$x_github_delivery}", $json);
return; return;
} }
$x_github_event = Str::lower($request->header('X-GitHub-Event')); $x_github_event = Str::lower($request->header('X-GitHub-Event'));
@ -108,6 +110,7 @@ class Github extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Invalid signature.', 'message' => 'Invalid signature.',
]); ]);
continue; continue;
} }
$isFunctional = $application->destination->server->isFunctional(); $isFunctional = $application->destination->server->isFunctional();
@ -117,6 +120,7 @@ class Github extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Server is not functional.', 'message' => 'Server is not functional.',
]); ]);
continue; continue;
} }
if ($x_github_event === 'push') { if ($x_github_event === 'push') {
@ -218,12 +222,15 @@ class Github extends Controller
} }
} }
ray($return_payloads); ray($return_payloads);
return response($return_payloads); return response($return_payloads);
} catch (Exception $e) { } catch (Exception $e) {
ray($e->getMessage()); ray($e->getMessage());
return handleError($e); return handleError($e);
} }
} }
public function normal(Request $request) public function normal(Request $request)
{ {
try { try {
@ -239,6 +246,7 @@ class Github extends Controller
})->first(); })->first();
if ($github_delivery_found) { if ($github_delivery_found) {
ray('Webhook already found'); ray('Webhook already found');
return; return;
} }
$data = [ $data = [
@ -253,6 +261,7 @@ class Github extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::normal_{$x_github_delivery}", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::normal_{$x_github_delivery}", $json);
return; return;
} }
$x_github_event = Str::lower($request->header('X-GitHub-Event')); $x_github_event = Str::lower($request->header('X-GitHub-Event'));
@ -280,6 +289,7 @@ class Github extends Controller
if ($action === 'new_permissions_accepted') { if ($action === 'new_permissions_accepted') {
GithubAppPermissionJob::dispatch($github_app); GithubAppPermissionJob::dispatch($github_app);
} }
return response('cool'); return response('cool');
} }
if ($x_github_event === 'push') { if ($x_github_event === 'push') {
@ -329,6 +339,7 @@ class Github extends Controller
'application_uuid' => $application->uuid, 'application_uuid' => $application->uuid,
'application_name' => $application->name, 'application_name' => $application->name,
]); ]);
continue; continue;
} }
if ($x_github_event === 'push') { if ($x_github_event === 'push') {
@ -431,12 +442,15 @@ class Github extends Controller
} }
} }
} }
return response($return_payloads); return response($return_payloads);
} catch (Exception $e) { } catch (Exception $e) {
ray($e->getMessage()); ray($e->getMessage());
return handleError($e); return handleError($e);
} }
} }
public function redirect(Request $request) public function redirect(Request $request)
{ {
try { try {
@ -464,11 +478,13 @@ class Github extends Controller
$github_app->webhook_secret = $webhook_secret; $github_app->webhook_secret = $webhook_secret;
$github_app->private_key_id = $private_key->id; $github_app->private_key_id = $private_key->id;
$github_app->save(); $github_app->save();
return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]); return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
} catch (Exception $e) { } catch (Exception $e) {
return handleError($e); return handleError($e);
} }
} }
public function install(Request $request) public function install(Request $request)
{ {
try { try {
@ -488,6 +504,7 @@ class Github extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::install_{$installation_id}", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::install_{$installation_id}", $json);
return; return;
} }
$source = $request->get('source'); $source = $request->get('source');
@ -497,6 +514,7 @@ class Github extends Controller
$github_app->installation_id = $installation_id; $github_app->installation_id = $installation_id;
$github_app->save(); $github_app->save();
} }
return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]); return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
} catch (Exception $e) { } catch (Exception $e) {
return handleError($e); return handleError($e);

View File

@ -31,6 +31,7 @@ class Gitlab extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitlab::manual_gitlab", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitlab::manual_gitlab", $json);
return; return;
} }
$return_payloads = collect([]); $return_payloads = collect([]);
@ -44,6 +45,7 @@ class Gitlab extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Event not allowed. Only push and merge_request events are allowed.', 'message' => 'Event not allowed. Only push and merge_request events are allowed.',
]); ]);
return response($return_payloads); return response($return_payloads);
} }
@ -58,6 +60,7 @@ class Gitlab extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Nothing to do. No branch found in the request.', 'message' => 'Nothing to do. No branch found in the request.',
]); ]);
return response($return_payloads); return response($return_payloads);
} }
$added_files = data_get($payload, 'commits.*.added'); $added_files = data_get($payload, 'commits.*.added');
@ -78,6 +81,7 @@ class Gitlab extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => 'Nothing to do. No branch found in the request.', 'message' => 'Nothing to do. No branch found in the request.',
]); ]);
return response($return_payloads); 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); ray('Webhook GitHub Pull Request Event with branch: '.$branch.' and base branch: '.$base_branch.' and pull request id: '.$pull_request_id);
@ -90,6 +94,7 @@ class Gitlab extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => "Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name.", 'message' => "Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name.",
]); ]);
return response($return_payloads); return response($return_payloads);
} }
} }
@ -100,6 +105,7 @@ class Gitlab extends Controller
'status' => 'failed', 'status' => 'failed',
'message' => "Nothing to do. No applications found with branch '$base_branch'.", 'message' => "Nothing to do. No applications found with branch '$base_branch'.",
]); ]);
return response($return_payloads); return response($return_payloads);
} }
} }
@ -112,6 +118,7 @@ class Gitlab extends Controller
'message' => 'Invalid signature.', 'message' => 'Invalid signature.',
]); ]);
ray('Invalid signature'); ray('Invalid signature');
continue; continue;
} }
$isFunctional = $application->destination->server->isFunctional(); $isFunctional = $application->destination->server->isFunctional();
@ -122,6 +129,7 @@ class Gitlab extends Controller
'message' => 'Server is not functional', 'message' => 'Server is not functional',
]); ]);
ray('Server is not functional: '.$application->destination->server->name); ray('Server is not functional: '.$application->destination->server->name);
continue; continue;
} }
if ($x_gitlab_event === 'push') { if ($x_gitlab_event === 'push') {
@ -214,6 +222,7 @@ class Gitlab extends Controller
'status' => 'success', 'status' => 'success',
'message' => 'Preview Deployment closed', 'message' => 'Preview Deployment closed',
]); ]);
return response($return_payloads); return response($return_payloads);
} }
$return_payloads->push([ $return_payloads->push([
@ -230,9 +239,11 @@ class Gitlab extends Controller
} }
} }
} }
return response($return_payloads); return response($return_payloads);
} catch (Exception $e) { } catch (Exception $e) {
ray($e->getMessage()); ray($e->getMessage());
return handleError($e); return handleError($e);
} }
} }

View File

@ -36,6 +36,7 @@ class Stripe extends Controller
]; ];
$json = json_encode($data); $json = json_encode($data);
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Stripe::events_stripe", $json); Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Stripe::events_stripe", $json);
return; return;
} }
$webhookSecret = config('subscription.stripe_webhook_secret'); $webhookSecret = config('subscription.stripe_webhook_secret');
@ -48,7 +49,7 @@ class Stripe extends Controller
); );
$webhook = Webhook::create([ $webhook = Webhook::create([
'type' => 'stripe', 'type' => 'stripe',
'payload' => $request->getContent() 'payload' => $request->getContent(),
]); ]);
$type = data_get($event, 'type'); $type = data_get($event, 'type');
$data = data_get($event, 'data.object'); $data = data_get($event, 'data.object');
@ -108,11 +109,13 @@ class Stripe extends Controller
$subscription = Subscription::where('stripe_customer_id', $customerId)->first(); $subscription = Subscription::where('stripe_customer_id', $customerId)->first();
if (! $subscription) { if (! $subscription) {
send_internal_notification('invoice.payment_failed failed but no subscription found in Coolify for customer: '.$customerId); send_internal_notification('invoice.payment_failed failed but no subscription found in Coolify for customer: '.$customerId);
return response('No subscription found in Coolify.'); return response('No subscription found in Coolify.');
} }
$team = data_get($subscription, 'team'); $team = data_get($subscription, 'team');
if (! $team) { if (! $team) {
send_internal_notification('invoice.payment_failed failed but no team found in Coolify for customer: '.$customerId); send_internal_notification('invoice.payment_failed failed but no team found in Coolify for customer: '.$customerId);
return response('No team found in Coolify.'); return response('No team found in Coolify.');
} }
if (! $subscription->stripe_invoice_paid) { if (! $subscription->stripe_invoice_paid) {
@ -127,10 +130,12 @@ class Stripe extends Controller
$subscription = Subscription::where('stripe_customer_id', $customerId)->first(); $subscription = Subscription::where('stripe_customer_id', $customerId)->first();
if (! $subscription) { if (! $subscription) {
send_internal_notification('payment_intent.payment_failed, no subscription found in Coolify for customer: '.$customerId); send_internal_notification('payment_intent.payment_failed, no subscription found in Coolify for customer: '.$customerId);
return response('No subscription found in Coolify.'); return response('No subscription found in Coolify.');
} }
if ($subscription->stripe_invoice_paid) { if ($subscription->stripe_invoice_paid) {
send_internal_notification('payment_intent.payment_failed but invoice is active for customer: '.$customerId); send_internal_notification('payment_intent.payment_failed but invoice is active for customer: '.$customerId);
return; return;
} }
send_internal_notification('Subscription payment failed for customer: '.$customerId); send_internal_notification('Subscription payment failed for customer: '.$customerId);
@ -152,10 +157,12 @@ class Stripe extends Controller
if (! $subscription) { if (! $subscription) {
if ($status === 'incomplete_expired') { if ($status === 'incomplete_expired') {
send_internal_notification('Subscription incomplete expired for customer: '.$customerId); send_internal_notification('Subscription incomplete expired for customer: '.$customerId);
return response("Subscription incomplete expired", 200);
return response('Subscription incomplete expired', 200);
} }
send_internal_notification('No subscription found for: '.$customerId); send_internal_notification('No subscription found for: '.$customerId);
return response("No subscription found", 400);
return response('No subscription found', 400);
} }
$trialEndedAlready = data_get($subscription, 'stripe_trial_already_ended'); $trialEndedAlready = data_get($subscription, 'stripe_trial_already_ended');
$cancelAtPeriodEnd = data_get($data, 'cancel_at_period_end'); $cancelAtPeriodEnd = data_get($data, 'cancel_at_period_end');
@ -264,6 +271,7 @@ class Stripe extends Controller
'status' => 'failed', 'status' => 'failed',
'failure_reason' => $e->getMessage(), 'failure_reason' => $e->getMessage(),
]); ]);
return response($e->getMessage(), 400); return response($e->getMessage(), 400);
} }
} }

View File

@ -22,21 +22,26 @@ class Waitlist extends Controller
$found->verified = true; $found->verified = true;
$found->save(); $found->save();
send_internal_notification('Waitlist confirmed: '.$email); send_internal_notification('Waitlist confirmed: '.$email);
return 'Thank you for confirming your email address. We will notify you when you are next in line.'; return 'Thank you for confirming your email address. We will notify you when you are next in line.';
} else { } else {
$found->delete(); $found->delete();
send_internal_notification('Waitlist expired: '.$email); send_internal_notification('Waitlist expired: '.$email);
return 'Your confirmation code has expired. Please sign up again.'; return 'Your confirmation code has expired. Please sign up again.';
} }
} }
} }
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} catch (Exception $e) { } catch (Exception $e) {
send_internal_notification('Waitlist confirmation failed: '.$e->getMessage()); send_internal_notification('Waitlist confirmation failed: '.$e->getMessage());
ray($e->getMessage()); ray($e->getMessage());
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
} }
public function cancel(Request $request) public function cancel(Request $request)
{ {
$email = request()->get('email'); $email = request()->get('email');
@ -46,12 +51,15 @@ class Waitlist extends Controller
if ($found && ! $found->verified) { if ($found && ! $found->verified) {
$found->delete(); $found->delete();
send_internal_notification('Waitlist cancelled: '.$email); send_internal_notification('Waitlist cancelled: '.$email);
return 'Your email address has been removed from the waitlist.'; return 'Your email address has been removed from the waitlist.';
} }
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} catch (Exception $e) { } catch (Exception $e) {
send_internal_notification('Waitlist cancellation failed: '.$e->getMessage()); send_internal_notification('Waitlist cancellation failed: '.$e->getMessage());
ray($e->getMessage()); ray($e->getMessage());
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
} }

View File

@ -20,6 +20,7 @@ class CheckForcePasswordReset
auth()->logout(); auth()->logout();
request()->session()->invalidate(); request()->session()->invalidate();
request()->session()->regenerateToken(); request()->session()->regenerateToken();
return $next($request); return $next($request);
} }
$force_password_reset = auth()->user()->force_password_reset; $force_password_reset = auth()->user()->force_password_reset;
@ -27,9 +28,11 @@ class CheckForcePasswordReset
if ($request->routeIs('auth.force-password-reset') || $request->path() === 'force-password-reset' || $request->path() === 'livewire/update' || $request->path() === 'logout') { if ($request->routeIs('auth.force-password-reset') || $request->path() === 'force-password-reset' || $request->path() === 'livewire/update' || $request->path() === 'logout') {
return $next($request); return $next($request);
} }
return redirect()->route('auth.force-password-reset'); return redirect()->route('auth.force-password-reset');
} }
} }
return $next($request); return $next($request);
} }
} }

View File

@ -5,8 +5,8 @@ namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider; use App\Providers\RouteServiceProvider;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;
class DecideWhatToDoWithUser class DecideWhatToDoWithUser
{ {
@ -23,12 +23,14 @@ class DecideWhatToDoWithUser
if (! isCloud() && showBoarding() && ! in_array($request->path(), allowedPathsForBoardingAccounts())) { if (! isCloud() && showBoarding() && ! in_array($request->path(), allowedPathsForBoardingAccounts())) {
return redirect()->route('onboarding'); return redirect()->route('onboarding');
} }
return $next($request); return $next($request);
} }
if (! auth()->user()->hasVerifiedEmail()) { if (! auth()->user()->hasVerifiedEmail()) {
if ($request->path() === 'verify' || in_array($request->path(), allowedPathsForInvalidAccounts()) || $request->routeIs('verify.verify')) { if ($request->path() === 'verify' || in_array($request->path(), allowedPathsForInvalidAccounts()) || $request->routeIs('verify.verify')) {
return $next($request); return $next($request);
} }
return redirect()->route('verify.email'); return redirect()->route('verify.email');
} }
if (! isSubscriptionActive() && ! isSubscriptionOnGracePeriod()) { if (! isSubscriptionActive() && ! isSubscriptionOnGracePeriod()) {
@ -36,6 +38,7 @@ class DecideWhatToDoWithUser
if (Str::startsWith($request->path(), 'invitations')) { if (Str::startsWith($request->path(), 'invitations')) {
return $next($request); return $next($request);
} }
return redirect()->route('subscription.index'); return redirect()->route('subscription.index');
} }
} }
@ -43,6 +46,7 @@ class DecideWhatToDoWithUser
if (Str::startsWith($request->path(), 'invitations')) { if (Str::startsWith($request->path(), 'invitations')) {
return $next($request); return $next($request);
} }
return redirect()->route('onboarding'); return redirect()->route('onboarding');
} }
if (auth()->user()->hasVerifiedEmail() && $request->path() === 'verify') { if (auth()->user()->hasVerifiedEmail() && $request->path() === 'verify') {
@ -51,6 +55,7 @@ class DecideWhatToDoWithUser
if (isSubscriptionActive() && $request->routeIs('subscription.index')) { if (isSubscriptionActive() && $request->routeIs('subscription.index')) {
return redirect(RouteServiceProvider::HOME); return redirect(RouteServiceProvider::HOME);
} }
return $next($request); return $next($request);
} }
} }

View File

@ -13,6 +13,6 @@ class PreventRequestsDuringMaintenance extends Middleware
*/ */
protected $except = [ protected $except = [
'webhooks/*', 'webhooks/*',
'/api/health' '/api/health',
]; ];
} }

View File

@ -24,6 +24,7 @@ class RedirectIfAuthenticated
return redirect(RouteServiceProvider::HOME); return redirect(RouteServiceProvider::HOME);
} }
} }
return $next($request); return $next($request);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,12 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted class ApplicationPullRequestUpdateJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public string $build_logs_url; public string $build_logs_url;
public string $body; public string $body;
public function __construct( public function __construct(
@ -32,10 +33,12 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
try { try {
if ($this->application->is_public_repository()) { if ($this->application->is_public_repository()) {
ray('Public repository. Skipping comment update.'); ray('Public repository. Skipping comment update.');
return; return;
} }
if ($this->status === ProcessStatus::CLOSED) { if ($this->status === ProcessStatus::CLOSED) {
$this->delete_comment(); $this->delete_comment();
return; return;
} elseif ($this->status === ProcessStatus::IN_PROGRESS) { } elseif ($this->status === ProcessStatus::IN_PROGRESS) {
$this->body = "The preview deployment is in progress. 🟡\n\n"; $this->body = "The preview deployment is in progress. 🟡\n\n";
@ -49,8 +52,8 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
} }
$this->build_logs_url = base_url()."/project/{$this->application->environment->project->uuid}/{$this->application->environment->name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}"; $this->build_logs_url = base_url()."/project/{$this->application->environment->project->uuid}/{$this->application->environment->name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
$this->body .= "[Open Build Logs](" . $this->build_logs_url . ")\n\n\n"; $this->body .= '[Open Build Logs]('.$this->build_logs_url.")\n\n\n";
$this->body .= "Last updated at: " . now()->toDateTimeString() . " CET"; $this->body .= 'Last updated at: '.now()->toDateTimeString().' CET';
ray('Updating comment', $this->body); ray('Updating comment', $this->body);
if ($this->preview->pull_request_issue_comment_id) { if ($this->preview->pull_request_issue_comment_id) {
@ -60,6 +63,7 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
ray($e); ray($e);
return $e; return $e;
} }
} }
@ -83,6 +87,7 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
$this->preview->pull_request_issue_comment_id = $data['id']; $this->preview->pull_request_issue_comment_id = $data['id'];
$this->preview->save(); $this->preview->save();
} }
private function delete_comment() private function delete_comment()
{ {
githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'delete'); githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'delete');

View File

@ -10,19 +10,23 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class ApplicationRestartJob implements ShouldBeEncrypted, ShouldQueue
class ApplicationRestartJob implements ShouldQueue, ShouldBeEncrypted
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, ExecuteRemoteCommand; use Dispatchable, ExecuteRemoteCommand, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 3600; public $timeout = 3600;
public $tries = 1; public $tries = 1;
public string $applicationDeploymentQueueId; public string $applicationDeploymentQueueId;
public function __construct(string $applicationDeploymentQueueId) public function __construct(string $applicationDeploymentQueueId)
{ {
$this->applicationDeploymentQueueId = $applicationDeploymentQueueId; $this->applicationDeploymentQueueId = $applicationDeploymentQueueId;
} }
public function handle() {
public function handle()
{
ray('Restarting application'); ray('Restarting application');
} }
} }

View File

@ -15,13 +15,14 @@ use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Sleep; use Illuminate\Support\Sleep;
class CheckLogDrainContainerJob implements ShouldQueue, ShouldBeEncrypted class CheckLogDrainContainerJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(public Server $server) public function __construct(public Server $server)
{ {
} }
public function middleware(): array public function middleware(): array
{ {
return [(new WithoutOverlapping($this->server->id))->dontRelease()]; return [(new WithoutOverlapping($this->server->id))->dontRelease()];
@ -31,6 +32,7 @@ class CheckLogDrainContainerJob implements ShouldQueue, ShouldBeEncrypted
{ {
return $this->server->id; return $this->server->id;
} }
public function healthcheck() public function healthcheck()
{ {
$status = instant_remote_process(["docker inspect --format='{{json .State.Status}}' coolify-log-drain"], $this->server, false); $status = instant_remote_process(["docker inspect --format='{{json .State.Status}}' coolify-log-drain"], $this->server, false);
@ -40,14 +42,15 @@ class CheckLogDrainContainerJob implements ShouldQueue, ShouldBeEncrypted
return false; return false;
} }
} }
public function handle() public function handle()
{ {
// ray("checking log drain statuses for {$this->server->id}"); // ray("checking log drain statuses for {$this->server->id}");
try { try {
if (! $this->server->isFunctional()) { if (! $this->server->isFunctional()) {
return; return;
}; }
$containers = instant_remote_process(["docker container ls -q"], $this->server, false); $containers = instant_remote_process(['docker container ls -q'], $this->server, false);
if (! $containers) { if (! $containers) {
return; return;
} }
@ -66,6 +69,7 @@ class CheckLogDrainContainerJob implements ShouldQueue, ShouldBeEncrypted
$this->server->team?->notify(new ContainerRestarted('Coolify Log Drainer', $this->server)); $this->server->team?->notify(new ContainerRestarted('Coolify Log Drainer', $this->server));
$this->server->update(['log_drain_notification_sent' => false]); $this->server->update(['log_drain_notification_sent' => false]);
} }
return; return;
} }
if (! $this->server->log_drain_notification_sent) { if (! $this->server->log_drain_notification_sent) {
@ -80,8 +84,11 @@ class CheckLogDrainContainerJob implements ShouldQueue, ShouldBeEncrypted
} }
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
if (!isCloud()) send_internal_notification("CheckLogDrainContainerJob failed on ({$this->server->id}) with: " . $e->getMessage()); if (! isCloud()) {
send_internal_notification("CheckLogDrainContainerJob failed on ({$this->server->id}) with: ".$e->getMessage());
}
ray($e->getMessage()); ray($e->getMessage());
return handleError($e); return handleError($e);
} }
} }

View File

@ -10,7 +10,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class CheckResaleLicenseJob implements ShouldQueue, ShouldBeEncrypted class CheckResaleLicenseJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

View File

@ -11,7 +11,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class CleanupHelperContainersJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncrypted class CleanupHelperContainersJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

View File

@ -12,7 +12,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class CleanupInstanceStuffsJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncrypted class CleanupInstanceStuffsJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -49,6 +49,7 @@ class CleanupInstanceStuffsJob implements ShouldQueue, ShouldBeUnique, ShouldBeE
$item->delete(); $item->delete();
} }
} }
private function cleanup_invitation_link() private function cleanup_invitation_link()
{ {
$invitation = TeamInvitation::all(); $invitation = TeamInvitation::all();

View File

@ -12,18 +12,21 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted class ContainerStatusJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 4; public $tries = 4;
public function backoff(): int public function backoff(): int
{ {
return isDev() ? 1 : 3; return isDev() ? 1 : 3;
} }
public function __construct(public Server $server) public function __construct(public Server $server)
{ {
} }
public function middleware(): array public function middleware(): array
{ {
return [(new WithoutOverlapping($this->server->uuid))]; return [(new WithoutOverlapping($this->server->uuid))];

View File

@ -11,7 +11,7 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
class CoolifyTask implements ShouldQueue, ShouldBeEncrypted class CoolifyTask implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -35,7 +35,7 @@ class CoolifyTask implements ShouldQueue, ShouldBeEncrypted
'activity' => $this->activity, 'activity' => $this->activity,
'ignore_errors' => $this->ignore_errors, 'ignore_errors' => $this->ignore_errors,
'call_event_on_finish' => $this->call_event_on_finish, 'call_event_on_finish' => $this->call_event_on_finish,
'call_event_data' => $this->call_event_data 'call_event_data' => $this->call_event_data,
]); ]);
$remote_process(); $remote_process();

View File

@ -25,26 +25,37 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Throwable;
class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public ?Team $team = null; public ?Team $team = null;
public Server $server; public Server $server;
public ScheduledDatabaseBackup $backup; public ScheduledDatabaseBackup $backup;
public StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase $database; public StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase $database;
public ?string $container_name = null; public ?string $container_name = null;
public ?string $directory_name = null; public ?string $directory_name = null;
public ?ScheduledDatabaseBackupExecution $backup_log = null; public ?ScheduledDatabaseBackupExecution $backup_log = null;
public string $backup_status = 'failed'; public string $backup_status = 'failed';
public ?string $backup_location = null; public ?string $backup_location = null;
public string $backup_dir; public string $backup_dir;
public string $backup_file; public string $backup_file;
public int $size = 0; public int $size = 0;
public ?string $backup_output = null; public ?string $backup_output = null;
public ?S3Storage $s3 = null; public ?S3Storage $s3 = null;
public function __construct($backup) public function __construct($backup)
@ -84,11 +95,13 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
$this->backup->update(['status' => 'failed']); $this->backup->update(['status' => 'failed']);
StopDatabase::run($this->database); StopDatabase::run($this->database);
$this->database->delete(); $this->database->delete();
return; return;
} }
$status = Str::of(data_get($this->database, 'status')); $status = Str::of(data_get($this->database, 'status'));
if (! $status->startsWith('running') && $this->database->id !== 0) { if (! $status->startsWith('running') && $this->database->id !== 0) {
ray('database not running'); ray('database not running');
return; return;
} }
if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') { if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') {
@ -223,20 +236,20 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
return; return;
} }
} }
$this->backup_dir = backup_dir() . "/databases/" . Str::of($this->team->name)->slug() . '-' . $this->team->id . '/' . $this->directory_name; $this->backup_dir = backup_dir().'/databases/'.Str::of($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name;
if ($this->database->name === 'coolify-db') { if ($this->database->name === 'coolify-db') {
$databasesToBackup = ['coolify']; $databasesToBackup = ['coolify'];
$this->directory_name = $this->container_name = "coolify-db"; $this->directory_name = $this->container_name = 'coolify-db';
$ip = Str::slug($this->server->ip); $ip = Str::slug($this->server->ip);
$this->backup_dir = backup_dir() . "/coolify" . "/coolify-db-$ip"; $this->backup_dir = backup_dir().'/coolify'."/coolify-db-$ip";
} }
foreach ($databasesToBackup as $database) { foreach ($databasesToBackup as $database) {
$size = 0; $size = 0;
ray('Backing up '.$database); ray('Backing up '.$database);
try { try {
if (str($databaseType)->contains('postgres')) { if (str($databaseType)->contains('postgres')) {
$this->backup_file = "/pg-dump-$database-" . Carbon::now()->timestamp . ".dmp"; $this->backup_file = "/pg-dump-$database-".Carbon::now()->timestamp.'.dmp';
$this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_location = $this->backup_dir.$this->backup_file;
$this->backup_log = ScheduledDatabaseBackupExecution::create([ $this->backup_log = ScheduledDatabaseBackupExecution::create([
'database_name' => $database, 'database_name' => $database,
@ -255,7 +268,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
$databaseName = $database; $databaseName = $database;
} }
} }
$this->backup_file = "/mongo-dump-$databaseName-" . Carbon::now()->timestamp . ".tar.gz"; $this->backup_file = "/mongo-dump-$databaseName-".Carbon::now()->timestamp.'.tar.gz';
$this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_location = $this->backup_dir.$this->backup_file;
$this->backup_log = ScheduledDatabaseBackupExecution::create([ $this->backup_log = ScheduledDatabaseBackupExecution::create([
'database_name' => $databaseName, 'database_name' => $databaseName,
@ -264,7 +277,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
]); ]);
$this->backup_standalone_mongodb($database); $this->backup_standalone_mongodb($database);
} elseif (str($databaseType)->contains('mysql')) { } elseif (str($databaseType)->contains('mysql')) {
$this->backup_file = "/mysql-dump-$database-" . Carbon::now()->timestamp . ".dmp"; $this->backup_file = "/mysql-dump-$database-".Carbon::now()->timestamp.'.dmp';
$this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_location = $this->backup_dir.$this->backup_file;
$this->backup_log = ScheduledDatabaseBackupExecution::create([ $this->backup_log = ScheduledDatabaseBackupExecution::create([
'database_name' => $database, 'database_name' => $database,
@ -273,7 +286,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
]); ]);
$this->backup_standalone_mysql($database); $this->backup_standalone_mysql($database);
} elseif (str($databaseType)->contains('mariadb')) { } elseif (str($databaseType)->contains('mariadb')) {
$this->backup_file = "/mariadb-dump-$database-" . Carbon::now()->timestamp . ".dmp"; $this->backup_file = "/mariadb-dump-$database-".Carbon::now()->timestamp.'.dmp';
$this->backup_location = $this->backup_dir.$this->backup_file; $this->backup_location = $this->backup_dir.$this->backup_file;
$this->backup_log = ScheduledDatabaseBackupExecution::create([ $this->backup_log = ScheduledDatabaseBackupExecution::create([
'database_name' => $database, 'database_name' => $database,
@ -301,7 +314,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
'status' => 'failed', 'status' => 'failed',
'message' => $this->backup_output, 'message' => $this->backup_output,
'size' => $size, 'size' => $size,
'filename' => null 'filename' => null,
]); ]);
} }
send_internal_notification('DatabaseBackupJob failed with: '.$e->getMessage()); send_internal_notification('DatabaseBackupJob failed with: '.$e->getMessage());
@ -315,13 +328,14 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
BackupCreated::dispatch($this->team->id); BackupCreated::dispatch($this->team->id);
} }
} }
private function backup_standalone_mongodb(string $databaseWithCollections): void private function backup_standalone_mongodb(string $databaseWithCollections): void
{ {
try { try {
ray($this->database->toArray()); ray($this->database->toArray());
$url = $this->database->get_db_url(useInternal: true); $url = $this->database->get_db_url(useInternal: true);
if ($databaseWithCollections === 'all') { if ($databaseWithCollections === 'all') {
$commands[] = "mkdir -p " . $this->backup_dir; $commands[] = 'mkdir -p '.$this->backup_dir;
if (str($this->database->image)->startsWith('mongo:4.0')) { if (str($this->database->image)->startsWith('mongo:4.0')) {
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location"; $commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
} else { } else {
@ -335,7 +349,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
$databaseName = $databaseWithCollections; $databaseName = $databaseWithCollections;
$collectionsToExclude = collect(); $collectionsToExclude = collect();
} }
$commands[] = "mkdir -p " . $this->backup_dir; $commands[] = 'mkdir -p '.$this->backup_dir;
if ($collectionsToExclude->count() === 0) { if ($collectionsToExclude->count() === 0) {
if (str($this->database->image)->startsWith('mongo:4.0')) { if (str($this->database->image)->startsWith('mongo:4.0')) {
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location"; $commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
@ -362,10 +376,11 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
throw $e; throw $e;
} }
} }
private function backup_standalone_postgresql(string $database): void private function backup_standalone_postgresql(string $database): void
{ {
try { try {
$commands[] = "mkdir -p " . $this->backup_dir; $commands[] = 'mkdir -p '.$this->backup_dir;
$commands[] = "docker exec $this->container_name pg_dump --format=custom --no-acl --no-owner --username {$this->database->postgres_user} $database > $this->backup_location"; $commands[] = "docker exec $this->container_name pg_dump --format=custom --no-acl --no-owner --username {$this->database->postgres_user} $database > $this->backup_location";
$this->backup_output = instant_remote_process($commands, $this->server); $this->backup_output = instant_remote_process($commands, $this->server);
$this->backup_output = trim($this->backup_output); $this->backup_output = trim($this->backup_output);
@ -379,10 +394,11 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
throw $e; throw $e;
} }
} }
private function backup_standalone_mysql(string $database): void private function backup_standalone_mysql(string $database): void
{ {
try { try {
$commands[] = "mkdir -p " . $this->backup_dir; $commands[] = 'mkdir -p '.$this->backup_dir;
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} $database > $this->backup_location"; $commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} $database > $this->backup_location";
ray($commands); ray($commands);
$this->backup_output = instant_remote_process($commands, $this->server); $this->backup_output = instant_remote_process($commands, $this->server);
@ -397,10 +413,11 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
throw $e; throw $e;
} }
} }
private function backup_standalone_mariadb(string $database): void private function backup_standalone_mariadb(string $database): void
{ {
try { try {
$commands[] = "mkdir -p " . $this->backup_dir; $commands[] = 'mkdir -p '.$this->backup_dir;
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location"; $commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location";
ray($commands); ray($commands);
$this->backup_output = instant_remote_process($commands, $this->server); $this->backup_output = instant_remote_process($commands, $this->server);
@ -415,6 +432,7 @@ class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
throw $e; throw $e;
} }
} }
private function add_to_backup_output($output): void private function add_to_backup_output($output): void
{ {
if ($this->backup_output) { if ($this->backup_output) {

View File

@ -3,19 +3,16 @@
namespace App\Jobs; namespace App\Jobs;
use App\Models\ScheduledDatabaseBackup; use App\Models\ScheduledDatabaseBackup;
use App\Models\Server;
use App\Models\Team; use App\Models\Team;
use App\Notifications\Database\DailyBackup; use App\Notifications\Database\DailyBackup;
use App\Notifications\Server\HighDiskUsage;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class DatabaseBackupStatusJob implements ShouldQueue, ShouldBeEncrypted class DatabaseBackupStatusJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -42,13 +39,6 @@ class DatabaseBackupStatusJob implements ShouldQueue, ShouldBeEncrypted
// } // }
// } // }
// $scheduled_backups = ScheduledDatabaseBackup::all(); // $scheduled_backups = ScheduledDatabaseBackup::all();
// $databases = collect(); // $databases = collect();
// $teams = collect(); // $teams = collect();

View File

@ -24,7 +24,7 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
class DeleteResourceJob implements ShouldQueue, ShouldBeEncrypted class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

View File

@ -10,21 +10,22 @@ use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use RuntimeException; use RuntimeException;
class DockerCleanupJob implements ShouldQueue, ShouldBeEncrypted class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 300; public $timeout = 300;
public ?int $usageBefore = null; public ?int $usageBefore = null;
public function __construct(public Server $server) public function __construct(public Server $server)
{ {
} }
public function handle(): void public function handle(): void
{ {
try { try {
@ -32,6 +33,7 @@ class DockerCleanupJob implements ShouldQueue, ShouldBeEncrypted
$this->server->applications()->each(function ($application) use (&$isInprogress) { $this->server->applications()->each(function ($application) use (&$isInprogress) {
if ($application->isDeploymentInprogress()) { if ($application->isDeploymentInprogress()) {
$isInprogress = true; $isInprogress = true;
return; return;
} }
}); });

View File

@ -12,18 +12,21 @@ use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
class GithubAppPermissionJob implements ShouldQueue, ShouldBeEncrypted class GithubAppPermissionJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 4; public $tries = 4;
public function backoff(): int public function backoff(): int
{ {
return isDev() ? 1 : 3; return isDev() ? 1 : 3;
} }
public function __construct(public GithubApp $github_app) public function __construct(public GithubApp $github_app)
{ {
} }
public function middleware(): array public function middleware(): array
{ {
return [(new WithoutOverlapping($this->github_app->uuid))]; return [(new WithoutOverlapping($this->github_app->uuid))];
@ -40,7 +43,7 @@ class GithubAppPermissionJob implements ShouldQueue, ShouldBeEncrypted
$github_access_token = generate_github_jwt_token($this->github_app); $github_access_token = generate_github_jwt_token($this->github_app);
$response = Http::withHeaders([ $response = Http::withHeaders([
'Authorization' => "Bearer $github_access_token", 'Authorization' => "Bearer $github_access_token",
'Accept' => 'application/vnd.github+json' 'Accept' => 'application/vnd.github+json',
])->get("{$this->github_app->api_url}/app"); ])->get("{$this->github_app->api_url}/app");
$response = $response->json(); $response = $response->json();
$permissions = data_get($response, 'permissions'); $permissions = data_get($response, 'permissions');

View File

@ -11,11 +11,12 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class InstanceAutoUpdateJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncrypted class InstanceAutoUpdateJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 600; public $timeout = 600;
public $tries = 1; public $tries = 1;
public function __construct() public function __construct()

View File

@ -13,7 +13,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
class PullCoolifyImageJob implements ShouldQueue, ShouldBeEncrypted class PullCoolifyImageJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -22,6 +22,7 @@ class PullCoolifyImageJob implements ShouldQueue, ShouldBeEncrypted
public function __construct() public function __construct()
{ {
} }
public function handle(): void public function handle(): void
{ {
try { try {
@ -49,8 +50,8 @@ class PullCoolifyImageJob implements ShouldQueue, ShouldBeEncrypted
return; return;
} }
instant_remote_process([ instant_remote_process([
"curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh", 'curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh',
"bash /data/coolify/source/upgrade.sh $latest_version" "bash /data/coolify/source/upgrade.sh $latest_version",
], $server); ], $server);
} catch (\Throwable $e) { } catch (\Throwable $e) {
throw $e; throw $e;

View File

@ -11,7 +11,7 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class PullHelperImageJob implements ShouldQueue, ShouldBeEncrypted class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -26,9 +26,11 @@ class PullHelperImageJob implements ShouldQueue, ShouldBeEncrypted
{ {
return $this->server->uuid; return $this->server->uuid;
} }
public function __construct(public Server $server) public function __construct(public Server $server)
{ {
} }
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -12,7 +12,7 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\Middleware\WithoutOverlapping; use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class PullSentinelImageJob implements ShouldQueue, ShouldBeEncrypted class PullSentinelImageJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -27,15 +27,18 @@ class PullSentinelImageJob implements ShouldQueue, ShouldBeEncrypted
{ {
return $this->server->uuid; return $this->server->uuid;
} }
public function __construct(public Server $server) public function __construct(public Server $server)
{ {
} }
public function handle(): void public function handle(): void
{ {
try { try {
$version = get_latest_sentinel_version(); $version = get_latest_sentinel_version();
if (! $version) { if (! $version) {
ray('Failed to get latest Sentinel version'); ray('Failed to get latest Sentinel version');
return; return;
} }
$local_version = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false); $local_version = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false);
@ -44,6 +47,7 @@ class PullSentinelImageJob implements ShouldQueue, ShouldBeEncrypted
} }
if (version_compare($local_version, $version, '<')) { if (version_compare($local_version, $version, '<')) {
StartSentinel::run($this->server, $version, true); StartSentinel::run($this->server, $version, true);
return; return;
} }
ray('Sentinel image is up to date'); ray('Sentinel image is up to date');

View File

@ -2,7 +2,6 @@
namespace App\Jobs; namespace App\Jobs;
use App\Models\Server;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -12,7 +11,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
class PullTemplatesFromCDN implements ShouldQueue, ShouldBeEncrypted class PullTemplatesFromCDN implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -21,6 +20,7 @@ class PullTemplatesFromCDN implements ShouldQueue, ShouldBeEncrypted
public function __construct() public function __construct()
{ {
} }
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -11,7 +11,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
class PullVersionsFromCDN implements ShouldQueue, ShouldBeEncrypted class PullVersionsFromCDN implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
@ -20,6 +20,7 @@ class PullVersionsFromCDN implements ShouldQueue, ShouldBeEncrypted
public function __construct() public function __construct()
{ {
} }
public function handle(): void public function handle(): void
{ {
try { try {

View File

@ -2,10 +2,10 @@
namespace App\Jobs; namespace App\Jobs;
use App\Models\Application;
use App\Models\ScheduledTask; use App\Models\ScheduledTask;
use App\Models\ScheduledTaskExecution; use App\Models\ScheduledTaskExecution;
use App\Models\Server; use App\Models\Server;
use App\Models\Application;
use App\Models\Service; use App\Models\Service;
use App\Models\Team; use App\Models\Team;
use App\Notifications\ScheduledTask\TaskFailed; use App\Notifications\ScheduledTask\TaskFailed;
@ -21,13 +21,19 @@ class ScheduledTaskJob implements ShouldQueue
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public ?Team $team = null; public ?Team $team = null;
public Server $server; public Server $server;
public ScheduledTask $task; public ScheduledTask $task;
public Application|Service $resource; public Application|Service $resource;
public ?ScheduledTaskExecution $task_log = null; public ?ScheduledTaskExecution $task_log = null;
public string $task_status = 'failed'; public string $task_status = 'failed';
public ?string $task_output = null; public ?string $task_output = null;
public array $containers = []; public array $containers = [];
public function __construct($task) public function __construct($task)
@ -69,8 +75,7 @@ class ScheduledTaskJob implements ShouldQueue
$this->containers[] = str_replace('/', '', $container['Names']); $this->containers[] = str_replace('/', '', $container['Names']);
}); });
} }
} } elseif ($this->resource->type() == 'service') {
elseif ($this->resource->type() == 'service') {
$this->resource->applications()->get()->each(function ($application) { $this->resource->applications()->get()->each(function ($application) {
if (str(data_get($application, 'status'))->contains('running')) { if (str(data_get($application, 'status'))->contains('running')) {
$this->containers[] = data_get($application, 'name').'-'.data_get($this->resource, 'uuid'); $this->containers[] = data_get($application, 'name').'-'.data_get($this->resource, 'uuid');
@ -99,13 +104,13 @@ class ScheduledTaskJob implements ShouldQueue
'status' => 'success', 'status' => 'success',
'message' => $this->task_output, 'message' => $this->task_output,
]); ]);
return; return;
} }
} }
// No valid container was found. // No valid container was found.
throw new \Exception('ScheduledTaskJob failed: No valid container was found. Is the container name correct?'); throw new \Exception('ScheduledTaskJob failed: No valid container was found. Is the container name correct?');
} catch (\Throwable $e) { } catch (\Throwable $e) {
if ($this->task_log) { if ($this->task_log) {
$this->task_log->update([ $this->task_log->update([

View File

@ -2,19 +2,15 @@
namespace App\Jobs; namespace App\Jobs;
use App\Models\InstanceSettings;
use App\Models\Waitlist;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendConfirmationForWaitlistJob implements ShouldQueue, ShouldBeEncrypted class SendConfirmationForWaitlistJob implements ShouldBeEncrypted, ShouldQueue
{ {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

Some files were not shown because too many files have changed in this diff Show More