mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-18 20:59:24 +00:00
Compare commits
54 Commits
v4.0.0-bet
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12fc5a8f91 | ||
|
|
9eba058cf7 | ||
|
|
fa4f5fea8c | ||
|
|
898563fe7c | ||
|
|
c418a17161 | ||
|
|
cd0da04ea2 | ||
|
|
01e942c6a0 | ||
|
|
bb9abafa82 | ||
|
|
d0cd926517 | ||
|
|
9baf0161c7 | ||
|
|
8ba18b2ce1 | ||
|
|
ab021ee535 | ||
|
|
c76a1b1ba5 | ||
|
|
6266a5e500 | ||
|
|
5d27e89bfa | ||
|
|
6da4e78374 | ||
|
|
be30651172 | ||
|
|
95764c2b76 | ||
|
|
92a75685b5 | ||
|
|
a1592373aa | ||
|
|
5747a87f66 | ||
|
|
9cda671aef | ||
|
|
2c9983046c | ||
|
|
11d33f328e | ||
|
|
f79c741d95 | ||
|
|
8a39a4469a | ||
|
|
42daae10c6 | ||
|
|
64a65e2018 | ||
|
|
16c71f3647 | ||
|
|
363f525ad1 | ||
|
|
f4fb519d55 | ||
|
|
b7786504b8 | ||
|
|
f0adf10e6a | ||
|
|
cc8c6c5d16 | ||
|
|
4782446f42 | ||
|
|
230155312f | ||
|
|
3ab4365fca | ||
|
|
7349068b95 | ||
|
|
da6cc151d1 | ||
|
|
50527cf0a3 | ||
|
|
26f490bb00 | ||
|
|
dc4f412227 | ||
|
|
ec4234e243 | ||
|
|
f47fcb01ce | ||
|
|
02f6673345 | ||
|
|
e6cd8702b5 | ||
|
|
fda4ea8cca | ||
|
|
655d004ce7 | ||
|
|
56981d134c | ||
|
|
b9d49d2951 | ||
|
|
0c1e7c499e | ||
|
|
32fead5753 | ||
|
|
e5e9faba35 | ||
|
|
2852630d6c |
4
.github/workflows/development-build.yml
vendored
4
.github/workflows/development-build.yml
vendored
@@ -13,7 +13,7 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
amd64:
|
amd64:
|
||||||
runs-on: ubuntu-latest
|
runs-on: [self-hosted, x64]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Login to ghcr.io
|
- name: Login to ghcr.io
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next-aarch64
|
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next-aarch64
|
||||||
merge-manifest:
|
merge-manifest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: [self-hosted, x64]
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ class RunRemoteProcess
|
|||||||
'status' => $status->value,
|
'status' => $status->value,
|
||||||
]);
|
]);
|
||||||
$this->activity->save();
|
$this->activity->save();
|
||||||
|
|
||||||
if ($processResult->exitCode() != 0 && !$this->ignore_errors) {
|
if ($processResult->exitCode() != 0 && !$this->ignore_errors) {
|
||||||
throw new \RuntimeException($processResult->errorOutput());
|
throw new \RuntimeException($processResult->errorOutput());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,13 +57,13 @@ class CheckResaleLicense
|
|||||||
throw new \Exception('Invalid license key.');
|
throw new \Exception('Invalid license key.');
|
||||||
}
|
}
|
||||||
throw new \Exception('Cannot activate license key.');
|
throw new \Exception('Cannot activate license key.');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
ray($th);
|
ray($e);
|
||||||
$settings->update([
|
$settings->update([
|
||||||
'resale_license' => null,
|
'resale_license' => null,
|
||||||
'is_resale_license_active' => false,
|
'is_resale_license_active' => false,
|
||||||
]);
|
]);
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ class SaveConfigurationSync
|
|||||||
"mkdir -p $proxy_path",
|
"mkdir -p $proxy_path",
|
||||||
"echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml",
|
"echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml",
|
||||||
], $server);
|
], $server);
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
ray($th);
|
ray($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Actions\Proxy;
|
namespace App\Actions\Proxy;
|
||||||
|
|
||||||
use App\Enums\ProxyStatus;
|
|
||||||
use App\Enums\ProxyTypes;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Spatie\Activitylog\Models\Activity;
|
use Spatie\Activitylog\Models\Activity;
|
||||||
@@ -30,19 +28,22 @@ class StartProxy
|
|||||||
$server->save();
|
$server->save();
|
||||||
|
|
||||||
$activity = remote_process([
|
$activity = remote_process([
|
||||||
"echo 'Creating required Docker networks...'",
|
"echo '####### Creating required Docker networks...'",
|
||||||
...$create_networks_command,
|
...$create_networks_command,
|
||||||
"cd $proxy_path",
|
"cd $proxy_path",
|
||||||
"echo 'Creating Docker Compose file...'",
|
"echo '####### Creating Docker Compose file...'",
|
||||||
"echo 'Pulling docker image...'",
|
"echo '####### Pulling docker image...'",
|
||||||
'docker compose pull -q',
|
'docker compose pull',
|
||||||
"echo 'Stopping existing proxy...'",
|
"echo '####### Stopping existing coolify-proxy...'",
|
||||||
'docker compose down -v --remove-orphans',
|
'docker compose down -v --remove-orphans',
|
||||||
"lsof -nt -i:80 | xargs -r kill -9",
|
"lsof -nt -i:80 | xargs -r kill -9",
|
||||||
"lsof -nt -i:443 | xargs -r kill -9",
|
"lsof -nt -i:443 | xargs -r kill -9",
|
||||||
"echo 'Starting proxy...'",
|
"systemctl disable nginx > /dev/null 2>&1 || true",
|
||||||
|
"systemctl disable apache2 > /dev/null 2>&1 || true",
|
||||||
|
"systemctl disable apache > /dev/null 2>&1 || true",
|
||||||
|
"echo '####### Starting coolify-proxy...'",
|
||||||
'docker compose up -d --remove-orphans',
|
'docker compose up -d --remove-orphans',
|
||||||
"echo 'Proxy installed successfully...'"
|
"echo '####### Proxy installed successfully...'"
|
||||||
], $server);
|
], $server);
|
||||||
|
|
||||||
return $activity;
|
return $activity;
|
||||||
|
|||||||
@@ -18,31 +18,6 @@ class InstallDocker
|
|||||||
"max-file": "3"
|
"max-file": "3"
|
||||||
}
|
}
|
||||||
}');
|
}');
|
||||||
if (isDev()) {
|
|
||||||
$activity = remote_process([
|
|
||||||
"echo ####### Installing Prerequisites...",
|
|
||||||
"echo ####### Installing/updating Docker Engine...",
|
|
||||||
"echo ####### Configuring Docker Engine (merging existing configuration with the required)...",
|
|
||||||
"echo ####### Restarting Docker Engine...",
|
|
||||||
], $server);
|
|
||||||
} else {
|
|
||||||
$activity = remote_process([
|
|
||||||
"echo ####### Installing Prerequisites...",
|
|
||||||
"command -v jq >/dev/null || apt-get update",
|
|
||||||
"command -v jq >/dev/null || apt install -y jq",
|
|
||||||
"echo ####### Installing/updating Docker Engine...",
|
|
||||||
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh",
|
|
||||||
"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\"`\" || echo '{$config}' | base64 -d > /etc/docker/daemon.json",
|
|
||||||
"echo '{$config}' | base64 -d > /etc/docker/daemon.json.coolify",
|
|
||||||
"cat <<< $(jq . /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json.coolify",
|
|
||||||
"cat <<< $(jq -s '.[0] * .[1]' /etc/docker/daemon.json /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json",
|
|
||||||
"echo ####### Restarting Docker Engine...",
|
|
||||||
"systemctl restart docker",
|
|
||||||
"echo ####### Creating default network...",
|
|
||||||
"docker network create --attachable coolify >/dev/null 2>&1 || true",
|
|
||||||
"echo ####### Done!"
|
|
||||||
], $server);
|
|
||||||
$found = StandaloneDocker::where('server_id', $server->id);
|
$found = StandaloneDocker::where('server_id', $server->id);
|
||||||
if ($found->count() == 0) {
|
if ($found->count() == 0) {
|
||||||
StandaloneDocker::create([
|
StandaloneDocker::create([
|
||||||
@@ -51,9 +26,34 @@ class InstallDocker
|
|||||||
'server_id' => $server->id,
|
'server_id' => $server->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
if (isDev()) {
|
||||||
|
return remote_process([
|
||||||
|
"echo '####### Installing Prerequisites...'",
|
||||||
return $activity;
|
"sleep 1",
|
||||||
|
"echo '####### Installing/updating Docker Engine...'",
|
||||||
|
"echo '####### Configuring Docker Engine (merging existing configuration with the required)...'",
|
||||||
|
"sleep 4",
|
||||||
|
"echo '####### Restarting Docker Engine...'",
|
||||||
|
"ls -l /tmp"
|
||||||
|
], $server);
|
||||||
|
} else {
|
||||||
|
return remote_process([
|
||||||
|
"echo '####### Installing Prerequisites...'",
|
||||||
|
"command -v jq >/dev/null || apt-get update",
|
||||||
|
"command -v jq >/dev/null || apt install -y jq",
|
||||||
|
"echo '####### Installing/updating Docker Engine...'",
|
||||||
|
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh",
|
||||||
|
"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\"`\" || echo '{$config}' | base64 -d > /etc/docker/daemon.json",
|
||||||
|
"echo '{$config}' | base64 -d > /etc/docker/daemon.json.coolify",
|
||||||
|
"cat <<< $(jq . /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json.coolify",
|
||||||
|
"cat <<< $(jq -s '.[0] * .[1]' /etc/docker/daemon.json /etc/docker/daemon.json.coolify) > /etc/docker/daemon.json",
|
||||||
|
"echo '####### Restarting Docker Engine...'",
|
||||||
|
"systemctl restart docker",
|
||||||
|
"echo '####### Creating default Docker network (coolify)...'",
|
||||||
|
"docker network create --attachable coolify >/dev/null 2>&1 || true",
|
||||||
|
"echo '####### Done!'"
|
||||||
|
], $server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,11 @@ class UpdateCoolify
|
|||||||
$this->update();
|
$this->update();
|
||||||
}
|
}
|
||||||
send_internal_notification('InstanceAutoUpdateJob done to version: ' . $this->latestVersion . ' from version: ' . $this->currentVersion);
|
send_internal_notification('InstanceAutoUpdateJob done to version: ' . $this->latestVersion . ' from version: ' . $this->currentVersion);
|
||||||
} catch (\Exception $th) {
|
} catch (\Throwable $e) {
|
||||||
ray('InstanceAutoUpdateJob failed');
|
ray('InstanceAutoUpdateJob failed');
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
send_internal_notification('InstanceAutoUpdateJob failed: ' . $th->getMessage());
|
send_internal_notification('InstanceAutoUpdateJob failed: ' . $e->getMessage());
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
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\Server;
|
||||||
use App\Models\StandalonePostgresql;
|
use App\Models\StandalonePostgresql;
|
||||||
|
use App\Models\Team;
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\TeamInvitation;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Waitlist;
|
||||||
use App\Notifications\Application\DeploymentFailed;
|
use App\Notifications\Application\DeploymentFailed;
|
||||||
use App\Notifications\Application\DeploymentSuccess;
|
use App\Notifications\Application\DeploymentSuccess;
|
||||||
use App\Notifications\Application\StatusChanged;
|
use App\Notifications\Application\StatusChanged;
|
||||||
@@ -22,30 +26,31 @@ use Illuminate\Notifications\Messages\MailMessage;
|
|||||||
use Mail;
|
use Mail;
|
||||||
use Str;
|
use Str;
|
||||||
|
|
||||||
|
use function Laravel\Prompts\confirm;
|
||||||
use function Laravel\Prompts\select;
|
use function Laravel\Prompts\select;
|
||||||
use function Laravel\Prompts\text;
|
use function Laravel\Prompts\text;
|
||||||
|
|
||||||
class TestEmail extends Command
|
class Emails extends Command
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'email:test';
|
protected $signature = 'emails';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Send a test email to the admin';
|
protected $description = 'Send out test / prod emails';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*/
|
*/
|
||||||
private ?MailMessage $mail = null;
|
private ?MailMessage $mail = null;
|
||||||
private string $email = 'andras.bacsai@protonmail.com';
|
private ?string $email = null;
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$type = select(
|
$type = select(
|
||||||
@@ -60,9 +65,14 @@ class TestEmail extends Command
|
|||||||
'invitation-link' => 'Invitation Link',
|
'invitation-link' => 'Invitation Link',
|
||||||
'waitlist-invitation-link' => 'Waitlist Invitation Link',
|
'waitlist-invitation-link' => 'Waitlist Invitation Link',
|
||||||
'waitlist-confirmation' => 'Waitlist Confirmation',
|
'waitlist-confirmation' => 'Waitlist Confirmation',
|
||||||
|
'realusers-before-trial' => 'REAL - Registered Users Before Trial without Subscription',
|
||||||
|
'realusers-server-lost-connection' => 'REAL - Server Lost Connection',
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
$emailsGathered = ['realusers-before-trial','realusers-server-lost-connection'];
|
||||||
|
if (!in_array($type, $emailsGathered)) {
|
||||||
$this->email = text('Email Address to send to');
|
$this->email = text('Email Address to send to');
|
||||||
|
}
|
||||||
set_transanctional_email_settings();
|
set_transanctional_email_settings();
|
||||||
|
|
||||||
$this->mail = new MailMessage();
|
$this->mail = new MailMessage();
|
||||||
@@ -148,28 +158,82 @@ class TestEmail extends Command
|
|||||||
case 'waitlist-invitation-link':
|
case 'waitlist-invitation-link':
|
||||||
$this->mail = new MailMessage();
|
$this->mail = new MailMessage();
|
||||||
$this->mail->view('emails.waitlist-invitation', [
|
$this->mail->view('emails.waitlist-invitation', [
|
||||||
'email' => 'test2@example.com',
|
'loginLink' => 'https://coolify.io',
|
||||||
'password' => "supersecretpassword",
|
|
||||||
]);
|
]);
|
||||||
$this->mail->subject('Congratulations! You are invited to join Coolify Cloud.');
|
$this->mail->subject('Congratulations! You are invited to join Coolify Cloud.');
|
||||||
$this->sendEmail();
|
$this->sendEmail();
|
||||||
break;
|
break;
|
||||||
case 'waitlist-confirmation':
|
case 'waitlist-confirmation':
|
||||||
|
$found = Waitlist::where('email', $this->email)->first();
|
||||||
|
if ($found) {
|
||||||
|
SendConfirmationForWaitlistJob::dispatch($this->email, $found->uuid);
|
||||||
|
} else {
|
||||||
|
throw new Exception('Waitlist not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'realusers-before-trial':
|
||||||
$this->mail = new MailMessage();
|
$this->mail = new MailMessage();
|
||||||
$this->mail->view(
|
$this->mail->view('emails.before-trial-conversion');
|
||||||
'emails.waitlist-confirmation',
|
$this->mail->subject('Trial period has been added for all subscription plans.');
|
||||||
[
|
$teams = Team::doesntHave('subscription')->where('id', '!=', 0)->get();
|
||||||
'confirmation_url' => 'http://example.com',
|
if (!$teams || $teams->isEmpty()) {
|
||||||
'cancel_url' => 'http://example.com',
|
echo 'No teams found.' . PHP_EOL;
|
||||||
]
|
return;
|
||||||
);
|
}
|
||||||
$this->mail->subject('You are on the waitlist!');
|
$emails = [];
|
||||||
$this->sendEmail();
|
foreach ($teams as $team) {
|
||||||
|
foreach ($team->members as $member) {
|
||||||
|
if ($member->email) {
|
||||||
|
$emails[] = $member->email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$emails = array_unique($emails);
|
||||||
|
$this->info("Sending to " . count($emails) . " emails.");
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
$this->info($email);
|
||||||
|
}
|
||||||
|
$confirmed = confirm('Are you sure?');
|
||||||
|
if ($confirmed) {
|
||||||
|
foreach ($emails as $email) {
|
||||||
|
$this->sendEmail($email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'realusers-server-lost-connection':
|
||||||
|
$serverId = text('Server Id');
|
||||||
|
$server = Server::find($serverId);
|
||||||
|
if (!$server) {
|
||||||
|
throw new Exception('Server not found');
|
||||||
|
}
|
||||||
|
$admins = [];
|
||||||
|
$members = $server->team->members;
|
||||||
|
foreach ($members as $member) {
|
||||||
|
if ($member->isAdmin()) {
|
||||||
|
$admins[] = $member->email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->info('Sending to ' . count($admins) . ' admins.');
|
||||||
|
foreach ($admins as $admin) {
|
||||||
|
$this->info($admin);
|
||||||
|
}
|
||||||
|
$this->mail = new MailMessage();
|
||||||
|
$this->mail->view('emails.server-lost-connection', [
|
||||||
|
'name' => $server->name,
|
||||||
|
]);
|
||||||
|
$this->mail->subject('Action required: Server ' . $server->name . ' lost connection.');
|
||||||
|
foreach ($admins as $email) {
|
||||||
|
$this->sendEmail($email);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private function sendEmail()
|
private function sendEmail(string $email = null)
|
||||||
{
|
{
|
||||||
|
if ($email) {
|
||||||
|
$this->email = $email;
|
||||||
|
}
|
||||||
Mail::send(
|
Mail::send(
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
@@ -178,5 +242,6 @@ class TestEmail extends Command
|
|||||||
->subject($this->mail->subject)
|
->subject($this->mail->subject)
|
||||||
->html((string)$this->mail->render())
|
->html((string)$this->mail->render())
|
||||||
);
|
);
|
||||||
|
$this->info("Email sent to $this->email successfully. 📧");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ class Init extends Command
|
|||||||
$deployment->status = ApplicationDeploymentStatus::FAILED->value;
|
$deployment->status = ApplicationDeploymentStatus::FAILED->value;
|
||||||
$deployment->save();
|
$deployment->save();
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
echo "Error: {$e->getMessage()}\n";
|
echo "Error: {$e->getMessage()}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class SyncBunny extends Command
|
|||||||
$pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"),
|
$pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"),
|
||||||
]);
|
]);
|
||||||
echo "All files uploaded & purged...\n";
|
echo "All files uploaded & purged...\n";
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
echo $e->getMessage();
|
echo $e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class WaitlistInvite extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'waitlist:invite {email?} {--only-email}';
|
protected $signature = 'waitlist:invite {--people=1} {--only-email} {email?}';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
@@ -33,6 +33,12 @@ class WaitlistInvite extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
$people = $this->option('people');
|
||||||
|
for ($i = 0; $i < $people; $i++) {
|
||||||
|
$this->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();
|
||||||
@@ -86,13 +92,10 @@ class WaitlistInvite extends Command
|
|||||||
}
|
}
|
||||||
private function send_email()
|
private function send_email()
|
||||||
{
|
{
|
||||||
ray($this->next_patient->email, $this->password);
|
|
||||||
$token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password");
|
$token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password");
|
||||||
$loginLink = route('auth.link', ['token' => $token]);
|
$loginLink = route('auth.link', ['token' => $token]);
|
||||||
$mail = new MailMessage();
|
$mail = new MailMessage();
|
||||||
$mail->view('emails.waitlist-invitation', [
|
$mail->view('emails.waitlist-invitation', [
|
||||||
'email' => $this->next_patient->email,
|
|
||||||
'password' => $this->password,
|
|
||||||
'loginLink' => $loginLink,
|
'loginLink' => $loginLink,
|
||||||
]);
|
]);
|
||||||
$mail->subject('Congratulations! You are invited to join Coolify Cloud.');
|
$mail->subject('Congratulations! You are invited to join Coolify Cloud.');
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
|
use App\Enums\ProxyTypes;
|
||||||
use App\Jobs\ApplicationContainerStatusJob;
|
use App\Jobs\ApplicationContainerStatusJob;
|
||||||
use App\Jobs\CheckResaleLicenseJob;
|
use App\Jobs\CheckResaleLicenseJob;
|
||||||
use App\Jobs\CleanupInstanceStuffsJob;
|
use App\Jobs\CleanupInstanceStuffsJob;
|
||||||
@@ -9,11 +10,12 @@ use App\Jobs\DatabaseBackupJob;
|
|||||||
use App\Jobs\DatabaseContainerStatusJob;
|
use App\Jobs\DatabaseContainerStatusJob;
|
||||||
use App\Jobs\DockerCleanupJob;
|
use App\Jobs\DockerCleanupJob;
|
||||||
use App\Jobs\InstanceAutoUpdateJob;
|
use App\Jobs\InstanceAutoUpdateJob;
|
||||||
use App\Jobs\ProxyCheckJob;
|
use App\Jobs\ProxyContainerStatusJob;
|
||||||
use App\Jobs\ResourceStatusJob;
|
use App\Jobs\ServerDetailsCheckJob;
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
use App\Models\ScheduledDatabaseBackup;
|
use App\Models\ScheduledDatabaseBackup;
|
||||||
|
use App\Models\Server;
|
||||||
use App\Models\StandalonePostgresql;
|
use App\Models\StandalonePostgresql;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
@@ -23,23 +25,32 @@ class Kernel extends ConsoleKernel
|
|||||||
protected function schedule(Schedule $schedule): void
|
protected function schedule(Schedule $schedule): void
|
||||||
{
|
{
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
$schedule->command('horizon:snapshot')->everyMinute();
|
$schedule->job(new ServerDetailsCheckJob(Server::find(0)))->everyTenMinutes()->onOneServer();
|
||||||
// $schedule->job(new ResourceStatusJob)->everyMinute();
|
// $schedule->command('horizon:snapshot')->everyMinute();
|
||||||
$schedule->job(new ProxyCheckJob)->everyFiveMinutes();
|
// $schedule->job(new CleanupInstanceStuffsJob)->everyMinute();
|
||||||
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute();
|
|
||||||
// $schedule->job(new CheckResaleLicenseJob)->hourly();
|
// $schedule->job(new CheckResaleLicenseJob)->hourly();
|
||||||
$schedule->job(new DockerCleanupJob)->everyOddHour();
|
// $schedule->job(new DockerCleanupJob)->everyOddHour();
|
||||||
|
// $this->instance_auto_update($schedule);
|
||||||
|
// $this->check_scheduled_backups($schedule);
|
||||||
|
// $this->check_resources($schedule);
|
||||||
|
// $this->check_proxies($schedule);
|
||||||
} else {
|
} else {
|
||||||
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
||||||
$schedule->job(new CleanupInstanceStuffsJob)->everyTenMinutes()->onOneServer();
|
$schedule->job(new CleanupInstanceStuffsJob)->everyTenMinutes()->onOneServer();
|
||||||
// $schedule->job(new ResourceStatusJob)->everyMinute()->onOneServer();
|
|
||||||
$schedule->job(new CheckResaleLicenseJob)->hourly()->onOneServer();
|
$schedule->job(new CheckResaleLicenseJob)->hourly()->onOneServer();
|
||||||
$schedule->job(new ProxyCheckJob)->everyFiveMinutes()->onOneServer();
|
|
||||||
$schedule->job(new DockerCleanupJob)->everyTenMinutes()->onOneServer();
|
$schedule->job(new DockerCleanupJob)->everyTenMinutes()->onOneServer();
|
||||||
}
|
|
||||||
$this->instance_auto_update($schedule);
|
$this->instance_auto_update($schedule);
|
||||||
$this->check_scheduled_backups($schedule);
|
$this->check_scheduled_backups($schedule);
|
||||||
$this->check_resources($schedule);
|
$this->check_resources($schedule);
|
||||||
|
$this->check_proxies($schedule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private function check_proxies($schedule)
|
||||||
|
{
|
||||||
|
$servers = Server::all()->where('settings.is_usable', true)->where('settings.is_reachable', true)->whereNotNull('proxy.type')->where('proxy.type', '!=', ProxyTypes::NONE->value);
|
||||||
|
foreach ($servers as $server) {
|
||||||
|
$schedule->job(new ProxyContainerStatusJob($server))->everyMinute()->onOneServer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private function check_resources($schedule)
|
private function check_resources($schedule)
|
||||||
{
|
{
|
||||||
@@ -53,7 +64,8 @@ class Kernel extends ConsoleKernel
|
|||||||
$schedule->job(new DatabaseContainerStatusJob($postgresql))->everyMinute()->onOneServer();
|
$schedule->job(new DatabaseContainerStatusJob($postgresql))->everyMinute()->onOneServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private function instance_auto_update($schedule){
|
private function instance_auto_update($schedule)
|
||||||
|
{
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -74,6 +86,11 @@ class Kernel extends ConsoleKernel
|
|||||||
if (!$scheduled_backup->enabled) {
|
if (!$scheduled_backup->enabled) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (is_null(data_get($scheduled_backup, 'database'))) {
|
||||||
|
ray('database not found');
|
||||||
|
$scheduled_backup->delete();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset(VALID_CRON_STRINGS[$scheduled_backup->frequency])) {
|
if (isset(VALID_CRON_STRINGS[$scheduled_backup->frequency])) {
|
||||||
$scheduled_backup->frequency = VALID_CRON_STRINGS[$scheduled_backup->frequency];
|
$scheduled_backup->frequency = VALID_CRON_STRINGS[$scheduled_backup->frequency];
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Handler extends ExceptionHandler
|
|||||||
* @var array<int, class-string<\Throwable>>
|
* @var array<int, class-string<\Throwable>>
|
||||||
*/
|
*/
|
||||||
protected $dontReport = [
|
protected $dontReport = [
|
||||||
//
|
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.
|
||||||
@@ -51,7 +51,12 @@ class Handler extends ExceptionHandler
|
|||||||
}
|
}
|
||||||
app('sentry')->configureScope(
|
app('sentry')->configureScope(
|
||||||
function (Scope $scope) {
|
function (Scope $scope) {
|
||||||
$scope->setUser(['id'=> config('sentry.server_name')]);
|
$scope->setUser(
|
||||||
|
[
|
||||||
|
'id' => config('sentry.server_name'),
|
||||||
|
'email' => auth()->user()->email
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Integration::captureUnhandledException($e);
|
Integration::captureUnhandledException($e);
|
||||||
|
|||||||
10
app/Exceptions/ProcessException.php
Normal file
10
app/Exceptions/ProcessException.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class ProcessException extends Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -154,8 +154,8 @@ class Controller extends BaseController
|
|||||||
$invitation->delete();
|
$invitation->delete();
|
||||||
abort(401);
|
abort(401);
|
||||||
}
|
}
|
||||||
} catch (Throwable $th) {
|
} catch (Throwable $e) {
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,8 +172,8 @@ class Controller extends BaseController
|
|||||||
}
|
}
|
||||||
$invitation->delete();
|
$invitation->delete();
|
||||||
return redirect()->route('team.index');
|
return redirect()->route('team.index');
|
||||||
} catch (Throwable $th) {
|
} catch (Throwable $e) {
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
|||||||
{
|
{
|
||||||
$this->selectedExistingPrivateKey = null;
|
$this->selectedExistingPrivateKey = null;
|
||||||
$this->privateKeyType = $type;
|
$this->privateKeyType = $type;
|
||||||
if ($type === 'create' && !isDev()) {
|
if ($type === 'create') {
|
||||||
$this->createNewPrivateKey();
|
$this->createNewPrivateKey();
|
||||||
}
|
}
|
||||||
$this->currentState = 'create-private-key';
|
$this->currentState = 'create-private-key';
|
||||||
@@ -193,7 +193,7 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
|||||||
}
|
}
|
||||||
$this->getProxyType();
|
$this->getProxyType();
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
|
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ class CheckLicense extends Component
|
|||||||
try {
|
try {
|
||||||
resolve(CheckResaleLicense::class)();
|
resolve(CheckResaleLicense::class)();
|
||||||
$this->emit('reloadWindow');
|
$this->emit('reloadWindow');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
session()->flash('error', 'Something went wrong. Please contact support. <br>Error: ' . $th->getMessage());
|
session()->flash('error', 'Something went wrong. Please contact support. <br>Error: ' . $e->getMessage());
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
return redirect()->to('/settings/license');
|
return redirect()->to('/settings/license');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class Form extends Component
|
|||||||
}
|
}
|
||||||
$this->destination->delete();
|
$this->destination->delete();
|
||||||
return redirect()->route('dashboard');
|
return redirect()->route('dashboard');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e);
|
return general_error_handler(err: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class StandaloneDocker extends Component
|
|||||||
}
|
}
|
||||||
$this->createNetworkAndAttachToProxy();
|
$this->createNetworkAndAttachToProxy();
|
||||||
return redirect()->route('destination.show', $docker->uuid);
|
return redirect()->route('destination.show', $docker->uuid);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class ForcePasswordReset extends Component
|
|||||||
send_internal_notification('First login for ' . auth()->user()->email);
|
send_internal_notification('First login for ' . auth()->user()->email);
|
||||||
}
|
}
|
||||||
return redirect()->route('dashboard');
|
return redirect()->route('dashboard');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Help extends Component
|
|||||||
try {
|
try {
|
||||||
$this->rateLimit(1, 60);
|
$this->rateLimit(1, 60);
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$subscriptionType = auth()->user()?->subscription?->type() ?? 'unknown';
|
$subscriptionType = auth()->user()?->subscription?->type() ?? 'Free';
|
||||||
$debug = "Route: {$this->path}";
|
$debug = "Route: {$this->path}";
|
||||||
$mail = new MailMessage();
|
$mail = new MailMessage();
|
||||||
$mail->view(
|
$mail->view(
|
||||||
@@ -41,9 +41,9 @@ class Help extends Component
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
$mail->subject("[HELP - {$subscriptionType}]: {$this->subject}");
|
$mail->subject("[HELP - {$subscriptionType}]: {$this->subject}");
|
||||||
send_user_an_email($mail, 'hi@coollabs.io');
|
send_user_an_email($mail, 'hi@coollabs.io', auth()->user()?->email);
|
||||||
$this->emit('success', 'Your message has been sent successfully. We will get in touch with you as soon as possible.');
|
$this->emit('success', 'Your message has been sent successfully. We will get in touch with you as soon as possible.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class DiscordSettings extends Component
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->submit();
|
$this->submit();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
ray($e->getMessage());
|
ray($e->getMessage());
|
||||||
$this->team->discord_enabled = false;
|
$this->team->discord_enabled = false;
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class EmailSettings extends Component
|
|||||||
]);
|
]);
|
||||||
$this->team->save();
|
$this->team->save();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ class EmailSettings extends Component
|
|||||||
$this->team->resend_enabled = false;
|
$this->team->resend_enabled = false;
|
||||||
$this->team->save();
|
$this->team->save();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ class EmailSettings extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team->smtp_enabled = false;
|
$this->team->smtp_enabled = false;
|
||||||
$this->submitResend();
|
$this->submitResend();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->team->smtp_enabled = false;
|
$this->team->smtp_enabled = false;
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ class EmailSettings extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team->resend_enabled = false;
|
$this->team->resend_enabled = false;
|
||||||
$this->submit();
|
$this->submit();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->team->smtp_enabled = false;
|
$this->team->smtp_enabled = false;
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
@@ -131,7 +131,7 @@ class EmailSettings extends Component
|
|||||||
]);
|
]);
|
||||||
$this->team->save();
|
$this->team->save();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->team->smtp_enabled = false;
|
$this->team->smtp_enabled = false;
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ class EmailSettings extends Component
|
|||||||
$this->team->save();
|
$this->team->save();
|
||||||
refreshSession();
|
refreshSession();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->team->resend_enabled = false;
|
$this->team->resend_enabled = false;
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class TelegramSettings extends Component
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->submit();
|
$this->submit();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
ray($e->getMessage());
|
ray($e->getMessage());
|
||||||
$this->team->telegram_enabled = false;
|
$this->team->telegram_enabled = false;
|
||||||
$this->validate();
|
$this->validate();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use Livewire\Component;
|
|||||||
class Change extends Component
|
class Change extends Component
|
||||||
{
|
{
|
||||||
public PrivateKey $private_key;
|
public PrivateKey $private_key;
|
||||||
|
public $public_key;
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'private_key.name' => 'required|string',
|
'private_key.name' => 'required|string',
|
||||||
'private_key.description' => 'nullable|string',
|
'private_key.description' => 'nullable|string',
|
||||||
@@ -21,6 +21,14 @@ class Change extends Component
|
|||||||
'private_key.private_key' => 'private key'
|
'private_key.private_key' => 'private key'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->public_key = $this->private_key->publicKey();
|
||||||
|
}catch(\Exception $e) {
|
||||||
|
return general_error_handler(err: $e, that: $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
public function delete()
|
public function delete()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -30,7 +38,7 @@ class Change extends Component
|
|||||||
return redirect()->route('security.private-key.index');
|
return redirect()->route('security.private-key.index');
|
||||||
}
|
}
|
||||||
$this->emit('error', 'This private key is in use and cannot be deleted. Please delete all servers, applications, and GitHub/GitLab apps that use this private key before deleting it.');
|
$this->emit('error', 'This private key is in use and cannot be deleted. Please delete all servers, applications, and GitHub/GitLab apps that use this private key before deleting it.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +49,7 @@ class Change extends Component
|
|||||||
$this->private_key->private_key = formatPrivateKey($this->private_key->private_key);
|
$this->private_key->private_key = formatPrivateKey($this->private_key->private_key);
|
||||||
$this->private_key->save();
|
$this->private_key->save();
|
||||||
refresh_server_connection($this->private_key);
|
refresh_server_connection($this->private_key);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ class Create extends Component
|
|||||||
if ($this->from === 'server') {
|
if ($this->from === 'server') {
|
||||||
return redirect()->route('server.create');
|
return redirect()->route('server.create');
|
||||||
}
|
}
|
||||||
return redirect()->route('private-key.show', ['private_key_uuid' => $private_key->uuid]);
|
return redirect()->route('security.private-key.show', ['private_key_uuid' => $private_key->uuid]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class AddEmpty extends Component
|
|||||||
'team_id' => currentTeam()->id,
|
'team_id' => currentTeam()->id,
|
||||||
]);
|
]);
|
||||||
return redirect()->route('project.show', $project->uuid);
|
return redirect()->route('project.show', $project->uuid);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
general_error_handler($e, $this);
|
general_error_handler($e, $this);
|
||||||
} finally {
|
} finally {
|
||||||
$this->name = '';
|
$this->name = '';
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class AddEnvironment extends Component
|
|||||||
'project_uuid' => $this->project->uuid,
|
'project_uuid' => $this->project->uuid,
|
||||||
'environment_name' => $environment->name,
|
'environment_name' => $environment->name,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
general_error_handler($e, $this);
|
general_error_handler($e, $this);
|
||||||
} finally {
|
} finally {
|
||||||
$this->name = '';
|
$this->name = '';
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class General extends Component
|
|||||||
}
|
}
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
$this->emit('success', 'Application settings updated!');
|
$this->emit('success', 'Application settings updated!');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class BackupEdit extends Component
|
|||||||
$this->backup->save();
|
$this->backup->save();
|
||||||
$this->backup->refresh();
|
$this->backup->refresh();
|
||||||
$this->emit('success', 'Backup updated successfully');
|
$this->emit('success', 'Backup updated successfully');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->emit('error', $e->getMessage());
|
$this->emit('error', $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ class BackupEdit extends Component
|
|||||||
$this->backup->save();
|
$this->backup->save();
|
||||||
$this->backup->refresh();
|
$this->backup->refresh();
|
||||||
$this->emit('success', 'Backup updated successfully');
|
$this->emit('success', 'Backup updated successfully');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->emit('error', $e->getMessage());
|
$this->emit('error', $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class CreateScheduledBackup extends Component
|
|||||||
'team_id' => currentTeam()->id,
|
'team_id' => currentTeam()->id,
|
||||||
]);
|
]);
|
||||||
$this->emit('refreshScheduledBackups');
|
$this->emit('refreshScheduledBackups');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
general_error_handler($e, $this);
|
general_error_handler($e, $this);
|
||||||
} finally {
|
} finally {
|
||||||
$this->frequency = '';
|
$this->frequency = '';
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class Edit extends Component
|
|||||||
try {
|
try {
|
||||||
$this->project->save();
|
$this->project->save();
|
||||||
$this->emit('saved');
|
$this->emit('saved');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ class GithubPrivateRepository extends Component
|
|||||||
'environment_name' => $environment->name,
|
'environment_name' => $environment->name,
|
||||||
'project_uuid' => $project->uuid,
|
'project_uuid' => $project->uuid,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class GithubPrivateRepositoryDeployKey extends Component
|
|||||||
'environment_name' => $environment->name,
|
'environment_name' => $environment->name,
|
||||||
'application_uuid' => $application->uuid,
|
'application_uuid' => $application->uuid,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,14 +75,14 @@ class PublicGitRepository extends Component
|
|||||||
$this->get_git_source();
|
$this->get_git_source();
|
||||||
$this->get_branch();
|
$this->get_branch();
|
||||||
$this->selected_branch = $this->git_branch;
|
$this->selected_branch = $this->git_branch;
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
if (!$this->branch_found && $this->git_branch == 'main') {
|
if (!$this->branch_found && $this->git_branch == 'main') {
|
||||||
try {
|
try {
|
||||||
$this->git_branch = 'master';
|
$this->git_branch = 'master';
|
||||||
$this->get_branch();
|
$this->get_branch();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ class PublicGitRepository extends Component
|
|||||||
'environment_name' => $environment->name,
|
'environment_name' => $environment->name,
|
||||||
'application_uuid' => $application->uuid,
|
'application_uuid' => $application->uuid,
|
||||||
]);
|
]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class Select extends Component
|
|||||||
// try {
|
// try {
|
||||||
// instantCommand("psql {$this->existingPostgresqlUrl} -c 'SELECT 1'");
|
// instantCommand("psql {$this->existingPostgresqlUrl} -c 'SELECT 1'");
|
||||||
// $this->emit('success', 'Successfully connected to the database.');
|
// $this->emit('success', 'Successfully connected to the database.');
|
||||||
// } catch (\Exception $e) {
|
// } catch (\Throwable $e) {
|
||||||
// return general_error_handler($e, $this);
|
// return general_error_handler($e, $this);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ class All extends Component
|
|||||||
$environment->save();
|
$environment->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($isPreview) {
|
||||||
|
$this->emit('success', 'Preview environment variables updated successfully.');
|
||||||
|
} else {
|
||||||
|
$this->emit('success', 'Environment variables updated successfully.');
|
||||||
|
}
|
||||||
$this->refreshEnvs();
|
$this->refreshEnvs();
|
||||||
}
|
}
|
||||||
public function refreshEnvs()
|
public function refreshEnvs()
|
||||||
@@ -108,7 +113,7 @@ class All extends Component
|
|||||||
$environment->save();
|
$environment->save();
|
||||||
$this->refreshEnvs();
|
$this->refreshEnvs();
|
||||||
$this->emit('success', 'Environment variable added successfully.');
|
$this->emit('success', 'Environment variable added successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class ResourceLimits extends Component
|
|||||||
$this->validate();
|
$this->validate();
|
||||||
$this->resource->save();
|
$this->resource->save();
|
||||||
$this->emit('success', 'Resource limits updated successfully.');
|
$this->emit('success', 'Resource limits updated successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class All extends Component
|
|||||||
$this->resource->refresh();
|
$this->resource->refresh();
|
||||||
$this->emit('success', 'Storage added successfully');
|
$this->emit('success', 'Storage added successfully');
|
||||||
$this->emit('clearAddStorage');
|
$this->emit('clearAddStorage');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class RunCommand extends Component
|
|||||||
try {
|
try {
|
||||||
$activity = remote_process([$this->command], Server::where('uuid', $this->server)->first(), ignore_errors: true);
|
$activity = remote_process([$this->command], Server::where('uuid', $this->server)->first(), ignore_errors: true);
|
||||||
$this->emit('newMonitorActivity', $activity->id);
|
$this->emit('newMonitorActivity', $activity->id);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e);
|
return general_error_handler(err: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,13 +54,20 @@ class Form extends Component
|
|||||||
['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server);
|
['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server);
|
||||||
if ($uptime) {
|
if ($uptime) {
|
||||||
$this->uptime = $uptime;
|
$this->uptime = $uptime;
|
||||||
|
$this->emit('success', 'Server is reachable!');
|
||||||
|
} else {
|
||||||
|
$this->emit('error', 'Server is not rachable');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if ($dockerVersion) {
|
if ($dockerVersion) {
|
||||||
$this->dockerVersion = $dockerVersion;
|
$this->dockerVersion = $dockerVersion;
|
||||||
$this->emit('proxyStatusUpdated');
|
$this->emit('proxyStatusUpdated');
|
||||||
|
$this->emit('success', 'Docker Engine 23+ is installed!');
|
||||||
|
} else {
|
||||||
|
$this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.');
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
|
return general_error_handler($e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +81,9 @@ class Form extends Component
|
|||||||
}
|
}
|
||||||
$this->server->delete();
|
$this->server->delete();
|
||||||
return redirect()->route('server.all');
|
return redirect()->route('server.all');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public function submit()
|
public function submit()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class ByIp extends Component
|
|||||||
{
|
{
|
||||||
$this->validate();
|
$this->validate();
|
||||||
try {
|
try {
|
||||||
if (!$this->private_key_id) {
|
if (is_null($this->private_key_id)) {
|
||||||
return $this->emit('error', 'You must select a private key');
|
return $this->emit('error', 'You must select a private key');
|
||||||
}
|
}
|
||||||
$server = Server::create([
|
$server = Server::create([
|
||||||
@@ -78,7 +78,7 @@ class ByIp extends Component
|
|||||||
$server->settings->is_part_of_swarm = $this->is_part_of_swarm;
|
$server->settings->is_part_of_swarm = $this->is_part_of_swarm;
|
||||||
$server->settings->save();
|
$server->settings->save();
|
||||||
return redirect()->route('server.show', $server->uuid);
|
return redirect()->route('server.show', $server->uuid);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e);
|
return general_error_handler(err: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ class Proxy extends Component
|
|||||||
|
|
||||||
public ?string $selectedProxy = null;
|
public ?string $selectedProxy = null;
|
||||||
public $proxy_settings = null;
|
public $proxy_settings = null;
|
||||||
public string|null $redirect_url = null;
|
public ?string $redirect_url = null;
|
||||||
|
|
||||||
protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit'];
|
protected $listeners = ['proxyStatusUpdated', 'saveConfiguration' => 'submit'];
|
||||||
|
|
||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->selectedProxy = $this->server->proxy->type;
|
$this->selectedProxy = data_get($this->server, 'proxy.type');
|
||||||
$this->redirect_url = $this->server->proxy->redirect_url;
|
$this->redirect_url = data_get($this->server, 'proxy.redirect_url');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function proxyStatusUpdated()
|
public function proxyStatusUpdated()
|
||||||
@@ -55,7 +55,7 @@ class Proxy extends Component
|
|||||||
|
|
||||||
setup_default_redirect_404(redirect_url: $this->server->proxy->redirect_url, server: $this->server);
|
setup_default_redirect_404(redirect_url: $this->server->proxy->redirect_url, server: $this->server);
|
||||||
$this->emit('success', 'Proxy configuration saved.');
|
$this->emit('success', 'Proxy configuration saved.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e);
|
return general_error_handler(err: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,16 +64,17 @@ class Proxy extends Component
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server, true);
|
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server, true);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e);
|
return general_error_handler(err: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function load_proxy_configuration()
|
public function loadProxyConfiguration()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
ray('loadProxyConfiguration');
|
||||||
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server);
|
$this->proxy_settings = resolve(CheckConfigurationSync::class)($this->server);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e);
|
return general_error_handler(err: $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,20 @@ class Deploy extends Component
|
|||||||
{
|
{
|
||||||
public Server $server;
|
public Server $server;
|
||||||
public $proxy_settings = null;
|
public $proxy_settings = null;
|
||||||
|
protected $listeners = ['proxyStatusUpdated'];
|
||||||
|
|
||||||
public function start_proxy()
|
public function proxyStatusUpdated() {
|
||||||
|
$this->server->refresh();
|
||||||
|
}
|
||||||
|
public function startProxy()
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
$this->server->proxy->last_applied_settings &&
|
$this->server->proxy->last_applied_settings &&
|
||||||
$this->server->proxy->last_saved_settings !== $this->server->proxy->last_applied_settings
|
$this->server->proxy->last_saved_settings !== $this->server->proxy->last_applied_settings
|
||||||
) {
|
) {
|
||||||
$this->emit('saveConfiguration', $this->server);
|
resolve(SaveConfigurationSync::class)($this->server, $this->proxy_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
$activity = resolve(StartProxy::class)($this->server);
|
$activity = resolve(StartProxy::class)($this->server);
|
||||||
$this->emit('newMonitorActivity', $activity->id);
|
$this->emit('newMonitorActivity', $activity->id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Server\Proxy;
|
namespace App\Http\Livewire\Server\Proxy;
|
||||||
|
|
||||||
use App\Jobs\ProxyContainerStatusJob;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
@@ -10,14 +9,27 @@ class Status extends Component
|
|||||||
{
|
{
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
|
||||||
public function get_status()
|
protected $listeners = ['proxyStatusUpdated'];
|
||||||
|
public function proxyStatusUpdated()
|
||||||
{
|
{
|
||||||
if (data_get($this->server,'settings.is_usable')) {
|
|
||||||
dispatch_sync(new ProxyContainerStatusJob(
|
|
||||||
server: $this->server
|
|
||||||
));
|
|
||||||
$this->server->refresh();
|
$this->server->refresh();
|
||||||
|
}
|
||||||
|
public function getProxyStatus()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($this->server->isFunctional()) {
|
||||||
|
$container = getContainerStatus(server: $this->server, container_id: 'coolify-proxy');
|
||||||
|
$this->server->proxy->status = $container;
|
||||||
|
$this->server->save();
|
||||||
$this->emit('proxyStatusUpdated');
|
$this->emit('proxyStatusUpdated');
|
||||||
}
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return general_error_handler(err: $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function getProxyStatusWithNoti()
|
||||||
|
{
|
||||||
|
$this->emit('success', 'Refreshed proxy status.');
|
||||||
|
$this->getProxyStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace App\Http\Livewire\Server;
|
|||||||
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Masmerise\Toaster\Toaster;
|
|
||||||
|
|
||||||
class ShowPrivateKey extends Component
|
class ShowPrivateKey extends Component
|
||||||
{
|
{
|
||||||
@@ -12,14 +11,24 @@ class ShowPrivateKey extends Component
|
|||||||
public $privateKeys;
|
public $privateKeys;
|
||||||
public $parameters;
|
public $parameters;
|
||||||
|
|
||||||
public function setPrivateKey($private_key_id)
|
public function setPrivateKey($newPrivateKeyId)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
$oldPrivateKeyId = $this->server->private_key_id;
|
||||||
$this->server->update([
|
$this->server->update([
|
||||||
'private_key_id' => $private_key_id
|
'private_key_id' => $newPrivateKeyId
|
||||||
]);
|
]);
|
||||||
refresh_server_connection($this->server->privateKey);
|
|
||||||
$this->server->refresh();
|
$this->server->refresh();
|
||||||
|
refresh_server_connection($this->server->privateKey);
|
||||||
$this->checkConnection();
|
$this->checkConnection();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
$this->server->update([
|
||||||
|
'private_key_id' => $oldPrivateKeyId
|
||||||
|
]);
|
||||||
|
$this->server->refresh();
|
||||||
|
refresh_server_connection($this->server->privateKey);
|
||||||
|
return general_error_handler($e, that: $this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkConnection()
|
public function checkConnection()
|
||||||
@@ -27,13 +36,18 @@ class ShowPrivateKey extends Component
|
|||||||
try {
|
try {
|
||||||
['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server);
|
['uptime' => $uptime, 'dockerVersion' => $dockerVersion] = validateServer($this->server);
|
||||||
if ($uptime) {
|
if ($uptime) {
|
||||||
Toaster::success('Server is reachable with this private key.');
|
$this->emit('success', 'Server is reachable with this private key.');
|
||||||
|
} else {
|
||||||
|
$this->emit('error', 'Server is not reachable with this private key.');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if ($dockerVersion) {
|
if ($dockerVersion) {
|
||||||
Toaster::success('Server is usable for Coolify.');
|
$this->emit('success', 'Server is usable for Coolify.');
|
||||||
|
} else {
|
||||||
|
$this->emit('error', 'Old (lower than 23) or no Docker version detected. Install Docker Engine on the General tab.');
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(customErrorMessage: "Server is not reachable. Reason: {$e->getMessage()}", that: $this);
|
throw new \Exception($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Settings;
|
namespace App\Http\Livewire\Settings;
|
||||||
|
|
||||||
use App\Jobs\ProxyStartJob;
|
use App\Jobs\ProxyContainerStatusJob;
|
||||||
use App\Models\InstanceSettings as ModelsInstanceSettings;
|
use App\Models\InstanceSettings as ModelsInstanceSettings;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
@@ -124,7 +124,7 @@ class Configuration extends Component
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
$this->save_configuration_to_disk($traefik_dynamic_conf, $file);
|
$this->save_configuration_to_disk($traefik_dynamic_conf, $file);
|
||||||
dispatch(new ProxyStartJob($this->server));
|
dispatch(new ProxyContainerStatusJob($this->server));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class Email extends Component
|
|||||||
]);
|
]);
|
||||||
$this->settings->save();
|
$this->settings->save();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ class Email extends Component
|
|||||||
]);
|
]);
|
||||||
$this->settings->save();
|
$this->settings->save();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$this->settings->resend_enabled = false;
|
$this->settings->resend_enabled = false;
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ class Email extends Component
|
|||||||
try {
|
try {
|
||||||
$this->settings->smtp_enabled = false;
|
$this->settings->smtp_enabled = false;
|
||||||
$this->submitResend();
|
$this->submitResend();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ class Email extends Component
|
|||||||
try {
|
try {
|
||||||
$this->settings->resend_enabled = false;
|
$this->settings->resend_enabled = false;
|
||||||
$this->submit();
|
$this->submit();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ class Email extends Component
|
|||||||
]);
|
]);
|
||||||
$this->settings->save();
|
$this->settings->save();
|
||||||
$this->emit('success', 'Settings saved successfully.');
|
$this->emit('success', 'Settings saved successfully.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class Change extends Component
|
|||||||
try {
|
try {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
$this->github_app->save();
|
$this->github_app->save();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ class Change extends Component
|
|||||||
try {
|
try {
|
||||||
$this->github_app->delete();
|
$this->github_app->delete();
|
||||||
redirect()->route('source.all');
|
redirect()->route('source.all');
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class Create extends Component
|
|||||||
session(['from' => session('from') + ['source_id' => $github_app->id]]);
|
session(['from' => session('from') + ['source_id' => $github_app->id]]);
|
||||||
}
|
}
|
||||||
redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
|
redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class Actions extends Component
|
|||||||
$this->emit('success', 'Subscription cancelled successfully. Reloading in 5s.');
|
$this->emit('success', 'Subscription cancelled successfully. Reloading in 5s.');
|
||||||
$this->emit('reloadWindow', 5000);
|
$this->emit('reloadWindow', 5000);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ class Actions extends Component
|
|||||||
$this->emit('success', 'Subscription resumed successfully. Reloading in 5s.');
|
$this->emit('success', 'Subscription resumed successfully. Reloading in 5s.');
|
||||||
$this->emit('reloadWindow', 5000);
|
$this->emit('reloadWindow', 5000);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($e, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,13 @@ use Stripe\Checkout\Session;
|
|||||||
|
|
||||||
class PricingPlans extends Component
|
class PricingPlans extends Component
|
||||||
{
|
{
|
||||||
|
public bool $isTrial = false;
|
||||||
|
public function mount() {
|
||||||
|
$this->isTrial = !data_get(currentTeam(),'subscription.stripe_trial_already_ended');
|
||||||
|
}
|
||||||
public function subscribeStripe($type)
|
public function subscribeStripe($type)
|
||||||
{
|
{
|
||||||
|
$team = currentTeam();
|
||||||
Stripe::setApiKey(config('subscription.stripe_api_key'));
|
Stripe::setApiKey(config('subscription.stripe_api_key'));
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'basic-monthly':
|
case 'basic-monthly':
|
||||||
@@ -50,10 +55,23 @@ class PricingPlans extends Component
|
|||||||
'automatic_tax' => [
|
'automatic_tax' => [
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
'mode' => 'subscription',
|
'mode' => 'subscription',
|
||||||
'success_url' => route('dashboard', ['success' => true]),
|
'success_url' => route('dashboard', ['success' => true]),
|
||||||
'cancel_url' => route('subscription.index', ['cancelled' => true]),
|
'cancel_url' => route('subscription.index', ['cancelled' => true]),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (!data_get($team,'subscription.stripe_trial_already_ended')) {
|
||||||
|
$payload['subscription_data'] = [
|
||||||
|
'trial_period_days' => config('constants.limits.trial_period'),
|
||||||
|
'trial_settings' => [
|
||||||
|
'end_behavior' => [
|
||||||
|
'missing_payment_method' => 'cancel',
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
||||||
|
$payload['payment_method_collection'] = 'if_required';
|
||||||
|
}
|
||||||
$customer = currentTeam()->subscription?->stripe_customer_id ?? null;
|
$customer = currentTeam()->subscription?->stripe_customer_id ?? null;
|
||||||
if ($customer) {
|
if ($customer) {
|
||||||
$payload['customer'] = $customer;
|
$payload['customer'] = $customer;
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ class Create extends Component
|
|||||||
auth()->user()->teams()->attach($team, ['role' => 'admin']);
|
auth()->user()->teams()->attach($team, ['role' => 'admin']);
|
||||||
refreshSession();
|
refreshSession();
|
||||||
return redirect()->route('team.index');
|
return redirect()->route('team.index');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ class Form extends Component
|
|||||||
try {
|
try {
|
||||||
$this->team->save();
|
$this->team->save();
|
||||||
refreshSession();
|
refreshSession();
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ class Create extends Component
|
|||||||
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
$this->storage->save();
|
$this->storage->save();
|
||||||
return redirect()->route('team.storages.show', $this->storage->uuid);
|
return redirect()->route('team.storages.show', $this->storage->uuid);
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +77,8 @@ class Create extends Component
|
|||||||
try {
|
try {
|
||||||
$this->storage->testConnection();
|
$this->storage->testConnection();
|
||||||
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ class Form extends Component
|
|||||||
try {
|
try {
|
||||||
$this->storage->testConnection();
|
$this->storage->testConnection();
|
||||||
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +42,8 @@ class Form extends Component
|
|||||||
try {
|
try {
|
||||||
$this->storage->delete();
|
$this->storage->delete();
|
||||||
return redirect()->route('team.storages.all');
|
return redirect()->route('team.storages.all');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@ class Form extends Component
|
|||||||
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
$this->storage->save();
|
$this->storage->save();
|
||||||
$this->emit('success', 'Storage settings saved.');
|
$this->emit('success', 'Storage settings saved.');
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler($th, $this);
|
return general_error_handler($e, $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class Upgrade extends Component
|
|||||||
$this->showProgress = true;
|
$this->showProgress = true;
|
||||||
resolve(UpdateCoolify::class)(true);
|
resolve(UpdateCoolify::class)(true);
|
||||||
Toaster::success("Upgrading to {$this->latestVersion} version...");
|
Toaster::success("Upgrading to {$this->latestVersion} version...");
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use Livewire\Component;
|
|||||||
class Index extends Component
|
class Index extends Component
|
||||||
{
|
{
|
||||||
public string $email;
|
public string $email;
|
||||||
|
public int $users = 0;
|
||||||
public int $waitingInLine = 0;
|
public int $waitingInLine = 0;
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
@@ -22,6 +23,7 @@ class Index extends Component
|
|||||||
public function mount()
|
public function mount()
|
||||||
{
|
{
|
||||||
$this->waitingInLine = Waitlist::whereVerified(true)->count();
|
$this->waitingInLine = Waitlist::whereVerified(true)->count();
|
||||||
|
$this->users = User::count();
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
$this->email = 'waitlist@example.com';
|
$this->email = 'waitlist@example.com';
|
||||||
}
|
}
|
||||||
@@ -50,7 +52,7 @@ class Index extends Component
|
|||||||
|
|
||||||
$this->emit('success', 'Check your email to verify your email address.');
|
$this->emit('success', 'Check your email to verify your email address.');
|
||||||
dispatch(new SendConfirmationForWaitlistJob($this->email, $waitlist->uuid));
|
dispatch(new SendConfirmationForWaitlistJob($this->email, $waitlist->uuid));
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
return general_error_handler(err: $e, that: $this);
|
return general_error_handler(err: $e, that: $this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class IsBoardingFlow
|
|||||||
*/
|
*/
|
||||||
public function handle(Request $request, Closure $next): Response
|
public function handle(Request $request, Closure $next): Response
|
||||||
{
|
{
|
||||||
ray()->showQueries()->color('orange');
|
// ray()->showQueries()->color('orange');
|
||||||
if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) {
|
if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) {
|
||||||
return redirect('boarding');
|
return redirect('boarding');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ class ApplicationContainerStatusJob implements ShouldQueue, ShouldBeUnique
|
|||||||
$this->application->status = $status;
|
$this->application->status = $status;
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
}
|
}
|
||||||
} catch (\Exception $th) {
|
} catch (\Throwable $e) {
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ use Spatie\Url\Url;
|
|||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use Visus\Cuid2\Cuid2;
|
use Visus\Cuid2\Cuid2;
|
||||||
|
use Yosymfony\Toml\Toml;
|
||||||
|
use Yosymfony\Toml\TomlArray;
|
||||||
|
|
||||||
class ApplicationDeploymentJob implements ShouldQueue
|
class ApplicationDeploymentJob implements ShouldQueue
|
||||||
{
|
{
|
||||||
@@ -133,7 +135,7 @@ class ApplicationDeploymentJob implements ShouldQueue
|
|||||||
$this->deploy();
|
$this->deploy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->application->fqdn) dispatch(new ProxyStartJob($this->server));
|
if ($this->application->fqdn) dispatch(new ProxyContainerStatusJob($this->server));
|
||||||
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ray($e);
|
ray($e);
|
||||||
@@ -498,7 +500,7 @@ class ApplicationDeploymentJob implements ShouldQueue
|
|||||||
$this->destination->network => [
|
$this->destination->network => [
|
||||||
'external' => true,
|
'external' => true,
|
||||||
'name' => $this->destination->network,
|
'name' => $this->destination->network,
|
||||||
'attachable' => true,
|
'attachable' => true
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
@@ -638,6 +640,10 @@ class ApplicationDeploymentJob implements ShouldQueue
|
|||||||
|
|
||||||
private function generate_healthcheck_commands()
|
private function generate_healthcheck_commands()
|
||||||
{
|
{
|
||||||
|
if ($this->application->dockerfile) {
|
||||||
|
// TODO: disabled HC because there are several ways to hc a simple docker image, hard to figure out a good way. Like some docker images (pocketbase) does not have curl.
|
||||||
|
return 'exit 0';
|
||||||
|
}
|
||||||
if (!$this->application->health_check_port) {
|
if (!$this->application->health_check_port) {
|
||||||
$this->application->health_check_port = $this->application->ports_exposes_array[0];
|
$this->application->health_check_port = $this->application->ports_exposes_array[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class ApplicationPullRequestUpdateJob implements ShouldQueue
|
|||||||
} else {
|
} else {
|
||||||
$this->create_comment();
|
$this->create_comment();
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
ray($e);
|
ray($e);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ class CheckResaleLicenseJob implements ShouldQueue
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
resolve(CheckResaleLicense::class)();
|
resolve(CheckResaleLicense::class)();
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification('CheckResaleLicenseJob failed with: ' . $th->getMessage());
|
send_internal_notification('CheckResaleLicenseJob failed with: ' . $e->getMessage());
|
||||||
ray($th);
|
ray($e);
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ class CleanupInstanceStuffsJob implements ShouldQueue, ShouldBeUnique
|
|||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->cleanup_waitlist();
|
// $this->cleanup_waitlist();
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification('CleanupInstanceStuffsJob failed with error: ' . $e->getMessage());
|
send_internal_notification('CleanupInstanceStuffsJob failed with error: ' . $e->getMessage());
|
||||||
ray($e->getMessage());
|
ray($e->getMessage());
|
||||||
throw $e;
|
throw $e;
|
||||||
|
|||||||
@@ -26,10 +26,8 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
|
|
||||||
public ?Team $team = null;
|
public ?Team $team = null;
|
||||||
public Server $server;
|
public Server $server;
|
||||||
public ?ScheduledDatabaseBackup $backup = null;
|
public ScheduledDatabaseBackup $backup;
|
||||||
public string $database_type;
|
public StandalonePostgresql $database;
|
||||||
public ?StandalonePostgresql $database = null;
|
|
||||||
public string $database_status;
|
|
||||||
|
|
||||||
public ?string $container_name = null;
|
public ?string $container_name = null;
|
||||||
public ?ScheduledDatabaseBackupExecution $backup_log = null;
|
public ?ScheduledDatabaseBackupExecution $backup_log = null;
|
||||||
@@ -45,14 +43,8 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
{
|
{
|
||||||
$this->backup = $backup;
|
$this->backup = $backup;
|
||||||
$this->team = Team::find($backup->team_id);
|
$this->team = Team::find($backup->team_id);
|
||||||
$this->database = $this->backup->database;
|
$this->database = data_get($this->backup, 'database');
|
||||||
if (!$this->database) {
|
|
||||||
ray('Database not found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->database_type = $this->database->type();
|
|
||||||
$this->server = $this->database->destination->server;
|
$this->server = $this->database->destination->server;
|
||||||
$this->database_status = $this->database->status;
|
|
||||||
$this->s3 = $this->backup->s3;
|
$this->s3 = $this->backup->s3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +61,7 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if ($this->database_status !== 'running') {
|
if (data_get($this->database, 'status') !== 'running') {
|
||||||
ray('database not running');
|
ray('database not running');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,7 +80,7 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
'filename' => $this->backup_location,
|
'filename' => $this->backup_location,
|
||||||
'scheduled_database_backup_id' => $this->backup->id,
|
'scheduled_database_backup_id' => $this->backup->id,
|
||||||
]);
|
]);
|
||||||
if ($this->database_type === 'standalone-postgresql') {
|
if ($this->database->type() === 'standalone-postgresql') {
|
||||||
$this->backup_standalone_postgresql();
|
$this->backup_standalone_postgresql();
|
||||||
}
|
}
|
||||||
$this->calculate_size();
|
$this->calculate_size();
|
||||||
@@ -98,12 +90,11 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
}
|
}
|
||||||
$this->save_backup_logs();
|
$this->save_backup_logs();
|
||||||
// TODO: Notify user
|
// TODO: Notify user
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
send_internal_notification('DatabaseBackupJob failed with: ' . $th->getMessage());
|
send_internal_notification('DatabaseBackupJob failed with: ' . $e->getMessage());
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function backup_standalone_postgresql(): void
|
private function backup_standalone_postgresql(): void
|
||||||
@@ -125,10 +116,10 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
|
|
||||||
$this->backup_status = 'success';
|
$this->backup_status = 'success';
|
||||||
$this->team->notify(new BackupSuccess($this->backup, $this->database));
|
$this->team->notify(new BackupSuccess($this->backup, $this->database));
|
||||||
} catch (Throwable $th) {
|
} catch (Throwable $e) {
|
||||||
$this->backup_status = 'failed';
|
$this->backup_status = 'failed';
|
||||||
$this->add_to_backup_output($th->getMessage());
|
$this->add_to_backup_output($e->getMessage());
|
||||||
ray('Backup failed for ' . $this->container_name . ' at ' . $this->server->name . ':' . $this->backup_location . '\n\nError:' . $th->getMessage());
|
ray('Backup failed for ' . $this->container_name . ' at ' . $this->server->name . ':' . $this->backup_location . '\n\nError:' . $e->getMessage());
|
||||||
$this->team->notify(new BackupFailed($this->backup, $this->database, $this->backup_output));
|
$this->team->notify(new BackupFailed($this->backup, $this->database, $this->backup_output));
|
||||||
} finally {
|
} finally {
|
||||||
$this->backup_log->update([
|
$this->backup_log->update([
|
||||||
@@ -182,9 +173,9 @@ class DatabaseBackupJob implements ShouldQueue
|
|||||||
instant_remote_process($commands, $this->server);
|
instant_remote_process($commands, $this->server);
|
||||||
$this->add_to_backup_output('Uploaded to S3.');
|
$this->add_to_backup_output('Uploaded to S3.');
|
||||||
ray('Uploaded to S3. ' . $this->backup_location . ' to s3://' . $bucket . $this->backup_dir);
|
ray('Uploaded to S3. ' . $this->backup_location . ' to s3://' . $bucket . $this->backup_dir);
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
$this->add_to_backup_output($th->getMessage());
|
$this->add_to_backup_output($e->getMessage());
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
$command = "docker rm -f backup-of-{$this->backup->uuid}";
|
$command = "docker rm -f backup-of-{$this->backup->uuid}";
|
||||||
instant_remote_process([$command], $this->server);
|
instant_remote_process([$command], $this->server);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class DatabaseContainerStatusJob implements ShouldQueue, ShouldBeUnique
|
|||||||
$this->database->status = $status;
|
$this->database->status = $status;
|
||||||
$this->database->save();
|
$this->database->save();
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification('DatabaseContainerStatusJob failed with: ' . $e->getMessage());
|
send_internal_notification('DatabaseContainerStatusJob failed with: ' . $e->getMessage());
|
||||||
ray($e->getMessage());
|
ray($e->getMessage());
|
||||||
throw $e;
|
throw $e;
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ class DockerCleanupJob implements ShouldQueue
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ray()->showQueries()->color('orange');
|
// ray()->showQueries()->color('orange');
|
||||||
$servers = Server::all();
|
$servers = Server::all();
|
||||||
foreach ($servers as $server) {
|
foreach ($servers as $server) {
|
||||||
if (
|
if (
|
||||||
!$server->settings->is_reachable && !$server->settings->is_usable
|
!$server->isFunctional()
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ class DockerCleanupJob implements ShouldQueue
|
|||||||
ray('No need to clean up ' . $server->name)->color('orange');
|
ray('No need to clean up ' . $server->name)->color('orange');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification('DockerCleanupJob failed with: ' . $e->getMessage());
|
send_internal_notification('DockerCleanupJob failed with: ' . $e->getMessage());
|
||||||
ray($e->getMessage())->color('orange');
|
ray($e->getMessage())->color('orange');
|
||||||
throw $e;
|
throw $e;
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Jobs;
|
|
||||||
|
|
||||||
use App\Actions\Proxy\StartProxy;
|
|
||||||
use App\Models\Server;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
class ProxyCheckJob implements ShouldQueue
|
|
||||||
{
|
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$container_name = 'coolify-proxy';
|
|
||||||
$servers = Server::all();
|
|
||||||
foreach ($servers as $server) {
|
|
||||||
if (
|
|
||||||
$server->settings->is_reachable === false || $server->settings->is_usable === false
|
|
||||||
) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$status = getContainerStatus(server: $server, container_id: $container_name);
|
|
||||||
if ($status === 'running') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (data_get($server, 'proxy.type')) {
|
|
||||||
resolve(StartProxy::class)($server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
ray($th->getMessage());
|
|
||||||
send_internal_notification('ProxyCheckJob failed with: ' . $th->getMessage());
|
|
||||||
throw $th;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Actions\Proxy\StartProxy;
|
||||||
|
use App\Enums\ProxyStatus;
|
||||||
use App\Enums\ProxyTypes;
|
use App\Enums\ProxyTypes;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
@@ -11,7 +13,6 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
|||||||
use Illuminate\Queue\InteractsWithQueue;
|
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;
|
|
||||||
|
|
||||||
class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
|
class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
|
||||||
{
|
{
|
||||||
@@ -28,31 +29,51 @@ class ProxyContainerStatusJob implements ShouldQueue, ShouldBeUnique
|
|||||||
|
|
||||||
public function middleware(): array
|
public function middleware(): array
|
||||||
{
|
{
|
||||||
return [new WithoutOverlapping($this->server->id)];
|
return [new WithoutOverlapping($this->server->uuid)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function uniqueId(): int
|
public function uniqueId(): string
|
||||||
{
|
{
|
||||||
return $this->server->id;
|
ray($this->server->uuid);
|
||||||
|
return $this->server->uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false);
|
$proxyType = data_get($this->server, 'proxy.type');
|
||||||
$status = data_get($container, 'State.Status');
|
if ($proxyType === ProxyTypes::NONE->value) {
|
||||||
if ($status && data_get($this->server, 'proxy.status') !== $status) {
|
return;
|
||||||
$this->server->proxy->status = $status;
|
}
|
||||||
if ($this->server->proxy->status === 'running') {
|
if (is_null($proxyType)) {
|
||||||
$traefik = $container['Config']['Labels']['org.opencontainers.image.title'];
|
if ($this->server->isProxyShouldRun()) {
|
||||||
$version = $container['Config']['Labels']['org.opencontainers.image.version'];
|
|
||||||
if (isset($version) && isset($traefik) && $traefik === 'Traefik' && Str::of($version)->startsWith('v2')) {
|
|
||||||
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
|
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
|
||||||
}
|
$this->server->proxy->status = ProxyStatus::EXITED->value;
|
||||||
}
|
|
||||||
$this->server->save();
|
$this->server->save();
|
||||||
|
resolve(StartProxy::class)($this->server);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
}
|
||||||
|
|
||||||
|
$container = getContainerStatus(server: $this->server, all_data: true, container_id: 'coolify-proxy', throwError: false);
|
||||||
|
$containerStatus = data_get($container, 'State.Status');
|
||||||
|
$databaseContainerStatus = data_get($this->server, 'proxy.status', 'exited');
|
||||||
|
|
||||||
|
|
||||||
|
if ($proxyType !== ProxyTypes::NONE->value) {
|
||||||
|
if ($containerStatus === 'running') {
|
||||||
|
$this->server->proxy->status = $containerStatus;
|
||||||
|
$this->server->save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((is_null($containerStatus) ||$containerStatus !== 'running' || $databaseContainerStatus !== 'running' || ($containerStatus && $databaseContainerStatus !== $containerStatus)) && $this->server->isProxyShouldRun()) {
|
||||||
|
$this->server->proxy->status = $containerStatus;
|
||||||
|
$this->server->save();
|
||||||
|
resolve(StartProxy::class)($this->server);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
if ($e->getCode() === 1) {
|
if ($e->getCode() === 1) {
|
||||||
$this->server->proxy->status = 'exited';
|
$this->server->proxy->status = 'exited';
|
||||||
$this->server->save();
|
$this->server->save();
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Jobs;
|
|
||||||
|
|
||||||
use App\Actions\Proxy\StartProxy;
|
|
||||||
use App\Enums\ProxyStatus;
|
|
||||||
use App\Enums\ProxyTypes;
|
|
||||||
use App\Models\Server;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
class ProxyStartJob implements ShouldQueue
|
|
||||||
{
|
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
||||||
|
|
||||||
public function __construct(protected Server $server)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$container_name = 'coolify-proxy';
|
|
||||||
ray('Starting proxy for server: ' . $this->server->name);
|
|
||||||
$status = getContainerStatus(server: $this->server, container_id: $container_name);
|
|
||||||
if ($status === 'running') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (is_null(data_get($this->server, 'proxy.type'))) {
|
|
||||||
$this->server->proxy->type = ProxyTypes::TRAEFIK_V2->value;
|
|
||||||
$this->server->proxy->status = ProxyStatus::EXITED->value;
|
|
||||||
$this->server->save();
|
|
||||||
}
|
|
||||||
resolve(StartProxy::class)($this->server);
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
send_internal_notification('ProxyStartJob failed with: ' . $th->getMessage());
|
|
||||||
ray($th->getMessage());
|
|
||||||
throw $th;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Jobs;
|
|
||||||
|
|
||||||
use App\Models\Application;
|
|
||||||
use App\Models\StandalonePostgresql;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
class ResourceStatusJob implements ShouldQueue, ShouldBeUnique
|
|
||||||
{
|
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
||||||
|
|
||||||
public $applications;
|
|
||||||
public $postgresqls;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->applications = Application::all();
|
|
||||||
$this->postgresqls = StandalonePostgresql::all();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(): void
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
foreach ($this->applications as $application) {
|
|
||||||
dispatch(new ApplicationContainerStatusJob(
|
|
||||||
application: $application,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
foreach ($this->postgresqls as $postgresql) {
|
|
||||||
dispatch(new DatabaseContainerStatusJob(
|
|
||||||
database: $postgresql,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
} catch (\Exception $th) {
|
|
||||||
send_internal_notification('ResourceStatusJob failed with: ' . $th->getMessage());
|
|
||||||
ray($th);
|
|
||||||
throw $th;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,10 +25,8 @@ class SendConfirmationForWaitlistJob implements ShouldQueue
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$mail = new MailMessage();
|
$mail = new MailMessage();
|
||||||
|
|
||||||
$confirmation_url = base_url() . '/webhooks/waitlist/confirm?email=' . $this->email . '&confirmation_code=' . $this->uuid;
|
$confirmation_url = base_url() . '/webhooks/waitlist/confirm?email=' . $this->email . '&confirmation_code=' . $this->uuid;
|
||||||
$cancel_url = base_url() . '/webhooks/waitlist/cancel?email=' . $this->email . '&confirmation_code=' . $this->uuid;
|
$cancel_url = base_url() . '/webhooks/waitlist/cancel?email=' . $this->email . '&confirmation_code=' . $this->uuid;
|
||||||
|
|
||||||
$mail->view('emails.waitlist-confirmation',
|
$mail->view('emails.waitlist-confirmation',
|
||||||
[
|
[
|
||||||
'confirmation_url' => $confirmation_url,
|
'confirmation_url' => $confirmation_url,
|
||||||
@@ -36,10 +34,10 @@ class SendConfirmationForWaitlistJob implements ShouldQueue
|
|||||||
]);
|
]);
|
||||||
$mail->subject('You are on the waitlist!');
|
$mail->subject('You are on the waitlist!');
|
||||||
send_user_an_email($mail, $this->email);
|
send_user_an_email($mail, $this->email);
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification("SendConfirmationForWaitlistJob failed for {$mail} with error: " . $th->getMessage());
|
send_internal_notification("SendConfirmationForWaitlistJob failed for {$this->email} with error: " . $e->getMessage());
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
79
app/Jobs/ServerDetailsCheckJob.php
Normal file
79
app/Jobs/ServerDetailsCheckJob.php
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Server;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Str;
|
||||||
|
|
||||||
|
class ServerDetailsCheckJob implements ShouldQueue, ShouldBeUnique
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public $tries = 1;
|
||||||
|
public $timeout = 120;
|
||||||
|
|
||||||
|
public function __construct(public Server $server)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function middleware(): array
|
||||||
|
{
|
||||||
|
return [new WithoutOverlapping($this->server->uuid)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uniqueId(): string
|
||||||
|
{
|
||||||
|
return $this->server->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
ray()->clearAll();
|
||||||
|
$containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this->server);
|
||||||
|
$containers = format_docker_command_output_to_json($containers);
|
||||||
|
$applications = $this->server->applications();
|
||||||
|
// ray($applications);
|
||||||
|
// ray(format_docker_command_output_to_json($containers));
|
||||||
|
foreach ($applications as $application) {
|
||||||
|
$uuid = data_get($application, 'uuid');
|
||||||
|
$foundContainer = $containers->filter(function ($value, $key) use ($uuid) {
|
||||||
|
$image = data_get($value, 'Config.Image');
|
||||||
|
return Str::startsWith($image, $uuid);
|
||||||
|
})->first();
|
||||||
|
|
||||||
|
if ($foundContainer) {
|
||||||
|
$containerStatus = data_get($foundContainer, 'State.Status');
|
||||||
|
$databaseStatus = data_get($application, 'status');
|
||||||
|
ray($containerStatus, $databaseStatus);
|
||||||
|
if ($containerStatus !== $databaseStatus) {
|
||||||
|
// $application->update(['status' => $containerStatus]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// foreach ($containers as $container) {
|
||||||
|
// $labels = format_docker_labels_to_json(data_get($container,'Config.Labels'));
|
||||||
|
// $foundLabel = $labels->filter(fn ($value, $key) => Str::startsWith($key, 'coolify.applicationId'));
|
||||||
|
// if ($foundLabel->count() > 0) {
|
||||||
|
// $appFound = $applications->where('id', $foundLabel['coolify.applicationId'])->first();
|
||||||
|
// if ($appFound) {
|
||||||
|
// $containerStatus = data_get($container, 'State.Status');
|
||||||
|
// $databaseStatus = data_get($appFound, 'status');
|
||||||
|
// ray($containerStatus, $databaseStatus);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
// send_internal_notification('ServerDetailsCheckJob failed with: ' . $e->getMessage());
|
||||||
|
ray($e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,10 +33,10 @@ class SubscriptionInvoiceFailedJob implements ShouldQueue
|
|||||||
send_user_an_email($mail, $member->email);
|
send_user_an_email($mail, $member->email);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification('SubscriptionInvoiceFailedJob failed with: ' . $th->getMessage());
|
send_internal_notification('SubscriptionInvoiceFailedJob failed with: ' . $e->getMessage());
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
throw $th;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
app/Jobs/SubscriptionTrialEndedJob.php
Executable file
44
app/Jobs/SubscriptionTrialEndedJob.php
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Team;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class SubscriptionTrialEndedJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public Team $team
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$session = getStripeCustomerPortalSession($this->team);
|
||||||
|
$mail = new MailMessage();
|
||||||
|
$mail->subject('Action required: You trial in Coolify Cloud ended.');
|
||||||
|
$mail->view('emails.trial-ended', [
|
||||||
|
'stripeCustomerPortal' => $session->url,
|
||||||
|
]);
|
||||||
|
$this->team->members()->each(function ($member) use ($mail) {
|
||||||
|
if ($member->isAdmin()) {
|
||||||
|
ray('Sending trial ended email to ' . $member->email);
|
||||||
|
send_user_an_email($mail, $member->email);
|
||||||
|
send_internal_notification('Trial reminder email sent to ' . $member->email);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
send_internal_notification('SubscriptionTrialEndsSoonJob failed with: ' . $e->getMessage());
|
||||||
|
ray($e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
app/Jobs/SubscriptionTrialEndsSoonJob.php
Executable file
44
app/Jobs/SubscriptionTrialEndsSoonJob.php
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Models\Team;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class SubscriptionTrialEndsSoonJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public Team $team
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$session = getStripeCustomerPortalSession($this->team);
|
||||||
|
$mail = new MailMessage();
|
||||||
|
$mail->subject('You trial in Coolify Cloud ends soon.');
|
||||||
|
$mail->view('emails.trial-ends-soon', [
|
||||||
|
'stripeCustomerPortal' => $session->url,
|
||||||
|
]);
|
||||||
|
$this->team->members()->each(function ($member) use ($mail) {
|
||||||
|
if ($member->isAdmin()) {
|
||||||
|
ray('Sending trial ending email to ' . $member->email);
|
||||||
|
send_user_an_email($mail, $member->email);
|
||||||
|
send_internal_notification('Trial reminder email sent to ' . $member->email);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
send_internal_notification('SubscriptionTrialEndsSoonJob failed with: ' . $e->getMessage());
|
||||||
|
ray($e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,27 +45,23 @@ class EnvironmentVariable extends Model
|
|||||||
private function get_environment_variables(string $environment_variable): string|null
|
private function get_environment_variables(string $environment_variable): string|null
|
||||||
{
|
{
|
||||||
// $team_id = currentTeam()->id;
|
// $team_id = currentTeam()->id;
|
||||||
if (str_contains(trim($environment_variable), '{{') && str_contains(trim($environment_variable), '}}')) {
|
$environment_variable = trim(decrypt($environment_variable));
|
||||||
$environment_variable = preg_replace('/\s+/', '', $environment_variable);
|
if (Str::startsWith($environment_variable, '{{') && Str::endsWith($environment_variable, '}}') && Str::contains($environment_variable, 'global.')) {
|
||||||
$environment_variable = str_replace('{{', '', $environment_variable);
|
$variable = Str::after($environment_variable, 'global.');
|
||||||
$environment_variable = str_replace('}}', '', $environment_variable);
|
$variable = Str::before($variable, '}}');
|
||||||
if (str_starts_with($environment_variable, 'global.')) {
|
$variable = Str::of($variable)->trim()->value;
|
||||||
$environment_variable = str_replace('global.', '', $environment_variable);
|
|
||||||
// $environment_variable = GlobalEnvironmentVariable::where('name', $environment_variable)->where('team_id', $team_id)->first()?->value;
|
// $environment_variable = GlobalEnvironmentVariable::where('name', $environment_variable)->where('team_id', $team_id)->first()?->value;
|
||||||
|
ray('global env variable');
|
||||||
return $environment_variable;
|
return $environment_variable;
|
||||||
}
|
}
|
||||||
}
|
return $environment_variable;
|
||||||
return decrypt($environment_variable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_environment_variables(string $environment_variable): string|null
|
private function set_environment_variables(string $environment_variable): string|null
|
||||||
{
|
{
|
||||||
$environment_variable = trim($environment_variable);
|
$environment_variable = trim($environment_variable);
|
||||||
if (!str_contains(trim($environment_variable), '{{') && !str_contains(trim($environment_variable), '}}')) {
|
|
||||||
return encrypt($environment_variable);
|
return encrypt($environment_variable);
|
||||||
}
|
}
|
||||||
return $environment_variable;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function key(): Attribute
|
protected function key(): Attribute
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use phpseclib3\Crypt\PublicKeyLoader;
|
||||||
|
|
||||||
class PrivateKey extends BaseModel
|
class PrivateKey extends BaseModel
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,15 @@ class PrivateKey extends BaseModel
|
|||||||
return PrivateKey::whereTeamId(currentTeam()->id)->select($selectArray->all());
|
return PrivateKey::whereTeamId(currentTeam()->id)->select($selectArray->all());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function publicKey()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return PublicKeyLoader::load($this->private_key)->getPublicKey()->toString('OpenSSH',['comment' => '']);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return 'Error loading private key';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function isEmpty()
|
public function isEmpty()
|
||||||
{
|
{
|
||||||
if ($this->servers()->count() === 0 && $this->applications()->count() === 0 && $this->githubApps()->count() === 0 && $this->gitlabApps()->count() === 0) {
|
if ($this->servers()->count() === 0 && $this->applications()->count() === 0 && $this->githubApps()->count() === 0 && $this->gitlabApps()->count() === 0) {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ class Server extends BaseModel
|
|||||||
'server_id' => $server->id,
|
'server_id' => $server->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
static::deleting(function ($server) {
|
static::deleting(function ($server) {
|
||||||
$server->destinations()->each(function ($destination) {
|
$server->destinations()->each(function ($destination) {
|
||||||
@@ -72,7 +71,6 @@ class Server extends BaseModel
|
|||||||
$swarmDocker = collect($server->swarmDockers->all());
|
$swarmDocker = collect($server->swarmDockers->all());
|
||||||
return $standaloneDocker->concat($swarmDocker);
|
return $standaloneDocker->concat($swarmDocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function settings()
|
public function settings()
|
||||||
{
|
{
|
||||||
return $this->hasOne(ServerSetting::class);
|
return $this->hasOne(ServerSetting::class);
|
||||||
@@ -93,7 +91,8 @@ class Server extends BaseModel
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function databases() {
|
public function databases()
|
||||||
|
{
|
||||||
return $this->destinations()->map(function ($standaloneDocker) {
|
return $this->destinations()->map(function ($standaloneDocker) {
|
||||||
$postgresqls = $standaloneDocker->postgresqls;
|
$postgresqls = $standaloneDocker->postgresqls;
|
||||||
return $postgresqls?->concat([]) ?? collect([]);
|
return $postgresqls?->concat([]) ?? collect([]);
|
||||||
@@ -137,4 +136,24 @@ class Server extends BaseModel
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(Team::class);
|
return $this->belongsTo(Team::class);
|
||||||
}
|
}
|
||||||
|
public function isProxyShouldRun()
|
||||||
|
{
|
||||||
|
$shouldRun = false;
|
||||||
|
foreach ($this->applications() as $application) {
|
||||||
|
if (data_get($application, 'fqdn')) {
|
||||||
|
$shouldRun = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->id === 0) {
|
||||||
|
$settings = InstanceSettings::get();
|
||||||
|
if (data_get($settings, 'fqdn')) {
|
||||||
|
$shouldRun = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $shouldRun;
|
||||||
|
}
|
||||||
|
public function isFunctional() {
|
||||||
|
return $this->settings->is_reachable && $this->settings->is_usable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ class StandalonePostgresql extends BaseModel
|
|||||||
'is_readonly' => true
|
'is_readonly' => true
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
static::deleted(function ($database) {
|
||||||
|
$database->scheduledBackups()->delete();
|
||||||
|
$database->persistentStorages()->delete();
|
||||||
|
instant_remote_process(['docker volume rm postgres-data-' . $database->uuid], $database->destination->server, false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function portsMappings(): Attribute
|
public function portsMappings(): Attribute
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class Subscription extends Model
|
|||||||
}
|
}
|
||||||
if (isStripe()) {
|
if (isStripe()) {
|
||||||
if (!$this->stripe_plan_id) {
|
if (!$this->stripe_plan_id) {
|
||||||
return 'unknown';
|
return 'zero';
|
||||||
}
|
}
|
||||||
$subscription = Subscription::where('id', $this->id)->first();
|
$subscription = Subscription::where('id', $this->id)->first();
|
||||||
if (!$subscription) {
|
if (!$subscription) {
|
||||||
@@ -54,6 +54,6 @@ class Subscription extends Model
|
|||||||
return Str::of($stripePlanId)->after('stripe_price_id_')->before('_')->lower();
|
return Str::of($stripePlanId)->after('stripe_price_id_')->before('_')->lower();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 'unknown';
|
return 'zero';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,4 +120,20 @@ class Team extends Model implements SendsDiscord, SendsEmail
|
|||||||
{
|
{
|
||||||
return $this->hasMany(S3Storage::class);
|
return $this->hasMany(S3Storage::class);
|
||||||
}
|
}
|
||||||
|
public function trialEnded() {
|
||||||
|
foreach ($this->servers as $server) {
|
||||||
|
$server->settings()->update([
|
||||||
|
'is_usable' => false,
|
||||||
|
'is_reachable' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function trialEndedButSubscribed() {
|
||||||
|
foreach ($this->servers as $server) {
|
||||||
|
$server->settings()->update([
|
||||||
|
'is_usable' => true,
|
||||||
|
'is_reachable' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,17 @@ class GeneralNotification extends Notification implements ShouldQueue
|
|||||||
|
|
||||||
public function via(object $notifiable): array
|
public function via(object $notifiable): array
|
||||||
{
|
{
|
||||||
return [TelegramChannel::class, DiscordChannel::class];
|
$channels = [];
|
||||||
|
$isDiscordEnabled = data_get($notifiable, 'discord_enabled');
|
||||||
|
$isTelegramEnabled = data_get($notifiable, 'telegram_enabled');
|
||||||
|
|
||||||
|
if ($isDiscordEnabled) {
|
||||||
|
$channels[] = DiscordChannel::class;
|
||||||
|
}
|
||||||
|
if ($isTelegramEnabled) {
|
||||||
|
$channels[] = TelegramChannel::class;
|
||||||
|
}
|
||||||
|
return $channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toDiscord(): string
|
public function toDiscord(): string
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ class Modal extends Component
|
|||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $modalId,
|
public string $modalId,
|
||||||
public string|null $modalTitle = null,
|
public ?string $submitWireAction = null,
|
||||||
public string|null $modalBody = null,
|
public ?string $modalTitle = null,
|
||||||
public string|null $modalSubmit = null,
|
public ?string $modalBody = null,
|
||||||
|
public ?string $modalSubmit = null,
|
||||||
|
public bool $noSubmit = false,
|
||||||
public bool $yesOrNo = false,
|
public bool $yesOrNo = false,
|
||||||
public string $action = 'delete'
|
public string $action = 'delete'
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -26,8 +26,11 @@ function format_docker_command_output_to_json($rawOutput): Collection
|
|||||||
->map(fn ($outputLine) => json_decode($outputLine, true, flags: JSON_THROW_ON_ERROR));
|
->map(fn ($outputLine) => json_decode($outputLine, true, flags: JSON_THROW_ON_ERROR));
|
||||||
}
|
}
|
||||||
|
|
||||||
function format_docker_labels_to_json($rawOutput): Collection
|
function format_docker_labels_to_json(string|Array $rawOutput): Collection
|
||||||
{
|
{
|
||||||
|
if (is_array($rawOutput)) {
|
||||||
|
return collect($rawOutput);
|
||||||
|
}
|
||||||
$outputLines = explode(PHP_EOL, $rawOutput);
|
$outputLines = explode(PHP_EOL, $rawOutput);
|
||||||
|
|
||||||
return collect($outputLines)
|
return collect($outputLines)
|
||||||
@@ -52,7 +55,7 @@ function format_docker_envs_to_json($rawOutput)
|
|||||||
$env = explode('=', $env);
|
$env = explode('=', $env);
|
||||||
return [$env[0] => $env[1]];
|
return [$env[0] => $env[1]];
|
||||||
});
|
});
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
return collect([]);
|
return collect([]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,9 +164,9 @@ function refresh_server_connection(PrivateKey $private_key)
|
|||||||
// Delete the old ssh mux file to force a new one to be created
|
// Delete the old ssh mux file to force a new one to be created
|
||||||
Storage::disk('ssh-mux')->delete($server->muxFilename());
|
Storage::disk('ssh-mux')->delete($server->muxFilename());
|
||||||
// check if user is authenticated
|
// check if user is authenticated
|
||||||
if (currentTeam()->id) {
|
// if (currentTeam()->id) {
|
||||||
currentTeam()->privateKeys = PrivateKey::where('team_id', currentTeam()->id)->get();
|
// currentTeam()->privateKeys = PrivateKey::where('team_id', currentTeam()->id)->get();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ function validateServer(Server $server)
|
|||||||
}
|
}
|
||||||
$server->settings->is_reachable = true;
|
$server->settings->is_reachable = true;
|
||||||
|
|
||||||
$dockerVersion = instant_remote_process(['docker version|head -2|grep -i version'], $server, false);
|
$dockerVersion = instant_remote_process(["docker version|head -2|grep -i version| awk '{print $2}'"], $server, false);
|
||||||
if (!$dockerVersion) {
|
if (!$dockerVersion) {
|
||||||
$dockerVersion = null;
|
$dockerVersion = null;
|
||||||
return [
|
return [
|
||||||
@@ -192,17 +192,23 @@ function validateServer(Server $server)
|
|||||||
"dockerVersion" => null,
|
"dockerVersion" => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
$majorDockerVersion = Str::of($dockerVersion)->before('.')->value();
|
||||||
|
if ($majorDockerVersion <= 22) {
|
||||||
|
$dockerVersion = null;
|
||||||
|
$server->settings->is_usable = false;
|
||||||
|
} else {
|
||||||
$server->settings->is_usable = true;
|
$server->settings->is_usable = true;
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
"uptime" => $uptime,
|
"uptime" => $uptime,
|
||||||
"dockerVersion" => $dockerVersion,
|
"dockerVersion" => $dockerVersion,
|
||||||
];
|
];
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
$server->settings->is_reachable = false;
|
$server->settings->is_reachable = false;
|
||||||
$server->settings->is_usable = false;
|
$server->settings->is_usable = false;
|
||||||
throw $e;
|
throw $e;
|
||||||
} finally {
|
} finally {
|
||||||
$server->settings->save();
|
if(data_get($server,'settings')) $server->settings->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +219,7 @@ function check_server_connection(Server $server)
|
|||||||
instant_remote_process(['uptime'], $server);
|
instant_remote_process(['uptime'], $server);
|
||||||
$server->unreachable_count = 0;
|
$server->unreachable_count = 0;
|
||||||
$server->settings->is_reachable = true;
|
$server->settings->is_reachable = true;
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
if ($server->unreachable_count == 2) {
|
if ($server->unreachable_count == 2) {
|
||||||
$server->team->notify(new NotReachable($server));
|
$server->team->notify(new NotReachable($server));
|
||||||
$server->settings->is_reachable = false;
|
$server->settings->is_reachable = false;
|
||||||
@@ -240,7 +246,7 @@ function checkRequiredCommands(Server $server)
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'apt update && apt install -y {$command}'"], $server);
|
instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'apt update && apt install -y {$command}'"], $server);
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
ray('could not install ' . $command);
|
ray('could not install ' . $command);
|
||||||
ray($e);
|
ray($e);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -89,18 +89,18 @@ function general_error_handler(Throwable | null $err = null, $that = null, $isJs
|
|||||||
}
|
}
|
||||||
throw new Exception($customErrorMessage ?? $err->getMessage());
|
throw new Exception($customErrorMessage ?? $err->getMessage());
|
||||||
}
|
}
|
||||||
} catch (Throwable $error) {
|
} catch (Throwable $e) {
|
||||||
if ($that) {
|
if ($that) {
|
||||||
return $that->emit('error', $customErrorMessage ?? $error->getMessage());
|
return $that->emit('error', $customErrorMessage ?? $e->getMessage());
|
||||||
} elseif ($isJson) {
|
} elseif ($isJson) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'code' => $error->getCode(),
|
'code' => $e->getCode(),
|
||||||
'error' => $error->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
ray($customErrorMessage);
|
ray($customErrorMessage);
|
||||||
ray($error);
|
ray($e);
|
||||||
return $customErrorMessage ?? $error->getMessage();
|
return $customErrorMessage ?? $e->getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,9 +116,9 @@ function get_latest_version_of_coolify(): string
|
|||||||
$response = Http::get('https://cdn.coollabs.io/coolify/versions.json');
|
$response = Http::get('https://cdn.coollabs.io/coolify/versions.json');
|
||||||
$versions = $response->json();
|
$versions = $response->json();
|
||||||
return data_get($versions, 'coolify.v4.version');
|
return data_get($versions, 'coolify.v4.version');
|
||||||
} catch (Throwable $th) {
|
} catch (Throwable $e) {
|
||||||
//throw $th;
|
//throw $e;
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
return '0.0.0';
|
return '0.0.0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,17 +258,28 @@ function send_internal_notification(string $message): void
|
|||||||
$baseUrl = config('app.name');
|
$baseUrl = config('app.name');
|
||||||
$team = Team::find(0);
|
$team = Team::find(0);
|
||||||
$team->notify(new GeneralNotification("👀 {$baseUrl}: " . $message));
|
$team->notify(new GeneralNotification("👀 {$baseUrl}: " . $message));
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $e) {
|
||||||
ray($th->getMessage());
|
ray($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function send_user_an_email(MailMessage $mail, string $email): void
|
function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null): void
|
||||||
{
|
{
|
||||||
$settings = InstanceSettings::get();
|
$settings = InstanceSettings::get();
|
||||||
$type = set_transanctional_email_settings($settings);
|
$type = set_transanctional_email_settings($settings);
|
||||||
if (!$type) {
|
if (!$type) {
|
||||||
throw new Exception('No email settings found.');
|
throw new Exception('No email settings found.');
|
||||||
}
|
}
|
||||||
|
if ($cc) {
|
||||||
|
Mail::send(
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
fn (Message $message) => $message
|
||||||
|
->to($email)
|
||||||
|
->cc($cc)
|
||||||
|
->subject($mail->subject)
|
||||||
|
->html((string) $mail->render())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
Mail::send(
|
Mail::send(
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
@@ -278,6 +289,7 @@ function send_user_an_email(MailMessage $mail, string $email): void
|
|||||||
->html((string) $mail->render())
|
->html((string) $mail->render())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
function isEmailEnabled($notifiable)
|
function isEmailEnabled($notifiable)
|
||||||
{
|
{
|
||||||
return data_get($notifiable, 'smtp_enabled') || data_get($notifiable, 'resend_enabled') || data_get($notifiable, 'use_instance_email_settings');
|
return data_get($notifiable, 'smtp_enabled') || data_get($notifiable, 'resend_enabled') || data_get($notifiable, 'use_instance_email_settings');
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
"spatie/url": "^2.2",
|
"spatie/url": "^2.2",
|
||||||
"stripe/stripe-php": "^12.0",
|
"stripe/stripe-php": "^12.0",
|
||||||
"symfony/yaml": "^6.2",
|
"symfony/yaml": "^6.2",
|
||||||
"visus/cuid2": "^2.0.0"
|
"visus/cuid2": "^2.0.0",
|
||||||
|
"yosymfony/toml": "^1.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^v1.21.0",
|
"fakerphp/faker": "^v1.21.0",
|
||||||
|
|||||||
112
composer.lock
generated
112
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "0603276b60e77cd859fabacdaaf31550",
|
"content-hash": "cf138424c896f30b035bc8cdff63e8d1",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
@@ -9771,6 +9771,116 @@
|
|||||||
},
|
},
|
||||||
"time": "2022-06-03T18:03:27+00:00"
|
"time": "2022-06-03T18:03:27+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "yosymfony/parser-utils",
|
||||||
|
"version": "v2.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/yosymfony/parser-utils.git",
|
||||||
|
"reference": "00bec9a12722b21f2baf7f9db35f127e90c162c9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/yosymfony/parser-utils/zipball/00bec9a12722b21f2baf7f9db35f127e90c162c9",
|
||||||
|
"reference": "00bec9a12722b21f2baf7f9db35f127e90c162c9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^6"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Yosymfony\\ParserUtils\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Puertas",
|
||||||
|
"email": "vpgugr@gmail.com",
|
||||||
|
"homepage": "http://yosymfony.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Parser utilities",
|
||||||
|
"homepage": "http://github.com/yosymfony/toml",
|
||||||
|
"keywords": [
|
||||||
|
"lexer",
|
||||||
|
"parser"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/yosymfony/parser-utils/issues",
|
||||||
|
"source": "https://github.com/yosymfony/parser-utils/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2018-06-29T15:31:11+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "yosymfony/toml",
|
||||||
|
"version": "v1.0.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/yosymfony/toml.git",
|
||||||
|
"reference": "bdab92ad920d0e36810a3a3e4a998d23f3498f8e"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/yosymfony/toml/zipball/bdab92ad920d0e36810a3a3e4a998d23f3498f8e",
|
||||||
|
"reference": "bdab92ad920d0e36810a3a3e4a998d23f3498f8e",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1",
|
||||||
|
"yosymfony/parser-utils": "^2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Yosymfony\\Toml\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Puertas",
|
||||||
|
"email": "vpgugr@gmail.com",
|
||||||
|
"homepage": "http://yosymfony.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A PHP parser for TOML compatible with specification 0.4.0",
|
||||||
|
"homepage": "http://github.com/yosymfony/toml",
|
||||||
|
"keywords": [
|
||||||
|
"mojombo",
|
||||||
|
"parser",
|
||||||
|
"toml"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/yosymfony/toml/issues",
|
||||||
|
"source": "https://github.com/yosymfony/toml/tree/master"
|
||||||
|
},
|
||||||
|
"time": "2018-08-08T15:08:14+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "zbateson/mail-mime-parser",
|
"name": "zbateson/mail-mime-parser",
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ return [
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
'limits' => [
|
'limits' => [
|
||||||
|
'trial_period'=> 14,
|
||||||
'server' => [
|
'server' => [
|
||||||
'zero' => 0,
|
'zero' => 0,
|
||||||
'self-hosted' => 999999999999,
|
'self-hosted' => 999999999999,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ return [
|
|||||||
'queue' => 'long-running',
|
'queue' => 'long-running',
|
||||||
'retry_after' => 3600,
|
'retry_after' => 3600,
|
||||||
'block_for' => null,
|
'block_for' => null,
|
||||||
'after_commit' => false,
|
'after_commit' => true,
|
||||||
],
|
],
|
||||||
'database' => [
|
'database' => [
|
||||||
'driver' => 'database',
|
'driver' => 'database',
|
||||||
@@ -75,7 +75,7 @@ return [
|
|||||||
'queue' => env('REDIS_QUEUE', 'default'),
|
'queue' => env('REDIS_QUEUE', 'default'),
|
||||||
'retry_after' => 300,
|
'retry_after' => 300,
|
||||||
'block_for' => null,
|
'block_for' => null,
|
||||||
'after_commit' => false,
|
'after_commit' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ return [
|
|||||||
|
|
||||||
// The release version of your application
|
// The release version of your application
|
||||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||||
'release' => '4.0.0-beta.29',
|
'release' => '4.0.0-beta.35',
|
||||||
'server_name' => env('APP_ID', 'coolify'),
|
'server_name' => env('APP_ID', 'coolify'),
|
||||||
// When left empty or `null` the Laravel environment will be used
|
// When left empty or `null` the Laravel environment will be used
|
||||||
'environment' => config('app.env'),
|
'environment' => config('app.env'),
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return '4.0.0-beta.29';
|
return '4.0.0-beta.35';
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('applications', function (Blueprint $table) {
|
||||||
|
$table->string('nixpkgsarchive')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('teams', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('nixpkgsarchive');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('applications', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('nixpkgsarchive');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('teams', function (Blueprint $table) {
|
||||||
|
$table->string('nixpkgsarchive')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('subscriptions', function (Blueprint $table) {
|
||||||
|
$table->boolean('stripe_trial_already_ended')->default(false)->after('stripe_cancel_at_period_end');
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('subscriptions', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('stripe_trial_already_ended');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -38,7 +38,7 @@ class InstanceSettingsSeeder extends Seeder
|
|||||||
if (is_null($settings->public_ipv6) && $ipv6) {
|
if (is_null($settings->public_ipv6) && $ipv6) {
|
||||||
$settings->update(['public_ipv6' => $ipv6]);
|
$settings->update(['public_ipv6' => $ipv6]);
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
echo "Error: {$e->getMessage()}\n";
|
echo "Error: {$e->getMessage()}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class ProductionSeeder extends Seeder
|
|||||||
$settings->update(['public_ipv6' => $ipv6]);
|
$settings->update(['public_ipv6' => $ipv6]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Throwable $e) {
|
||||||
echo "Error: {$e->getMessage()}\n";
|
echo "Error: {$e->getMessage()}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ ARG DOCKER_BUILDX_VERSION=0.11.2
|
|||||||
# https://github.com/buildpacks/pack/releases
|
# https://github.com/buildpacks/pack/releases
|
||||||
ARG PACK_VERSION=0.30.0
|
ARG PACK_VERSION=0.30.0
|
||||||
# https://github.com/railwayapp/nixpacks/releases
|
# https://github.com/railwayapp/nixpacks/releases
|
||||||
ARG NIXPACKS_VERSION=1.13.0
|
ARG NIXPACKS_VERSION=1.14.0
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
WORKDIR /artifacts
|
WORKDIR /artifacts
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ ARG DOCKER_BUILDX_VERSION=0.11.2
|
|||||||
# https://github.com/buildpacks/pack/releases
|
# https://github.com/buildpacks/pack/releases
|
||||||
ARG PACK_VERSION=0.30.0
|
ARG PACK_VERSION=0.30.0
|
||||||
# https://github.com/railwayapp/nixpacks/releases
|
# https://github.com/railwayapp/nixpacks/releases
|
||||||
ARG NIXPACKS_VERSION=1.13.0
|
ARG NIXPACKS_VERSION=1.14.0
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user