diff --git a/README.md b/README.md index 663fe0db0..6e6d80c59 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,9 @@ Special thanks to our biggest sponsors, [CCCareers](https://cccareers.org/) and cccareers logo appwrite logo -## Github Sponsors ($15+) +## Github Sponsors ($40+) +CryptoJobsList +typebot BC Direct Corentin Clichy Corentin Clichy diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php index 6ec71c4f3..30b301095 100644 --- a/app/Actions/Service/StartService.php +++ b/app/Actions/Service/StartService.php @@ -16,7 +16,7 @@ class StartService $commands[] = "cd " . $service->workdir(); $commands[] = "echo 'Saved configuration files to {$service->workdir()}.'"; $commands[] = "echo 'Creating Docker network.'"; - $commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid >/dev/null 2>&1 || true"; + $commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid"; $commands[] = "echo Starting service."; $commands[] = "echo 'Pulling images.'"; $commands[] = "docker compose pull"; diff --git a/app/Livewire/Project/Resource/Create.php b/app/Livewire/Project/Resource/Create.php index db5dc03f4..62ccac076 100644 --- a/app/Livewire/Project/Resource/Create.php +++ b/app/Livewire/Project/Resource/Create.php @@ -10,7 +10,8 @@ use Livewire\Component; class Create extends Component { public $type; - public function mount() { + public function mount() + { $services = getServiceTemplates(); $type = str(request()->query('type')); $destination_uuid = request()->query('destination'); @@ -70,7 +71,7 @@ class Create extends Component $generatedValue = $value; if ($value->contains('SERVICE_')) { $command = $value->after('SERVICE_')->beforeLast('_'); - $generatedValue = generateEnvValue($command->value()); + $generatedValue = generateEnvValue($command->value(), $service); } EnvironmentVariable::create([ 'key' => $key, diff --git a/app/Livewire/Server/Resources.php b/app/Livewire/Server/Resources.php index 99d988271..194fd8269 100644 --- a/app/Livewire/Server/Resources.php +++ b/app/Livewire/Server/Resources.php @@ -55,7 +55,7 @@ class Resources extends Component } catch (\Throwable $e) { return handleError($e, $this); } - $this->loadUnmanagedContainers(); + // $this->loadUnmanagedContainers(); } public function render() { diff --git a/app/Models/Server.php b/app/Models/Server.php index 73e10a587..d43256c8d 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -263,17 +263,19 @@ class Server extends BaseModel } public function loadUnmanagedContainers() { - $containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this); - $containers = format_docker_command_output_to_json($containers); - $containers = $containers->map(function ($container) { - $labels = data_get($container, 'Labels'); - if (!str($labels)->contains("coolify.managed")) { - return $container; - } - return null; - }); - $containers = $containers->filter(); - return collect($containers); + if ($this->isFunctional()) { + $containers = instant_remote_process(["docker ps -a --format '{{json .}}' "], $this); + $containers = format_docker_command_output_to_json($containers); + $containers = $containers->map(function ($container) { + $labels = data_get($container, 'Labels'); + if (!str($labels)->contains("coolify.managed")) { + return $container; + } + return null; + }); + $containers = $containers->filter(); + return collect($containers); + } } public function hasDefinedResources() { diff --git a/app/Models/Service.php b/app/Models/Service.php index 9fa175bae..e8b0c97f0 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -102,6 +102,30 @@ class Service extends BaseModel foreach ($applications as $application) { $image = str($application->image)->before(':')->value(); switch ($image) { + case str($image)?->contains('kong'): + $data = collect([]); + $dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first(); + $dashboard_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first(); + if ($dashboard_user) { + $data = $data->merge([ + 'Dashboard User' => [ + 'key' => data_get($dashboard_user, 'key'), + 'value' => data_get($dashboard_user, 'value'), + 'rules' => 'required', + ], + ]); + } + if ($dashboard_password) { + $data = $data->merge([ + 'Dashboard Password' => [ + 'key' => data_get($dashboard_password, 'key'), + 'value' => data_get($dashboard_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + $fields->put('Supabase', $data->toArray()); case str($image)?->contains('minio'): $data = collect([]); $console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first(); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 4a49f34a2..86a874985 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -33,6 +33,11 @@ use Illuminate\Support\Facades\Request; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; use Illuminate\Support\Stringable; +use Lcobucci\JWT\Encoding\ChainedFormatter; +use Lcobucci\JWT\Encoding\JoseEncoder; +use Lcobucci\JWT\Signer\Key\InMemory; +use Lcobucci\JWT\Signer\Hmac\Sha256; +use Lcobucci\JWT\Token\Builder; use Poliander\Cron\CronExpression; use Visus\Cuid2\Cuid2; use phpseclib3\Crypt\RSA; @@ -625,7 +630,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } $definedNetwork = collect([$resource->uuid]); - $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource) { $serviceVolumes = collect(data_get($service, 'volumes', [])); $servicePorts = collect(data_get($service, 'ports', [])); @@ -927,6 +931,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $savedService->fqdn = $fqdn; $savedService->save(); } + EnvironmentVariable::create([ + 'key' => $key, + 'value' => $fqdn, + 'is_build_time' => false, + 'service_id' => $resource->id, + 'is_preview' => false, + ]); } // data_forget($service, "environment.$variableName"); // $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName"); @@ -978,7 +989,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal } } } else { - $generatedValue = generateEnvValue($command); + $generatedValue = generateEnvValue($command, $resource); if (!$foundEnv) { EnvironmentVariable::create([ 'key' => $key, @@ -1394,7 +1405,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal ]); } } else { - $generatedValue = generateEnvValue($command); + $generatedValue = generateEnvValue($command, $service); if (!$foundEnv) { EnvironmentVariable::create([ 'key' => $key, @@ -1570,7 +1581,7 @@ function parseEnvVariable(Str|string $value) 'port' => $port, ]; } -function generateEnvValue(string $command) +function generateEnvValue(string $command, Service $service) { switch ($command) { case 'PASSWORD': @@ -1591,6 +1602,46 @@ function generateEnvValue(string $command) case 'USER': $generatedValue = Str::random(16); break; + case 'SUPABASEANON': + $signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first(); + if (is_null($signingKey)) { + return; + } else { + $signingKey = $signingKey->value; + } + $key = InMemory::plainText($signingKey); + $algorithm = new Sha256(); + $tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default())); + $now = new DateTimeImmutable(); + $now = $now->setTime($now->format('H'), $now->format('i')); + $token = $tokenBuilder + ->issuedBy('supabase') + ->issuedAt($now) + ->expiresAt($now->modify('+100 year')) + ->withClaim('role', 'anon') + ->getToken($algorithm, $key); + $generatedValue = $token->toString(); + break; + case 'SUPABASESERVICE': + $signingKey = $service->environment_variables()->where('key', 'SERVICE_PASSWORD_JWT')->first(); + if (is_null($signingKey)) { + return; + } else { + $signingKey = $signingKey->value; + } + $key = InMemory::plainText($signingKey); + $algorithm = new Sha256(); + $tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default())); + $now = new DateTimeImmutable(); + $now = $now->setTime($now->format('H'), $now->format('i')); + $token = $tokenBuilder + ->issuedBy('supabase') + ->issuedAt($now) + ->expiresAt($now->modify('+100 year')) + ->withClaim('role', 'service_role') + ->getToken($algorithm, $key); + $generatedValue = $token->toString(); + break; default: $generatedValue = Str::random(16); break; diff --git a/config/sentry.php b/config/sentry.php index c216bb219..5b50fdd7a 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.227', + 'release' => '4.0.0-beta.228', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index 3a84eb6f2..d3995a90a 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ + + diff --git a/public/svgs/supabase.svg b/public/svgs/supabase.svg new file mode 100644 index 000000000..ad802ac16 --- /dev/null +++ b/public/svgs/supabase.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/resources/views/components/internal-link.blade.php b/resources/views/components/internal-link.blade.php new file mode 100644 index 000000000..19fe52635 --- /dev/null +++ b/resources/views/components/internal-link.blade.php @@ -0,0 +1 @@ + diff --git a/resources/views/emails/trial-ends-soon.blade.php b/resources/views/emails/trial-ends-soon.blade.php index b60692c02..508af2c41 100644 --- a/resources/views/emails/trial-ends-soon.blade.php +++ b/resources/views/emails/trial-ends-soon.blade.php @@ -1,5 +1,5 @@ Your trial ends soon. Please update payment details [here]({{ $stripeCustomerPortal }}), -Your servers & deployed resources will be untouched, but you won't be able to deploy new resources and lost all automations and integrations. +Your servers & deployed resources will be untouched, but you won't be able to deploy new resources and lose all automations and integrations. diff --git a/resources/views/livewire/destination/show.blade.php b/resources/views/livewire/destination/show.blade.php index a13823fdd..04b76f603 100644 --- a/resources/views/livewire/destination/show.blade.php +++ b/resources/views/livewire/destination/show.blade.php @@ -16,7 +16,6 @@ @empty -
N/A
@endforelse @forelse ($server->swarmDockers as $docker) {{ data_get($docker, 'network') }} @empty -
N/A
@endforelse
diff --git a/resources/views/livewire/project/resource/index.blade.php b/resources/views/livewire/project/resource/index.blade.php index ac59b0c18..3ff2f9fb8 100644 --- a/resources/views/livewire/project/resource/index.blade.php +++ b/resources/views/livewire/project/resource/index.blade.php @@ -50,7 +50,7 @@