2023-08-10 13:52:54 +00:00
< ? php
2023-12-07 18:06:32 +00:00
namespace App\Livewire\Project\Database ;
2023-08-10 13:52:54 +00:00
2024-10-22 10:29:48 +00:00
use App\Models\InstanceSettings ;
2024-05-24 15:20:20 +00:00
use App\Models\ScheduledDatabaseBackup ;
2024-11-04 11:40:10 +00:00
use Exception ;
2024-09-23 17:51:31 +00:00
use Illuminate\Support\Facades\Auth ;
use Illuminate\Support\Facades\Hash ;
2024-11-04 11:40:10 +00:00
use Livewire\Attributes\Locked ;
2024-11-05 08:36:40 +00:00
use Livewire\Attributes\Validate ;
2023-08-10 13:52:54 +00:00
use Livewire\Component ;
2023-11-07 11:11:47 +00:00
use Spatie\Url\Url ;
2023-08-10 13:52:54 +00:00
class BackupEdit extends Component
{
2024-11-04 11:40:10 +00:00
public ScheduledDatabaseBackup $backup ;
2024-06-10 20:43:34 +00:00
2024-11-04 11:40:10 +00:00
#[Locked]
2023-08-11 14:13:53 +00:00
public $s3s ;
2024-06-10 20:43:34 +00:00
2024-11-04 11:40:10 +00:00
#[Locked]
public $parameters ;
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'boolean'])]
2024-09-02 17:27:21 +00:00
public bool $delete_associated_backups_locally = false ;
2024-09-23 17:51:31 +00:00
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'boolean'])]
2024-09-02 17:27:21 +00:00
public bool $delete_associated_backups_s3 = false ;
2024-09-23 17:51:31 +00:00
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'boolean'])]
2024-09-02 17:27:21 +00:00
public bool $delete_associated_backups_sftp = false ;
2024-08-31 16:29:19 +00:00
2024-11-05 08:36:40 +00:00
#[Validate(['nullable', 'string'])]
2023-10-10 11:10:43 +00:00
public ? string $status = null ;
2024-06-10 20:43:34 +00:00
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'boolean'])]
2024-11-04 11:40:10 +00:00
public bool $backupEnabled = false ;
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'string'])]
2024-11-04 11:40:10 +00:00
public string $frequency = '' ;
2025-01-07 08:29:38 +00:00
#[Validate(['string'])]
2025-01-03 19:39:27 +00:00
public string $timezone = '' ;
2025-01-13 15:38:16 +00:00
#[Validate(['required', 'integer'])]
public int $databaseBackupRetentionAmountLocally = 0 ;
#[Validate(['required', 'integer'])]
public ? int $databaseBackupRetentionDaysLocally = 0 ;
2025-01-13 18:49:12 +00:00
#[Validate(['required', 'numeric', 'min:0'])]
public ? float $databaseBackupRetentionMaxStorageLocally = 0 ;
2025-01-13 15:38:16 +00:00
#[Validate(['required', 'integer'])]
public ? int $databaseBackupRetentionAmountS3 = 0 ;
#[Validate(['required', 'integer'])]
public ? int $databaseBackupRetentionDaysS3 = 0 ;
2025-01-13 18:49:12 +00:00
#[Validate(['required', 'numeric', 'min:0'])]
public ? float $databaseBackupRetentionMaxStorageS3 = 0 ;
2024-11-04 11:40:10 +00:00
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'boolean'])]
2024-11-04 11:40:10 +00:00
public bool $saveS3 = false ;
2025-08-17 10:34:20 +00:00
#[Validate(['required', 'boolean'])]
public bool $disableLocalBackup = false ;
2025-01-13 20:26:20 +00:00
#[Validate(['nullable', 'integer'])]
2024-11-08 10:48:15 +00:00
public ? int $s3StorageId = 1 ;
2024-11-04 11:40:10 +00:00
2025-01-13 20:26:20 +00:00
#[Validate(['nullable', 'string'])]
2024-11-04 11:40:10 +00:00
public ? string $databasesToBackup = null ;
2024-11-05 08:36:40 +00:00
#[Validate(['required', 'boolean'])]
2024-11-04 11:40:10 +00:00
public bool $dumpAll = false ;
2023-08-10 13:52:54 +00:00
2025-07-18 13:47:14 +00:00
#[Validate(['required', 'int', 'min:1', 'max:36000'])]
public int $timeout = 3600 ;
2023-08-10 14:28:29 +00:00
public function mount ()
{
2024-11-04 11:40:10 +00:00
try {
$this -> parameters = get_route_parameters ();
$this -> syncData ();
} catch ( Exception $e ) {
return handleError ( $e , $this );
}
}
public function syncData ( bool $toModel = false )
{
if ( $toModel ) {
$this -> backup -> enabled = $this -> backupEnabled ;
$this -> backup -> frequency = $this -> frequency ;
2025-01-13 15:38:16 +00:00
$this -> backup -> database_backup_retention_amount_locally = $this -> databaseBackupRetentionAmountLocally ;
$this -> backup -> database_backup_retention_days_locally = $this -> databaseBackupRetentionDaysLocally ;
2025-01-13 18:49:12 +00:00
$this -> backup -> database_backup_retention_max_storage_locally = $this -> databaseBackupRetentionMaxStorageLocally ;
2025-01-13 15:38:16 +00:00
$this -> backup -> database_backup_retention_amount_s3 = $this -> databaseBackupRetentionAmountS3 ;
$this -> backup -> database_backup_retention_days_s3 = $this -> databaseBackupRetentionDaysS3 ;
$this -> backup -> database_backup_retention_max_storage_s3 = $this -> databaseBackupRetentionMaxStorageS3 ;
2024-11-04 11:40:10 +00:00
$this -> backup -> save_s3 = $this -> saveS3 ;
2025-08-17 10:34:20 +00:00
$this -> backup -> disable_local_backup = $this -> disableLocalBackup ;
2024-11-04 11:40:10 +00:00
$this -> backup -> s3_storage_id = $this -> s3StorageId ;
$this -> backup -> databases_to_backup = $this -> databasesToBackup ;
$this -> backup -> dump_all = $this -> dumpAll ;
2025-07-18 13:47:14 +00:00
$this -> backup -> timeout = $this -> timeout ;
2025-01-07 08:29:38 +00:00
$this -> customValidate ();
2024-11-04 11:40:10 +00:00
$this -> backup -> save ();
} else {
$this -> backupEnabled = $this -> backup -> enabled ;
$this -> frequency = $this -> backup -> frequency ;
2025-01-03 19:39:27 +00:00
$this -> timezone = data_get ( $this -> backup -> server (), 'settings.server_timezone' , 'Instance timezone' );
2025-01-13 15:38:16 +00:00
$this -> databaseBackupRetentionAmountLocally = $this -> backup -> database_backup_retention_amount_locally ;
$this -> databaseBackupRetentionDaysLocally = $this -> backup -> database_backup_retention_days_locally ;
2025-01-13 18:49:12 +00:00
$this -> databaseBackupRetentionMaxStorageLocally = $this -> backup -> database_backup_retention_max_storage_locally ;
2025-01-13 15:38:16 +00:00
$this -> databaseBackupRetentionAmountS3 = $this -> backup -> database_backup_retention_amount_s3 ;
$this -> databaseBackupRetentionDaysS3 = $this -> backup -> database_backup_retention_days_s3 ;
$this -> databaseBackupRetentionMaxStorageS3 = $this -> backup -> database_backup_retention_max_storage_s3 ;
2024-11-04 11:40:10 +00:00
$this -> saveS3 = $this -> backup -> save_s3 ;
2025-08-17 10:34:20 +00:00
$this -> disableLocalBackup = $this -> backup -> disable_local_backup ? ? false ;
2024-11-04 11:40:10 +00:00
$this -> s3StorageId = $this -> backup -> s3_storage_id ;
$this -> databasesToBackup = $this -> backup -> databases_to_backup ;
$this -> dumpAll = $this -> backup -> dump_all ;
2025-07-18 13:47:14 +00:00
$this -> timeout = $this -> backup -> timeout ;
2023-08-11 14:13:53 +00:00
}
2023-08-10 14:28:29 +00:00
}
2024-08-31 16:29:19 +00:00
public function delete ( $password )
2023-08-10 14:25:59 +00:00
{
2025-01-07 14:31:43 +00:00
if ( ! data_get ( InstanceSettings :: get (), 'disable_two_step_confirmation' )) {
if ( ! Hash :: check ( $password , Auth :: user () -> password )) {
$this -> addError ( 'password' , 'The provided password is incorrect.' );
2024-09-23 17:51:31 +00:00
2025-01-07 14:31:43 +00:00
return ;
}
2024-08-31 16:29:19 +00:00
}
2024-03-21 11:44:32 +00:00
try {
2025-01-13 16:31:55 +00:00
$server = null ;
if ( $this -> backup -> database instanceof \App\Models\ServiceDatabase ) {
$server = $this -> backup -> database -> service -> destination -> server ;
} elseif ( $this -> backup -> database -> destination && $this -> backup -> database -> destination -> server ) {
$server = $this -> backup -> database -> destination -> server ;
2024-09-02 17:27:21 +00:00
}
2025-01-13 16:31:55 +00:00
$filenames = $this -> backup -> executions ()
-> whereNotNull ( 'filename' )
-> where ( 'filename' , '!=' , '' )
-> where ( 'scheduled_database_backup_id' , $this -> backup -> id )
-> pluck ( 'filename' )
-> filter ()
-> all ();
if ( ! empty ( $filenames )) {
if ( $this -> delete_associated_backups_locally && $server ) {
deleteBackupsLocally ( $filenames , $server );
}
if ( $this -> delete_associated_backups_s3 && $this -> backup -> s3 ) {
deleteBackupsS3 ( $filenames , $this -> backup -> s3 );
}
2024-08-31 16:29:19 +00:00
}
2024-03-21 11:44:32 +00:00
$this -> backup -> delete ();
2024-08-31 16:29:19 +00:00
2025-01-07 14:31:43 +00:00
if ( $this -> backup -> database -> getMorphClass () === \App\Models\ServiceDatabase :: class ) {
2024-03-21 11:44:32 +00:00
$previousUrl = url () -> previous ();
$url = Url :: fromString ( $previousUrl );
$url = $url -> withoutQueryParameter ( 'selectedBackupId' );
$url = $url -> withFragment ( 'backups' );
2024-09-23 17:51:31 +00:00
$url = $url -> getPath () . " # { $url -> getFragment () } " ;
2024-06-10 20:43:34 +00:00
2024-03-21 11:44:32 +00:00
return redirect ( $url );
2025-01-07 14:31:43 +00:00
} else {
return redirect () -> route ( 'project.database.backup.index' , $this -> parameters );
2024-03-21 11:44:32 +00:00
}
2025-01-13 16:31:55 +00:00
} catch ( \Exception $e ) {
$this -> dispatch ( 'error' , 'Failed to delete backup: ' . $e -> getMessage ());
2024-03-21 11:44:32 +00:00
return handleError ( $e , $this );
2023-11-07 11:11:47 +00:00
}
2023-08-10 14:25:59 +00:00
}
2023-08-10 13:52:54 +00:00
public function instantSave ()
{
2023-08-11 14:13:53 +00:00
try {
2024-11-04 11:40:10 +00:00
$this -> syncData ( true );
2024-03-21 11:44:32 +00:00
$this -> dispatch ( 'success' , 'Backup updated successfully.' );
2025-01-07 14:31:43 +00:00
} catch ( \Throwable $e ) {
2023-12-07 18:06:32 +00:00
$this -> dispatch ( 'error' , $e -> getMessage ());
2023-08-11 14:13:53 +00:00
}
2023-08-10 13:52:54 +00:00
}
2024-11-04 11:40:10 +00:00
private function customValidate ()
2023-08-10 13:52:54 +00:00
{
2024-06-10 20:43:34 +00:00
if ( ! is_numeric ( $this -> backup -> s3_storage_id )) {
2023-08-11 18:48:52 +00:00
$this -> backup -> s3_storage_id = null ;
}
2025-08-17 10:34:20 +00:00
// Validate that disable_local_backup can only be true when S3 backup is enabled
if ( $this -> backup -> disable_local_backup && ! $this -> backup -> save_s3 ) {
throw new \Exception ( 'Local backup can only be disabled when S3 backup is enabled.' );
}
2023-08-10 13:52:54 +00:00
$isValid = validate_cron_expression ( $this -> backup -> frequency );
2024-06-10 20:43:34 +00:00
if ( ! $isValid ) {
2025-01-07 14:31:43 +00:00
throw new \Exception ( 'Invalid Cron / Human expression' );
2023-08-10 13:52:54 +00:00
}
$this -> validate ();
2023-08-11 14:13:53 +00:00
}
public function submit ()
{
try {
2024-11-04 11:40:10 +00:00
$this -> syncData ( true );
$this -> dispatch ( 'success' , 'Backup updated successfully.' );
2025-01-07 14:31:43 +00:00
} catch ( \Throwable $e ) {
2023-12-07 18:06:32 +00:00
$this -> dispatch ( 'error' , $e -> getMessage ());
2023-08-11 14:13:53 +00:00
}
2023-08-10 13:52:54 +00:00
}
2024-08-31 16:29:19 +00:00
public function render ()
{
return view ( 'livewire.project.database.backup-edit' , [
'checkboxes' => [
2024-09-27 15:29:36 +00:00
[ 'id' => 'delete_associated_backups_locally' , 'label' => __ ( 'database.delete_backups_locally' )],
2025-01-14 08:22:15 +00:00
[ 'id' => 'delete_associated_backups_s3' , 'label' => 'All backups will be permanently deleted (associated with this backup job) from the selected S3 Storage.' ],
2024-09-02 17:27:21 +00:00
// ['id' => 'delete_associated_backups_sftp', 'label' => 'All backups associated with this backup job from this database will be permanently deleted from the selected SFTP Storage.']
2024-09-23 17:51:31 +00:00
],
2024-08-31 16:29:19 +00:00
]);
}
2023-08-10 13:52:54 +00:00
}