@@ -21,6 +21,11 @@ class InitiateBackupService
2121 */
2222 private $ ignoredFiles ;
2323
24+ /**
25+ * @var bool
26+ */
27+ private $ isLocked = false ;
28+
2429 /**
2530 * @var \Pterodactyl\Repositories\Eloquent\BackupRepository
2631 */
@@ -49,7 +54,11 @@ class InitiateBackupService
4954 /**
5055 * InitiateBackupService constructor.
5156 *
57+ * @param \Pterodactyl\Repositories\Eloquent\BackupRepository $repository
58+ * @param \Illuminate\Database\ConnectionInterface $connection
59+ * @param \Pterodactyl\Repositories\Wings\DaemonBackupRepository $daemonBackupRepository
5260 * @param \Pterodactyl\Services\Backups\DeleteBackupService $deleteBackupService
61+ * @param \Pterodactyl\Extensions\Backups\BackupManager $backupManager
5362 */
5463 public function __construct (
5564 BackupRepository $ repository ,
@@ -65,6 +74,19 @@ public function __construct(
6574 $ this ->deleteBackupService = $ deleteBackupService ;
6675 }
6776
77+ /**
78+ * Set if the backup should be locked once it is created which will prevent
79+ * its deletion by users or automated system processes.
80+ *
81+ * @return $this
82+ */
83+ public function setIsLocked (bool $ isLocked ): self
84+ {
85+ $ this ->isLocked = $ isLocked ;
86+
87+ return $ this ;
88+ }
89+
6890 /**
6991 * Sets the files to be ignored by this backup.
7092 *
@@ -91,7 +113,7 @@ public function setIgnoredFiles(?array $ignored)
91113 }
92114
93115 /**
94- * Initiates the backup process for a server on the daemon .
116+ * Initiates the backup process for a server on Wings .
95117 *
96118 * @throws \Throwable
97119 * @throws \Pterodactyl\Exceptions\Service\Backup\TooManyBackupsException
@@ -104,23 +126,30 @@ public function handle(Server $server, string $name = null, bool $override = fal
104126 if ($ period > 0 ) {
105127 $ previous = $ this ->repository ->getBackupsGeneratedDuringTimespan ($ server ->id , $ period );
106128 if ($ previous ->count () >= $ limit ) {
107- throw new TooManyRequestsHttpException (CarbonImmutable::now ()->diffInSeconds ($ previous ->last ()->created_at ->addSeconds ($ period )), sprintf ('Only %d backups may be generated within a %d second span of time. ' , $ limit , $ period ));
129+ $ message = sprintf ('Only %d backups may be generated within a %d second span of time. ' , $ limit , $ period );
130+
131+ throw new TooManyRequestsHttpException (CarbonImmutable::now ()->diffInSeconds ($ previous ->last ()->created_at ->addSeconds ($ period )), $ message );
108132 }
109133 }
110134
111- // Check if the server has reached or exceeded it's backup limit
112- if (!$ server ->backup_limit || $ server ->backups ()->where ('is_successful ' , true )->count () >= $ server ->backup_limit ) {
135+ // Check if the server has reached or exceeded it's backup limit.
136+ $ successful = $ server ->backups ()->where ('is_successful ' , true );
137+ if (!$ server ->backup_limit || $ successful ->count () >= $ server ->backup_limit ) {
113138 // Do not allow the user to continue if this server is already at its limit and can't override.
114139 if (!$ override || $ server ->backup_limit <= 0 ) {
115140 throw new TooManyBackupsException ($ server ->backup_limit );
116141 }
117142
118- // Get the oldest backup the server has.
119- /** @var \Pterodactyl\Models\Backup $oldestBackup */
120- $ oldestBackup = $ server ->backups ()->where ('is_successful ' , true )->orderBy ('created_at ' )->first ();
143+ // Get the oldest backup the server has that is not "locked" (indicating a backup that should
144+ // never be automatically purged). If we find a backup we will delete it and then continue with
145+ // this process. If no backup is found that can be used an exception is thrown.
146+ /** @var \Pterodactyl\Models\Backup $oldest */
147+ $ oldest = $ successful ->where ('is_locked ' , false )->orderBy ('created_at ' )->first ();
148+ if (!$ oldest ) {
149+ throw new TooManyBackupsException ($ server ->backup_limit );
150+ }
121151
122- // Delete the oldest backup.
123- $ this ->deleteBackupService ->handle ($ oldestBackup );
152+ $ this ->deleteBackupService ->handle ($ oldest );
124153 }
125154
126155 return $ this ->connection ->transaction (function () use ($ server , $ name ) {
@@ -131,6 +160,7 @@ public function handle(Server $server, string $name = null, bool $override = fal
131160 'name ' => trim ($ name ) ?: sprintf ('Backup at %s ' , CarbonImmutable::now ()->toDateTimeString ()),
132161 'ignored_files ' => array_values ($ this ->ignoredFiles ?? []),
133162 'disk ' => $ this ->backupManager ->getDefaultAdapter (),
163+ 'is_locked ' => $ this ->isLocked ,
134164 ], true , true );
135165
136166 $ this ->daemonBackupRepository ->setServer ($ server )
0 commit comments