diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 0714a5d75..b580979ff 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,12 +2,14 @@ namespace App\Console; +use App\Jobs\BackupDatabaseJob; use App\Jobs\CheckResaleLicenseJob; use App\Jobs\CheckResaleLicenseKeys; use App\Jobs\DockerCleanupJob; use App\Jobs\InstanceApplicationsStatusJob; use App\Jobs\InstanceAutoUpdateJob; use App\Jobs\ProxyCheckJob; +use App\Models\ScheduledDatabaseBackup; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -15,10 +17,12 @@ class Kernel extends ConsoleKernel { protected function schedule(Schedule $schedule): void { +// $schedule->call(fn() => $this->check_scheduled_backups($schedule))->everyTenSeconds(); if (isDev()) { $schedule->command('horizon:snapshot')->everyMinute(); $schedule->job(new InstanceApplicationsStatusJob)->everyMinute(); $schedule->job(new ProxyCheckJob)->everyFiveMinutes(); + // $schedule->job(new CheckResaleLicenseJob)->hourly(); // $schedule->job(new DockerCleanupJob)->everyOddHour(); // $schedule->job(new InstanceAutoUpdateJob(true))->everyMinute(); @@ -30,6 +34,24 @@ class Kernel extends ConsoleKernel $schedule->job(new DockerCleanupJob)->everyTenMinutes(); $schedule->job(new InstanceAutoUpdateJob)->everyTenMinutes(); } + $this->check_scheduled_backups($schedule); + } + + private function check_scheduled_backups($schedule) + { + ray('check_scheduled_backups'); + $scheduled_backups = ScheduledDatabaseBackup::all(); + if ($scheduled_backups->isEmpty()) { + ray('no scheduled backups'); + return; + } + foreach ($scheduled_backups as $scheduled_backup) { + if (!$scheduled_backup->enabled) continue; + $schedule->job(new BackupDatabaseJob( + backup: $scheduled_backup + ))->cron($scheduled_backup->frequency); + } + } protected function commands(): void diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 0c4838a97..125f56d70 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -11,6 +11,7 @@ use App\Models\User; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; +use Throwable; class Controller extends BaseController { @@ -43,7 +44,6 @@ class Controller extends BaseController $s3s = S3Storage::ownedByCurrentTeam()->get(); $resources = 0; foreach ($projects as $project) { - ray($project->postgresqls); $resources += $project->applications->count(); $resources += $project->postgresqls->count(); } @@ -140,7 +140,7 @@ class Controller extends BaseController $invitation->delete(); abort(401); } - } catch (\Throwable $th) { + } catch (Throwable $th) { throw $th; } } @@ -158,7 +158,7 @@ class Controller extends BaseController } $invitation->delete(); return redirect()->route('team.show'); - } catch (\Throwable $th) { + } catch (Throwable $th) { throw $th; } } diff --git a/app/Http/Livewire/Dev/ScheduledBackups.php b/app/Http/Livewire/Dev/ScheduledBackups.php new file mode 100644 index 000000000..a7599d44a --- /dev/null +++ b/app/Http/Livewire/Dev/ScheduledBackups.php @@ -0,0 +1,16 @@ +scheduledDatabaseBackup = ScheduledDatabaseBackup::all(); + } +} diff --git a/app/Jobs/BackupDatabaseJob.php b/app/Jobs/BackupDatabaseJob.php new file mode 100644 index 000000000..276451ad0 --- /dev/null +++ b/app/Jobs/BackupDatabaseJob.php @@ -0,0 +1,24 @@ +backup); + } +} diff --git a/app/Models/ScheduledDatabaseBackup.php b/app/Models/ScheduledDatabaseBackup.php new file mode 100644 index 000000000..62dcccc64 --- /dev/null +++ b/app/Models/ScheduledDatabaseBackup.php @@ -0,0 +1,15 @@ +morphTo(); + } +} diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index d4a225d2c..6cbcffab2 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -64,6 +64,11 @@ class StandalonePostgresql extends BaseModel return $this->morphTo(); } + public function scheduled_database_backups() + { + return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); + } + public function environment_variables(): HasMany { return $this->hasMany(EnvironmentVariable::class); diff --git a/app/Notifications/Channels/EmailChannel.php b/app/Notifications/Channels/EmailChannel.php index 044bb9b07..64051c931 100644 --- a/app/Notifications/Channels/EmailChannel.php +++ b/app/Notifications/Channels/EmailChannel.php @@ -2,6 +2,7 @@ namespace App\Notifications\Channels; +use Exception; use Illuminate\Mail\Message; use Illuminate\Notifications\Notification; use Illuminate\Support\Facades\Mail; @@ -15,7 +16,7 @@ class EmailChannel $recepients = $notifiable->getRecepients($notification); if (count($recepients) === 0) { - throw new \Exception('No email recipients found'); + throw new Exception('No email recipients found'); } $mailMessage = $notification->toMail($notifiable); diff --git a/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php b/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php new file mode 100644 index 000000000..991e1d1b7 --- /dev/null +++ b/database/migrations/2023_08_08_150103_create_scheduled_database_backups_table.php @@ -0,0 +1,24 @@ +id(); + $table->boolean('enabled')->default(true); + $table->string('frequency'); + $table->morphs('database'); + $table->foreignId('team_id'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('scheduled_database_backups'); + } +}; diff --git a/database/seeders/ScheduledDatabaseBackupSeeder.php b/database/seeders/ScheduledDatabaseBackupSeeder.php new file mode 100644 index 000000000..9d7032181 --- /dev/null +++ b/database/seeders/ScheduledDatabaseBackupSeeder.php @@ -0,0 +1,34 @@ + '* * * * *', + 'database_id' => 1, + 'database_type' => 'App\Models\StandalonePostgresql', + 'team_id' => 0, + ]); + ScheduledDatabaseBackup::create([ + 'frequency' => '*/2 * * * *', + 'database_id' => 1, + 'database_type' => 'App\Models\StandalonePostgresql', + 'team_id' => 0, + ]); + ScheduledDatabaseBackup::create([ + 'frequency' => '*/3 * * * *', + 'database_id' => 1, + 'database_type' => 'App\Models\StandalonePostgresql', + 'team_id' => 0, + ]); + } +} diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 8c4e8c363..9ce1c2633 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -24,5 +24,6 @@ @if (isDev()) + @endif diff --git a/resources/views/livewire/dev/scheduled-backups.blade.php b/resources/views/livewire/dev/scheduled-backups.blade.php new file mode 100644 index 000000000..8e53d40f9 --- /dev/null +++ b/resources/views/livewire/dev/scheduled-backups.blade.php @@ -0,0 +1,13 @@ +
+

Scheduled Databse Backups

+ @foreach($scheduledDatabaseBackup as $backup) +
+ {{$backup->id}} + {{$backup->database->id}} + {{$backup->frequency}} + {{$backup->database->type()}} + {{$backup->created_at}} + {{$backup->updated_at}} +
+ @endforeach +