diff --git a/app/Console/Commands/BackupDatabaseCommand.php b/app/Console/Commands/BackupDatabaseCommand.php new file mode 100644 index 0000000..86dab8a --- /dev/null +++ b/app/Console/Commands/BackupDatabaseCommand.php @@ -0,0 +1,70 @@ +format('Ymd-His') . '.sql'; + $path = $dir . '/' . $filename; + + $process = new Process([ + 'mysqldump', + '-h', $db['host'], + '-P', (string) $db['port'], + '-u', $db['username'], + '--single-transaction', + '--skip-lock-tables', + '--no-tablespaces', + '--result-file=' . $path, + $db['database'], + ], null, ['MYSQL_PWD' => $db['password']]); + + $process->setTimeout(120); + $process->run(); + + if (!$process->isSuccessful()) { + $this->error('Backup gagal: ' . $process->getErrorOutput()); + ActivityLog::create([ + 'user_id' => null, + 'user_name' => 'Sistem', + 'action' => 'backup', + 'description' => 'Backup terjadwal GAGAL: ' . $process->getErrorOutput(), + 'ip_address' => '127.0.0.1', + ]); + return self::FAILURE; + } + + // Prune: hapus backup lebih dari 7 file terlama + $files = glob($dir . '/backup-webgis-*.sql'); + usort($files, fn($a, $b) => filemtime($b) - filemtime($a)); + foreach (array_slice($files, 7) as $old) { + unlink($old); + } + + $this->info("Backup disimpan: {$filename}"); + ActivityLog::create([ + 'user_id' => null, + 'user_name' => 'Sistem', + 'action' => 'backup', + 'description' => "Backup terjadwal berhasil: {$filename}", + 'ip_address' => '127.0.0.1', + ]); + return self::SUCCESS; + } +} diff --git a/app/Http/Controllers/BackupController.php b/app/Http/Controllers/BackupController.php index 36fc3f3..6fcb6b2 100644 --- a/app/Http/Controllers/BackupController.php +++ b/app/Http/Controllers/BackupController.php @@ -38,4 +38,29 @@ class BackupController extends Controller 'Content-Disposition' => "attachment; filename=\"{$filename}\"", ]); } + + public function listBackups() + { + $dir = storage_path('app/backups'); + $files = is_dir($dir) ? glob($dir . '/backup-webgis-*.sql') : []; + usort($files, fn($a, $b) => filemtime($b) - filemtime($a)); + + $list = array_map(fn($f) => [ + 'name' => basename($f), + 'size_kb' => round(filesize($f) / 1024, 1), + 'created_at' => date('d/m/Y H:i', filemtime($f)), + ], $files); + + return response()->json($list); + } + + public function downloadStored(string $filename) + { + if (!preg_match('/^backup-webgis-[\d-]+\.sql$/', $filename)) { + abort(400, 'Nama file tidak valid'); + } + $path = storage_path('app/backups/' . $filename); + if (!file_exists($path)) abort(404); + return response()->download($path); + } } diff --git a/docker/app/entrypoint.sh b/docker/app/entrypoint.sh index eecd175..465acc6 100644 --- a/docker/app/entrypoint.sh +++ b/docker/app/entrypoint.sh @@ -20,4 +20,6 @@ fi php artisan migrate --force --no-ansi php artisan db:seed --force --no-ansi +php artisan schedule:work --no-interaction > /dev/null 2>&1 & + exec "$@" diff --git a/resources/views/admin/users.blade.php b/resources/views/admin/users.blade.php index f71e3b9..b8df32e 100644 --- a/resources/views/admin/users.blade.php +++ b/resources/views/admin/users.blade.php @@ -126,6 +126,30 @@
+ + +| File | Ukuran | Waktu | + |
|---|---|---|---|
| Memuat... | |||