From 06707fd33a2b8727ebf89738b451ed6da090bc36 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 9 Apr 2020 22:35:38 -0700 Subject: [PATCH] Better throttling of backup generation --- .php_cs | 1 + .../Api/Client/Servers/BackupController.php | 25 +++++++++++++++++-- .../Eloquent/BackupRepository.php | 18 +++++++++++++ routes/api-client.php | 2 +- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.php_cs b/.php_cs index fdb94601d..8a52ffee6 100644 --- a/.php_cs +++ b/.php_cs @@ -46,6 +46,7 @@ return PhpCsFixer\Config::create() 'psr0' => ['dir' => 'app'], 'psr4' => true, 'random_api_migration' => true, + 'single_line_throw' => false, 'standardize_not_equals' => true, 'ternary_to_null_coalescing' => true, 'yoda_style' => [ diff --git a/app/Http/Controllers/Api/Client/Servers/BackupController.php b/app/Http/Controllers/Api/Client/Servers/BackupController.php index f908f81f8..222f6711c 100644 --- a/app/Http/Controllers/Api/Client/Servers/BackupController.php +++ b/app/Http/Controllers/Api/Client/Servers/BackupController.php @@ -2,13 +2,16 @@ namespace Pterodactyl\Http\Controllers\Api\Client\Servers; +use Carbon\Carbon; use Pterodactyl\Models\Backup; use Pterodactyl\Models\Server; use Illuminate\Http\JsonResponse; use Pterodactyl\Services\Backups\DeleteBackupService; +use Pterodactyl\Repositories\Eloquent\BackupRepository; use Pterodactyl\Services\Backups\InitiateBackupService; use Pterodactyl\Transformers\Api\Client\BackupTransformer; use Pterodactyl\Http\Controllers\Api\Client\ClientApiController; +use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; use Pterodactyl\Http\Requests\Api\Client\Servers\Backups\GetBackupsRequest; use Pterodactyl\Http\Requests\Api\Client\Servers\Backups\StoreBackupRequest; use Pterodactyl\Http\Requests\Api\Client\Servers\Backups\DeleteBackupRequest; @@ -25,18 +28,28 @@ class BackupController extends ClientApiController */ private $deleteBackupService; + /** + * @var \Pterodactyl\Repositories\Eloquent\BackupRepository + */ + private $repository; + /** * BackupController constructor. * + * @param \Pterodactyl\Repositories\Eloquent\BackupRepository $repository * @param \Pterodactyl\Services\Backups\DeleteBackupService $deleteBackupService * @param \Pterodactyl\Services\Backups\InitiateBackupService $initiateBackupService */ - public function __construct(DeleteBackupService $deleteBackupService, InitiateBackupService $initiateBackupService) - { + public function __construct( + BackupRepository $repository, + DeleteBackupService $deleteBackupService, + InitiateBackupService $initiateBackupService + ) { parent::__construct(); $this->initiateBackupService = $initiateBackupService; $this->deleteBackupService = $deleteBackupService; + $this->repository = $repository; } /** @@ -65,6 +78,14 @@ class BackupController extends ClientApiController */ public function store(StoreBackupRequest $request, Server $server) { + $previous = $this->repository->getBackupsGeneratedDuringTimespan($server->id, 10); + if ($previous->count() >= 2) { + throw new TooManyRequestsHttpException( + Carbon::now()->diffInSeconds($previous->last()->created_at->addMinutes(10)), + 'Only two backups may be generated within a 10 minute span of time.' + ); + } + $backup = $this->initiateBackupService ->setIgnoredFiles($request->input('ignored')) ->handle($server, $request->input('name')); diff --git a/app/Repositories/Eloquent/BackupRepository.php b/app/Repositories/Eloquent/BackupRepository.php index 2ff206325..4afdd4bd2 100644 --- a/app/Repositories/Eloquent/BackupRepository.php +++ b/app/Repositories/Eloquent/BackupRepository.php @@ -2,6 +2,7 @@ namespace Pterodactyl\Repositories\Eloquent; +use Carbon\Carbon; use Pterodactyl\Models\Backup; class BackupRepository extends EloquentRepository @@ -13,4 +14,21 @@ class BackupRepository extends EloquentRepository { return Backup::class; } + + /** + * Determines if too many backups have been generated by the server. + * + * @param int $server + * @param int $minutes + * @return \Pterodactyl\Models\Backup[]|\Illuminate\Support\Collection + */ + public function getBackupsGeneratedDuringTimespan(int $server, int $minutes = 10) + { + return $this->getBuilder() + ->withTrashed() + ->where('server_id', $server) + ->where('created_at', '>=', Carbon::now()->subMinutes($minutes)->toDateTimeString()) + ->get() + ->toBase(); + } } diff --git a/routes/api-client.php b/routes/api-client.php index 3d0971c10..5ad045801 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -89,7 +89,7 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ Route::group(['prefix' => '/backups'], function () { Route::get('/', 'Servers\BackupController@index'); - Route::post('/', 'Servers\BackupController@store')->middleware('throttle:2,10'); + Route::post('/', 'Servers\BackupController@store'); Route::get('/{backup}', 'Servers\BackupController@view'); Route::get('/{backup}/download', 'Servers\DownloadBackupController'); Route::delete('/{backup}', 'Servers\BackupController@delete');