Allow users to upload DirectAdmin backups
This commit is contained in:
@@ -13,6 +13,7 @@ use Filament\Actions\Action;
|
||||
use Filament\Actions\Concerns\InteractsWithActions;
|
||||
use Filament\Actions\Contracts\HasActions;
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Radio;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
@@ -215,6 +216,113 @@ class DirectAdminMigration extends Page implements HasActions, HasForms
|
||||
->icon('heroicon-o-folder')
|
||||
->visible(fn (Get $get): bool => $get('importMethod') === 'backup_file')
|
||||
->headerActions([
|
||||
Action::make('uploadBackup')
|
||||
->label(__('Upload'))
|
||||
->icon('heroicon-o-arrow-up-tray')
|
||||
->color('gray')
|
||||
->modalHeading(__('Upload Backup'))
|
||||
->modalDescription(fn (): string => ($user = $this->getUser())
|
||||
? __('Upload a DirectAdmin backup archive into /home/:user/backups', ['user' => $user->username])
|
||||
: __('Upload a DirectAdmin backup archive into your backups folder'))
|
||||
->modalSubmitActionLabel(__('Upload'))
|
||||
->form([
|
||||
FileUpload::make('backup')
|
||||
->label(__('DirectAdmin Backup Archive'))
|
||||
->storeFiles(false)
|
||||
->required()
|
||||
->acceptedFileTypes([
|
||||
'application/octet-stream',
|
||||
'application/x-tar',
|
||||
'application/zstd',
|
||||
'application/x-zstd',
|
||||
'application/gzip',
|
||||
'application/x-gzip',
|
||||
])
|
||||
->maxSize(512000) // 500MB in KB
|
||||
->helperText(__('Supported formats: .tar.zst, .tar.gz, .tgz (max 500MB via upload)')),
|
||||
])
|
||||
->action(function (array $data): void {
|
||||
try {
|
||||
$user = $this->getUser();
|
||||
if (! $user) {
|
||||
throw new Exception(__('You must be logged in.'));
|
||||
}
|
||||
|
||||
$file = $data['backup'] ?? null;
|
||||
if (! $file) {
|
||||
throw new Exception(__('Please select a backup file.'));
|
||||
}
|
||||
|
||||
$filename = (string) $file->getClientOriginalName();
|
||||
$filename = basename($filename);
|
||||
|
||||
if (! preg_match('/\\.(tar\\.zst|tar\\.gz|tgz)$/i', $filename)) {
|
||||
throw new Exception(__('Backup must be a .tar.zst, .tar.gz or .tgz file.'));
|
||||
}
|
||||
|
||||
$maxBytes = 500 * 1024 * 1024;
|
||||
$fileSize = (int) ($file->getSize() ?? 0);
|
||||
if ($fileSize > $maxBytes) {
|
||||
throw new Exception(__('File too large for upload (max 500MB). Upload it via SSH/SFTP to /home/:user/backups.', [
|
||||
'user' => $user->username,
|
||||
]));
|
||||
}
|
||||
|
||||
// Ensure backups folder exists
|
||||
$this->getAgent()->fileMkdir($user->username, 'backups');
|
||||
|
||||
// Stage into the agent-allowed temp dir, then let the agent move it.
|
||||
$tmpDir = '/tmp/jabali-uploads';
|
||||
if (! is_dir($tmpDir)) {
|
||||
mkdir($tmpDir, 0700, true);
|
||||
chmod($tmpDir, 0700);
|
||||
} else {
|
||||
@chmod($tmpDir, 0700);
|
||||
}
|
||||
|
||||
$safeName = preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename);
|
||||
$tmpPath = $tmpDir.'/'.uniqid('upload_', true).'_'.$safeName;
|
||||
|
||||
if (! @copy($file->getRealPath(), $tmpPath)) {
|
||||
throw new Exception(__('Failed to stage upload.'));
|
||||
}
|
||||
@chmod($tmpPath, 0600);
|
||||
|
||||
$result = $this->getAgent()->send('file.upload_temp', [
|
||||
'username' => $user->username,
|
||||
'path' => 'backups',
|
||||
'filename' => $safeName,
|
||||
'temp_path' => $tmpPath,
|
||||
]);
|
||||
|
||||
if (! ($result['success'] ?? false)) {
|
||||
if (file_exists($tmpPath)) {
|
||||
@unlink($tmpPath);
|
||||
}
|
||||
throw new Exception((string) ($result['error'] ?? __('Upload failed')));
|
||||
}
|
||||
|
||||
$this->loadLocalBackups();
|
||||
|
||||
$uploadedPath = $result['path'] ?? null;
|
||||
if (is_string($uploadedPath) && $uploadedPath !== '') {
|
||||
$this->localBackupPath = $uploadedPath;
|
||||
$this->selectLocalBackup();
|
||||
}
|
||||
|
||||
Notification::make()
|
||||
->title(__('Backup uploaded'))
|
||||
->body(__('Uploaded :name', ['name' => $safeName]))
|
||||
->success()
|
||||
->send();
|
||||
} catch (Exception $e) {
|
||||
Notification::make()
|
||||
->title(__('Upload failed'))
|
||||
->body($e->getMessage())
|
||||
->danger()
|
||||
->send();
|
||||
}
|
||||
}),
|
||||
Action::make('refreshLocalBackups')
|
||||
->label(__('Refresh'))
|
||||
->icon('heroicon-o-arrow-path')
|
||||
|
||||
Reference in New Issue
Block a user