Don't allow backups to be made via schedules if limit = 0 (#3323)
This commit is contained in:
parent
5a82dd6a18
commit
76ac1998cf
6 changed files with 42 additions and 21 deletions
|
@ -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') ?? '',
|
||||
|
|
|
@ -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()}>
|
||||
|
|
|
@ -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.'
|
||||
:
|
||||
|
|
|
@ -81,7 +81,7 @@ export default () => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<PageContentBlock>
|
||||
<PageContentBlock title={'Schedules'}>
|
||||
<FlashMessageRender byKey={'schedules'} css={tw`mb-4`}/>
|
||||
{!schedule || isLoading ?
|
||||
<Spinner size={'large'} centered/>
|
||||
|
|
|
@ -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,6 +79,10 @@ const TaskDetailsModal = ({ schedule, task }: Props) => {
|
|||
|
||||
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
|
||||
clearFlashes('schedule: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);
|
||||
|
@ -93,6 +98,7 @@ const TaskDetailsModal = ({ schedule, task }: Props) => {
|
|||
setSubmitting(false);
|
||||
addError({ message: httpErrorToHuman(error), key: 'schedule:task' });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -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.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue