Files
biiproject-kit-v1/app/Http/Controllers/SystemSettings/BackupRestoreController.php
T

257 lines
8.8 KiB
PHP

<?php
namespace App\Http\Controllers\SystemSettings;
use App\Http\Controllers\Controller;
use App\Services\System\BackupManagementService;
use App\Services\SystemConfig\SystemConfigService;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Laravel\Socialite\Facades\Socialite;
class BackupRestoreController extends Controller
{
protected $backupService;
protected $systemConfig;
public function __construct(
BackupManagementService $backupService,
SystemConfigService $systemConfig
) {
$this->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());
}
}
}