diff --git a/app/Livewire/Admin/Index.php b/app/Livewire/Admin/Index.php index b5f6d2929..c68bba3e8 100644 --- a/app/Livewire/Admin/Index.php +++ b/app/Livewire/Admin/Index.php @@ -45,6 +45,9 @@ public function back() public function submitSearch() { + if (Auth::id() !== 0 && ! session('impersonating')) { + return redirect()->route('dashboard'); + } if ($this->search !== '') { $this->foundUsers = User::where(function ($query) { $query->where('name', 'like', "%{$this->search}%") @@ -55,6 +58,9 @@ public function submitSearch() public function getSubscribers() { + if (Auth::id() !== 0 && ! session('impersonating')) { + return redirect()->route('dashboard'); + } $this->inactiveSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', false)->count(); $this->activeSubscribers = Team::whereRelation('subscription', 'stripe_invoice_paid', true)->count(); } diff --git a/app/Livewire/Project/Application/DeploymentNavbar.php b/app/Livewire/Project/Application/DeploymentNavbar.php index f71b7f753..fcd0d4cf4 100644 --- a/app/Livewire/Project/Application/DeploymentNavbar.php +++ b/app/Livewire/Project/Application/DeploymentNavbar.php @@ -52,6 +52,7 @@ public function show_debug() public function force_start() { try { + $this->authorize('deploy', $this->application); force_start_deployment($this->application_deployment_queue); } catch (\Throwable $e) { return handleError($e, $this); @@ -82,6 +83,11 @@ public function copyLogsToClipboard(): string public function cancel() { + try { + $this->authorize('deploy', $this->application); + } catch (\Throwable $e) { + return handleError($e, $this); + } $deployment_uuid = $this->application_deployment_queue->deployment_uuid; $kill_command = "docker rm -f {$deployment_uuid}"; $build_server_id = $this->application_deployment_queue->build_server_id ?? $this->application->destination->server_id; diff --git a/app/Livewire/Project/Application/Swarm.php b/app/Livewire/Project/Application/Swarm.php index 197dc41ed..94d627e67 100644 --- a/app/Livewire/Project/Application/Swarm.php +++ b/app/Livewire/Project/Application/Swarm.php @@ -3,11 +3,14 @@ namespace App\Livewire\Project\Application; use App\Models\Application; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Attributes\Validate; use Livewire\Component; class Swarm extends Component { + use AuthorizesRequests; + public Application $application; #[Validate('required')] @@ -51,6 +54,7 @@ public function syncData(bool $toModel = false) public function instantSave() { try { + $this->authorize('update', $this->application); $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { @@ -61,6 +65,7 @@ public function instantSave() public function submit() { try { + $this->authorize('update', $this->application); $this->syncData(true); $this->dispatch('success', 'Swarm settings updated.'); } catch (\Throwable $e) { diff --git a/app/Livewire/Project/Database/BackupEdit.php b/app/Livewire/Project/Database/BackupEdit.php index 35262d7b0..8b67105cc 100644 --- a/app/Livewire/Project/Database/BackupEdit.php +++ b/app/Livewire/Project/Database/BackupEdit.php @@ -201,6 +201,18 @@ public function delete($password) } } + public function backupNow() + { + try { + $this->authorize('manageBackups', $this->backup->database); + + \App\Jobs\DatabaseBackupJob::dispatch($this->backup); + $this->dispatch('success', 'Backup queued. It will be available in a few minutes.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function instantSave() { try { diff --git a/app/Livewire/Project/Database/BackupExecutions.php b/app/Livewire/Project/Database/BackupExecutions.php index 44f903fcc..5ffe6f509 100644 --- a/app/Livewire/Project/Database/BackupExecutions.php +++ b/app/Livewire/Project/Database/BackupExecutions.php @@ -3,12 +3,15 @@ namespace App\Livewire\Project\Database; use App\Models\ScheduledDatabaseBackup; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Livewire\Component; class BackupExecutions extends Component { + use AuthorizesRequests; + public ?ScheduledDatabaseBackup $backup = null; public $database; @@ -44,29 +47,45 @@ public function getListeners() public function cleanupFailed() { - if ($this->backup) { - $this->backup->executions()->where('status', 'failed')->delete(); - $this->refreshBackupExecutions(); - $this->dispatch('success', 'Failed backups cleaned up.'); + try { + $this->authorize('manageBackups', $this->database); + if ($this->backup) { + $this->backup->executions()->where('status', 'failed')->delete(); + $this->refreshBackupExecutions(); + $this->dispatch('success', 'Failed backups cleaned up.'); + } + } catch (\Throwable $e) { + return handleError($e, $this); } } public function cleanupDeleted() { - if ($this->backup) { - $deletedCount = $this->backup->executions()->where('local_storage_deleted', true)->count(); - if ($deletedCount > 0) { - $this->backup->executions()->where('local_storage_deleted', true)->delete(); - $this->refreshBackupExecutions(); - $this->dispatch('success', "Cleaned up {$deletedCount} backup entries deleted from local storage."); - } else { - $this->dispatch('info', 'No backup entries found that are deleted from local storage.'); + try { + $this->authorize('manageBackups', $this->database); + if ($this->backup) { + $deletedCount = $this->backup->executions()->where('local_storage_deleted', true)->count(); + if ($deletedCount > 0) { + $this->backup->executions()->where('local_storage_deleted', true)->delete(); + $this->refreshBackupExecutions(); + $this->dispatch('success', "Cleaned up {$deletedCount} backup entries deleted from local storage."); + } else { + $this->dispatch('info', 'No backup entries found that are deleted from local storage.'); + } } + } catch (\Throwable $e) { + return handleError($e, $this); } } public function deleteBackup($executionId, $password) { + try { + $this->authorize('manageBackups', $this->database); + } catch (\Throwable $e) { + return handleError($e, $this); + } + if (! verifyPasswordConfirmation($password, $this)) { return; } diff --git a/app/Livewire/Project/Service/EditCompose.php b/app/Livewire/Project/Service/EditCompose.php index 32cf72067..0f5c739b1 100644 --- a/app/Livewire/Project/Service/EditCompose.php +++ b/app/Livewire/Project/Service/EditCompose.php @@ -3,10 +3,13 @@ namespace App\Livewire\Project\Service; use App\Models\Service; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class EditCompose extends Component { + use AuthorizesRequests; + public Service $service; public $serviceId; @@ -72,19 +75,29 @@ public function validateCompose() public function saveEditedCompose() { - $this->dispatch('info', 'Saving new docker compose...'); - $this->dispatch('saveCompose', $this->dockerComposeRaw); - $this->dispatch('refreshStorages'); + try { + $this->authorize('update', $this->service); + $this->dispatch('info', 'Saving new docker compose...'); + $this->dispatch('saveCompose', $this->dockerComposeRaw); + $this->dispatch('refreshStorages'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function instantSave() { - $this->validate([ - 'isContainerLabelEscapeEnabled' => 'required', - ]); - $this->syncData(true); - $this->service->save(['is_container_label_escape_enabled' => $this->isContainerLabelEscapeEnabled]); - $this->dispatch('success', 'Service updated successfully'); + try { + $this->authorize('update', $this->service); + $this->validate([ + 'isContainerLabelEscapeEnabled' => 'required', + ]); + $this->syncData(true); + $this->service->save(['is_container_label_escape_enabled' => $this->isContainerLabelEscapeEnabled]); + $this->dispatch('success', 'Service updated successfully'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function render() diff --git a/app/Livewire/Project/Service/StackForm.php b/app/Livewire/Project/Service/StackForm.php index 64a7d8d8b..678db17e8 100644 --- a/app/Livewire/Project/Service/StackForm.php +++ b/app/Livewire/Project/Service/StackForm.php @@ -4,12 +4,15 @@ use App\Models\Service; use App\Support\ValidationPatterns; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Livewire\Component; class StackForm extends Component { + use AuthorizesRequests; + public Service $service; public Collection $fields; @@ -128,14 +131,20 @@ public function saveCompose($raw) public function instantSave() { - $this->syncData(true); - $this->service->save(); - $this->dispatch('success', 'Service settings saved.'); + try { + $this->authorize('update', $this->service); + $this->syncData(true); + $this->service->save(); + $this->dispatch('success', 'Service settings saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function submit($notify = true) { try { + $this->authorize('update', $this->service); $this->validate(); $this->syncData(true); diff --git a/app/Livewire/Project/Shared/UploadConfig.php b/app/Livewire/Project/Shared/UploadConfig.php index 1b10f588b..0f0894687 100644 --- a/app/Livewire/Project/Shared/UploadConfig.php +++ b/app/Livewire/Project/Shared/UploadConfig.php @@ -3,10 +3,13 @@ namespace App\Livewire\Project\Shared; use App\Models\Application; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class UploadConfig extends Component { + use AuthorizesRequests; + public $config; public $applicationId; @@ -29,13 +32,12 @@ public function mount() public function uploadConfig() { try { - $application = Application::findOrFail($this->applicationId); + $application = Application::ownedByCurrentTeam()->findOrFail($this->applicationId); + $this->authorize('update', $application); $application->setConfig($this->config); $this->dispatch('success', 'Application settings updated'); - } catch (\Exception $e) { - $this->dispatch('error', $e->getMessage()); - - return; + } catch (\Throwable $e) { + return handleError($e, $this); } } diff --git a/app/Livewire/Upgrade.php b/app/Livewire/Upgrade.php index 7948ad6a9..be4ea1cf0 100644 --- a/app/Livewire/Upgrade.php +++ b/app/Livewire/Upgrade.php @@ -44,6 +44,9 @@ public function checkUpdate() public function upgrade() { try { + if (! isInstanceAdmin()) { + abort(403); + } if ($this->updateInProgress) { return; } diff --git a/resources/views/livewire/project/database/backup-edit.blade.php b/resources/views/livewire/project/database/backup-edit.blade.php index bb5dcfc4d..b818e8f75 100644 --- a/resources/views/livewire/project/database/backup-edit.blade.php +++ b/resources/views/livewire/project/database/backup-edit.blade.php @@ -5,7 +5,7 @@ Save @if (str($status)->startsWith('running')) - + Backup Now @endif @if ($backup->database_id !== 0)