From adb8f9d88ef7ddf94391e0771b9e2b48d8740ece Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 23 Aug 2025 18:50:35 +0200 Subject: [PATCH] feat(auth): implement authorization checks for database management --- app/Livewire/Project/Database/BackupEdit.php | 9 ++ app/Livewire/Project/Database/BackupNow.php | 5 + .../Project/Database/Clickhouse/General.php | 9 ++ .../Project/Database/Configuration.php | 49 ++++++---- .../Database/CreateScheduledBackup.php | 5 + .../Project/Database/Dragonfly/General.php | 13 +++ app/Livewire/Project/Database/Heading.php | 9 ++ app/Livewire/Project/Database/Import.php | 5 + .../Project/Database/Keydb/General.php | 13 +++ .../Project/Database/Mariadb/General.php | 13 +++ .../Project/Database/Mongodb/General.php | 13 +++ .../Project/Database/Mysql/General.php | 13 +++ .../Project/Database/Postgresql/General.php | 19 ++++ .../Project/Database/Redis/General.php | 13 +++ .../Project/Database/ScheduledBackups.php | 10 +- .../Shared/EnvironmentVariable/All.php | 17 ++-- app/Policies/DatabasePolicy.php | 93 +++++++++++++++++++ 17 files changed, 281 insertions(+), 27 deletions(-) create mode 100644 app/Policies/DatabasePolicy.php diff --git a/app/Livewire/Project/Database/BackupEdit.php b/app/Livewire/Project/Database/BackupEdit.php index 8a5b3d9a2..98d076ac0 100644 --- a/app/Livewire/Project/Database/BackupEdit.php +++ b/app/Livewire/Project/Database/BackupEdit.php @@ -5,6 +5,7 @@ namespace App\Livewire\Project\Database; use App\Models\InstanceSettings; use App\Models\ScheduledDatabaseBackup; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Livewire\Attributes\Locked; @@ -14,6 +15,8 @@ use Spatie\Url\Url; class BackupEdit extends Component { + use AuthorizesRequests; + public ScheduledDatabaseBackup $backup; #[Locked] @@ -129,6 +132,8 @@ class BackupEdit extends Component public function delete($password) { + $this->authorize('manageBackups', $this->backup->database); + if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) { if (! Hash::check($password, Auth::user()->password)) { $this->addError('password', 'The provided password is incorrect.'); @@ -186,6 +191,8 @@ class BackupEdit extends Component public function instantSave() { try { + $this->authorize('manageBackups', $this->backup->database); + $this->syncData(true); $this->dispatch('success', 'Backup updated successfully.'); } catch (\Throwable $e) { @@ -214,6 +221,8 @@ class BackupEdit extends Component public function submit() { try { + $this->authorize('manageBackups', $this->backup->database); + $this->syncData(true); $this->dispatch('success', 'Backup updated successfully.'); } catch (\Throwable $e) { diff --git a/app/Livewire/Project/Database/BackupNow.php b/app/Livewire/Project/Database/BackupNow.php index 3cd360562..decd59a4c 100644 --- a/app/Livewire/Project/Database/BackupNow.php +++ b/app/Livewire/Project/Database/BackupNow.php @@ -3,14 +3,19 @@ namespace App\Livewire\Project\Database; use App\Jobs\DatabaseBackupJob; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class BackupNow extends Component { + use AuthorizesRequests; + public $backup; public function backupNow() { + $this->authorize('manageBackups', $this->backup->database); + DatabaseBackupJob::dispatch($this->backup); $this->dispatch('success', 'Backup queued. It will be available in a few minutes.'); } diff --git a/app/Livewire/Project/Database/Clickhouse/General.php b/app/Livewire/Project/Database/Clickhouse/General.php index f6eb54a50..b80775853 100644 --- a/app/Livewire/Project/Database/Clickhouse/General.php +++ b/app/Livewire/Project/Database/Clickhouse/General.php @@ -8,11 +8,14 @@ use App\Models\Server; use App\Models\StandaloneClickhouse; use App\Support\ValidationPatterns; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + public Server $server; public StandaloneClickhouse $database; @@ -131,6 +134,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -149,6 +154,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; @@ -186,6 +193,8 @@ class General extends Component public function submit() { try { + $this->authorize('update', $this->database); + if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } diff --git a/app/Livewire/Project/Database/Configuration.php b/app/Livewire/Project/Database/Configuration.php index 6c4d0867e..88ecccf99 100644 --- a/app/Livewire/Project/Database/Configuration.php +++ b/app/Livewire/Project/Database/Configuration.php @@ -26,27 +26,38 @@ class Configuration extends Component public function mount() { - $this->currentRoute = request()->route()->getName(); + try { + $this->currentRoute = request()->route()->getName(); - $project = currentTeam() - ->projects() - ->select('id', 'uuid', 'team_id') - ->where('uuid', request()->route('project_uuid')) - ->firstOrFail(); - $environment = $project->environments() - ->select('id', 'name', 'project_id', 'uuid') - ->where('uuid', request()->route('environment_uuid')) - ->firstOrFail(); - $database = $environment->databases() - ->where('uuid', request()->route('database_uuid')) - ->firstOrFail(); + $project = currentTeam() + ->projects() + ->select('id', 'uuid', 'team_id') + ->where('uuid', request()->route('project_uuid')) + ->firstOrFail(); + $environment = $project->environments() + ->select('id', 'name', 'project_id', 'uuid') + ->where('uuid', request()->route('environment_uuid')) + ->firstOrFail(); + $database = $environment->databases() + ->where('uuid', request()->route('database_uuid')) + ->firstOrFail(); - $this->database = $database; - $this->project = $project; - $this->environment = $environment; - if (str($this->database->status)->startsWith('running') && is_null($this->database->config_hash)) { - $this->database->isConfigurationChanged(true); - $this->dispatch('configurationChanged'); + $this->database = $database; + $this->project = $project; + $this->environment = $environment; + if (str($this->database->status)->startsWith('running') && is_null($this->database->config_hash)) { + $this->database->isConfigurationChanged(true); + $this->dispatch('configurationChanged'); + } + } catch (\Throwable $e) { + if ($e instanceof \Illuminate\Auth\Access\AuthorizationException) { + return redirect()->route('dashboard'); + } + if ($e instanceof \Illuminate\Support\ItemNotFoundException) { + return redirect()->route('dashboard'); + } + + return handleError($e, $this); } } diff --git a/app/Livewire/Project/Database/CreateScheduledBackup.php b/app/Livewire/Project/Database/CreateScheduledBackup.php index 01108c290..7f807afe2 100644 --- a/app/Livewire/Project/Database/CreateScheduledBackup.php +++ b/app/Livewire/Project/Database/CreateScheduledBackup.php @@ -3,6 +3,7 @@ namespace App\Livewire\Project\Database; use App\Models\ScheduledDatabaseBackup; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Collection; use Livewire\Attributes\Locked; use Livewire\Attributes\Validate; @@ -10,6 +11,8 @@ use Livewire\Component; class CreateScheduledBackup extends Component { + use AuthorizesRequests; + #[Validate(['required', 'string'])] public $frequency; @@ -41,6 +44,8 @@ class CreateScheduledBackup extends Component public function submit() { try { + $this->authorize('manageBackups', $this->database); + $this->validate(); $isValid = validate_cron_expression($this->frequency); diff --git a/app/Livewire/Project/Database/Dragonfly/General.php b/app/Livewire/Project/Database/Dragonfly/General.php index 2a6fc99a9..fabbc7cb4 100644 --- a/app/Livewire/Project/Database/Dragonfly/General.php +++ b/app/Livewire/Project/Database/Dragonfly/General.php @@ -11,11 +11,14 @@ use App\Models\StandaloneDragonfly; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + public Server $server; public StandaloneDragonfly $database; @@ -142,6 +145,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -160,6 +165,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; @@ -197,6 +204,8 @@ class General extends Component public function submit() { try { + $this->authorize('update', $this->database); + if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } @@ -216,6 +225,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { @@ -226,6 +237,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { diff --git a/app/Livewire/Project/Database/Heading.php b/app/Livewire/Project/Database/Heading.php index d1da60469..6a287f8cc 100644 --- a/app/Livewire/Project/Database/Heading.php +++ b/app/Livewire/Project/Database/Heading.php @@ -7,10 +7,13 @@ use App\Actions\Database\StartDatabase; use App\Actions\Database\StopDatabase; use App\Actions\Docker\GetContainersStatus; use App\Events\ServiceStatusChanged; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class Heading extends Component { + use AuthorizesRequests; + public $database; public array $parameters; @@ -67,6 +70,8 @@ class Heading extends Component public function stop() { try { + $this->authorize('manage', $this->database); + $this->dispatch('info', 'Gracefully stopping database.'); StopDatabase::dispatch($this->database, false, $this->docker_cleanup); } catch (\Exception $e) { @@ -76,12 +81,16 @@ class Heading extends Component public function restart() { + $this->authorize('manage', $this->database); + $activity = RestartDatabase::run($this->database); $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } public function start() { + $this->authorize('manage', $this->database); + $activity = StartDatabase::run($this->database); $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); } diff --git a/app/Livewire/Project/Database/Import.php b/app/Livewire/Project/Database/Import.php index eb80ca6f6..6622abaaf 100644 --- a/app/Livewire/Project/Database/Import.php +++ b/app/Livewire/Project/Database/Import.php @@ -3,12 +3,15 @@ namespace App\Livewire\Project\Database; use App\Models\Server; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; use Livewire\Component; class Import extends Component { + use AuthorizesRequests; + public bool $unsupported = false; public $resource; @@ -165,6 +168,8 @@ EOD; public function runImport() { + $this->authorize('update', $this->resource); + if ($this->filename === '') { $this->dispatch('error', 'Please select a file to import.'); diff --git a/app/Livewire/Project/Database/Keydb/General.php b/app/Livewire/Project/Database/Keydb/General.php index 6ddffc05a..7502d001d 100644 --- a/app/Livewire/Project/Database/Keydb/General.php +++ b/app/Livewire/Project/Database/Keydb/General.php @@ -11,11 +11,14 @@ use App\Models\StandaloneKeydb; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + public Server $server; public StandaloneKeydb $database; @@ -150,6 +153,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->isLogDrainEnabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -168,6 +173,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->isPublic && ! $this->publicPort) { $this->dispatch('error', 'Public port is required.'); $this->isPublic = false; @@ -205,6 +212,8 @@ class General extends Component public function submit() { try { + $this->authorize('manageEnvironment', $this->database); + if (str($this->publicPort)->isEmpty()) { $this->publicPort = null; } @@ -224,6 +233,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->syncData(true); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { @@ -234,6 +245,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php index 202056311..c82c4538f 100644 --- a/app/Livewire/Project/Database/Mariadb/General.php +++ b/app/Livewire/Project/Database/Mariadb/General.php @@ -11,11 +11,14 @@ use App\Models\StandaloneMariadb; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + protected $listeners = ['refresh']; public Server $server; @@ -108,6 +111,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -125,6 +130,8 @@ class General extends Component public function submit() { try { + $this->authorize('update', $this->database); + if (str($this->database->public_port)->isEmpty()) { $this->database->public_port = null; } @@ -145,6 +152,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->database->is_public && ! $this->database->public_port) { $this->dispatch('error', 'Public port is required.'); $this->database->is_public = false; @@ -176,6 +185,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->database->save(); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { @@ -186,6 +197,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php index dc90b6b55..4fbc45437 100644 --- a/app/Livewire/Project/Database/Mongodb/General.php +++ b/app/Livewire/Project/Database/Mongodb/General.php @@ -11,11 +11,14 @@ use App\Models\StandaloneMongodb; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + protected $listeners = ['refresh']; public Server $server; @@ -108,6 +111,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -125,6 +130,8 @@ class General extends Component public function submit() { try { + $this->authorize('update', $this->database); + if (str($this->database->public_port)->isEmpty()) { $this->database->public_port = null; } @@ -148,6 +155,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->database->is_public && ! $this->database->public_port) { $this->dispatch('error', 'Public port is required.'); $this->database->is_public = false; @@ -184,6 +193,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->database->save(); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { @@ -194,6 +205,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php index 4753141ec..ada1b3a2c 100644 --- a/app/Livewire/Project/Database/Mysql/General.php +++ b/app/Livewire/Project/Database/Mysql/General.php @@ -11,11 +11,14 @@ use App\Models\StandaloneMysql; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + protected $listeners = ['refresh']; public StandaloneMysql $database; @@ -111,6 +114,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -128,6 +133,8 @@ class General extends Component public function submit() { try { + $this->authorize('update', $this->database); + if (str($this->database->public_port)->isEmpty()) { $this->database->public_port = null; } @@ -148,6 +155,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->database->is_public && ! $this->database->public_port) { $this->dispatch('error', 'Public port is required.'); $this->database->is_public = false; @@ -184,6 +193,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->database->save(); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { @@ -194,6 +205,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index ae49ae4d2..2d37620b9 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -11,11 +11,14 @@ use App\Models\StandalonePostgresql; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + public StandalonePostgresql $database; public Server $server; @@ -118,6 +121,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -140,6 +145,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->database->save(); $this->dispatch('success', 'SSL configuration updated.'); $this->db_url = $this->database->internal_db_url; @@ -152,6 +159,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { @@ -184,6 +193,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->database->is_public && ! $this->database->public_port) { $this->dispatch('error', 'Public port is required.'); $this->database->is_public = false; @@ -214,6 +225,8 @@ class General extends Component public function save_init_script($script) { + $this->authorize('update', $this->database); + $initScripts = collect($this->database->init_scripts ?? []); $existingScript = $initScripts->firstWhere('filename', $script['filename']); @@ -264,6 +277,8 @@ class General extends Component public function delete_init_script($script) { + $this->authorize('update', $this->database); + $collection = collect($this->database->init_scripts); $found = $collection->firstWhere('filename', $script['filename']); if ($found) { @@ -298,6 +313,8 @@ class General extends Component public function save_new_init_script() { + $this->authorize('update', $this->database); + $this->validate([ 'new_filename' => 'required|string', 'new_content' => 'required|string', @@ -327,6 +344,8 @@ class General extends Component public function submit() { try { + $this->authorize('update', $this->database); + if (str($this->database->public_port)->isEmpty()) { $this->database->public_port = null; } diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index 95a72ea6a..1eb4f5c8d 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -11,11 +11,14 @@ use App\Models\StandaloneRedis; use App\Support\ValidationPatterns; use Carbon\Carbon; use Exception; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Facades\Auth; use Livewire\Component; class General extends Component { + use AuthorizesRequests; + public Server $server; public StandaloneRedis $database; @@ -105,6 +108,8 @@ class General extends Component public function instantSaveAdvanced() { try { + $this->authorize('update', $this->database); + if (! $this->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); @@ -122,6 +127,8 @@ class General extends Component public function submit() { try { + $this->authorize('manageEnvironment', $this->database); + $this->validate(); if (version_compare($this->redis_version, '6.0', '>=')) { @@ -147,6 +154,8 @@ class General extends Component public function instantSave() { try { + $this->authorize('update', $this->database); + if ($this->database->is_public && ! $this->database->public_port) { $this->dispatch('error', 'Public port is required.'); $this->database->is_public = false; @@ -178,6 +187,8 @@ class General extends Component public function instantSaveSSL() { try { + $this->authorize('update', $this->database); + $this->database->save(); $this->dispatch('success', 'SSL configuration updated.'); } catch (Exception $e) { @@ -188,6 +199,8 @@ class General extends Component public function regenerateSslCertificate() { try { + $this->authorize('update', $this->database); + $existingCert = $this->database->sslCertificates()->first(); if (! $existingCert) { diff --git a/app/Livewire/Project/Database/ScheduledBackups.php b/app/Livewire/Project/Database/ScheduledBackups.php index 51d8cb33e..1cf5e53f6 100644 --- a/app/Livewire/Project/Database/ScheduledBackups.php +++ b/app/Livewire/Project/Database/ScheduledBackups.php @@ -3,10 +3,13 @@ namespace App\Livewire\Project\Database; use App\Models\ScheduledDatabaseBackup; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Livewire\Component; class ScheduledBackups extends Component { + use AuthorizesRequests; + public $database; public $parameters; @@ -53,6 +56,8 @@ class ScheduledBackups extends Component public function setCustomType() { + $this->authorize('update', $this->database); + $this->database->custom_type = $this->custom_type; $this->database->save(); $this->dispatch('success', 'Database type set.'); @@ -61,7 +66,10 @@ class ScheduledBackups extends Component public function delete($scheduled_backup_id): void { - $this->database->scheduledBackups->find($scheduled_backup_id)->delete(); + $backup = $this->database->scheduledBackups->find($scheduled_backup_id); + $this->authorize('manageBackups', $this->database); + + $backup->delete(); $this->dispatch('success', 'Scheduled backup deleted.'); $this->refreshScheduledBackups(); } diff --git a/app/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Livewire/Project/Shared/EnvironmentVariable/All.php index 88b8a0b17..3631a43c8 100644 --- a/app/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -45,12 +45,16 @@ class All extends Component public function instantSave() { - $this->authorize('manageEnvironment', $this->resource); + try { + $this->authorize('manageEnvironment', $this->resource); - $this->resource->settings->is_env_sorting_enabled = $this->is_env_sorting_enabled; - $this->resource->settings->save(); - $this->sortEnvironmentVariables(); - $this->dispatch('success', 'Environment variable settings updated.'); + $this->resource->settings->is_env_sorting_enabled = $this->is_env_sorting_enabled; + $this->resource->settings->save(); + $this->sortEnvironmentVariables(); + $this->dispatch('success', 'Environment variable settings updated.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } } public function sortEnvironmentVariables() @@ -98,9 +102,8 @@ class All extends Component public function submit($data = null) { - $this->authorize('manageEnvironment', $this->resource); - try { + $this->authorize('manageEnvironment', $this->resource); if ($data === null) { $this->handleBulkSubmit(); } else { diff --git a/app/Policies/DatabasePolicy.php b/app/Policies/DatabasePolicy.php new file mode 100644 index 000000000..b38dad923 --- /dev/null +++ b/app/Policies/DatabasePolicy.php @@ -0,0 +1,93 @@ +teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->isAdmin(); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, $database): Response + { + if ($user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null) { + return Response::allow(); + } + + return Response::deny('As a member, you cannot update this database.

You need at least admin or owner permissions.'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, $database): bool + { + return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, $database): bool + { + return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, $database): bool + { + return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } + + /** + * Determine whether the user can start/stop the database. + */ + public function manage(User $user, $database): bool + { + return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } + + /** + * Determine whether the user can manage database backups. + */ + public function manageBackups(User $user, $database): bool + { + return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } + + /** + * Determine whether the user can manage environment variables. + */ + public function manageEnvironment(User $user, $database): bool + { + return $user->isAdmin() && $user->teams()->get()->firstWhere('id', $database->team()->first()->id) !== null; + } +}