coolify/app/Livewire/Server/Proxy.php

271 lines
8.5 KiB
PHP
Raw Normal View History

2023-05-03 05:23:45 +00:00
<?php
2023-12-07 18:06:32 +00:00
namespace App\Livewire\Server;
2023-05-03 05:23:45 +00:00
use App\Actions\Proxy\GetProxyConfiguration;
use App\Actions\Proxy\SaveProxyConfiguration;
use App\Enums\ProxyTypes;
2023-05-03 05:23:45 +00:00
use App\Models\Server;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Support\Facades\File;
2024-06-10 20:43:34 +00:00
use Livewire\Component;
2023-05-03 05:23:45 +00:00
class Proxy extends Component
{
use AuthorizesRequests;
2023-05-03 05:23:45 +00:00
public Server $server;
2023-09-06 13:00:56 +00:00
public ?string $selectedProxy = null;
2024-06-10 20:43:34 +00:00
public $proxySettings = null;
2024-06-10 20:43:34 +00:00
public bool $redirectEnabled = true;
2024-12-06 13:08:34 +00:00
public ?string $redirectUrl = null;
2023-05-03 05:23:45 +00:00
Complete Livewire legacy model binding migration (25+ components) This completes the migration from Livewire's legacy `id="model.property"` pattern to explicit properties with manual synchronization. This allows disabling the `legacy_model_binding` feature flag. **Components Migrated (Final Session - 9 components):** - Server/Proxy.php (1 field) - Service/EditDomain.php (1 field) - Fixed Collection/string bug & parent sync - Application/Previews.php (2 fields - array handling) - Service/EditCompose.php (4 fields) - Service/FileStorage.php (6 fields) - Service/Database.php (7 fields) - Service/ServiceApplicationView.php (10 fields) - Application/General.php (53 fields) - LARGEST migration - Application/PreviewsCompose.php (1 field) **Total Migration Summary:** - 25+ components migrated across all phases - 150+ explicit properties added - 0 legacy bindings remaining (verified via grep) - All wire:model, id, @entangle bindings updated - All updater hooks renamed (updatedApplicationX → updatedX) **Technical Changes:** - Added explicit public properties (camelCase) - Implemented syncData(bool $toModel) bidirectional sync - Updated validation rules (removed model. prefix) - Updated all action methods (mount, submit, instantSave) - Fixed updater hooks: updatedBuildPack, updatedBaseDirectory, updatedIsStatic - Updated Blade views (id & wire:model bindings) - Applied Collection/string confusion fixes - Added model refresh + re-sync pattern **Critical Fixes:** - EditDomain.php Collection/string confusion (use intermediate variables) - EditDomain.php parent component sync (refresh + re-sync after save) - General.php domain field empty (syncData at end of mount) - General.php wire:model bindings (application.* → property) - General.php updater hooks (wrong naming convention) **Files Modified:** 34 files - 17 PHP Livewire components - 17 Blade view templates - 1 MIGRATION_REPORT.md (documentation) **Ready to disable legacy_model_binding flag in config/livewire.php** 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:38:59 +00:00
public bool $generateExactLabels = false;
public function getListeners()
{
$teamId = auth()->user()->currentTeam()->id;
return [
'saveConfiguration' => 'submit',
"echo-private:team.{$teamId},ProxyStatusChangedUI" => '$refresh',
];
}
protected $rules = [
Complete Livewire legacy model binding migration (25+ components) This completes the migration from Livewire's legacy `id="model.property"` pattern to explicit properties with manual synchronization. This allows disabling the `legacy_model_binding` feature flag. **Components Migrated (Final Session - 9 components):** - Server/Proxy.php (1 field) - Service/EditDomain.php (1 field) - Fixed Collection/string bug & parent sync - Application/Previews.php (2 fields - array handling) - Service/EditCompose.php (4 fields) - Service/FileStorage.php (6 fields) - Service/Database.php (7 fields) - Service/ServiceApplicationView.php (10 fields) - Application/General.php (53 fields) - LARGEST migration - Application/PreviewsCompose.php (1 field) **Total Migration Summary:** - 25+ components migrated across all phases - 150+ explicit properties added - 0 legacy bindings remaining (verified via grep) - All wire:model, id, @entangle bindings updated - All updater hooks renamed (updatedApplicationX → updatedX) **Technical Changes:** - Added explicit public properties (camelCase) - Implemented syncData(bool $toModel) bidirectional sync - Updated validation rules (removed model. prefix) - Updated all action methods (mount, submit, instantSave) - Fixed updater hooks: updatedBuildPack, updatedBaseDirectory, updatedIsStatic - Updated Blade views (id & wire:model bindings) - Applied Collection/string confusion fixes - Added model refresh + re-sync pattern **Critical Fixes:** - EditDomain.php Collection/string confusion (use intermediate variables) - EditDomain.php parent component sync (refresh + re-sync after save) - General.php domain field empty (syncData at end of mount) - General.php wire:model bindings (application.* → property) - General.php updater hooks (wrong naming convention) **Files Modified:** 34 files - 17 PHP Livewire components - 17 Blade view templates - 1 MIGRATION_REPORT.md (documentation) **Ready to disable legacy_model_binding flag in config/livewire.php** 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:38:59 +00:00
'generateExactLabels' => 'required|boolean',
];
2023-06-22 12:18:17 +00:00
public function mount()
{
$this->selectedProxy = $this->server->proxyType();
$this->redirectEnabled = data_get($this->server, 'proxy.redirect_enabled', true);
$this->redirectUrl = data_get($this->server, 'proxy.redirect_url');
Complete Livewire legacy model binding migration (25+ components) This completes the migration from Livewire's legacy `id="model.property"` pattern to explicit properties with manual synchronization. This allows disabling the `legacy_model_binding` feature flag. **Components Migrated (Final Session - 9 components):** - Server/Proxy.php (1 field) - Service/EditDomain.php (1 field) - Fixed Collection/string bug & parent sync - Application/Previews.php (2 fields - array handling) - Service/EditCompose.php (4 fields) - Service/FileStorage.php (6 fields) - Service/Database.php (7 fields) - Service/ServiceApplicationView.php (10 fields) - Application/General.php (53 fields) - LARGEST migration - Application/PreviewsCompose.php (1 field) **Total Migration Summary:** - 25+ components migrated across all phases - 150+ explicit properties added - 0 legacy bindings remaining (verified via grep) - All wire:model, id, @entangle bindings updated - All updater hooks renamed (updatedApplicationX → updatedX) **Technical Changes:** - Added explicit public properties (camelCase) - Implemented syncData(bool $toModel) bidirectional sync - Updated validation rules (removed model. prefix) - Updated all action methods (mount, submit, instantSave) - Fixed updater hooks: updatedBuildPack, updatedBaseDirectory, updatedIsStatic - Updated Blade views (id & wire:model bindings) - Applied Collection/string confusion fixes - Added model refresh + re-sync pattern **Critical Fixes:** - EditDomain.php Collection/string confusion (use intermediate variables) - EditDomain.php parent component sync (refresh + re-sync after save) - General.php domain field empty (syncData at end of mount) - General.php wire:model bindings (application.* → property) - General.php updater hooks (wrong naming convention) **Files Modified:** 34 files - 17 PHP Livewire components - 17 Blade view templates - 1 MIGRATION_REPORT.md (documentation) **Ready to disable legacy_model_binding flag in config/livewire.php** 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:38:59 +00:00
$this->syncData(false);
}
private function syncData(bool $toModel = false): void
{
if ($toModel) {
$this->server->settings->generate_exact_labels = $this->generateExactLabels;
} else {
$this->generateExactLabels = $this->server->settings->generate_exact_labels ?? false;
}
2023-06-22 12:18:17 +00:00
}
public function getConfigurationFilePathProperty()
{
return $this->server->proxyPath().'docker-compose.yml';
}
public function changeProxy()
2023-06-08 06:39:00 +00:00
{
$this->authorize('update', $this->server);
2023-07-14 11:38:24 +00:00
$this->server->proxy = null;
2023-06-08 06:39:00 +00:00
$this->server->save();
2024-12-06 13:08:34 +00:00
$this->dispatch('reloadWindow');
2023-06-08 06:39:00 +00:00
}
public function selectProxy($proxy_type)
2023-05-15 11:45:37 +00:00
{
try {
$this->authorize('update', $this->server);
$this->server->changeProxy($proxy_type, async: false);
$this->selectedProxy = $this->server->proxy->type;
2024-12-06 13:08:34 +00:00
$this->dispatch('reloadWindow');
} catch (\Throwable $e) {
return handleError($e, $this);
}
2023-05-15 11:45:37 +00:00
}
public function instantSave()
{
try {
$this->authorize('update', $this->server);
$this->validate();
Complete Livewire legacy model binding migration (25+ components) This completes the migration from Livewire's legacy `id="model.property"` pattern to explicit properties with manual synchronization. This allows disabling the `legacy_model_binding` feature flag. **Components Migrated (Final Session - 9 components):** - Server/Proxy.php (1 field) - Service/EditDomain.php (1 field) - Fixed Collection/string bug & parent sync - Application/Previews.php (2 fields - array handling) - Service/EditCompose.php (4 fields) - Service/FileStorage.php (6 fields) - Service/Database.php (7 fields) - Service/ServiceApplicationView.php (10 fields) - Application/General.php (53 fields) - LARGEST migration - Application/PreviewsCompose.php (1 field) **Total Migration Summary:** - 25+ components migrated across all phases - 150+ explicit properties added - 0 legacy bindings remaining (verified via grep) - All wire:model, id, @entangle bindings updated - All updater hooks renamed (updatedApplicationX → updatedX) **Technical Changes:** - Added explicit public properties (camelCase) - Implemented syncData(bool $toModel) bidirectional sync - Updated validation rules (removed model. prefix) - Updated all action methods (mount, submit, instantSave) - Fixed updater hooks: updatedBuildPack, updatedBaseDirectory, updatedIsStatic - Updated Blade views (id & wire:model bindings) - Applied Collection/string confusion fixes - Added model refresh + re-sync pattern **Critical Fixes:** - EditDomain.php Collection/string confusion (use intermediate variables) - EditDomain.php parent component sync (refresh + re-sync after save) - General.php domain field empty (syncData at end of mount) - General.php wire:model bindings (application.* → property) - General.php updater hooks (wrong naming convention) **Files Modified:** 34 files - 17 PHP Livewire components - 17 Blade view templates - 1 MIGRATION_REPORT.md (documentation) **Ready to disable legacy_model_binding flag in config/livewire.php** 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 13:38:59 +00:00
$this->syncData(true);
$this->server->settings->save();
$this->dispatch('success', 'Settings saved.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function instantSaveRedirect()
{
try {
$this->authorize('update', $this->server);
$this->server->proxy->redirect_enabled = $this->redirectEnabled;
$this->server->save();
$this->server->setupDefaultRedirect();
$this->dispatch('success', 'Proxy configuration saved.');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
2023-07-28 12:44:26 +00:00
public function submit()
2023-05-15 11:45:37 +00:00
{
try {
$this->authorize('update', $this->server);
SaveProxyConfiguration::run($this->server, $this->proxySettings);
$this->server->proxy->redirect_url = $this->redirectUrl;
2023-06-22 12:18:17 +00:00
$this->server->save();
$this->server->setupDefaultRedirect();
2023-12-07 18:06:32 +00:00
$this->dispatch('success', 'Proxy configuration saved.');
2023-09-11 15:36:30 +00:00
} catch (\Throwable $e) {
return handleError($e, $this);
2023-05-15 11:45:37 +00:00
}
}
public function resetProxyConfiguration()
2023-05-03 05:23:45 +00:00
{
2023-05-15 11:45:37 +00:00
try {
$this->authorize('update', $this->server);
// Explicitly regenerate default configuration
$this->proxySettings = GetProxyConfiguration::run($this->server, forceRegenerate: true);
SaveProxyConfiguration::run($this->server, $this->proxySettings);
2024-03-12 09:42:56 +00:00
$this->server->save();
$this->dispatch('success', 'Proxy configuration reset to default.');
2023-09-11 15:36:30 +00:00
} catch (\Throwable $e) {
return handleError($e, $this);
2023-05-15 11:45:37 +00:00
}
2023-05-03 05:23:45 +00:00
}
2023-09-11 20:29:34 +00:00
public function loadProxyConfiguration()
2023-05-15 20:17:31 +00:00
{
try {
$this->proxySettings = GetProxyConfiguration::run($this->server);
2023-09-11 15:36:30 +00:00
} catch (\Throwable $e) {
return handleError($e, $this);
2023-05-15 20:17:31 +00:00
}
}
public function getLatestTraefikVersionProperty(): ?string
{
try {
$versionsPath = base_path('versions.json');
if (! File::exists($versionsPath)) {
return null;
}
$versions = json_decode(File::get($versionsPath), true);
$traefikVersions = data_get($versions, 'traefik');
if (! $traefikVersions) {
return null;
}
// Handle new structure (array of branches)
if (is_array($traefikVersions)) {
$currentVersion = $this->server->detected_traefik_version;
// If we have a current version, try to find matching branch
if ($currentVersion && $currentVersion !== 'latest') {
$current = ltrim($currentVersion, 'v');
if (preg_match('/^(\d+\.\d+)/', $current, $matches)) {
$branch = "v{$matches[1]}";
if (isset($traefikVersions[$branch])) {
$version = $traefikVersions[$branch];
return str_starts_with($version, 'v') ? $version : "v{$version}";
}
}
}
// Return the newest available version
$newestVersion = collect($traefikVersions)
->map(fn ($v) => ltrim($v, 'v'))
->sortBy(fn ($v) => $v, SORT_NATURAL)
->last();
return $newestVersion ? "v{$newestVersion}" : null;
}
// Handle old structure (simple string) for backward compatibility
return str_starts_with($traefikVersions, 'v') ? $traefikVersions : "v{$traefikVersions}";
} catch (\Throwable $e) {
return null;
}
}
public function getIsTraefikOutdatedProperty(): bool
{
if ($this->server->proxyType() !== ProxyTypes::TRAEFIK->value) {
return false;
}
$currentVersion = $this->server->detected_traefik_version;
if (! $currentVersion || $currentVersion === 'latest') {
return false;
}
$latestVersion = $this->latestTraefikVersion;
if (! $latestVersion) {
return false;
}
// Compare versions (strip 'v' prefix)
$current = ltrim($currentVersion, 'v');
$latest = ltrim($latestVersion, 'v');
return version_compare($current, $latest, '<');
}
public function getNewerTraefikBranchAvailableProperty(): ?string
{
try {
if ($this->server->proxyType() !== ProxyTypes::TRAEFIK->value) {
return null;
}
$currentVersion = $this->server->detected_traefik_version;
if (! $currentVersion || $currentVersion === 'latest') {
return null;
}
$versionsPath = base_path('versions.json');
if (! File::exists($versionsPath)) {
return null;
}
$versions = json_decode(File::get($versionsPath), true);
$traefikVersions = data_get($versions, 'traefik');
if (! is_array($traefikVersions)) {
return null;
}
// Extract current branch (e.g., "3.5" from "3.5.6")
$current = ltrim($currentVersion, 'v');
if (! preg_match('/^(\d+\.\d+)/', $current, $matches)) {
return null;
}
$currentBranch = $matches[1];
// Find the newest branch that's greater than current
$newestVersion = null;
foreach ($traefikVersions as $branch => $version) {
$branchNum = ltrim($branch, 'v');
if (version_compare($branchNum, $currentBranch, '>')) {
$cleanVersion = ltrim($version, 'v');
if (! $newestVersion || version_compare($cleanVersion, $newestVersion, '>')) {
$newestVersion = $cleanVersion;
}
}
}
return $newestVersion ? "v{$newestVersion}" : null;
} catch (\Throwable $e) {
return null;
}
}
}