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 ;
use Livewire\Attributes\Rule ;
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 ;
#[Rule(['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-04 11:40:10 +00:00
#[Rule(['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-04 11:40:10 +00:00
#[Rule(['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-04 11:40:10 +00:00
#[Rule(['nullable', 'string'])]
2023-10-10 11:10:43 +00:00
public ? string $status = null ;
2024-06-10 20:43:34 +00:00
2024-11-04 11:40:10 +00:00
#[Rule(['required', 'boolean'])]
public bool $backupEnabled = false ;
#[Rule(['required', 'string'])]
public string $frequency = '' ;
#[Rule(['required', 'integer', 'min:1'])]
public int $numberOfBackupsLocally = 1 ;
#[Rule(['required', 'boolean'])]
public bool $saveS3 = false ;
#[Rule(['required', 'integer'])]
public int $s3StorageId = 1 ;
#[Rule(['nullable', 'string'])]
public ? string $databasesToBackup = null ;
#[Rule(['required', 'boolean'])]
public bool $dumpAll = false ;
2023-08-10 13:52:54 +00:00
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 -> customValidate ();
$this -> backup -> enabled = $this -> backupEnabled ;
$this -> backup -> frequency = $this -> frequency ;
$this -> backup -> number_of_backups_locally = $this -> numberOfBackupsLocally ;
$this -> backup -> save_s3 = $this -> saveS3 ;
$this -> backup -> s3_storage_id = $this -> s3StorageId ;
$this -> backup -> databases_to_backup = $this -> databasesToBackup ;
$this -> backup -> dump_all = $this -> dumpAll ;
$this -> backup -> save ();
} else {
$this -> backupEnabled = $this -> backup -> enabled ;
$this -> frequency = $this -> backup -> frequency ;
$this -> numberOfBackupsLocally = $this -> backup -> number_of_backups_locally ;
$this -> saveS3 = $this -> backup -> save_s3 ;
$this -> s3StorageId = $this -> backup -> s3_storage_id ;
$this -> databasesToBackup = $this -> backup -> databases_to_backup ;
$this -> dumpAll = $this -> backup -> dump_all ;
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
{
2024-10-24 14:20:01 +00:00
if ( ! data_get ( InstanceSettings :: get (), 'disable_two_step_confirmation' )) {
2024-10-22 10:29:48 +00:00
if ( ! Hash :: check ( $password , Auth :: user () -> password )) {
$this -> addError ( 'password' , 'The provided password is incorrect.' );
2024-09-23 17:51:31 +00:00
2024-10-22 10:29:48 +00:00
return ;
}
2024-08-31 16:29:19 +00:00
}
2024-03-21 11:44:32 +00:00
try {
2024-09-02 17:27:21 +00:00
if ( $this -> delete_associated_backups_locally ) {
$this -> deleteAssociatedBackupsLocally ();
}
if ( $this -> delete_associated_backups_s3 ) {
$this -> deleteAssociatedBackupsS3 ();
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
2024-10-28 13:56:13 +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 );
} else {
return redirect () -> route ( 'project.database.backup.index' , $this -> parameters );
}
} catch ( \Throwable $e ) {
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.' );
2023-09-11 15:36:30 +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 ;
}
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 ) {
2023-08-11 14:13:53 +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.' );
2023-09-11 15:36:30 +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
2024-11-04 11:40:10 +00:00
private function deleteAssociatedBackupsLocally ()
2024-08-31 16:29:19 +00:00
{
$executions = $this -> backup -> executions ;
2024-08-31 16:38:57 +00:00
$backupFolder = null ;
2024-08-31 16:29:19 +00:00
foreach ( $executions as $execution ) {
2024-10-28 13:56:13 +00:00
if ( $this -> backup -> database -> getMorphClass () === \App\Models\ServiceDatabase :: class ) {
2024-08-31 16:38:57 +00:00
$server = $this -> backup -> database -> service -> destination -> server ;
2024-08-31 16:29:19 +00:00
} else {
2024-08-31 16:38:57 +00:00
$server = $this -> backup -> database -> destination -> server ;
2024-08-31 16:29:19 +00:00
}
2024-09-23 17:51:31 +00:00
if ( ! $backupFolder ) {
2024-08-31 16:38:57 +00:00
$backupFolder = dirname ( $execution -> filename );
}
2024-09-23 17:51:31 +00:00
2024-08-31 16:38:57 +00:00
delete_backup_locally ( $execution -> filename , $server );
2024-08-31 16:29:19 +00:00
$execution -> delete ();
}
2024-08-31 16:38:57 +00:00
2024-11-04 11:40:10 +00:00
if ( str ( $backupFolder ) -> isNotEmpty ()) {
2024-08-31 16:38:57 +00:00
$this -> deleteEmptyBackupFolder ( $backupFolder , $server );
}
}
2024-11-04 11:40:10 +00:00
private function deleteAssociatedBackupsS3 ()
2024-09-02 17:27:21 +00:00
{
//Add function to delete backups from S3
}
2024-11-04 11:40:10 +00:00
private function deleteAssociatedBackupsSftp ()
2024-09-02 17:27:21 +00:00
{
//Add function to delete backups from SFTP
}
2024-08-31 16:38:57 +00:00
private function deleteEmptyBackupFolder ( $folderPath , $server )
{
$checkEmpty = instant_remote_process ([ " [ -z \" $ (ls -A ' $folderPath ') \" ] && echo 'empty' || echo 'not empty' " ], $server );
2024-09-23 17:51:31 +00:00
2024-08-31 16:38:57 +00:00
if ( trim ( $checkEmpty ) === 'empty' ) {
instant_remote_process ([ " rmdir ' $folderPath ' " ], $server );
2024-09-23 17:51:31 +00:00
2024-08-31 16:38:57 +00:00
$parentFolder = dirname ( $folderPath );
$checkParentEmpty = instant_remote_process ([ " [ -z \" $ (ls -A ' $parentFolder ') \" ] && echo 'empty' || echo 'not empty' " ], $server );
2024-09-23 17:51:31 +00:00
2024-08-31 16:38:57 +00:00
if ( trim ( $checkParentEmpty ) === 'empty' ) {
instant_remote_process ([ " rmdir ' $parentFolder ' " ], $server );
}
}
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' )],
2024-09-02 17:27:21 +00:00
// ['id' => 'delete_associated_backups_s3', 'label' => 'All backups associated with this backup job from this database will be permanently deleted from the selected S3 Storage.']
// ['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
}