Don't allow backups to be made via schedules if limit = 0 (#3323)

This commit is contained in:
Charles Morgan 2021-05-16 12:47:36 -04:00 committed by GitHub
parent 5a82dd6a18
commit 76ac1998cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 21 deletions

View file

@ -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') ?? '',

View file

@ -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.
</p>
<pre css={tw`text-sm bg-neutral-900 rounded py-2 px-4 font-mono`}>
<code css={tw`font-mono`}>{apiKey}</code>
<CopyOnClick text={apiKey}><code css={tw`font-mono`}>{apiKey}</code></CopyOnClick>
</pre>
<div css={tw`flex justify-end mt-6`}>
<Button type={'button'} onClick={() => dismiss()}>

View file

@ -53,7 +53,7 @@ export default () => {
/>
))
:
<p css={tw`text-center text-sm text-neutral-400`}>
<p css={tw`text-center text-sm text-neutral-300`}>
{databaseLimit > 0 ?
'It looks like you have no databases.'
:

View file

@ -81,7 +81,7 @@ export default () => {
}, []);
return (
<PageContentBlock>
<PageContentBlock title={'Schedules'}>
<FlashMessageRender byKey={'schedules'} css={tw`mb-4`}/>
{!schedule || isLoading ?
<Spinner size={'large'} centered/>

View file

@ -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<Values>) => {
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 (

View file

@ -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.');
}
/**