From 76ac1998cfbb8798ce69844fccc196673b5294af Mon Sep 17 00:00:00 2001 From: Charles Morgan Date: Sun, 16 May 2021 12:47:36 -0400 Subject: [PATCH] Don't allow backups to be made via schedules if limit = 0 (#3323) --- .../Client/Servers/ScheduleTaskController.php | 10 ++++++ .../components/dashboard/ApiKeyModal.tsx | 3 +- .../server/databases/DatabasesContainer.tsx | 2 +- .../schedules/ScheduleEditContainer.tsx | 2 +- .../server/schedules/TaskDetailsModal.tsx | 34 +++++++++++-------- .../CreateServerScheduleTaskTest.php | 12 ++++--- 6 files changed, 42 insertions(+), 21 deletions(-) diff --git a/app/Http/Controllers/Api/Client/Servers/ScheduleTaskController.php b/app/Http/Controllers/Api/Client/Servers/ScheduleTaskController.php index 12bcf968..4ceed655 100644 --- a/app/Http/Controllers/Api/Client/Servers/ScheduleTaskController.php +++ b/app/Http/Controllers/Api/Client/Servers/ScheduleTaskController.php @@ -39,6 +39,7 @@ class ScheduleTaskController extends ClientApiController * * @return array * + * @throws \Pterodactyl\Exceptions\Model\HttpForbiddenException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Service\ServiceLimitExceededException */ @@ -49,6 +50,10 @@ class ScheduleTaskController extends ClientApiController throw new ServiceLimitExceededException("Schedules may not have more than {$limit} tasks associated with them. Creating this task would put this schedule over the limit."); } + if ($server->backup_limit === 0 && $request->action === 'backup') { + throw new HttpForbiddenException("A backup task cannot be created when the server's backup limit is set to 0."); + } + /** @var \Pterodactyl\Models\Task|null $lastTask */ $lastTask = $schedule->tasks()->orderByDesc('sequence_id')->first(); @@ -72,6 +77,7 @@ class ScheduleTaskController extends ClientApiController * * @return array * + * @throws \Pterodactyl\Exceptions\Model\HttpForbiddenException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ @@ -81,6 +87,10 @@ class ScheduleTaskController extends ClientApiController throw new NotFoundHttpException(); } + if ($server->backup_limit === 0 && $request->action === 'backup') { + throw new HttpForbiddenException("A backup task cannot be created when the server's backup limit is set to 0."); + } + $this->repository->update($task->id, [ 'action' => $request->input('action'), 'payload' => $request->input('payload') ?? '', diff --git a/resources/scripts/components/dashboard/ApiKeyModal.tsx b/resources/scripts/components/dashboard/ApiKeyModal.tsx index ba6568b8..e2c129a5 100644 --- a/resources/scripts/components/dashboard/ApiKeyModal.tsx +++ b/resources/scripts/components/dashboard/ApiKeyModal.tsx @@ -3,6 +3,7 @@ import tw from 'twin.macro'; import Button from '@/components/elements/Button'; import asModal from '@/hoc/asModal'; import ModalContext from '@/context/ModalContext'; +import CopyOnClick from '@/components/elements/CopyOnClick'; interface Props { apiKey: string; @@ -19,7 +20,7 @@ const ApiKeyModal = ({ apiKey }: Props) => { shown again.
- {apiKey} + {apiKey}
{apiKey}
+
{databaseLimit > 0 ? 'It looks like you have no databases.' : diff --git a/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx b/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx index a643d2a5..720f0c72 100644 --- a/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx +++ b/resources/scripts/components/server/schedules/ScheduleEditContainer.tsx @@ -81,7 +81,7 @@ export default () => { }, []); return ( - + {!schedule || isLoading ? diff --git a/resources/scripts/components/server/schedules/TaskDetailsModal.tsx b/resources/scripts/components/server/schedules/TaskDetailsModal.tsx index 9b30d66f..c83d754c 100644 --- a/resources/scripts/components/server/schedules/TaskDetailsModal.tsx +++ b/resources/scripts/components/server/schedules/TaskDetailsModal.tsx @@ -69,6 +69,7 @@ const TaskDetailsModal = ({ schedule, task }: Props) => { const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule); + const backupLimit = ServerContext.useStoreState(state => state.server.data!.featureLimits.backups); useEffect(() => { return () => { @@ -78,21 +79,26 @@ const TaskDetailsModal = ({ schedule, task }: Props) => { const submit = (values: Values, { setSubmitting }: FormikHelpers) => { clearFlashes('schedule:task'); - createOrUpdateScheduleTask(uuid, schedule.id, task?.id, values) - .then(task => { - let tasks = schedule.tasks.map(t => t.id === task.id ? task : t); - if (!schedule.tasks.find(t => t.id === task.id)) { - tasks = [ ...tasks, task ]; - } + if (backupLimit === 0 && values.action === 'backup') { + setSubmitting(false); + addError({ message: 'A backup task cannot be created when the server\'s backup limit is set to 0.', key: 'schedule:task' }); + } else { + createOrUpdateScheduleTask(uuid, schedule.id, task?.id, values) + .then(task => { + let tasks = schedule.tasks.map(t => t.id === task.id ? task : t); + if (!schedule.tasks.find(t => t.id === task.id)) { + tasks = [ ...tasks, task ]; + } - appendSchedule({ ...schedule, tasks }); - dismiss(); - }) - .catch(error => { - console.error(error); - setSubmitting(false); - addError({ message: httpErrorToHuman(error), key: 'schedule:task' }); - }); + appendSchedule({ ...schedule, tasks }); + dismiss(); + }) + .catch(error => { + console.error(error); + setSubmitting(false); + addError({ message: httpErrorToHuman(error), key: 'schedule:task' }); + }); + } }; return ( diff --git a/tests/Integration/Api/Client/Server/ScheduleTask/CreateServerScheduleTaskTest.php b/tests/Integration/Api/Client/Server/ScheduleTask/CreateServerScheduleTaskTest.php index 6add744c..d79173fb 100644 --- a/tests/Integration/Api/Client/Server/ScheduleTask/CreateServerScheduleTaskTest.php +++ b/tests/Integration/Api/Client/Server/ScheduleTask/CreateServerScheduleTaskTest.php @@ -89,9 +89,9 @@ class CreateServerScheduleTaskTest extends ClientApiIntegrationTestCase } /** - * Test that backups can be tasked out correctly since they do not require a payload. + * Test that backups can not be tasked when the backup limit is 0 */ - public function testBackupsCanBeTaskedCorrectly() + public function testBackupsCanNotBeTaskedIfLimit0() { [$user, $server] = $this->generateTestAccount(); @@ -101,13 +101,17 @@ class CreateServerScheduleTaskTest extends ClientApiIntegrationTestCase $this->actingAs($user)->postJson($this->link($schedule, '/tasks'), [ 'action' => 'backup', 'time_offset' => 0, - ])->assertOk(); + ]) + ->assertStatus(Response::HTTP_FORBIDDEN) + ->assertJsonPath('errors.0.detail', 'A backup task cannot be created when the server\'s backup limit is set to 0.'); $this->actingAs($user)->postJson($this->link($schedule, '/tasks'), [ 'action' => 'backup', 'payload' => "file.txt\nfile2.log", 'time_offset' => 0, - ])->assertOk(); + ]) + ->assertStatus(Response::HTTP_FORBIDDEN) + ->assertJsonPath('errors.0.detail', 'A backup task cannot be created when the server\'s backup limit is set to 0.'); } /**