From e4d5969326fbbe83716df0a7d0883f1eff0d559a Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 11:25:45 +0100 Subject: [PATCH 01/13] refactor swarm view livewire --- app/Livewire/Project/Application/Swarm.php | 52 ++++++++++++------- .../project/application/swarm.blade.php | 8 ++- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/app/Livewire/Project/Application/Swarm.php b/app/Livewire/Project/Application/Swarm.php index 0151b5222..c2cdcd667 100644 --- a/app/Livewire/Project/Application/Swarm.php +++ b/app/Livewire/Project/Application/Swarm.php @@ -3,32 +3,55 @@ namespace App\Livewire\Project\Application; use App\Models\Application; +use Livewire\Attributes\Rule; use Livewire\Component; class Swarm extends Component { public Application $application; - public string $swarm_placement_constraints = ''; + #[Rule('required')] + public int $swarmReplicas; - protected $rules = [ - 'application.swarm_replicas' => 'required', - 'application.swarm_placement_constraints' => 'nullable', - 'application.settings.is_swarm_only_worker_nodes' => 'required', - ]; + #[Rule(['nullable'])] + public ?string $swarmPlacementConstraints = null; + + #[Rule('required')] + public bool $isSwarmOnlyWorkerNodes; public function mount() { - if ($this->application->swarm_placement_constraints) { - $this->swarm_placement_constraints = base64_decode($this->application->swarm_placement_constraints); + try { + $this->syncData(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function syncData(bool $toModel = false) + { + if ($toModel) { + $this->validate(); + $this->application->swarm_replicas = $this->swarmReplicas; + $this->application->swarm_placement_constraints = $this->swarmPlacementConstraints ? base64_encode($this->swarmPlacementConstraints) : null; + $this->application->settings->is_swarm_only_worker_nodes = $this->isSwarmOnlyWorkerNodes; + $this->application->save(); + $this->application->settings->save(); + } else { + $this->swarmReplicas = $this->application->swarm_replicas; + if ($this->application->swarm_placement_constraints) { + $this->swarmPlacementConstraints = base64_decode($this->application->swarm_placement_constraints); + } else { + $this->swarmPlacementConstraints = null; + } + $this->isSwarmOnlyWorkerNodes = $this->application->settings->is_swarm_only_worker_nodes; } } public function instantSave() { try { - $this->validate(); - $this->application->settings->save(); + $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); @@ -38,14 +61,7 @@ class Swarm extends Component public function submit() { try { - $this->validate(); - if ($this->swarm_placement_constraints) { - $this->application->swarm_placement_constraints = base64_encode($this->swarm_placement_constraints); - } else { - $this->application->swarm_placement_constraints = null; - } - $this->application->save(); - + $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { return handleError($e, $this); diff --git a/resources/views/livewire/project/application/swarm.blade.php b/resources/views/livewire/project/application/swarm.blade.php index 2954c9e68..e733dbd07 100644 --- a/resources/views/livewire/project/application/swarm.blade.php +++ b/resources/views/livewire/project/application/swarm.blade.php @@ -6,15 +6,13 @@ Save - {{--
Advanced Swarm Configuration
--}}
- + + id="isSwarmOnlyWorkerNodes" label="Only Start on Worker nodes" />
- From e30dcf11013c2a99e432293435e15d2cdc7ad097 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 11:32:03 +0100 Subject: [PATCH 02/13] refactor application preview livewire --- .../Project/Application/Preview/Form.php | 79 ++++++++++--------- .../application/preview/form.blade.php | 8 +- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/app/Livewire/Project/Application/Preview/Form.php b/app/Livewire/Project/Application/Preview/Form.php index 73b423f90..79b3276a1 100644 --- a/app/Livewire/Project/Application/Preview/Form.php +++ b/app/Livewire/Project/Application/Preview/Form.php @@ -3,6 +3,7 @@ namespace App\Livewire\Project\Application\Preview; use App\Models\Application; +use Livewire\Attributes\Rule; use Livewire\Component; use Spatie\Url\Url; @@ -10,49 +11,53 @@ class Form extends Component { public Application $application; - public string $preview_url_template; - - protected $rules = [ - 'application.preview_url_template' => 'required', - ]; - - protected $validationAttributes = [ - 'application.preview_url_template' => 'preview url template', - ]; - - public function resetToDefault() - { - $this->application->preview_url_template = '{{pr_id}}.{{domain}}'; - $this->preview_url_template = $this->application->preview_url_template; - $this->application->save(); - $this->generate_real_url(); - } - - public function generate_real_url() - { - if (data_get($this->application, 'fqdn')) { - try { - $firstFqdn = str($this->application->fqdn)->before(','); - $url = Url::fromString($firstFqdn); - $host = $url->getHost(); - $this->preview_url_template = str($this->application->preview_url_template)->replace('{{domain}}', $host); - } catch (\Exception) { - $this->dispatch('error', 'Invalid FQDN.'); - } - } - } + #[Rule('required')] + public string $previewUrlTemplate; public function mount() { - $this->generate_real_url(); + try { + $this->previewUrlTemplate = $this->application->preview_url_template; + $this->generateRealUrl(); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function submit() { - $this->validate(); - $this->application->preview_url_template = str_replace(' ', '', $this->application->preview_url_template); - $this->application->save(); - $this->dispatch('success', 'Preview url template updated.'); - $this->generate_real_url(); + try { + $this->resetErrorBag(); + $this->validate(); + $this->application->preview_url_template = str_replace(' ', '', $this->previewUrlTemplate); + $this->application->save(); + $this->dispatch('success', 'Preview url template updated.'); + $this->generateRealUrl(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function resetToDefault() + { + try { + $this->application->preview_url_template = '{{pr_id}}.{{domain}}'; + $this->previewUrlTemplate = $this->application->preview_url_template; + $this->application->save(); + $this->generateRealUrl(); + $this->dispatch('success', 'Preview url template updated.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function generateRealUrl() + { + if (data_get($this->application, 'fqdn')) { + $firstFqdn = str($this->application->fqdn)->before(','); + $url = Url::fromString($firstFqdn); + $host = $url->getHost(); + $this->previewUrlTemplate = str($this->application->preview_url_template)->replace('{{domain}}', $host); + } } } diff --git a/resources/views/livewire/project/application/preview/form.blade.php b/resources/views/livewire/project/application/preview/form.blade.php index 62210a99d..fda54e31f 100644 --- a/resources/views/livewire/project/application/preview/form.blade.php +++ b/resources/views/livewire/project/application/preview/form.blade.php @@ -2,14 +2,14 @@

Preview Deployments

Save - Reset template to default + Reset template to default
Preview Deployments based on pull requests are here.
- - @if ($preview_url_template) -
Domain Preview: {{ $preview_url_template }}
+ @if ($previewUrlTemplate) +
Domain Preview: {{ $previewUrlTemplate }}
@endif
From c11dfdee1f716bce318b86f26ed67d43ea387ab7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 11:53:32 +0100 Subject: [PATCH 03/13] refactor create scheduled backup livewire --- .../Database/CreateScheduledBackup.php | 49 ++++++++++--------- .../create-scheduled-backup.blade.php | 10 ++-- .../livewire/project/service/index.blade.php | 2 +- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/app/Livewire/Project/Database/CreateScheduledBackup.php b/app/Livewire/Project/Database/CreateScheduledBackup.php index 52bced44f..d26348f5f 100644 --- a/app/Livewire/Project/Database/CreateScheduledBackup.php +++ b/app/Livewire/Project/Database/CreateScheduledBackup.php @@ -4,44 +4,45 @@ namespace App\Livewire\Project\Database; use App\Models\ScheduledDatabaseBackup; use Illuminate\Support\Collection; +use Livewire\Attributes\Locked; +use Livewire\Attributes\Rule; use Livewire\Component; class CreateScheduledBackup extends Component { - public $database; - + #[Rule(['required', 'string'])] public $frequency; + #[Rule(['required', 'boolean'])] + public bool $saveToS3 = false; + + #[Locked] + public $database; + public bool $enabled = true; - public bool $save_s3 = false; + #[Rule(['required', 'integer'])] + public int $s3StorageId; - public $s3_storage_id; - - public Collection $s3s; - - protected $rules = [ - 'frequency' => 'required|string', - 'save_s3' => 'required|boolean', - ]; - - protected $validationAttributes = [ - 'frequency' => 'Backup Frequency', - 'save_s3' => 'Save to S3', - ]; + public Collection $definedS3s; public function mount() { - $this->s3s = currentTeam()->s3s; - if ($this->s3s->count() > 0) { - $this->s3_storage_id = $this->s3s->first()->id; + try { + $this->definedS3s = currentTeam()->s3s; + if ($this->definedS3s->count() > 0) { + $this->s3StorageId = $this->definedS3s->first()->id; + } + } catch (\Throwable $e) { + return handleError($e, $this); } } - public function submit(): void + public function submit() { try { $this->validate(); + $isValid = validate_cron_expression($this->frequency); if (! $isValid) { $this->dispatch('error', 'Invalid Cron / Human expression.'); @@ -51,8 +52,8 @@ class CreateScheduledBackup extends Component $payload = [ 'enabled' => true, 'frequency' => $this->frequency, - 'save_s3' => $this->save_s3, - 's3_storage_id' => $this->s3_storage_id, + 'save_s3' => $this->saveToS3, + 's3_storage_id' => $this->s3StorageId, 'database_id' => $this->database->id, 'database_type' => $this->database->getMorphClass(), 'team_id' => currentTeam()->id, @@ -72,10 +73,10 @@ class CreateScheduledBackup extends Component $this->dispatch('refreshScheduledBackups'); } } catch (\Throwable $e) { - handleError($e, $this); + return handleError($e, $this); } finally { $this->frequency = ''; - $this->save_s3 = true; + $this->saveToS3 = true; } } } diff --git a/resources/views/livewire/project/database/create-scheduled-backup.blade.php b/resources/views/livewire/project/database/create-scheduled-backup.blade.php index 492bb9f27..ee2f3e121 100644 --- a/resources/views/livewire/project/database/create-scheduled-backup.blade.php +++ b/resources/views/livewire/project/database/create-scheduled-backup.blade.php @@ -2,13 +2,13 @@ - @if ($s3s->count() === 0) + @if ($definedS3s->count() === 0)
No validated S3 Storages found.
@else - - @if ($save_s3) - - @foreach ($s3s as $s3) + + @if ($saveToS3) + + @foreach ($definedS3s as $s3) @endforeach diff --git a/resources/views/livewire/project/service/index.blade.php b/resources/views/livewire/project/service/index.blade.php index 5fcfb6b29..fb3ed5636 100644 --- a/resources/views/livewire/project/service/index.blade.php +++ b/resources/views/livewire/project/service/index.blade.php @@ -38,7 +38,7 @@

Scheduled Backups

- +
From 2cbac34877a223932a50ce7d4699dfd65c431ffb Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 12:21:31 +0100 Subject: [PATCH 04/13] refactor initscripts view --- app/Livewire/Project/Database/InitScript.php | 38 +++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/app/Livewire/Project/Database/InitScript.php b/app/Livewire/Project/Database/InitScript.php index 336762981..6bc6904d7 100644 --- a/app/Livewire/Project/Database/InitScript.php +++ b/app/Livewire/Project/Database/InitScript.php @@ -3,39 +3,39 @@ namespace App\Livewire\Project\Database; use Exception; +use Livewire\Attributes\Locked; +use Livewire\Attributes\Rule; use Livewire\Component; class InitScript extends Component { + #[Locked] public array $script; + #[Locked] public int $index; - public ?string $filename; + #[Rule(['nullable', 'string'])] + public ?string $filename = null; - public ?string $content; - - protected $rules = [ - 'filename' => 'required|string', - 'content' => 'required|string', - ]; - - protected $validationAttributes = [ - 'filename' => 'Filename', - 'content' => 'Content', - ]; + #[Rule(['nullable', 'string'])] + public ?string $content = null; public function mount() { - $this->index = data_get($this->script, 'index'); - $this->filename = data_get($this->script, 'filename'); - $this->content = data_get($this->script, 'content'); + try { + $this->index = data_get($this->script, 'index'); + $this->filename = data_get($this->script, 'filename'); + $this->content = data_get($this->script, 'content'); + } catch (Exception $e) { + return handleError($e, $this); + } } public function submit() { - $this->validate(); try { + $this->validate(); $this->script['index'] = $this->index; $this->script['content'] = $this->content; $this->script['filename'] = $this->filename; @@ -47,6 +47,10 @@ class InitScript extends Component public function delete() { - $this->dispatch('delete_init_script', $this->script); + try { + $this->dispatch('delete_init_script', $this->script); + } catch (Exception $e) { + return handleError($e, $this); + } } } From 34c7aa122c919eade75010b109f52e5cdd299cfc Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 12:40:10 +0100 Subject: [PATCH 05/13] refactor backup edit view --- app/Livewire/Project/Database/BackupEdit.php | 106 +++++++++++------- .../project/database/backup-edit.blade.php | 24 ++-- 2 files changed, 77 insertions(+), 53 deletions(-) diff --git a/app/Livewire/Project/Database/BackupEdit.php b/app/Livewire/Project/Database/BackupEdit.php index 9b82c4b11..1e70eaba9 100644 --- a/app/Livewire/Project/Database/BackupEdit.php +++ b/app/Livewire/Project/Database/BackupEdit.php @@ -4,56 +4,87 @@ namespace App\Livewire\Project\Database; use App\Models\InstanceSettings; use App\Models\ScheduledDatabaseBackup; +use Exception; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; +use Livewire\Attributes\Locked; +use Livewire\Attributes\Rule; use Livewire\Component; use Spatie\Url\Url; class BackupEdit extends Component { - public ?ScheduledDatabaseBackup $backup; + public ScheduledDatabaseBackup $backup; + #[Locked] public $s3s; + #[Locked] + public $parameters; + + #[Rule(['required', 'boolean'])] public bool $delete_associated_backups_locally = false; + #[Rule(['required', 'boolean'])] public bool $delete_associated_backups_s3 = false; + #[Rule(['required', 'boolean'])] public bool $delete_associated_backups_sftp = false; + #[Rule(['nullable', 'string'])] public ?string $status = null; - public array $parameters; + #[Rule(['required', 'boolean'])] + public bool $backupEnabled = false; - protected $rules = [ - 'backup.enabled' => 'required|boolean', - 'backup.frequency' => 'required|string', - 'backup.number_of_backups_locally' => 'required|integer|min:1', - 'backup.save_s3' => 'required|boolean', - 'backup.s3_storage_id' => 'nullable|integer', - 'backup.databases_to_backup' => 'nullable', - 'backup.dump_all' => 'required|boolean', - ]; + #[Rule(['required', 'string'])] + public string $frequency = ''; - protected $validationAttributes = [ - 'backup.enabled' => 'Enabled', - 'backup.frequency' => 'Frequency', - 'backup.number_of_backups_locally' => 'Number of Backups Locally', - 'backup.save_s3' => 'Save to S3', - 'backup.s3_storage_id' => 'S3 Storage', - 'backup.databases_to_backup' => 'Databases to Backup', - 'backup.dump_all' => 'Backup All Databases', - ]; + #[Rule(['required', 'integer', 'min:1'])] + public int $numberOfBackupsLocally = 1; - protected $messages = [ - 'backup.s3_storage_id' => 'Select a S3 Storage', - ]; + #[Rule(['required', 'boolean'])] + public bool $saveS3 = false; + + #[Rule(['required', 'integer'])] + public int $s3StorageId = 1; + + #[Rule(['nullable', 'string'])] + public ?string $databasesToBackup = null; + + #[Rule(['required', 'boolean'])] + public bool $dumpAll = false; public function mount() { - $this->parameters = get_route_parameters(); - if (is_null(data_get($this->backup, 's3_storage_id'))) { - data_set($this->backup, 's3_storage_id', 'default'); + try { + $this->parameters = get_route_parameters(); + $this->syncData(); + } catch (Exception $e) { + return handleError($e, $this); + } + } + + public function syncData(bool $toModel = false) + { + if ($toModel) { + $this->customValidate(); + $this->backup->enabled = $this->backupEnabled; + $this->backup->frequency = $this->frequency; + $this->backup->number_of_backups_locally = $this->numberOfBackupsLocally; + $this->backup->save_s3 = $this->saveS3; + $this->backup->s3_storage_id = $this->s3StorageId; + $this->backup->databases_to_backup = $this->databasesToBackup; + $this->backup->dump_all = $this->dumpAll; + $this->backup->save(); + } else { + $this->backupEnabled = $this->backup->enabled; + $this->frequency = $this->backup->frequency; + $this->numberOfBackupsLocally = $this->backup->number_of_backups_locally; + $this->saveS3 = $this->backup->save_s3; + $this->s3StorageId = $this->backup->s3_storage_id; + $this->databasesToBackup = $this->backup->databases_to_backup; + $this->dumpAll = $this->backup->dump_all; } } @@ -96,16 +127,14 @@ class BackupEdit extends Component public function instantSave() { try { - $this->custom_validate(); - $this->backup->save(); - $this->backup->refresh(); + $this->syncData(true); $this->dispatch('success', 'Backup updated successfully.'); } catch (\Throwable $e) { $this->dispatch('error', $e->getMessage()); } } - private function custom_validate() + private function customValidate() { if (! is_numeric($this->backup->s3_storage_id)) { $this->backup->s3_storage_id = null; @@ -120,19 +149,14 @@ class BackupEdit extends Component public function submit() { try { - $this->custom_validate(); - if ($this->backup->databases_to_backup === '' || $this->backup->databases_to_backup === null) { - $this->backup->databases_to_backup = null; - } - $this->backup->save(); - $this->backup->refresh(); - $this->dispatch('success', 'Backup updated successfully'); + $this->syncData(true); + $this->dispatch('success', 'Backup updated successfully.'); } catch (\Throwable $e) { $this->dispatch('error', $e->getMessage()); } } - public function deleteAssociatedBackupsLocally() + private function deleteAssociatedBackupsLocally() { $executions = $this->backup->executions; $backupFolder = null; @@ -152,17 +176,17 @@ class BackupEdit extends Component $execution->delete(); } - if ($backupFolder) { + if (str($backupFolder)->isNotEmpty()) { $this->deleteEmptyBackupFolder($backupFolder, $server); } } - public function deleteAssociatedBackupsS3() + private function deleteAssociatedBackupsS3() { //Add function to delete backups from S3 } - public function deleteAssociatedBackupsSftp() + private function deleteAssociatedBackupsSftp() { //Add function to delete backups from SFTP } diff --git a/resources/views/livewire/project/database/backup-edit.blade.php b/resources/views/livewire/project/database/backup-edit.blade.php index c3288a4f9..b91b35802 100644 --- a/resources/views/livewire/project/database/backup-edit.blade.php +++ b/resources/views/livewire/project/database/backup-edit.blade.php @@ -19,12 +19,12 @@ @endif
- - + +
@if ($backup->save_s3)
- + @foreach ($s3s as $s3) @@ -37,40 +37,40 @@
@if ($backup->database_type === 'App\Models\StandalonePostgresql' && $backup->database_id !== 0)
- +
@if (!$backup->dump_all) + id="databasesToBackup" /> @endif @elseif($backup->database_type === 'App\Models\StandaloneMongodb') + id="databasesToBackup" /> @elseif($backup->database_type === 'App\Models\StandaloneMysql')
- +
@if (!$backup->dump_all) + id="databasesToBackup" /> @endif @elseif($backup->database_type === 'App\Models\StandaloneMariadb')
- +
@if (!$backup->dump_all) + id="databasesToBackup" /> @endif @endif
- - + +
From 165d35959e6c6c8f96ec5dbc947a971d6ed8ec02 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 12:53:01 +0100 Subject: [PATCH 06/13] fix: logdrains validation --- app/Livewire/Server/LogDrains.php | 40 ++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index fb8ef329f..67a6962dc 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -52,7 +52,7 @@ class LogDrains extends Component public function syncData(bool $toModel = false) { if ($toModel) { - $this->validate(); + $this->customValidation(); $this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled; $this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled; $this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled; @@ -79,6 +79,44 @@ class LogDrains extends Component } } + public function customValidation() + { + if ($this->isLogDrainNewRelicEnabled) { + try { + $this->validate([ + 'logDrainNewRelicLicenseKey' => ['required'], + 'logDrainNewRelicBaseUri' => ['required', 'url'], + ]); + } catch (\Throwable $e) { + $this->isLogDrainNewRelicEnabled = false; + + throw $e; + } + } elseif ($this->isLogDrainAxiomEnabled) { + try { + $this->validate([ + 'logDrainAxiomDatasetName' => ['required'], + 'logDrainAxiomApiKey' => ['required'], + ]); + } catch (\Throwable $e) { + $this->isLogDrainAxiomEnabled = false; + + throw $e; + } + } elseif ($this->isLogDrainCustomEnabled) { + try { + $this->validate([ + 'logDrainCustomConfig' => ['required'], + 'logDrainCustomConfigParser' => ['string', 'nullable'], + ]); + } catch (\Throwable $e) { + $this->isLogDrainCustomEnabled = false; + + throw $e; + } + } + } + public function instantSave() { try { From 1ab459a09b5a78e3f01a722abc1489b67cd13347 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 12:53:20 +0100 Subject: [PATCH 07/13] fix: reworded --- resources/views/livewire/server/log-drains.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/server/log-drains.blade.php b/resources/views/livewire/server/log-drains.blade.php index 19c33ef5d..a16993e96 100644 --- a/resources/views/livewire/server/log-drains.blade.php +++ b/resources/views/livewire/server/log-drains.blade.php @@ -11,7 +11,7 @@

Log Drains

-
Sends service logs to 3rd party tools.
+
Sends service logs to 3rd party tools.
From 7fb1a1fc759ab0ba3b171c80839df3443cb7bc4e Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 14:18:16 +0100 Subject: [PATCH 08/13] fix: use Auth(), add new db proxy stop event refactor clickhouse view --- app/Actions/Database/StopDatabaseProxy.php | 8 +- app/Events/DatabaseProxyStopped.php | 35 +++++ app/Events/DatabaseStatusChanged.php | 8 +- app/Events/ServiceStatusChanged.php | 3 +- app/Http/Controllers/Controller.php | 6 +- app/Livewire/Admin/Index.php | 8 +- app/Livewire/NavbarDeleteTeam.php | 3 +- app/Livewire/Profile/Index.php | 9 +- .../Project/Database/Clickhouse/General.php | 142 ++++++++++++------ app/Livewire/Project/Database/Heading.php | 3 +- app/Livewire/Project/Database/Import.php | 3 +- .../Project/Service/Configuration.php | 3 +- app/Livewire/Project/Service/Navbar.php | 3 +- app/Livewire/Subscription/PricingPlans.php | 7 +- app/Livewire/Team/Index.php | 3 +- app/Models/User.php | 17 ++- bootstrap/helpers/shared.php | 15 +- .../views/components/forms/checkbox.blade.php | 2 +- .../database/clickhouse/general.blade.php | 65 ++++---- .../database/dragonfly/general.blade.php | 3 - .../views/livewire/team/member.blade.php | 10 +- routes/channels.php | 3 +- 22 files changed, 236 insertions(+), 123 deletions(-) create mode 100644 app/Events/DatabaseProxyStopped.php diff --git a/app/Actions/Database/StopDatabaseProxy.php b/app/Actions/Database/StopDatabaseProxy.php index 9e9a62170..0a166d24a 100644 --- a/app/Actions/Database/StopDatabaseProxy.php +++ b/app/Actions/Database/StopDatabaseProxy.php @@ -2,7 +2,7 @@ namespace App\Actions\Database; -use App\Events\DatabaseStatusChanged; +use App\Events\DatabaseProxyStopped; use App\Models\ServiceDatabase; use App\Models\StandaloneClickhouse; use App\Models\StandaloneDragonfly; @@ -27,7 +27,11 @@ class StopDatabaseProxy $server = data_get($database, 'service.server'); } instant_remote_process(["docker rm -f {$uuid}-proxy"], $server); + + $database->is_public = false; $database->save(); - DatabaseStatusChanged::dispatch(); + + DatabaseProxyStopped::dispatch(); + } } diff --git a/app/Events/DatabaseProxyStopped.php b/app/Events/DatabaseProxyStopped.php new file mode 100644 index 000000000..b457dc6a0 --- /dev/null +++ b/app/Events/DatabaseProxyStopped.php @@ -0,0 +1,35 @@ +currentTeam()->id ?? null; + } + if (is_null($teamId)) { + throw new \Exception('Team id is null'); + } + $this->teamId = $teamId; + } + + public function broadcastOn(): array + { + return [ + new PrivateChannel("team.{$this->teamId}"), + ]; + } +} diff --git a/app/Events/DatabaseStatusChanged.php b/app/Events/DatabaseStatusChanged.php index a94bc2272..913b21bc2 100644 --- a/app/Events/DatabaseStatusChanged.php +++ b/app/Events/DatabaseStatusChanged.php @@ -7,27 +7,29 @@ use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Auth; class DatabaseStatusChanged implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; - public ?string $userId = null; + public $userId = null; public function __construct($userId = null) { if (is_null($userId)) { - $userId = auth()->user()->id ?? null; + $userId = Auth::id() ?? null; } if (is_null($userId)) { return false; } + $this->userId = $userId; } public function broadcastOn(): ?array { - if ($this->userId) { + if (! is_null($this->userId)) { return [ new PrivateChannel("user.{$this->userId}"), ]; diff --git a/app/Events/ServiceStatusChanged.php b/app/Events/ServiceStatusChanged.php index a86a8b02d..3950022e1 100644 --- a/app/Events/ServiceStatusChanged.php +++ b/app/Events/ServiceStatusChanged.php @@ -7,6 +7,7 @@ use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Auth; class ServiceStatusChanged implements ShouldBroadcast { @@ -17,7 +18,7 @@ class ServiceStatusChanged implements ShouldBroadcast public function __construct($userId = null) { if (is_null($userId)) { - $userId = auth()->user()->id ?? null; + $userId = Auth::id() ?? null; } if (is_null($userId)) { return false; diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 581118e16..718ba5ed4 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -131,7 +131,7 @@ class Controller extends BaseController } $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); $invitation->delete(); - if (auth()->user()?->id !== $user->id) { + if (Auth::id() !== $user->id) { return redirect()->route('login'); } refreshSession($invitation->team); @@ -146,10 +146,10 @@ class Controller extends BaseController { $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); $user = User::whereEmail($invitation->email)->firstOrFail(); - if (is_null(auth()->user())) { + if (is_null(Auth::user())) { return redirect()->route('login'); } - if (auth()->user()->id !== $user->id) { + if (Auth::id() !== $user->id) { abort(401); } $invitation->delete(); diff --git a/app/Livewire/Admin/Index.php b/app/Livewire/Admin/Index.php index 7078a21e9..2579c3db2 100644 --- a/app/Livewire/Admin/Index.php +++ b/app/Livewire/Admin/Index.php @@ -3,7 +3,9 @@ namespace App\Livewire\Admin; use App\Models\User; +use Illuminate\Container\Attributes\Auth as AttributesAuth; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; use Livewire\Component; @@ -23,7 +25,7 @@ class Index extends Component return redirect()->route('dashboard'); } - if (auth()->user()->id !== 0) { + if (Auth::id() !== 0) { return redirect()->route('dashboard'); } $this->getSubscribers(); @@ -51,13 +53,13 @@ class Index extends Component public function switchUser(int $user_id) { - if (auth()->user()->id !== 0) { + if (AttributesAuth::id() !== 0) { return redirect()->route('dashboard'); } $user = User::find($user_id); $team_to_switch_to = $user->teams->first(); Cache::forget("team:{$user->id}"); - auth()->login($user); + Auth::login($user); refreshSession($team_to_switch_to); return redirect(request()->header('Referer')); diff --git a/app/Livewire/NavbarDeleteTeam.php b/app/Livewire/NavbarDeleteTeam.php index 10ba0c86a..cc5d78f60 100644 --- a/app/Livewire/NavbarDeleteTeam.php +++ b/app/Livewire/NavbarDeleteTeam.php @@ -3,6 +3,7 @@ namespace App\Livewire; use App\Models\InstanceSettings; +use Illuminate\Container\Attributes\Auth as AttributesAuth; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; @@ -31,7 +32,7 @@ class NavbarDeleteTeam extends Component $currentTeam->delete(); $currentTeam->members->each(function ($user) use ($currentTeam) { - if ($user->id === auth()->user()->id) { + if ($user->id === AttributesAuth::id()) { return; } $user->teams()->detach($currentTeam); diff --git a/app/Livewire/Profile/Index.php b/app/Livewire/Profile/Index.php index 483f68cf8..53314cd5c 100644 --- a/app/Livewire/Profile/Index.php +++ b/app/Livewire/Profile/Index.php @@ -2,6 +2,7 @@ namespace App\Livewire\Profile; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\Rules\Password; use Livewire\Attributes\Validate; @@ -24,9 +25,9 @@ class Index extends Component public function mount() { - $this->userId = auth()->user()->id; - $this->name = auth()->user()->name; - $this->email = auth()->user()->email; + $this->userId = Auth::id(); + $this->name = Auth::user()->name; + $this->email = Auth::user()->email; } public function submit() @@ -35,7 +36,7 @@ class Index extends Component $this->validate([ 'name' => 'required', ]); - auth()->user()->update([ + Auth::user()->update([ 'name' => $this->name, ]); diff --git a/app/Livewire/Project/Database/Clickhouse/General.php b/app/Livewire/Project/Database/Clickhouse/General.php index 7a6446815..46688adca 100644 --- a/app/Livewire/Project/Database/Clickhouse/General.php +++ b/app/Livewire/Project/Database/Clickhouse/General.php @@ -7,6 +7,8 @@ use App\Actions\Database\StopDatabaseProxy; use App\Models\Server; use App\Models\StandaloneClickhouse; use Exception; +use Illuminate\Support\Facades\Auth; +use Livewire\Attributes\Rule; use Livewire\Component; class General extends Component @@ -15,54 +17,106 @@ class General extends Component public StandaloneClickhouse $database; - public ?string $db_url = null; + #[Rule(['required', 'string'])] + public string $name; - public ?string $db_url_public = null; + #[Rule(['nullable', 'string'])] + public ?string $description = null; - protected $listeners = ['refresh']; + #[Rule(['required', 'string'])] + public string $clickhouseAdminUser; - protected $rules = [ - 'database.name' => 'required', - 'database.description' => 'nullable', - 'database.clickhouse_admin_user' => 'required', - 'database.clickhouse_admin_password' => 'required', - 'database.image' => 'required', - 'database.ports_mappings' => 'nullable', - 'database.is_public' => 'nullable|boolean', - 'database.public_port' => 'nullable|integer', - 'database.is_log_drain_enabled' => 'nullable|boolean', - 'database.custom_docker_run_options' => 'nullable', - ]; + #[Rule(['required', 'string'])] + public string $clickhouseAdminPassword; - protected $validationAttributes = [ - 'database.name' => 'Name', - 'database.description' => 'Description', - 'database.clickhouse_admin_user' => 'Postgres User', - 'database.clickhouse_admin_password' => 'Postgres Password', - 'database.image' => 'Image', - 'database.ports_mappings' => 'Port Mapping', - 'database.is_public' => 'Is Public', - 'database.public_port' => 'Public Port', - 'database.custom_docker_run_options' => 'Custom Docker Run Options', - ]; + #[Rule(['required', 'string'])] + public string $image; + + #[Rule(['nullable', 'string'])] + public ?string $portsMappings = null; + + #[Rule(['nullable', 'boolean'])] + public ?bool $isPublic = null; + + #[Rule(['nullable', 'integer'])] + public ?int $publicPort = null; + + #[Rule(['nullable', 'string'])] + public ?string $customDockerRunOptions = null; + + #[Rule(['nullable', 'string'])] + public ?string $dbUrl = null; + + #[Rule(['nullable', 'string'])] + public ?string $dbUrlPublic = null; + + #[Rule(['nullable', 'boolean'])] + public bool $isLogDrainEnabled = false; + + public function getListeners() + { + $teamId = Auth::user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped', + ]; + } public function mount() { - $this->db_url = $this->database->internal_db_url; - $this->db_url_public = $this->database->external_db_url; - $this->server = data_get($this->database, 'destination.server'); + try { + $this->syncData(); + $this->server = data_get($this->database, 'destination.server'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function syncData(bool $toModel = false) + { + if ($toModel) { + $this->validate(); + $this->database->name = $this->name; + $this->database->description = $this->description; + $this->database->clickhouse_admin_user = $this->clickhouseAdminUser; + $this->database->clickhouse_admin_password = $this->clickhouseAdminPassword; + $this->database->image = $this->image; + $this->database->ports_mappings = $this->portsMappings; + $this->database->is_public = $this->isPublic; + $this->database->public_port = $this->publicPort; + $this->database->custom_docker_run_options = $this->customDockerRunOptions; + $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; + $this->database->save(); + + $this->dbUrl = $this->database->internal_db_url; + $this->dbUrlPublic = $this->database->external_db_url; + } else { + $this->name = $this->database->name; + $this->description = $this->database->description; + $this->clickhouseAdminUser = $this->database->clickhouse_admin_user; + $this->clickhouseAdminPassword = $this->database->clickhouse_admin_password; + $this->image = $this->database->image; + $this->portsMappings = $this->database->ports_mappings; + $this->isPublic = $this->database->is_public; + $this->publicPort = $this->database->public_port; + $this->customDockerRunOptions = $this->database->custom_docker_run_options; + $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; + $this->dbUrl = $this->database->internal_db_url; + $this->dbUrlPublic = $this->database->external_db_url; + } } public function instantSaveAdvanced() { try { if (! $this->server->isLogDrainEnabled()) { - $this->database->is_log_drain_enabled = false; + $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } - $this->database->save(); + $this->syncData(true); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { @@ -73,16 +127,16 @@ class General extends Component public function instantSave() { try { - if ($this->database->is_public && ! $this->database->public_port) { + if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); - $this->database->is_public = false; + $this->isPublic = false; return; } - if ($this->database->is_public) { + if ($this->isPublic) { if (! str($this->database->status)->startsWith('running')) { $this->dispatch('error', 'Database must be started to be publicly accessible.'); - $this->database->is_public = false; + $this->isPublic = false; return; } @@ -92,28 +146,28 @@ class General extends Component StopDatabaseProxy::run($this->database); $this->dispatch('success', 'Database is no longer publicly accessible.'); } - $this->db_url_public = $this->database->external_db_url; - $this->database->save(); + $this->dbUrlPublic = $this->database->external_db_url; + $this->syncData(true); } catch (\Throwable $e) { - $this->database->is_public = ! $this->database->is_public; + $this->isPublic = ! $this->isPublic; + $this->syncData(true); return handleError($e, $this); } } - public function refresh(): void + public function databaseProxyStopped() { - $this->database->refresh(); + $this->syncData(); } public function submit() { try { - if (str($this->database->public_port)->isEmpty()) { - $this->database->public_port = null; + if (str($this->publicPort)->isEmpty()) { + $this->publicPort = null; } - $this->validate(); - $this->database->save(); + $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); diff --git a/app/Livewire/Project/Database/Heading.php b/app/Livewire/Project/Database/Heading.php index 49884ff9a..fc0febd02 100644 --- a/app/Livewire/Project/Database/Heading.php +++ b/app/Livewire/Project/Database/Heading.php @@ -6,6 +6,7 @@ use App\Actions\Database\RestartDatabase; use App\Actions\Database\StartDatabase; use App\Actions\Database\StopDatabase; use App\Actions\Docker\GetContainersStatus; +use Illuminate\Support\Facades\Auth; use Livewire\Component; class Heading extends Component @@ -18,7 +19,7 @@ class Heading extends Component public function getListeners() { - $userId = auth()->user()->id; + $userId = Auth::id(); return [ "echo-private:user.{$userId},DatabaseStatusChanged" => 'activityFinished', diff --git a/app/Livewire/Project/Database/Import.php b/app/Livewire/Project/Database/Import.php index 663e7a6d7..062f454b1 100644 --- a/app/Livewire/Project/Database/Import.php +++ b/app/Livewire/Project/Database/Import.php @@ -3,6 +3,7 @@ namespace App\Livewire\Project\Database; use App\Models\Server; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; use Livewire\Component; @@ -46,7 +47,7 @@ class Import extends Component public function getListeners() { - $userId = auth()->user()->id; + $userId = Auth::id(); return [ "echo-private:user.{$userId},DatabaseStatusChanged" => '$refresh', diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php index a2e48fee7..319ead361 100644 --- a/app/Livewire/Project/Service/Configuration.php +++ b/app/Livewire/Project/Service/Configuration.php @@ -4,6 +4,7 @@ namespace App\Livewire\Project\Service; use App\Actions\Docker\GetContainersStatus; use App\Models\Service; +use Illuminate\Support\Facades\Auth; use Livewire\Component; class Configuration extends Component @@ -20,7 +21,7 @@ class Configuration extends Component public function getListeners() { - $userId = auth()->user()->id; + $userId = Auth::id(); return [ "echo-private:user.{$userId},ServiceStatusChanged" => 'check_status', diff --git a/app/Livewire/Project/Service/Navbar.php b/app/Livewire/Project/Service/Navbar.php index 67b575599..ee43dc911 100644 --- a/app/Livewire/Project/Service/Navbar.php +++ b/app/Livewire/Project/Service/Navbar.php @@ -7,6 +7,7 @@ use App\Actions\Service\StopService; use App\Actions\Shared\PullImage; use App\Events\ServiceStatusChanged; use App\Models\Service; +use Illuminate\Support\Facades\Auth; use Livewire\Component; use Spatie\Activitylog\Models\Activity; @@ -34,7 +35,7 @@ class Navbar extends Component public function getListeners() { - $userId = auth()->user()->id; + $userId = Auth::id(); return [ "echo-private:user.{$userId},ServiceStatusChanged" => 'serviceStarted', diff --git a/app/Livewire/Subscription/PricingPlans.php b/app/Livewire/Subscription/PricingPlans.php index 9186cc978..6b2d3fb36 100644 --- a/app/Livewire/Subscription/PricingPlans.php +++ b/app/Livewire/Subscription/PricingPlans.php @@ -2,6 +2,7 @@ namespace App\Livewire\Subscription; +use Illuminate\Support\Facades\Auth; use Livewire\Component; use Stripe\Checkout\Session; use Stripe\Stripe; @@ -26,7 +27,7 @@ class PricingPlans extends Component $payload = [ 'allow_promotion_codes' => true, 'billing_address_collection' => 'required', - 'client_reference_id' => auth()->user()->id.':'.currentTeam()->id, + 'client_reference_id' => Auth::id().':'.currentTeam()->id, 'line_items' => [[ 'price' => $priceId, 'adjustable_quantity' => [ @@ -43,7 +44,7 @@ class PricingPlans extends Component ], 'subscription_data' => [ 'metadata' => [ - 'user_id' => auth()->user()->id, + 'user_id' => Auth::id(), 'team_id' => currentTeam()->id, ], ], @@ -60,7 +61,7 @@ class PricingPlans extends Component 'name' => 'auto', ]; } else { - $payload['customer_email'] = auth()->user()->email; + $payload['customer_email'] = Auth::user()->email; } $session = Session::create($payload); diff --git a/app/Livewire/Team/Index.php b/app/Livewire/Team/Index.php index 45600dbfe..0972e7364 100644 --- a/app/Livewire/Team/Index.php +++ b/app/Livewire/Team/Index.php @@ -4,6 +4,7 @@ namespace App\Livewire\Team; use App\Models\Team; use App\Models\TeamInvitation; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Livewire\Component; @@ -55,7 +56,7 @@ class Index extends Component $currentTeam->delete(); $currentTeam->members->each(function ($user) use ($currentTeam) { - if ($user->id === auth()->user()->id) { + if ($user->id === Auth::id()) { return; } $user->teams()->detach($currentTeam); diff --git a/app/Models/User.php b/app/Models/User.php index ecc4ef6b6..25fb33d66 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -10,6 +10,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\URL; @@ -158,7 +159,7 @@ class User extends Authenticatable implements SendsEmail public function isAdminFromSession() { - if (auth()->user()->id === 0) { + if (Auth::id() === 0) { return true; } $teams = $this->teams()->get(); @@ -178,9 +179,9 @@ class User extends Authenticatable implements SendsEmail public function isInstanceAdmin() { - $found_root_team = auth()->user()->teams->filter(function ($team) { + $found_root_team = Auth::user()->teams->filter(function ($team) { if ($team->id == 0) { - if (! auth()->user()->isAdmin()) { + if (! Auth::user()->isAdmin()) { return false; } @@ -195,9 +196,9 @@ class User extends Authenticatable implements SendsEmail public function currentTeam() { - return Cache::remember('team:'.auth()->user()->id, 3600, function () { - if (is_null(data_get(session('currentTeam'), 'id')) && auth()->user()->teams->count() > 0) { - return auth()->user()->teams[0]; + return Cache::remember('team:'.Auth::id(), 3600, function () { + if (is_null(data_get(session('currentTeam'), 'id')) && Auth::user()->teams->count() > 0) { + return Auth::user()->teams[0]; } return Team::find(session('currentTeam')->id); @@ -206,7 +207,7 @@ class User extends Authenticatable implements SendsEmail public function otherTeams() { - return auth()->user()->teams->filter(function ($team) { + return Auth::user()->teams->filter(function ($team) { return $team->id != currentTeam()->id; }); } @@ -216,7 +217,7 @@ class User extends Authenticatable implements SendsEmail if (data_get($this, 'pivot')) { return $this->pivot->role; } - $user = auth()->user()->teams->where('id', currentTeam()->id)->first(); + $user = Auth::user()->teams->where('id', currentTeam()->id)->first(); return data_get($user, 'pivot.role'); } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index fb4ae3699..46dc5799b 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -35,6 +35,7 @@ use Illuminate\Mail\Message; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Process\Pool; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Http; @@ -100,12 +101,12 @@ function isInstanceAdmin() function currentTeam() { - return auth()?->user()?->currentTeam() ?? null; + return Auth::user()?->currentTeam() ?? null; } function showBoarding(): bool { - if (auth()->user()?->isMember()) { + if (Auth::user()->isMember()) { return false; } @@ -114,14 +115,14 @@ function showBoarding(): bool function refreshSession(?Team $team = null): void { if (! $team) { - if (auth()->user()?->currentTeam()) { - $team = Team::find(auth()->user()->currentTeam()->id); + if (Auth::user()->currentTeam()) { + $team = Team::find(Auth::user()->currentTeam()->id); } else { - $team = User::find(auth()->user()->id)->teams->first(); + $team = User::find(Auth::id())->teams->first(); } } - Cache::forget('team:'.auth()->user()->id); - Cache::remember('team:'.auth()->user()->id, 3600, function () use ($team) { + Cache::forget('team:'.Auth::id()); + Cache::remember('team:'.Auth::id(), 3600, function () use ($team) { return $team; }); session(['currentTeam' => $team]); diff --git a/resources/views/components/forms/checkbox.blade.php b/resources/views/components/forms/checkbox.blade.php index f5eb5778a..c8c4a499f 100644 --- a/resources/views/components/forms/checkbox.blade.php +++ b/resources/views/components/forms/checkbox.blade.php @@ -10,7 +10,7 @@ ])
$fullWidth, ])> @if (!$hideLabel) diff --git a/resources/views/livewire/project/database/clickhouse/general.blade.php b/resources/views/livewire/project/database/clickhouse/general.blade.php index f94d79ff4..087864ec5 100644 --- a/resources/views/livewire/project/database/clickhouse/general.blade.php +++ b/resources/views/livewire/project/database/clickhouse/general.blade.php @@ -7,68 +7,75 @@
- - - + +
@if ($database->started_at)
- - +
@else
Please verify these values. You can only modify them before the initial start. After that, you need to modify it in the database.
- - + +
@endif + id="customDockerRunOptions" label="Custom Docker Options" />

Network

-
- @if ($db_url_public) + type="password" readonly wire:model="dbUrl" /> + @if ($dbUrlPublic) + type="password" readonly wire:model="dbUrlPublic" /> + @else + @endif
-

Proxy

-
- - - Proxy Logs - - - - Proxy Logs - - +
+
+

Proxy

+ @if ($isPublic) + + Proxy Logs + + + + Logs + + @endif +
+
+

Advanced

-
+
+ instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
diff --git a/resources/views/livewire/project/database/dragonfly/general.blade.php b/resources/views/livewire/project/database/dragonfly/general.blade.php index e1ce5ddaf..e4cfb6ca3 100644 --- a/resources/views/livewire/project/database/dragonfly/general.blade.php +++ b/resources/views/livewire/project/database/dragonfly/general.blade.php @@ -47,9 +47,6 @@
- {{-- --}}

Advanced

$member->id == auth()->user()->id, + 'dark:bg-coolgray-100 bg-neutral-200' => $member->id == Auth::id(), ])> {{ $member->name }} @@ -12,9 +12,9 @@ {{ data_get($member, 'pivot.role') }} - @if (auth()->user()->isAdminFromSession()) - @if ($member->id !== auth()->user()->id) - @if (auth()->user()->isOwner()) + @if (Auth::user()->isAdminFromSession()) + @if ($member->id !== Auth::id()) + @if (Auth::user()->isOwner()) @if (data_get($member, 'pivot.role') === 'owner') To Admin To Member @@ -30,7 +30,7 @@ To Admin Remove @endif - @elseif (auth()->user()->isAdmin()) + @elseif (Auth::user()->isAdmin()) @if (data_get($member, 'pivot.role') === 'admin') To Member Remove diff --git a/routes/channels.php b/routes/channels.php index 2b9f33728..f75c30d0f 100644 --- a/routes/channels.php +++ b/routes/channels.php @@ -12,6 +12,7 @@ */ use App\Models\User; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Broadcast; Broadcast::channel('team.{teamId}', function (User $user, int $teamId) { @@ -23,7 +24,7 @@ Broadcast::channel('team.{teamId}', function (User $user, int $teamId) { }); Broadcast::channel('user.{userId}', function (User $user) { - if ($user->id === auth()->user()->id) { + if ($user->id === Auth::id()) { return true; } From ffb1e102482a50bc30db88cd41af679c4c0d50b0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 14:22:42 +0100 Subject: [PATCH 09/13] fix dragonfly view --- .../Project/Database/Dragonfly/General.php | 195 +++++++++++------- .../database/dragonfly/general.blade.php | 62 +++--- 2 files changed, 157 insertions(+), 100 deletions(-) diff --git a/app/Livewire/Project/Database/Dragonfly/General.php b/app/Livewire/Project/Database/Dragonfly/General.php index 394ba6c9a..5037f6283 100644 --- a/app/Livewire/Project/Database/Dragonfly/General.php +++ b/app/Livewire/Project/Database/Dragonfly/General.php @@ -7,60 +7,111 @@ use App\Actions\Database\StopDatabaseProxy; use App\Models\Server; use App\Models\StandaloneDragonfly; use Exception; +use Illuminate\Support\Facades\Auth; +use Livewire\Attributes\Rule; use Livewire\Component; class General extends Component { - protected $listeners = ['refresh']; - public Server $server; public StandaloneDragonfly $database; - public ?string $db_url = null; + #[Rule(['required', 'string'])] + public string $name; - public ?string $db_url_public = null; + #[Rule(['nullable', 'string'])] + public ?string $description = null; - protected $rules = [ - 'database.name' => 'required', - 'database.description' => 'nullable', - 'database.dragonfly_password' => 'required', - 'database.image' => 'required', - 'database.ports_mappings' => 'nullable', - 'database.is_public' => 'nullable|boolean', - 'database.public_port' => 'nullable|integer', - 'database.is_log_drain_enabled' => 'nullable|boolean', - 'database.custom_docker_run_options' => 'nullable', - ]; + #[Rule(['required', 'string'])] + public string $dragonflyPassword; - protected $validationAttributes = [ - 'database.name' => 'Name', - 'database.description' => 'Description', - 'database.dragonfly_password' => 'Redis Password', - 'database.image' => 'Image', - 'database.ports_mappings' => 'Port Mapping', - 'database.is_public' => 'Is Public', - 'database.public_port' => 'Public Port', - 'database.custom_docker_run_options' => 'Custom Docker Run Options', - ]; + #[Rule(['required', 'string'])] + public string $image; + + #[Rule(['nullable', 'string'])] + public ?string $portsMappings = null; + + #[Rule(['nullable', 'boolean'])] + public ?bool $isPublic = null; + + #[Rule(['nullable', 'integer'])] + public ?int $publicPort = null; + + #[Rule(['nullable', 'string'])] + public ?string $customDockerRunOptions = null; + + #[Rule(['nullable', 'string'])] + public ?string $dbUrl = null; + + #[Rule(['nullable', 'string'])] + public ?string $dbUrlPublic = null; + + #[Rule(['nullable', 'boolean'])] + public bool $isLogDrainEnabled = false; + + public function getListeners() + { + $teamId = Auth::user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped', + ]; + } public function mount() { - $this->db_url = $this->database->internal_db_url; - $this->db_url_public = $this->database->external_db_url; - $this->server = data_get($this->database, 'destination.server'); + try { + $this->syncData(); + $this->server = data_get($this->database, 'destination.server'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function syncData(bool $toModel = false) + { + if ($toModel) { + $this->validate(); + $this->database->name = $this->name; + $this->database->description = $this->description; + $this->database->dragonfly_password = $this->dragonflyPassword; + $this->database->image = $this->image; + $this->database->ports_mappings = $this->portsMappings; + $this->database->is_public = $this->isPublic; + $this->database->public_port = $this->publicPort; + $this->database->custom_docker_run_options = $this->customDockerRunOptions; + $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; + $this->database->save(); + + $this->dbUrl = $this->database->internal_db_url; + $this->dbUrlPublic = $this->database->external_db_url; + } else { + $this->name = $this->database->name; + $this->description = $this->database->description; + $this->dragonflyPassword = $this->database->dragonfly_password; + $this->image = $this->database->image; + $this->portsMappings = $this->database->ports_mappings; + $this->isPublic = $this->database->is_public; + $this->publicPort = $this->database->public_port; + $this->customDockerRunOptions = $this->database->custom_docker_run_options; + $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; + $this->dbUrl = $this->database->internal_db_url; + $this->dbUrlPublic = $this->database->external_db_url; + } } public function instantSaveAdvanced() { try { if (! $this->server->isLogDrainEnabled()) { - $this->database->is_log_drain_enabled = false; + $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } - $this->database->save(); + $this->syncData(true); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { @@ -68,11 +119,50 @@ class General extends Component } } + public function instantSave() + { + try { + if ($this->isPublic && ! $this->publicPort) { + $this->dispatch('error', 'Public port is required.'); + $this->isPublic = false; + + return; + } + if ($this->isPublic) { + if (! str($this->database->status)->startsWith('running')) { + $this->dispatch('error', 'Database must be started to be publicly accessible.'); + $this->isPublic = false; + + return; + } + StartDatabaseProxy::run($this->database); + $this->dispatch('success', 'Database is now publicly accessible.'); + } else { + StopDatabaseProxy::run($this->database); + $this->dispatch('success', 'Database is no longer publicly accessible.'); + } + $this->dbUrlPublic = $this->database->external_db_url; + $this->syncData(true); + } catch (\Throwable $e) { + $this->isPublic = ! $this->isPublic; + $this->syncData(true); + + return handleError($e, $this); + } + } + + public function databaseProxyStopped() + { + $this->syncData(); + } + public function submit() { try { - $this->validate(); - $this->database->save(); + if (str($this->publicPort)->isEmpty()) { + $this->publicPort = null; + } + $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); @@ -84,45 +174,4 @@ class General extends Component } } } - - public function instantSave() - { - try { - if ($this->database->is_public && ! $this->database->public_port) { - $this->dispatch('error', 'Public port is required.'); - $this->database->is_public = false; - - return; - } - if ($this->database->is_public) { - if (! str($this->database->status)->startsWith('running')) { - $this->dispatch('error', 'Database must be started to be publicly accessible.'); - $this->database->is_public = false; - - return; - } - StartDatabaseProxy::run($this->database); - $this->dispatch('success', 'Database is now publicly accessible.'); - } else { - StopDatabaseProxy::run($this->database); - $this->dispatch('success', 'Database is no longer publicly accessible.'); - } - $this->db_url_public = $this->database->external_db_url; - $this->database->save(); - } catch (\Throwable $e) { - $this->database->is_public = ! $this->database->is_public; - - return handleError($e, $this); - } - } - - public function refresh(): void - { - $this->database->refresh(); - } - - public function render() - { - return view('livewire.project.database.dragonfly.general'); - } } diff --git a/resources/views/livewire/project/database/dragonfly/general.blade.php b/resources/views/livewire/project/database/dragonfly/general.blade.php index e4cfb6ca3..63a2cbc6b 100644 --- a/resources/views/livewire/project/database/dragonfly/general.blade.php +++ b/resources/views/livewire/project/database/dragonfly/general.blade.php @@ -7,50 +7,58 @@
- - - + + +
+ id="customDockerRunOptions" label="Custom Docker Options" />

Network

-
- @if ($db_url_public) + type="password" readonly wire:model="dbUrl" /> + + @if ($dbUrlPublic) + type="password" readonly wire:model="dbUrlPublic" /> + @else + @endif
-

Proxy

-
- - - Proxy Logs - - - - Proxy Logs - - +
+
+

Proxy

+ @if ($isPublic) + + Proxy Logs + + + + Logs + + @endif +
+
-
-

Advanced

-
- +
+

Advanced

+
+ +
From 2baea6e89f35b5cdf480d8ef48eae8b5c50c8bd7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 14:23:21 +0100 Subject: [PATCH 10/13] fix --- .../views/livewire/project/database/dragonfly/general.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/project/database/dragonfly/general.blade.php b/resources/views/livewire/project/database/dragonfly/general.blade.php index 63a2cbc6b..8a856fb85 100644 --- a/resources/views/livewire/project/database/dragonfly/general.blade.php +++ b/resources/views/livewire/project/database/dragonfly/general.blade.php @@ -57,7 +57,7 @@

Advanced

-
+
From e1d105606dfa4a54d4e2ebd3468214ed5f963b99 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 14:33:00 +0100 Subject: [PATCH 11/13] fix: add user/pw to db view --- .../database/dragonfly/general.blade.php | 14 ++++ .../project/database/keydb/general.blade.php | 77 ++++++++++++------- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/resources/views/livewire/project/database/dragonfly/general.blade.php b/resources/views/livewire/project/database/dragonfly/general.blade.php index 8a856fb85..7e180af31 100644 --- a/resources/views/livewire/project/database/dragonfly/general.blade.php +++ b/resources/views/livewire/project/database/dragonfly/general.blade.php @@ -15,6 +15,20 @@ helper="You can add custom docker run options that will be used when your container is started.
Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.

Check the docs." placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k" id="customDockerRunOptions" label="Custom Docker Options" /> + + @if ($database->started_at) +
+ +
+ @else +
Please verify these values. You can only modify them before the initial + start. After that, you need to modify it in the database. +
+
+ +
+ @endif

Network

diff --git a/resources/views/livewire/project/database/keydb/general.blade.php b/resources/views/livewire/project/database/keydb/general.blade.php index cf8955a2f..f1c501c19 100644 --- a/resources/views/livewire/project/database/keydb/general.blade.php +++ b/resources/views/livewire/project/database/keydb/general.blade.php @@ -7,54 +7,75 @@
- - - + +
+ + @if ($database->started_at) +
+ +
+ @else +
Please verify these values. You can only modify them before the initial + start. After that, you need to modify it in the database. +
+
+ +
+ @endif + id="customDockerRunOptions" label="Custom Docker Options" />

Network

-
- @if ($db_url_public) + type="password" readonly wire:model="dbUrl" /> + @if ($dbUrlPublic) + type="password" readonly wire:model="dbUrlPublic" /> + @else + @endif
-

Proxy

-
- - - Proxy Logs - - - - Proxy Logs - - +
+
+

Proxy

+ @if ($isPublic) + + Proxy Logs + + + + Logs + + @endif +
+
+
-

Advanced

-
- -
+ label="Custom KeyDB Configuration" rows="10" id="keydbConf" /> +

Advanced

+
+ +
From 431c67e9b1a4c8be185feb668a237531c65cbab4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 14:33:10 +0100 Subject: [PATCH 12/13] fix: sort servers by name --- app/Livewire/Project/New/Select.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index 7f8247597..a562d8b66 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -326,7 +326,7 @@ class Select extends Component public function loadServers() { - $this->servers = Server::isUsable()->get(); + $this->servers = Server::isUsable()->get()->sortBy('name'); $this->allServers = $this->servers; } } From bf29dd47891041648a3f7cc484fe3e0d2673e745 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Nov 2024 14:33:44 +0100 Subject: [PATCH 13/13] fix: keydb view --- .../Project/Database/Keydb/General.php | 203 +++++++++++------- 1 file changed, 126 insertions(+), 77 deletions(-) diff --git a/app/Livewire/Project/Database/Keydb/General.php b/app/Livewire/Project/Database/Keydb/General.php index df04f70d7..f95173651 100644 --- a/app/Livewire/Project/Database/Keydb/General.php +++ b/app/Livewire/Project/Database/Keydb/General.php @@ -7,62 +7,116 @@ use App\Actions\Database\StopDatabaseProxy; use App\Models\Server; use App\Models\StandaloneKeydb; use Exception; +use Illuminate\Support\Facades\Auth; +use Livewire\Attributes\Rule; use Livewire\Component; class General extends Component { - protected $listeners = ['refresh']; - public Server $server; public StandaloneKeydb $database; - public ?string $db_url = null; + #[Rule(['required', 'string'])] + public string $name; - public ?string $db_url_public = null; + #[Rule(['nullable', 'string'])] + public ?string $description = null; - protected $rules = [ - 'database.name' => 'required', - 'database.description' => 'nullable', - 'database.keydb_conf' => 'nullable', - 'database.keydb_password' => 'required', - 'database.image' => 'required', - 'database.ports_mappings' => 'nullable', - 'database.is_public' => 'nullable|boolean', - 'database.public_port' => 'nullable|integer', - 'database.is_log_drain_enabled' => 'nullable|boolean', - 'database.custom_docker_run_options' => 'nullable', - ]; + #[Rule(['nullable', 'string'])] + public ?string $keydbConf = null; - protected $validationAttributes = [ - 'database.name' => 'Name', - 'database.description' => 'Description', - 'database.keydb_conf' => 'Redis Configuration', - 'database.keydb_password' => 'Redis Password', - 'database.image' => 'Image', - 'database.ports_mappings' => 'Port Mapping', - 'database.is_public' => 'Is Public', - 'database.public_port' => 'Public Port', - 'database.custom_docker_run_options' => 'Custom Docker Run Options', - ]; + #[Rule(['required', 'string'])] + public string $keydbPassword; + + #[Rule(['required', 'string'])] + public string $image; + + #[Rule(['nullable', 'string'])] + public ?string $portsMappings = null; + + #[Rule(['nullable', 'boolean'])] + public ?bool $isPublic = null; + + #[Rule(['nullable', 'integer'])] + public ?int $publicPort = null; + + #[Rule(['nullable', 'string'])] + public ?string $customDockerRunOptions = null; + + #[Rule(['nullable', 'string'])] + public ?string $dbUrl = null; + + #[Rule(['nullable', 'string'])] + public ?string $dbUrlPublic = null; + + #[Rule(['nullable', 'boolean'])] + public bool $isLogDrainEnabled = false; + + public function getListeners() + { + $teamId = Auth::user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped', + ]; + } public function mount() { - $this->db_url = $this->database->internal_db_url; - $this->db_url_public = $this->database->external_db_url; - $this->server = data_get($this->database, 'destination.server'); + try { + $this->syncData(); + $this->server = data_get($this->database, 'destination.server'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function syncData(bool $toModel = false) + { + if ($toModel) { + $this->validate(); + $this->database->name = $this->name; + $this->database->description = $this->description; + $this->database->keydb_conf = $this->keydbConf; + $this->database->keydb_password = $this->keydbPassword; + $this->database->image = $this->image; + $this->database->ports_mappings = $this->portsMappings; + $this->database->is_public = $this->isPublic; + $this->database->public_port = $this->publicPort; + $this->database->custom_docker_run_options = $this->customDockerRunOptions; + $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; + $this->database->save(); + + $this->dbUrl = $this->database->internal_db_url; + $this->dbUrlPublic = $this->database->external_db_url; + } else { + $this->name = $this->database->name; + $this->description = $this->database->description; + $this->keydbConf = $this->database->keydb_conf; + $this->keydbPassword = $this->database->keydb_password; + $this->image = $this->database->image; + $this->portsMappings = $this->database->ports_mappings; + $this->isPublic = $this->database->is_public; + $this->publicPort = $this->database->public_port; + $this->customDockerRunOptions = $this->database->custom_docker_run_options; + $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; + $this->dbUrl = $this->database->internal_db_url; + $this->dbUrlPublic = $this->database->external_db_url; + } } public function instantSaveAdvanced() { try { if (! $this->server->isLogDrainEnabled()) { - $this->database->is_log_drain_enabled = false; + $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; } - $this->database->save(); + $this->syncData(true); + $this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); } catch (Exception $e) { @@ -70,14 +124,50 @@ class General extends Component } } + public function instantSave() + { + try { + if ($this->isPublic && ! $this->publicPort) { + $this->dispatch('error', 'Public port is required.'); + $this->isPublic = false; + + return; + } + if ($this->isPublic) { + if (! str($this->database->status)->startsWith('running')) { + $this->dispatch('error', 'Database must be started to be publicly accessible.'); + $this->isPublic = false; + + return; + } + StartDatabaseProxy::run($this->database); + $this->dispatch('success', 'Database is now publicly accessible.'); + } else { + StopDatabaseProxy::run($this->database); + $this->dispatch('success', 'Database is no longer publicly accessible.'); + } + $this->dbUrlPublic = $this->database->external_db_url; + $this->syncData(true); + } catch (\Throwable $e) { + $this->isPublic = ! $this->isPublic; + $this->syncData(true); + + return handleError($e, $this); + } + } + + public function databaseProxyStopped() + { + $this->syncData(); + } + public function submit() { try { - $this->validate(); - if ($this->database->keydb_conf === '') { - $this->database->keydb_conf = null; + if (str($this->publicPort)->isEmpty()) { + $this->publicPort = null; } - $this->database->save(); + $this->syncData(true); $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); @@ -89,45 +179,4 @@ class General extends Component } } } - - public function instantSave() - { - try { - if ($this->database->is_public && ! $this->database->public_port) { - $this->dispatch('error', 'Public port is required.'); - $this->database->is_public = false; - - return; - } - if ($this->database->is_public) { - if (! str($this->database->status)->startsWith('running')) { - $this->dispatch('error', 'Database must be started to be publicly accessible.'); - $this->database->is_public = false; - - return; - } - StartDatabaseProxy::run($this->database); - $this->dispatch('success', 'Database is now publicly accessible.'); - } else { - StopDatabaseProxy::run($this->database); - $this->dispatch('success', 'Database is no longer publicly accessible.'); - } - $this->db_url_public = $this->database->external_db_url; - $this->database->save(); - } catch (\Throwable $e) { - $this->database->is_public = ! $this->database->is_public; - - return handleError($e, $this); - } - } - - public function refresh(): void - { - $this->database->refresh(); - } - - public function render() - { - return view('livewire.project.database.keydb.general'); - } }