Skip to content

Commit 76ac199

Browse files
Don't allow backups to be made via schedules if limit = 0 (pterodactyl#3323)
1 parent 5a82dd6 commit 76ac199

File tree

6 files changed

+42
-21
lines changed

6 files changed

+42
-21
lines changed

app/Http/Controllers/Api/Client/Servers/ScheduleTaskController.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public function __construct(TaskRepository $repository)
3939
*
4040
* @return array
4141
*
42+
* @throws \Pterodactyl\Exceptions\Model\HttpForbiddenException
4243
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
4344
* @throws \Pterodactyl\Exceptions\Service\ServiceLimitExceededException
4445
*/
@@ -49,6 +50,10 @@ public function store(StoreTaskRequest $request, Server $server, Schedule $sched
4950
throw new ServiceLimitExceededException("Schedules may not have more than {$limit} tasks associated with them. Creating this task would put this schedule over the limit.");
5051
}
5152

53+
if ($server->backup_limit === 0 && $request->action === 'backup') {
54+
throw new HttpForbiddenException("A backup task cannot be created when the server's backup limit is set to 0.");
55+
}
56+
5257
/** @var \Pterodactyl\Models\Task|null $lastTask */
5358
$lastTask = $schedule->tasks()->orderByDesc('sequence_id')->first();
5459

@@ -72,6 +77,7 @@ public function store(StoreTaskRequest $request, Server $server, Schedule $sched
7277
*
7378
* @return array
7479
*
80+
* @throws \Pterodactyl\Exceptions\Model\HttpForbiddenException
7581
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
7682
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
7783
*/
@@ -81,6 +87,10 @@ public function update(StoreTaskRequest $request, Server $server, Schedule $sche
8187
throw new NotFoundHttpException();
8288
}
8389

90+
if ($server->backup_limit === 0 && $request->action === 'backup') {
91+
throw new HttpForbiddenException("A backup task cannot be created when the server's backup limit is set to 0.");
92+
}
93+
8494
$this->repository->update($task->id, [
8595
'action' => $request->input('action'),
8696
'payload' => $request->input('payload') ?? '',

resources/scripts/components/dashboard/ApiKeyModal.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import tw from 'twin.macro';
33
import Button from '@/components/elements/Button';
44
import asModal from '@/hoc/asModal';
55
import ModalContext from '@/context/ModalContext';
6+
import CopyOnClick from '@/components/elements/CopyOnClick';
67

78
interface Props {
89
apiKey: string;
@@ -19,7 +20,7 @@ const ApiKeyModal = ({ apiKey }: Props) => {
1920
shown again.
2021
</p>
2122
<pre css={tw`text-sm bg-neutral-900 rounded py-2 px-4 font-mono`}>
22-
<code css={tw`font-mono`}>{apiKey}</code>
23+
<CopyOnClick text={apiKey}><code css={tw`font-mono`}>{apiKey}</code></CopyOnClick>
2324
</pre>
2425
<div css={tw`flex justify-end mt-6`}>
2526
<Button type={'button'} onClick={() => dismiss()}>

resources/scripts/components/server/databases/DatabasesContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export default () => {
5353
/>
5454
))
5555
:
56-
<p css={tw`text-center text-sm text-neutral-400`}>
56+
<p css={tw`text-center text-sm text-neutral-300`}>
5757
{databaseLimit > 0 ?
5858
'It looks like you have no databases.'
5959
:

resources/scripts/components/server/schedules/ScheduleEditContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default () => {
8181
}, []);
8282

8383
return (
84-
<PageContentBlock>
84+
<PageContentBlock title={'Schedules'}>
8585
<FlashMessageRender byKey={'schedules'} css={tw`mb-4`}/>
8686
{!schedule || isLoading ?
8787
<Spinner size={'large'} centered/>

resources/scripts/components/server/schedules/TaskDetailsModal.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const TaskDetailsModal = ({ schedule, task }: Props) => {
6969

7070
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
7171
const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
72+
const backupLimit = ServerContext.useStoreState(state => state.server.data!.featureLimits.backups);
7273

7374
useEffect(() => {
7475
return () => {
@@ -78,21 +79,26 @@ const TaskDetailsModal = ({ schedule, task }: Props) => {
7879

7980
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
8081
clearFlashes('schedule:task');
81-
createOrUpdateScheduleTask(uuid, schedule.id, task?.id, values)
82-
.then(task => {
83-
let tasks = schedule.tasks.map(t => t.id === task.id ? task : t);
84-
if (!schedule.tasks.find(t => t.id === task.id)) {
85-
tasks = [ ...tasks, task ];
86-
}
82+
if (backupLimit === 0 && values.action === 'backup') {
83+
setSubmitting(false);
84+
addError({ message: 'A backup task cannot be created when the server\'s backup limit is set to 0.', key: 'schedule:task' });
85+
} else {
86+
createOrUpdateScheduleTask(uuid, schedule.id, task?.id, values)
87+
.then(task => {
88+
let tasks = schedule.tasks.map(t => t.id === task.id ? task : t);
89+
if (!schedule.tasks.find(t => t.id === task.id)) {
90+
tasks = [ ...tasks, task ];
91+
}
8792

88-
appendSchedule({ ...schedule, tasks });
89-
dismiss();
90-
})
91-
.catch(error => {
92-
console.error(error);
93-
setSubmitting(false);
94-
addError({ message: httpErrorToHuman(error), key: 'schedule:task' });
95-
});
93+
appendSchedule({ ...schedule, tasks });
94+
dismiss();
95+
})
96+
.catch(error => {
97+
console.error(error);
98+
setSubmitting(false);
99+
addError({ message: httpErrorToHuman(error), key: 'schedule:task' });
100+
});
101+
}
96102
};
97103

98104
return (

tests/Integration/Api/Client/Server/ScheduleTask/CreateServerScheduleTaskTest.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ public function testValidationErrorsAreReturned()
8989
}
9090

9191
/**
92-
* Test that backups can be tasked out correctly since they do not require a payload.
92+
* Test that backups can not be tasked when the backup limit is 0
9393
*/
94-
public function testBackupsCanBeTaskedCorrectly()
94+
public function testBackupsCanNotBeTaskedIfLimit0()
9595
{
9696
[$user, $server] = $this->generateTestAccount();
9797

@@ -101,13 +101,17 @@ public function testBackupsCanBeTaskedCorrectly()
101101
$this->actingAs($user)->postJson($this->link($schedule, '/tasks'), [
102102
'action' => 'backup',
103103
'time_offset' => 0,
104-
])->assertOk();
104+
])
105+
->assertStatus(Response::HTTP_FORBIDDEN)
106+
->assertJsonPath('errors.0.detail', 'A backup task cannot be created when the server\'s backup limit is set to 0.');
105107

106108
$this->actingAs($user)->postJson($this->link($schedule, '/tasks'), [
107109
'action' => 'backup',
108110
'payload' => "file.txt\nfile2.log",
109111
'time_offset' => 0,
110-
])->assertOk();
112+
])
113+
->assertStatus(Response::HTTP_FORBIDDEN)
114+
->assertJsonPath('errors.0.detail', 'A backup task cannot be created when the server\'s backup limit is set to 0.');
111115
}
112116

113117
/**

0 commit comments

Comments
 (0)