backupService = $backupService; $this->systemConfig = $systemConfig; } public function index(Request $request) { if ($request->wantsJson() || $request->ajax()) { try { session_write_close(); $driver = $request->get('driver'); return response()->json([ 'success' => true, 'backups' => $this->backupService->getBackupList(), 'stats' => $this->backupService->getStorageStats($driver), ]); } catch (Exception $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } } return view('pages.system_settings.backup-restore', [ 'settings' => $this->systemConfig->all(), ]); } public function create() { try { // Prevent session locking during the long-running backup process session_write_close(); set_time_limit(0); ini_set('memory_limit', '512M'); $this->backupService->createBackup(); // ✍️ Log "Action Log" backup creation activity('backups') ->causedBy(auth()->user()) ->withProperties([ 'ip' => request()->ip(), 'agent' => request()->userAgent(), 'details' => __('Manually triggered a system and database backup.'), ]) ->log(__('Generated System Backup')); return response()->json([ 'success' => true, 'message' => __('Backup created successfully'), 'backups' => $this->backupService->getBackupList(forceRefresh: true), ]); } catch (Exception $e) { Log::error('Backup failed: '.$e->getMessage()); return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } } private function allowedDisks(): array { return ['local', 's3', 'gdrive']; } public function download(Request $request) { $validated = $request->validate([ 'disk' => ['required', 'string', Rule::in($this->allowedDisks())], 'path' => ['required', 'string'], ]); $disk = $validated['disk']; $path = $validated['path']; if (! Storage::disk($disk)->exists($path)) { abort(404, __('File not found')); } // ✍️ Log "Action Log" backup download activity('backups') ->causedBy(auth()->user()) ->withProperties([ 'ip' => $request->ip(), 'agent' => $request->userAgent(), 'file' => $path, 'disk' => $disk, 'details' => __('Downloaded backup file: :file from :disk storage.', ['file' => $path, 'disk' => $disk]), ]) ->log(__('Downloaded Backup File')); return Storage::disk($disk)->download($path); } public function destroy(Request $request) { try { session_write_close(); $validated = $request->validate([ 'disk' => ['required', 'string', Rule::in($this->allowedDisks())], 'path' => ['required', 'string'], ]); $disk = $validated['disk']; $path = $validated['path']; if (Storage::disk($disk)->exists($path)) { Storage::disk($disk)->delete($path); // ✍️ Log "Action Log" backup deletion activity('backups') ->causedBy(auth()->user()) ->withProperties([ 'ip' => $request->ip(), 'agent' => $request->userAgent(), 'file' => $path, 'details' => __('Permanently deleted backup file: :file', ['file' => $path]), ]) ->log(__('Deleted Backup File')); } return response()->json([ 'success' => true, 'message' => __('Backup deleted successfully'), 'backups' => $this->backupService->getBackupList(forceRefresh: true), ]); } catch (Exception $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } } public function restore(Request $request) { try { session_write_close(); set_time_limit(0); ini_set('memory_limit', '512M'); $validated = $request->validate([ 'disk' => ['required', 'string', Rule::in($this->allowedDisks())], 'path' => ['required', 'string'], ]); $disk = $validated['disk']; $path = $validated['path']; $this->backupService->restoreBackup($disk, $path); // ✍️ Log "Action Log" system restore activity('backups') ->causedBy(auth()->user()) ->withProperties([ 'ip' => $request->ip(), 'agent' => $request->userAgent(), 'file' => $path, 'details' => __('Successfully restored system from backup: :file', ['file' => $path]), ]) ->log(__('Restored System from Backup')); return response()->json([ 'message' => __('System restored successfully. Cache cleared.'), ]); } catch (Exception $e) { Log::error('Restore failed: '.$e->getMessage()); return response()->json(['message' => $e->getMessage()], 500); } } public function testConnection() { try { $result = $this->backupService->testConnection(); return response()->json($result); } catch (Exception $e) { return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } } /** * Redirect to Google for authorization. */ public function googleAuth() { $settings = $this->systemConfig->all(); if (empty($settings['gdrive_client_id']) || empty($settings['gdrive_client_secret'])) { return redirect()->back()->with('error', __('Please save Client ID and Secret first.')); } // Dynamically set config for Socialite to use settings from database config([ 'services.google.client_id' => $settings['gdrive_client_id'], 'services.google.client_secret' => $settings['gdrive_client_secret'], 'services.google.redirect' => route('backup-restore.google-callback'), ]); return Socialite::driver('google') ->scopes(['https://www.googleapis.com/auth/drive.file']) ->with(['access_type' => 'offline', 'prompt' => 'consent']) ->redirect(); } /** * Handle Google authorization callback. */ public function googleCallback() { try { $settings = $this->systemConfig->all(); config([ 'services.google.client_id' => $settings['gdrive_client_id'], 'services.google.client_secret' => $settings['gdrive_client_secret'], 'services.google.redirect' => route('backup-restore.google-callback'), ]); $user = Socialite::driver('google')->user(); $refreshToken = $user->refreshToken; if (! $refreshToken) { return redirect()->route('backup-restore.index')->with('error', __('Failed to get refresh token. Please ensure you have not already authorized this app, or try revoking access and authorizing again.')); } // Save the refresh token to system settings $this->systemConfig->update(['gdrive_refresh_token' => $refreshToken]); return redirect()->route('backup-restore.index')->with('status', __('Google Drive authorized successfully!')); } catch (Exception $e) { Log::error('Google Auth Failed: '.$e->getMessage()); return redirect()->route('backup-restore.index')->with('error', __('Authorization failed: ').$e->getMessage()); } } }