diff --git a/app/Jobs/Schedule/RunTaskJob.php b/app/Jobs/Schedule/RunTaskJob.php
index 8784a37c..ee3c3e16 100644
--- a/app/Jobs/Schedule/RunTaskJob.php
+++ b/app/Jobs/Schedule/RunTaskJob.php
@@ -69,7 +69,7 @@ class RunTaskJob extends Job implements ShouldQueue
$commandRepository->setServer($server)->send($this->task->payload);
break;
case 'backup':
- $backupService->setIgnoredFiles(explode(PHP_EOL, $this->task->payload))->handle($server, null);
+ $backupService->setIgnoredFiles(explode(PHP_EOL, $this->task->payload))->handle($server, null, true);
break;
default:
throw new InvalidArgumentException('Cannot run a task that points to a non-existent action.');
diff --git a/app/Services/Backups/InitiateBackupService.php b/app/Services/Backups/InitiateBackupService.php
index ca8c3dec..5c34961a 100644
--- a/app/Services/Backups/InitiateBackupService.php
+++ b/app/Services/Backups/InitiateBackupService.php
@@ -13,6 +13,7 @@ use Pterodactyl\Repositories\Eloquent\BackupRepository;
use Pterodactyl\Repositories\Wings\DaemonBackupRepository;
use Pterodactyl\Exceptions\Service\Backup\TooManyBackupsException;
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
+use Pterodactyl\Services\Backups\DeleteBackupService;
class InitiateBackupService
{
@@ -41,24 +42,32 @@ class InitiateBackupService
*/
private $backupManager;
+ /**
+ * @var \Pterodactyl\Services\Backups\DeleteBackupService
+ */
+ private $deleteBackupService;
+
/**
* InitiateBackupService constructor.
*
* @param \Pterodactyl\Repositories\Eloquent\BackupRepository $repository
* @param \Illuminate\Database\ConnectionInterface $connection
* @param \Pterodactyl\Repositories\Wings\DaemonBackupRepository $daemonBackupRepository
+ * @param \Pterodactyl\Services\Backups\DeleteBackupService $deleteBackupService
* @param \Pterodactyl\Extensions\Backups\BackupManager $backupManager
*/
public function __construct(
BackupRepository $repository,
ConnectionInterface $connection,
DaemonBackupRepository $daemonBackupRepository,
+ DeleteBackupService $deleteBackupService,
BackupManager $backupManager
) {
$this->repository = $repository;
$this->connection = $connection;
$this->daemonBackupRepository = $daemonBackupRepository;
$this->backupManager = $backupManager;
+ $this->deleteBackupService = $deleteBackupService;
}
/**
@@ -96,13 +105,8 @@ class InitiateBackupService
* @throws \Pterodactyl\Exceptions\Service\Backup\TooManyBackupsException
* @throws \Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException
*/
- public function handle(Server $server, string $name = null): Backup
+ public function handle(Server $server, string $name = null, bool $override = false): Backup
{
- // Do not allow the user to continue if this server is already at its limit.
- if (! $server->backup_limit || $server->backups()->where('is_successful', true)->count() >= $server->backup_limit) {
- throw new TooManyBackupsException($server->backup_limit);
- }
-
$previous = $this->repository->getBackupsGeneratedDuringTimespan($server->id, 10);
if ($previous->count() >= 2) {
throw new TooManyRequestsHttpException(
@@ -111,6 +115,18 @@ class InitiateBackupService
);
}
+ // Check if the server has reached or exceeded it's backup limit
+ if (!$server->backup_limit || $server->backups()->where('is_successful', true)->count() >= $server->backup_limit) {
+ // Do not allow the user to continue if this server is already at its limit and can't override.
+ if (!$override || $server->backup_limit <= 0) {
+ throw new TooManyBackupsException($server->backup_limit);
+ }
+
+ // Remove oldest backup
+ $oldestBackup = $server->backups()->where('is_successful', true)->orderByDesc('created_at')->first();
+ $this->deleteBackupService->handle($oldestBackup);
+ }
+
return $this->connection->transaction(function () use ($server, $name) {
/** @var \Pterodactyl\Models\Backup $backup */
$backup = $this->repository->create([
diff --git a/resources/scripts/components/server/schedules/TaskDetailsModal.tsx b/resources/scripts/components/server/schedules/TaskDetailsModal.tsx
index e1fca0cb..08f33b16 100644
--- a/resources/scripts/components/server/schedules/TaskDetailsModal.tsx
+++ b/resources/scripts/components/server/schedules/TaskDetailsModal.tsx
@@ -91,7 +91,7 @@ const TaskDetailsForm = ({ isEditingTask }: { isEditingTask: boolean }) => {