Skip to content

Commit d517c7a

Browse files
committed
Merge branch 'issue/353' into 353
2 parents 0e72189 + 704a1f8 commit d517c7a

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed

app/Filament/App/Resources/BackupResource.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class BackupResource extends Resource
1010
{
1111
protected static ?string $model = Backup::class;
1212

13+
protected static bool $canCreateAnother = false;
14+
1315
protected static ?string $navigationIcon = 'tabler-download';
1416

1517
public static function getPages(): array

app/Filament/App/Resources/BackupResource/Pages/ListBackups.php

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,57 @@
22

33
namespace App\Filament\App\Resources\BackupResource\Pages;
44

5+
use App\Enums\ServerState;
6+
use App\Facades\Activity;
57
use App\Filament\App\Resources\BackupResource;
68
use App\Http\Controllers\Api\Client\Servers\BackupController;
79
use App\Models\Backup;
10+
use App\Models\Permission;
11+
use App\Repositories\Daemon\DaemonBackupRepository;
812
use App\Services\Backups\DownloadLinkService;
13+
use App\Services\Backups\InitiateBackupService;
914
use Filament\Actions;
1015
use Filament\Facades\Filament;
16+
use Filament\Forms\Components\Checkbox;
17+
use Filament\Forms\Components\Placeholder;
18+
use Filament\Forms\Components\Textarea;
19+
use Filament\Forms\Components\TextInput;
20+
use Filament\Forms\Components\Toggle;
1121
use Filament\Forms\Form;
22+
use Filament\Notifications\Notification;
1223
use Filament\Resources\Pages\ListRecords;
1324
use Filament\Tables\Actions\Action;
1425
use Filament\Tables\Columns\IconColumn;
1526
use Filament\Tables\Columns\TextColumn;
1627
use Filament\Tables\Table;
1728
use Illuminate\Http\Request;
29+
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
1830

1931
class ListBackups extends ListRecords
2032
{
2133
protected static string $resource = BackupResource::class;
34+
protected static bool $canCreateAnother = false;
2235

2336
public function form(Form $form): Form
2437
{
2538
return $form
2639
->schema([
27-
//TODO
40+
TextInput::make('name')
41+
->label('Name')
42+
->columnSpanFull()
43+
->required(),
44+
TextArea::make('ignored')
45+
->columnSpanFull()
46+
->label('Ignored Files & Directories'),
47+
Toggle::make('is_locked')
48+
->label('Lock?')
49+
->helperText('Prevents this backup from being deleted until explicitly unlocked.'),
2850
]);
2951
}
3052

3153
public function table(Table $table): Table
3254
{
55+
/** @var \App\Models\Server $server */
3356
$server = Filament::getTenant();
3457

3558
return $table
@@ -51,22 +74,106 @@ public function table(Table $table): Table
5174
])
5275
->actions([
5376
Action::make('lock')
77+
->hidden(!auth()->user()->can(Permission::ACTION_BACKUP_DELETE, Filament::getTenant()))
5478
->label(fn (Backup $backup) => !$backup->is_locked ? 'Lock' : 'Unlock')
5579
->action(fn (BackupController $backupController, Backup $backup, Request $request) => $backupController->toggleLock($request, $server, $backup)),
5680
Action::make('download')
81+
->hidden(!auth()->user()->can(Permission::ACTION_BACKUP_DOWNLOAD, Filament::getTenant()))
5782
->url(function (DownloadLinkService $downloadLinkService, Backup $backup, Request $request) {
5883
return $downloadLinkService->handle($backup, $request->user());
5984
}, true),
60-
Action::make('restore'),
85+
Action::make('restore')
86+
->hidden(!auth()->user()->can(Permission::ACTION_BACKUP_RESTORE, Filament::getTenant()))
87+
->form([
88+
Placeholder::make('')
89+
->helperText('Your server will be stopped. You will not be able to control the power state, access the file manager, or create additional backups until this process is completed.'),
90+
Checkbox::make('truncate')
91+
->label('Delete all files before restoring backup?'),
92+
])
93+
->action(function (Backup $backup, $data, DaemonBackupRepository $daemonRepository, DownloadLinkService $downloadLinkService) {
94+
95+
/** @var \App\Models\Server $server */
96+
$server = Filament::getTenant();
97+
98+
if (!is_null($server->status)) {
99+
throw new BadRequestHttpException('This server is not currently in a state that allows for a backup to be restored.');
100+
}
101+
102+
if (!$backup->is_successful && is_null($backup->completed_at)) {
103+
throw new BadRequestHttpException('This backup cannot be restored at this time: not completed or failed.');
104+
}
105+
106+
$log = Activity::event('server:backup.restore')
107+
->subject($backup)
108+
->property(['name' => $backup->name, 'truncate' => $data['truncate']]);
109+
110+
$log->transaction(function () use ($downloadLinkService, $daemonRepository, $backup, $server, $data) {
111+
// If the backup is for an S3 file we need to generate a unique Download link for
112+
// it that will allow daemon to actually access the file.
113+
if ($backup->disk === Backup::ADAPTER_AWS_S3) {
114+
$url = $downloadLinkService->handle($backup, auth()->user());
115+
}
116+
117+
// Update the status right away for the server so that we know not to allow certain
118+
// actions against it via the Panel API.
119+
$server->update(['status' => ServerState::RestoringBackup]);
120+
121+
$daemonRepository->setServer($server)->restore($backup, $url ?? null, $data['truncate']);
122+
});
123+
124+
return Notification::make()->title('Restoring Backup')->send();
125+
}),
61126
Action::make('delete')
127+
->fillForm(fn (Backup $backup): array => [
128+
'name' => $backup->name,
129+
])
130+
->form([
131+
TextInput::make('name')
132+
->label('Name')
133+
->disabled(),
134+
])
135+
->disabled(fn (Backup $backup): bool => $backup->is_locked)
136+
->hidden(!auth()->user()->can(Permission::ACTION_BACKUP_DELETE, Filament::getTenant()))
137+
->requiresConfirmation()
62138
->action(fn (BackupController $backupController, Backup $backup, Request $request) => $backupController->delete($request, $server, $backup)),
63139
]);
64140
}
65141

66142
protected function getHeaderActions(): array
67143
{
144+
/** @var \App\Models\Server $server */
145+
$server = Filament::getTenant();
146+
68147
return [
69-
Actions\CreateAction::make(),
148+
Actions\CreateAction::make()
149+
->label(fn () => $server->backups()->count() >= $server->backup_limit ? 'Backup Limit Reached' : 'Create Backup')
150+
->disabled(fn () => $server->backups()->count() >= $server->backup_limit)
151+
->createAnother(false)
152+
->action(function (InitiateBackupService $initiateBackupService, $data) {
153+
154+
/** @var \App\Models\Server $server */
155+
$server = Filament::getTenant();
156+
157+
$action = $initiateBackupService
158+
->setIgnoredFiles(explode(PHP_EOL, $data['ignored'] ?? ''));
159+
160+
if (auth()->user()->can(Permission::ACTION_BACKUP_DELETE, $server)) {
161+
$action->setIsLocked((bool) $data['is_locked']);
162+
}
163+
164+
$backup = $action->handle($server, $data['name']);
165+
166+
Activity::event('server:backup.start')
167+
->subject($backup)
168+
->property(['name' => $backup->name, 'locked' => (bool) $data['is_locked']])
169+
->log();
170+
171+
return Notification::make()
172+
->title('Backup Created')
173+
->body($backup->name . ' created.')
174+
->success()
175+
->send();
176+
}),
70177
];
71178
}
72179

0 commit comments

Comments
 (0)