Begin refactoring Tasks to be apart of the Scheduler system
This commit is contained in:
parent
07965d0ce7
commit
2ac90b50f2
28 changed files with 902 additions and 468 deletions
|
@ -25,7 +25,6 @@
|
|||
namespace Pterodactyl\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Pterodactyl\Repositories\UserRepository;
|
||||
use Pterodactyl\Services\Users\UserCreationService;
|
||||
|
||||
class MakeUser extends Command
|
||||
|
@ -60,8 +59,7 @@ class MakeUser extends Command
|
|||
*/
|
||||
public function __construct(
|
||||
UserCreationService $creationService
|
||||
)
|
||||
{
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->creationService = $creationService;
|
||||
}
|
||||
|
@ -87,7 +85,6 @@ class MakeUser extends Command
|
|||
$data['root_admin'] = is_null($this->option('admin')) ? $this->confirm('Is this user a root administrator?') : $this->option('admin');
|
||||
|
||||
try {
|
||||
|
||||
$this->creationService->handle($data);
|
||||
|
||||
return $this->info('User successfully created.');
|
||||
|
|
|
@ -22,26 +22,23 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Services\Tasks;
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Pterodactyl\Contracts\Repository\TaskRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
|
||||
class TaskUpdateService
|
||||
interface ScheduleRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
protected $repository;
|
||||
/**
|
||||
* Return all of the schedules for a given server.
|
||||
*
|
||||
* @param int $server
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getServerSchedules($server);
|
||||
|
||||
protected $serverRepository;
|
||||
|
||||
public function __construct(
|
||||
ServerRepositoryInterface $serverRepository,
|
||||
TaskRepositoryInterface $repository
|
||||
) {
|
||||
$this->repository = $repository;
|
||||
$this->serverRepository = $serverRepository;
|
||||
}
|
||||
|
||||
public function handle($server, array $data, array $chain = null)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Return a schedule model with all of the associated tasks as a relationship.
|
||||
*
|
||||
* @param int $schedule
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getScheduleWithTasks($schedule);
|
||||
}
|
|
@ -26,22 +26,4 @@ namespace Pterodactyl\Contracts\Repository;
|
|||
|
||||
interface TaskRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Return the parent tasks and the count of children attached to that task.
|
||||
*
|
||||
* @param int $server
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParentTasksWithChainCount($server);
|
||||
|
||||
/**
|
||||
* Return a single task for a given server including all of the chained tasks.
|
||||
*
|
||||
* @param int $task
|
||||
* @param int $server
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function getTaskForServer($task, $server);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Schedule\Task;
|
||||
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class TaskIntervalTooLongException extends DisplayException
|
||||
{
|
||||
}
|
|
@ -24,20 +24,27 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Server\Tasks;
|
||||
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Http\Requests\Request;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Tasks\TaskCreationService;
|
||||
use Pterodactyl\Contracts\Extensions\HashidsInterface;
|
||||
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
||||
use Pterodactyl\Contracts\Repository\TaskRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Server\TaskCreationFormRequest;
|
||||
use Pterodactyl\Services\Schedules\ScheduleCreationService;
|
||||
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest;
|
||||
|
||||
class TaskManagementController extends Controller
|
||||
{
|
||||
use JavascriptInjection;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Tasks\TaskCreationService
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
*/
|
||||
protected $alert;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Schedules\ScheduleCreationService
|
||||
*/
|
||||
protected $creationService;
|
||||
|
||||
|
@ -47,7 +54,7 @@ class TaskManagementController extends Controller
|
|||
protected $hashids;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\TaskRepositoryInterface
|
||||
* @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
|
@ -59,17 +66,20 @@ class TaskManagementController extends Controller
|
|||
/**
|
||||
* TaskManagementController constructor.
|
||||
*
|
||||
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||
* @param \Pterodactyl\Contracts\Extensions\HashidsInterface $hashids
|
||||
* @param \Illuminate\Contracts\Session\Session $session
|
||||
* @param \Pterodactyl\Services\Tasks\TaskCreationService $creationService
|
||||
* @param \Pterodactyl\Contracts\Repository\TaskRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Services\Schedules\ScheduleCreationService $creationService
|
||||
* @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
AlertsMessageBag $alert,
|
||||
HashidsInterface $hashids,
|
||||
Session $session,
|
||||
TaskCreationService $creationService,
|
||||
TaskRepositoryInterface $repository
|
||||
ScheduleCreationService $creationService,
|
||||
ScheduleRepositoryInterface $repository
|
||||
) {
|
||||
$this->alert = $alert;
|
||||
$this->creationService = $creationService;
|
||||
$this->hashids = $hashids;
|
||||
$this->repository = $repository;
|
||||
|
@ -86,11 +96,11 @@ class TaskManagementController extends Controller
|
|||
public function index()
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
$this->authorize('list-tasks', $server);
|
||||
$this->authorize('list-schedules', $server);
|
||||
$this->injectJavascript();
|
||||
|
||||
return view('server.tasks.index', [
|
||||
'tasks' => $this->repository->getParentTasksWithChainCount($server->id),
|
||||
'schedules' => $this->repository->getServerSchedules($server->id),
|
||||
'actions' => [
|
||||
'command' => trans('server.tasks.actions.command'),
|
||||
'power' => trans('server.tasks.actions.power'),
|
||||
|
@ -108,64 +118,95 @@ class TaskManagementController extends Controller
|
|||
public function create()
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
$this->authorize('create-task', $server);
|
||||
$this->authorize('create-schedule', $server);
|
||||
$this->injectJavascript();
|
||||
|
||||
return view('server.tasks.new');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Pterodactyl\Http\Requests\Server\TaskCreationFormRequest $request
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException
|
||||
*/
|
||||
public function store(TaskCreationFormRequest $request)
|
||||
public function store(ScheduleCreationFormRequest $request)
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
$this->authorize('create-task', $server);
|
||||
$this->authorize('create-schedule', $server);
|
||||
|
||||
$task = $this->creationService->handle($server, $request->normalize(), $request->getChainedTasks());
|
||||
$schedule = $this->creationService->handle($server, $request->normalize(), $request->getTasks());
|
||||
$this->alert->success(trans('server.tasks.task_created'))->flash();
|
||||
|
||||
return redirect()->route('server.tasks.view', [
|
||||
'server' => $server->uuidShort,
|
||||
'task' => $task->id,
|
||||
'task' => $schedule->hashid,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to modify task settings.
|
||||
* Return a view to modify a schedule.
|
||||
*
|
||||
* @param string $uuid
|
||||
* @param string $task
|
||||
* @param \Pterodactyl\Http\Requests\Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view($uuid, $task)
|
||||
public function view(Request $request)
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
$this->authorize('edit-task', $server);
|
||||
$task = $this->repository->getTaskForServer($this->hashids->decodeFirst($task, 0), $server->id);
|
||||
$schedule = $request->attributes->get('schedule');
|
||||
$this->authorize('view-schedule', $server);
|
||||
|
||||
$this->injectJavascript([
|
||||
'chained' => $task->chained->map(function ($chain) {
|
||||
return collect($chain->toArray())->only('action', 'chain_delay', 'data')->all();
|
||||
'tasks' => $schedule->tasks->map(function ($schedule) {
|
||||
return collect($schedule->toArray())->only('action', 'time_offset', 'payload')->all();
|
||||
}),
|
||||
]);
|
||||
|
||||
return view('server.tasks.view', ['task' => $task]);
|
||||
return view('server.tasks.view', ['schedule' => $schedule]);
|
||||
}
|
||||
|
||||
public function update(TaskCreationFormRequest $request, $uuid, $task)
|
||||
/**
|
||||
* Update a specific parent task on the system.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(ScheduleCreationFormRequest $request)
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
$this->authorize('edit-task', $server);
|
||||
$task = $this->repository->getTaskForServer($this->hashids->decodeFirst($task, 0), $server->id);
|
||||
$schedule = $request->attributes->get('schedule');
|
||||
$this->authorize('edit-schedule', $server);
|
||||
|
||||
// $this->updateService->handle($task, $request->normalize(), $request->getChainedTasks());
|
||||
$this->alert->success(trans('server.tasks.task_updated'))->flash();
|
||||
|
||||
return redirect()->route('server.tasks.view', [
|
||||
'server' => $server->uuidShort,
|
||||
'task' => $schedule->hashid,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a parent task from the Panel.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function delete(Request $request)
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
$schedule = $request->attributes->get('schedule');
|
||||
$this->authorize('delete-schedule', $server);
|
||||
|
||||
$this->repository->delete($task->id);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
}
|
||||
|
|
91
app/Http/Middleware/Server/ScheduleAccess.php
Normal file
91
app/Http/Middleware/Server/ScheduleAccess.php
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Http\Middleware\Server;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Session\Session;
|
||||
use Pterodactyl\Contracts\Extensions\HashidsInterface;
|
||||
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
||||
|
||||
class ScheduleAccess
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Extensions\HashidsInterface
|
||||
*/
|
||||
protected $hashids;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Session\Session
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* TaskAccess constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Extensions\HashidsInterface $hashids
|
||||
* @param \Illuminate\Contracts\Session\Session $session
|
||||
* @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
HashidsInterface $hashids,
|
||||
Session $session,
|
||||
ScheduleRepositoryInterface $repository
|
||||
) {
|
||||
$this->hashids = $hashids;
|
||||
$this->repository = $repository;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a task is assigned to the active server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$server = $this->session->get('server_data.model');
|
||||
|
||||
$scheduleId = $this->hashids->decodeFirst($request->route()->parameter('task'), 0);
|
||||
$schedule = $this->repository->getScheduleWithTasks($scheduleId);
|
||||
|
||||
if ($schedule->server_id !== $server->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$request->attributes->set('schedule', $schedule);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ namespace Pterodactyl\Http\Requests\Server;
|
|||
|
||||
use Pterodactyl\Http\Requests\FrontendUserFormRequest;
|
||||
|
||||
class TaskCreationFormRequest extends FrontendUserFormRequest
|
||||
class ScheduleCreationFormRequest extends FrontendUserFormRequest
|
||||
{
|
||||
/**
|
||||
* Validation rules to apply to the request.
|
||||
|
@ -37,21 +37,19 @@ class TaskCreationFormRequest extends FrontendUserFormRequest
|
|||
{
|
||||
return [
|
||||
'name' => 'string|max:255',
|
||||
'day_of_week' => 'required|string',
|
||||
'day_of_month' => 'required|string',
|
||||
'hour' => 'required|string',
|
||||
'minute' => 'required|string',
|
||||
'action' => 'required|string|in:power,command',
|
||||
'data' => 'required|string',
|
||||
'chain' => 'sometimes|array|size:4',
|
||||
'chain.time_value' => 'required_with:chain|max:5',
|
||||
'chain.time_interval' => 'required_with:chain|max:5',
|
||||
'chain.action' => 'required_with:chain|max:5',
|
||||
'chain.payload' => 'required_with:chain|max:5',
|
||||
'chain.time_value.*' => 'numeric|between:1,60',
|
||||
'chain.time_interval.*' => 'string|in:s,m',
|
||||
'chain.action.*' => 'string|in:power,command',
|
||||
'chain.payload.*' => 'string',
|
||||
'cron_day_of_week' => 'required|string',
|
||||
'cron_day_of_month' => 'required|string',
|
||||
'cron_hour' => 'required|string',
|
||||
'cron_minute' => 'required|string',
|
||||
'tasks' => 'sometimes|array|size:4',
|
||||
'tasks.time_value' => 'required_with:chain|max:5',
|
||||
'tasks.time_interval' => 'required_with:chain|max:5',
|
||||
'tasks.action' => 'required_with:chain|max:5',
|
||||
'tasks.payload' => 'required_with:chain|max:5',
|
||||
'tasks.time_value.*' => 'numeric|between:1,60',
|
||||
'tasks.time_interval.*' => 'string|in:s,m',
|
||||
'tasks.action.*' => 'string|in:power,command',
|
||||
'tasks.payload.*' => 'string',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -62,18 +60,18 @@ class TaskCreationFormRequest extends FrontendUserFormRequest
|
|||
*/
|
||||
public function normalize()
|
||||
{
|
||||
return $this->only('name', 'day_of_week', 'day_of_month', 'hour', 'minute', 'action', 'data');
|
||||
return $this->only('name', 'cron_day_of_week', 'cron_day_of_month', 'cron_hour', 'cron_minute');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the chained tasks provided in the request.
|
||||
* Return the tasks provided in the request that are associated with this schedule.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getChainedTasks()
|
||||
public function getTasks()
|
||||
{
|
||||
$restructured = [];
|
||||
foreach (array_get($this->all(), 'chain', []) as $key => $values) {
|
||||
foreach (array_get($this->all(), 'tasks', []) as $key => $values) {
|
||||
for ($i = 0; $i < count($values); ++$i) {
|
||||
$restructured[$i][$key] = $values[$i];
|
||||
}
|
153
app/Models/Schedule.php
Normal file
153
app/Models/Schedule.php
Normal file
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Models;
|
||||
|
||||
use Sofa\Eloquence\Eloquence;
|
||||
use Sofa\Eloquence\Validable;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Sofa\Eloquence\Contracts\CleansAttributes;
|
||||
use Sofa\Eloquence\Contracts\Validable as ValidableContract;
|
||||
|
||||
class Schedule extends Model implements CleansAttributes, ValidableContract
|
||||
{
|
||||
use Eloquence, Validable;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'schedules';
|
||||
|
||||
/**
|
||||
* Mass assignable attributes on this model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'server_id',
|
||||
'name',
|
||||
'cron_day_of_week',
|
||||
'cron_day_of_month',
|
||||
'cron_hour',
|
||||
'cron_minute',
|
||||
'is_active',
|
||||
'is_processing',
|
||||
'last_run_at',
|
||||
'next_run_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'server_id' => 'integer',
|
||||
'is_active' => 'boolean',
|
||||
'is_processing' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Columns to mutate to a date.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = [
|
||||
self::CREATED_AT,
|
||||
self::UPDATED_AT,
|
||||
'last_run_at',
|
||||
'next_run_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = [
|
||||
'name' => null,
|
||||
'cron_day_of_week' => '*',
|
||||
'cron_day_of_month' => '*',
|
||||
'cron_hour' => '*',
|
||||
'cron_minute' => '*',
|
||||
'is_active' => true,
|
||||
'is_processing' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $applicationRules = [
|
||||
'server_id' => 'required',
|
||||
'cron_day_of_week' => 'required',
|
||||
'cron_day_of_month' => 'required',
|
||||
'cron_hour' => 'required',
|
||||
'cron_minute' => 'required',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $dataIntegrityRules = [
|
||||
'server_id' => 'exists:servers,id',
|
||||
'name' => 'nullable|string|max:255',
|
||||
'cron_day_of_week' => 'string',
|
||||
'cron_day_of_month' => 'string',
|
||||
'cron_hour' => 'string',
|
||||
'cron_minute' => 'string',
|
||||
'is_active' => 'boolean',
|
||||
'is_processing' => 'boolean',
|
||||
'last_run_at' => 'nullable|timestamp',
|
||||
'next_run_at' => 'nullable|timestamp',
|
||||
];
|
||||
|
||||
/**
|
||||
* Return a hashid encoded string to represent the ID of the schedule.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHashidAttribute()
|
||||
{
|
||||
return app()->make('hashids')->encode($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return tasks belonging to a schedule.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function tasks()
|
||||
{
|
||||
return $this->hasMany(Task::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server model that a schedule belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function server()
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
}
|
|
@ -42,11 +42,25 @@ class Task extends Model implements CleansAttributes, ValidableContract
|
|||
protected $table = 'tasks';
|
||||
|
||||
/**
|
||||
* Fields that are not mass assignable.
|
||||
* Relationships to be updated when this model is updated.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = ['id', 'created_at', 'updated_at'];
|
||||
protected $touches = ['schedule'];
|
||||
|
||||
/**
|
||||
* Fields that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'schedule_id',
|
||||
'squence_id',
|
||||
'action',
|
||||
'payload',
|
||||
'time_offset',
|
||||
'is_queued',
|
||||
];
|
||||
|
||||
/**
|
||||
* Cast values to correct type.
|
||||
|
@ -55,10 +69,10 @@ class Task extends Model implements CleansAttributes, ValidableContract
|
|||
*/
|
||||
protected $casts = [
|
||||
'id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'server_id' => 'integer',
|
||||
'queued' => 'boolean',
|
||||
'active' => 'boolean',
|
||||
'schedule_id' => 'integer',
|
||||
'squence_id' => 'integer',
|
||||
'time_offset' => 'integer',
|
||||
'is_queued' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -67,54 +81,32 @@ class Task extends Model implements CleansAttributes, ValidableContract
|
|||
* @var array
|
||||
*/
|
||||
protected $attributes = [
|
||||
'parent_task_id' => null,
|
||||
'chain_order' => null,
|
||||
'active' => true,
|
||||
'day_of_week' => '*',
|
||||
'day_of_month' => '*',
|
||||
'hour' => '*',
|
||||
'minute' => '*',
|
||||
'chain_delay' => null,
|
||||
'queued' => false,
|
||||
'is_queued' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $applicationRules = [
|
||||
'server_id' => 'required',
|
||||
'schedule_id' => 'required',
|
||||
'squence_id' => 'required',
|
||||
'action' => 'required',
|
||||
'data' => 'required',
|
||||
'payload' => 'required',
|
||||
'time_offset' => 'required',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $dataIntegrityRules = [
|
||||
'name' => 'nullable|string|max:255',
|
||||
'parent_task_id' => 'nullable|numeric|exists:tasks,id',
|
||||
'chain_order' => 'nullable|numeric|min:1',
|
||||
'server_id' => 'numeric|exists:servers,id',
|
||||
'active' => 'boolean',
|
||||
'schedule_id' => 'numeric|exists:schedules,id',
|
||||
'squence_id' => 'numeric|min:1',
|
||||
'action' => 'string',
|
||||
'data' => 'string',
|
||||
'queued' => 'boolean',
|
||||
'day_of_month' => 'string',
|
||||
'day_of_week' => 'string',
|
||||
'hour' => 'string',
|
||||
'minute' => 'string',
|
||||
'chain_delay' => 'nullable|numeric|between:1,900',
|
||||
'last_run' => 'nullable|timestamp',
|
||||
'next_run' => 'nullable|timestamp',
|
||||
'payload' => 'string',
|
||||
'time_offset' => 'numeric|between:0,900',
|
||||
'is_queued' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['last_run', 'next_run', 'created_at', 'updated_at'];
|
||||
|
||||
/**
|
||||
* Return a hashid encoded string to represent the ID of the task.
|
||||
*
|
||||
|
@ -126,32 +118,26 @@ class Task extends Model implements CleansAttributes, ValidableContract
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the server associated with a task.
|
||||
* Return the schedule that a task belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function schedule()
|
||||
{
|
||||
return $this->belongsTo(Schedule::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server a task is assigned to, acts as a belongsToThrough.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function server()
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user associated with a task.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return chained tasks for a parent task.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function chained()
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_task_id')->orderBy('chain_order', 'asc');
|
||||
if ($schedule = $this->schedule) {
|
||||
return $schedule->server();
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Instance of Task must have an associated Schedule in the database.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ use Pterodactyl\Repositories\Eloquent\SessionRepository;
|
|||
use Pterodactyl\Repositories\Eloquent\SubuserRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\DatabaseRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\PermissionRepository;
|
||||
use Pterodactyl\Repositories\Daemon\ConfigurationRepository;
|
||||
|
@ -59,6 +60,7 @@ use Pterodactyl\Contracts\Repository\SubuserRepositoryInterface;
|
|||
use Pterodactyl\Repositories\Eloquent\ServiceVariableRepository;
|
||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\PermissionRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface;
|
||||
|
@ -92,6 +94,7 @@ class RepositoryServiceProvider extends ServiceProvider
|
|||
$this->app->bind(OptionVariableRepositoryInterface::class, OptionVariableRepository::class);
|
||||
$this->app->bind(PackRepositoryInterface::class, PackRepository::class);
|
||||
$this->app->bind(PermissionRepositoryInterface::class, PermissionRepository::class);
|
||||
$this->app->bind(ScheduleRepositoryInterface::class, ScheduleRepository::class);
|
||||
$this->app->bind(ServerRepositoryInterface::class, ServerRepository::class);
|
||||
$this->app->bind(ServerVariableRepositoryInterface::class, ServerVariableRepository::class);
|
||||
$this->app->bind(ServiceRepositoryInterface::class, ServiceRepository::class);
|
||||
|
|
55
app/Repositories/Eloquent/ScheduleRepository.php
Normal file
55
app/Repositories/Eloquent/ScheduleRepository.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Repositories\Eloquent;
|
||||
|
||||
use Pterodactyl\Models\Schedule;
|
||||
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
||||
|
||||
class ScheduleRepository extends EloquentRepository implements ScheduleRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function model()
|
||||
{
|
||||
return Schedule::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getServerSchedules($server)
|
||||
{
|
||||
return $this->getBuilder()->withCount('tasks')->where('server_id', '=', $server)->get($this->getColumns());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getScheduleWithTasks($schedule)
|
||||
{
|
||||
return $this->getBuilder()->with('tasks')->find($schedule, $this->getColumns());
|
||||
}
|
||||
}
|
106
app/Services/Schedules/ScheduleCreationService.php
Normal file
106
app/Services/Schedules/ScheduleCreationService.php
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Services\Schedules;
|
||||
|
||||
use Webmozart\Assert\Assert;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Pterodactyl\Services\Schedules\Tasks\TaskCreationService;
|
||||
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
|
||||
|
||||
class ScheduleCreationService
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Schedules\Tasks\TaskCreationService
|
||||
*/
|
||||
protected $taskCreationService;
|
||||
|
||||
/**
|
||||
* ScheduleCreationService constructor.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||
* @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Services\Schedules\Tasks\TaskCreationService $taskCreationService
|
||||
*/
|
||||
public function __construct(
|
||||
ConnectionInterface $connection,
|
||||
ScheduleRepositoryInterface $repository,
|
||||
TaskCreationService $taskCreationService
|
||||
) {
|
||||
$this->connection = $connection;
|
||||
$this->repository = $repository;
|
||||
$this->taskCreationService = $taskCreationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new schedule for a specific server.
|
||||
*
|
||||
* @param int|\Pterodactyl\Models\Server $server
|
||||
* @param array $data
|
||||
* @param array $tasks
|
||||
* @return \Pterodactyl\Models\Schedule
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException
|
||||
*/
|
||||
public function handle($server, array $data, array $tasks = [])
|
||||
{
|
||||
Assert::true(($server instanceof Server || is_numeric($server)),
|
||||
'First argument passed to handle must be numeric or instance of \Pterodactyl\Models\Server, received %s.'
|
||||
);
|
||||
|
||||
$server = ($server instanceof Server) ? $server->id : $server;
|
||||
$data['server_id'] = $server;
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
$schedule = $this->repository->create($data);
|
||||
|
||||
if (! empty($tasks)) {
|
||||
foreach ($tasks as $index => $task) {
|
||||
$this->taskCreationService->handle($schedule, [
|
||||
'time_interval' => array_get($task, 'time_interval'),
|
||||
'time_value' => array_get($task, 'time_value'),
|
||||
'sequence_id' => $index + 1,
|
||||
'action' => array_get($task, 'action'),
|
||||
'payload' => array_get($task, 'payload'),
|
||||
], false);
|
||||
}
|
||||
}
|
||||
|
||||
$this->connection->commit();
|
||||
|
||||
return $schedule;
|
||||
}
|
||||
}
|
84
app/Services/Schedules/Tasks/TaskCreationService.php
Normal file
84
app/Services/Schedules/Tasks/TaskCreationService.php
Normal file
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Services\Schedules\Tasks;
|
||||
|
||||
use Webmozart\Assert\Assert;
|
||||
use Pterodactyl\Models\Schedule;
|
||||
use Pterodactyl\Contracts\Repository\TaskRepositoryInterface;
|
||||
use Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException;
|
||||
|
||||
class TaskCreationService
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\TaskRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* TaskCreationService constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\TaskRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(TaskRepositoryInterface $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new task that is assigned to a schedule.
|
||||
*
|
||||
* @param int|\Pterodactyl\Models\Schedule $schedule
|
||||
* @param array $data
|
||||
* @param bool $returnModel
|
||||
* @return bool|\Pterodactyl\Models\Task
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException
|
||||
*/
|
||||
public function handle($schedule, array $data, $returnModel = true)
|
||||
{
|
||||
Assert::true(($schedule instanceof Schedule || is_numeric($schedule)),
|
||||
'First argument passed to handle must be numeric or instance of \Pterodactyl\Models\Schedule, received %s.'
|
||||
);
|
||||
|
||||
$schedule = ($schedule instanceof Schedule) ? $schedule->id : $schedule;
|
||||
if ($data['time_interval'] === 'm' && $data['time_value'] > 15) {
|
||||
throw new TaskIntervalTooLongException(trans('exceptions.tasks.chain_interval_too_long'));
|
||||
}
|
||||
|
||||
$delay = $data['time_interval'] === 'm' ? $data['time_value'] * 60 : $data['time_value'];
|
||||
|
||||
$repository = ($returnModel) ? $this->repository : $this->repository->withoutFresh();
|
||||
$task = $repository->create([
|
||||
'schedule_id' => $schedule,
|
||||
'sequence_id' => $data['sequence_id'],
|
||||
'action' => $data['action'],
|
||||
'payload' => $data['payload'],
|
||||
'time_offset' => $delay,
|
||||
]);
|
||||
|
||||
return $task;
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Services\Tasks;
|
||||
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Pterodactyl\Contracts\Repository\TaskRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
|
||||
class TaskCreationService
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\TaskRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
|
||||
*/
|
||||
protected $serverRepository;
|
||||
|
||||
/**
|
||||
* TaskCreationService constructor.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $serverRepository
|
||||
* @param \Pterodactyl\Contracts\Repository\TaskRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
ConnectionInterface $connection,
|
||||
ServerRepositoryInterface $serverRepository,
|
||||
TaskRepositoryInterface $repository
|
||||
) {
|
||||
$this->connection = $connection;
|
||||
$this->repository = $repository;
|
||||
$this->serverRepository = $serverRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|\Pterodactyl\Models\Server $server
|
||||
* @param array $data
|
||||
* @param array|null $chain
|
||||
* @return \Pterodactyl\Models\Task
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function handle($server, array $data, array $chain = null)
|
||||
{
|
||||
if (! $server instanceof Server) {
|
||||
$server = $this->serverRepository->find($server);
|
||||
}
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
$data['server_id'] = $server->id;
|
||||
$task = $this->repository->create($data);
|
||||
|
||||
if (is_array($chain)) {
|
||||
foreach ($chain as $index => $values) {
|
||||
if ($values['time_interval'] === 'm' && $values['time_value'] > 15) {
|
||||
throw new \Exception('I should fix this.');
|
||||
}
|
||||
|
||||
$delay = $values['time_interval'] === 'm' ? $values['time_value'] * 60 : $values['time_value'];
|
||||
$this->repository->withoutFresh()->create([
|
||||
'parent_task_id' => $task->id,
|
||||
'chain_order' => $index + 1,
|
||||
'server_id' => $server->id,
|
||||
'action' => $values['action'],
|
||||
'data' => $values['payload'],
|
||||
'chain_delay' => $delay,
|
||||
]);
|
||||
}
|
||||
}
|
||||
$this->connection->commit();
|
||||
|
||||
return $task;
|
||||
}
|
||||
}
|
|
@ -21,8 +21,8 @@ class CreateSchedulesTable extends Migration
|
|||
$table->string('cron_minute');
|
||||
$table->boolean('is_active');
|
||||
$table->boolean('is_processing');
|
||||
$table->timestamp('last_run_at');
|
||||
$table->timestamp('next_run_at');
|
||||
$table->timestamp('last_run_at')->nullable();
|
||||
$table->timestamp('next_run_at')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->foreign('server_id')->references('id')->on('servers')->onDelete('cascade');
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -343,3 +343,20 @@ input.form-autocomplete-stop[readonly] {
|
|||
bottom: 1px;
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
|
||||
label.control-label > span {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
color: #dd4b39;
|
||||
}
|
||||
|
||||
label.control-label > span.field-required:before {
|
||||
content: "required";
|
||||
color: #dd4b39;
|
||||
}
|
||||
|
||||
label.control-label > span.field-optional:before {
|
||||
content: "optional";
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
|
|
@ -19,32 +19,6 @@
|
|||
// SOFTWARE.
|
||||
|
||||
$(document).ready(function () {
|
||||
$('select[name="action"]').select2();
|
||||
$('[data-action="update-field"]').on('change', function (event) {
|
||||
event.preventDefault();
|
||||
var updateField = $(this).data('field');
|
||||
var selected = $(this).map(function (i, opt) {
|
||||
return $(opt).val();
|
||||
}).toArray();
|
||||
if (selected.length === $(this).find('option').length) {
|
||||
$('input[name=' + updateField + ']').val('*');
|
||||
} else {
|
||||
$('input[name=' + updateField + ']').val(selected.join(','));
|
||||
}
|
||||
});
|
||||
|
||||
$('button[data-action="add-chain"]').on('click', function () {
|
||||
var clone = $('div[data-target="chain-clone"]').clone();
|
||||
clone.insertBefore('#chainLastSegment').removeAttr('data-target').removeClass('hidden');
|
||||
clone.find('select[name="chain[time_value][]"]').select2();
|
||||
clone.find('select[name="chain[time_interval][]"]').select2();
|
||||
clone.find('select[name="chain[action][]"]').select2();
|
||||
clone.find('button[data-action="remove-chain-element"]').on('click', function () {
|
||||
clone.remove();
|
||||
});
|
||||
$(this).data('element', clone);
|
||||
});
|
||||
|
||||
$('[data-action="delete-task"]').click(function () {
|
||||
var self = $(this);
|
||||
swal({
|
||||
|
@ -62,7 +36,7 @@ $(document).ready(function () {
|
|||
method: 'DELETE',
|
||||
url: Router.route('server.tasks.delete', {
|
||||
server: Pterodactyl.server.uuidShort,
|
||||
id: self.data('id'),
|
||||
task: self.data('taskid'),
|
||||
}),
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'),
|
||||
|
@ -101,7 +75,7 @@ $(document).ready(function () {
|
|||
method: 'POST',
|
||||
url: Router.route('server.tasks.toggle', {
|
||||
server: Pterodactyl.server.uuidShort,
|
||||
id: self.data('id'),
|
||||
task: self.data('taskid'),
|
||||
}),
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content'),
|
61
public/themes/pterodactyl/js/frontend/tasks/view-actions.js
Normal file
61
public/themes/pterodactyl/js/frontend/tasks/view-actions.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
$(document).ready(function () {
|
||||
function setupSelect2() {
|
||||
$('select[name="chain[time_value][]"]').select2();
|
||||
$('select[name="chain[time_interval][]"]').select2();
|
||||
$('select[name="chain[action][]"]').select2();
|
||||
}
|
||||
|
||||
setupSelect2();
|
||||
|
||||
$('[data-action="update-field"]').on('change', function (event) {
|
||||
event.preventDefault();
|
||||
var updateField = $(this).data('field');
|
||||
var selected = $(this).map(function (i, opt) {
|
||||
return $(opt).val();
|
||||
}).toArray();
|
||||
if (selected.length === $(this).find('option').length) {
|
||||
$('input[name=' + updateField + ']').val('*');
|
||||
} else {
|
||||
$('input[name=' + updateField + ']').val(selected.join(','));
|
||||
}
|
||||
});
|
||||
|
||||
$('button[data-action="add-new-task"]').on('click', function () {
|
||||
if ($('#containsTaskList').find('.task-list-item').length >= 5) {
|
||||
swal('Task Limit Reached', 'You may only assign a maximum of 5 tasks to one schedule.');
|
||||
return;
|
||||
}
|
||||
|
||||
var clone = $('div[data-target="task-clone"]').clone();
|
||||
clone.insertBefore('#taskAppendBefore').removeAttr('data-target');
|
||||
clone.find('select:first').attr('selected');
|
||||
clone.find('input').val('');
|
||||
clone.find('span.select2-container').remove();
|
||||
clone.find('div[data-attribute="remove-task-element"]').addClass('input-group').find('div.input-group-btn').removeClass('hidden');
|
||||
clone.find('button[data-action="remove-task"]').on('click', function () {
|
||||
clone.remove();
|
||||
});
|
||||
setupSelect2();
|
||||
$(this).data('element', clone);
|
||||
});
|
||||
});
|
|
@ -62,4 +62,7 @@ return [
|
|||
'databases' => [
|
||||
'delete_has_databases' => 'Cannot delete a database host server that has active databases linked to it.',
|
||||
],
|
||||
'tasks' => [
|
||||
'chain_interval_too_long' => 'The maximum interval time for a chained task is 15 minutes.',
|
||||
],
|
||||
];
|
||||
|
|
|
@ -6,7 +6,29 @@ return [
|
|||
'header' => 'Server Console',
|
||||
'header_sub' => 'Control your server in real time.',
|
||||
],
|
||||
'schedule' => [
|
||||
'new' => [
|
||||
'header' => 'Create New Schedule',
|
||||
'header_sub' => 'Create a new set of scheduled tasks for this server.',
|
||||
'submit' => 'Create Schedule',
|
||||
],
|
||||
'task' => [
|
||||
'time' => 'After',
|
||||
'action' => 'Perform Action',
|
||||
'payload' => 'With Payload',
|
||||
'add_more' => 'Add Another Task',
|
||||
],
|
||||
'setup' => 'Schedule Setup',
|
||||
'day_of_week' => 'Day of Week',
|
||||
'day_of_month' => 'Day of Month',
|
||||
'hour' => 'Hour of Day',
|
||||
'minute' => 'Minute of Hour',
|
||||
'time_help' => 'The schedule system supports the use of Cronjob syntax when defining when tasks should begin running. Use the fields above to specify when these tasks should begin running or select options from the multiple select menus.',
|
||||
'task_help' => 'Times for tasks are relative to the previously defined task. Each schedule may have no more than 5 tasks assigned to it and tasks may not be scheduled more than 15 minutes apart.',
|
||||
],
|
||||
'tasks' => [
|
||||
'task_created' => 'Successfully created a new task on the Panel.',
|
||||
'task_updated' => 'Task has successfully been updated. Any currently queued task actions will be cancelled and run again at the next defined time.',
|
||||
'header' => 'Scheduled Tasks',
|
||||
'header_sub' => 'Automate your server.',
|
||||
'current' => 'Current Scheduled Tasks',
|
||||
|
|
|
@ -71,7 +71,7 @@ return [
|
|||
'admin' => 'Admin',
|
||||
'subuser' => 'Subuser',
|
||||
'captcha_invalid' => 'The provided captcha is invalid.',
|
||||
'child_tasks' => 'Child Tasks',
|
||||
'tasks' => 'Tasks',
|
||||
'seconds' => 'Seconds',
|
||||
'minutes' => 'Minutes',
|
||||
];
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
<a href="{{ route('server.tasks', $server->uuidShort)}}">
|
||||
<i class="fa fa-clock-o"></i> <span>@lang('navigation.server.task_management')</span>
|
||||
<span class="pull-right-container">
|
||||
<span class="label label-primary pull-right">{{ \Pterodactyl\Models\Task::select('id')->where('server_id', $server->id)->where('active', 1)->count() }}</span>
|
||||
<span class="label label-primary pull-right">{{ \Pterodactyl\Models\Schedule::select('id')->where('server_id', $server->id)->where('is_active', 1)->count() }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
@section('tasks::chain-template')
|
||||
<div class="box-footer with-border hidden" data-target="chain-clone">
|
||||
<div class="box-footer with-border task-list-item" data-target="task-clone">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-3">
|
||||
<label class="control-label">@lang('server.tasks.new.chain_then'):</label>
|
||||
<label class="control-label">@lang('server.schedule.task.time')</label>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<select name="chain[time_value][]" class="form-control">
|
||||
@foreach(range(1, 60) as $number)
|
||||
@foreach(range(0, 59) as $number)
|
||||
<option value="{{ $number }}">{{ $number }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
@ -20,7 +20,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label class="control-label">@lang('server.tasks.new.chain_do'):</label>
|
||||
<label class="control-label">@lang('server.schedule.task.action')</label>
|
||||
<div>
|
||||
<select name="chain[action][]" class="form-control">
|
||||
<option value="command">@lang('server.tasks.actions.command')</option>
|
||||
|
@ -29,11 +29,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label class="control-label">@lang('server.tasks.new.chain_arguments'):</label>
|
||||
<div class="input-group">
|
||||
<label class="control-label">@lang('server.schedule.task.payload')</label>
|
||||
<div data-attribute="remove-task-element">
|
||||
<input type="text" name="chain[payload][]" class="form-control">
|
||||
<div class="input-group-btn">
|
||||
<button type="button" class="btn btn-danger" data-action="remove-chain-element"><i class="fa fa-close"></i></button>
|
||||
<div class="input-group-btn hidden">
|
||||
<button type="button" class="btn btn-danger" data-action="remove-task"><i class="fa fa-close"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -48,40 +48,40 @@
|
|||
<tr>
|
||||
<th>@lang('strings.name')</th>
|
||||
<th class="text-center">@lang('strings.queued')</th>
|
||||
<th class="text-center">@lang('strings.child_tasks')</th>
|
||||
<th class="text-center">@lang('strings.tasks')</th>
|
||||
<th>@lang('strings.last_run')</th>
|
||||
<th>@lang('strings.next_run')</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@foreach($tasks as $task)
|
||||
<tr @if(! $task->active)class="muted muted-hover"@endif>
|
||||
@foreach($schedules as $schedule)
|
||||
<tr @if(! $schedule->is_active)class="muted muted-hover"@endif>
|
||||
<td class="middle">
|
||||
@can('edit-task', $server)
|
||||
<a href="{{ route('server.tasks.view', ['server' => $server->uuidShort, 'task' => $task->hashid]) }}">{{ $task->name }}</a>
|
||||
@can('edit-schedule', $server)
|
||||
<a href="{{ route('server.tasks.view', ['server' => $server->uuidShort, '$schedule' => $schedule->hashid]) }}">{{ $schedule->name }}</a>
|
||||
@else
|
||||
{{ $task->name }}
|
||||
{{ $schedule->name }}
|
||||
@endcan
|
||||
</td>
|
||||
<td class="middle text-center">
|
||||
@if ($task->queued)
|
||||
@if ($schedule->is_processing)
|
||||
<span class="label label-success">@lang('strings.yes')</span>
|
||||
@else
|
||||
<span class="label label-default">@lang('strings.no')</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="middle text-center"><span class="label label-primary">{{ $task->chained_count }}</span></td>
|
||||
<td class="middle text-center"><span class="label label-primary">{{ $schedule->tasks_count }}</span></td>
|
||||
<td class="middle">
|
||||
@if($task->last_run)
|
||||
{{ Carbon::parse($task->last_run)->toDayDateTimeString() }}<br /><span class="text-muted small">({{ Carbon::parse($task->last_run)->diffForHumans() }})</span>
|
||||
@if($schedule->last_run_at)
|
||||
{{ Carbon::parse($schedule->last_run_at)->toDayDateTimeString() }}<br /><span class="text-muted small">({{ Carbon::parse($schedule->last_run_at)->diffForHumans() }})</span>
|
||||
@else
|
||||
<em class="text-muted">@lang('strings.not_run_yet')</em>
|
||||
@endif
|
||||
</td>
|
||||
<td class="middle">
|
||||
@if($task->active !== 0)
|
||||
@if($task->last_run)
|
||||
{{ Carbon::parse($task->next_run)->toDayDateTimeString() }}<br /><span class="text-muted small">({{ Carbon::parse($task->next_run)->diffForHumans() }})</span>
|
||||
@if($schedule->is_active)
|
||||
@if($schedule->last_run_at)
|
||||
{{ Carbon::parse($schedule->next_run_at)->toDayDateTimeString() }}<br /><span class="text-muted small">({{ Carbon::parse($schedule->next_run_at)->diffForHumans() }})</span>
|
||||
@else
|
||||
<em class="text-muted">@lang('strings.not_run_yet')</em>
|
||||
@endif
|
||||
|
@ -89,15 +89,14 @@
|
|||
<em>n/a</em>
|
||||
@endif
|
||||
</td>
|
||||
@can('delete-task', $server)
|
||||
<td class="text-center middle"><a href="#" data-action="delete-task" data-id="{{ $task->id }}"><i class="fa fa-fw fa-trash-o text-danger" data-toggle="tooltip" data-placement="top" title="@lang('strings.delete')"></i></a></td>
|
||||
@can('delete-schedule', $server)
|
||||
<td class="text-center middle"><a href="#" data-action="delete-task" data-taskid="{{ $schedule->hashid }}"><i class="fa fa-fw fa-trash-o text-danger" data-toggle="tooltip" data-placement="top" title="@lang('strings.delete')"></i></a></td>
|
||||
@endcan
|
||||
@can('toggle-task', $server)
|
||||
<td class="text-center middle"><a href="#" data-action="toggle-task" data-active="{{ $task->active }}" data-id="{{ $task->id }}"><i class="fa fa-fw fa-eye-slash text-primary" data-toggle="tooltip" data-placement="top" title="@lang('server.tasks.toggle')"></i></a></td>
|
||||
@can('toggle-schedule', $server)
|
||||
<td class="text-center middle"><a href="#" data-action="toggle-task" data-active="{{ $schedule->active }}" data-taskid="{{ $schedule->hashid }}"><i class="fa fa-fw fa-eye-slash text-primary" data-toggle="tooltip" data-placement="top" title="@lang('server.tasks.toggle')"></i></a></td>
|
||||
@endcan
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -109,5 +108,5 @@
|
|||
@section('footer-scripts')
|
||||
@parent
|
||||
{!! Theme::js('js/frontend/server.socket.js') !!}
|
||||
{!! Theme::js('js/frontend/tasks.js') !!}
|
||||
{!! Theme::js('js/frontend/tasks/management-actions.js') !!}
|
||||
@endsection
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
@endsection
|
||||
|
||||
@section('content-header')
|
||||
<h1>@lang('server.tasks.new.header')<small>@lang('server.tasks.new.header_sub')</small></h1>
|
||||
<h1>@lang('server.schedule.new.header')<small>@lang('server.schedule.new.header_sub')</small></h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ route('index') }}">@lang('strings.home')</a></li>
|
||||
<li><a href="{{ route('server.index', $server->uuidShort) }}">{{ $server->name }}</a></li>
|
||||
<li><a href="{{ route('server.tasks', $server->uuidShort) }}">@lang('navigation.server.task_management')</a></li>
|
||||
<li class="active">@lang('server.tasks.new_task')</li>
|
||||
<li class="active">@lang('server.schedule.new.header')</li>
|
||||
</ol>
|
||||
@endsection
|
||||
|
||||
|
@ -44,28 +44,22 @@
|
|||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('server.schedule.setup')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-xs-12">
|
||||
<label class="control-label">@lang('server.tasks.new.task_name'):</label>
|
||||
<label class="control-label" for="scheduleName">@lang('strings.name') <span class="field-optional"></span></label>
|
||||
<div>
|
||||
<input type="text" name="name" class="form-control" value="{{ old('name') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="text" name="name" id="scheduleName" class="form-control" value="{{ old('name') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-sm-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('server.tasks.new.day_of_week')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12">
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="form-group">
|
||||
<label for="scheduleDayOfWeek" class="control-label">@lang('server.schedule.day_of_week')</label>
|
||||
<div>
|
||||
<select data-action="update-field" data-field="day_of_week" class="form-control" multiple>
|
||||
<option value="0">@lang('server.tasks.new.sun')</option>
|
||||
|
@ -78,24 +72,13 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label class="control-label">@lang('server.tasks.new.custom')</label>
|
||||
<div>
|
||||
<input type="text" class="form-control" name="day_of_week" />
|
||||
<div class="form-group">
|
||||
<input type="text" id="scheduleDayOfWeek" class="form-control" name="day_of_week" value="{{ old('day_of_week') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('server.tasks.new.day_of_month')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12">
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="form-group">
|
||||
<label for="scheduleDayOfMonth" class="control-label">@lang('server.schedule.day_of_month')</label>
|
||||
<div>
|
||||
<select data-action="update-field" data-field="day_of_month" class="form-control" multiple>
|
||||
@foreach(range(1, 31) as $i)
|
||||
|
@ -104,24 +87,13 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" id="scheduleDayOfMonth" class="form-control" name="day_of_month" value="{{ old('day_of_month') }}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="form-group col-md-12">
|
||||
<label class="control-label">@lang('server.tasks.new.custom')</label>
|
||||
<div>
|
||||
<input type="text" class="form-control" name="day_of_month" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('server.tasks.new.hour')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12">
|
||||
<label for="scheduleHour" class="control-label">@lang('server.schedule.hour')</label>
|
||||
<div>
|
||||
<select data-action="update-field" data-field="hour" class="form-control" multiple>
|
||||
@foreach(range(0, 23) as $i)
|
||||
|
@ -131,23 +103,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label class="control-label">@lang('server.tasks.new.custom')</label>
|
||||
<div>
|
||||
<input type="text" class="form-control" name="hour" />
|
||||
<input type="text" id="scheduleHour" class="form-control" name="hour" value="{{ old('hour') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">@lang('server.tasks.new.minute')</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-12">
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="form-group">
|
||||
<label for="scheduleMinute" class="control-label">@lang('server.schedule.minute')</label>
|
||||
<div>
|
||||
<select data-action="update-field" data-field="minute" class="form-control" multiple>
|
||||
@foreach(range(0, 55) as $i)
|
||||
|
@ -158,60 +119,41 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label class="control-label">@lang('server.tasks.new.custom')</label>
|
||||
<div>
|
||||
<input type="text" class="form-control" name="minute" />
|
||||
<div class="form-group">
|
||||
<input type="text" id="scheduleMinute" class="form-control" name="minute" value="{{ old('minute') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer with-border">
|
||||
<p class="small text-muted no-margin-bottom">@lang('server.schedule.time_help')</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box box-primary">
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-4">
|
||||
<label class="control-label">@lang('server.tasks.new.type'):</label>
|
||||
<div>
|
||||
<select name="action" class="form-control">
|
||||
<option value="command">@lang('server.tasks.actions.command')</option>
|
||||
<option value="power">@lang('server.tasks.actions.power')</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-8">
|
||||
<label class="control-label">@lang('server.tasks.new.payload'):</label>
|
||||
<div>
|
||||
<input type="text" name="data" class="form-control" value="{{ old('data') }}">
|
||||
<span class="text-muted small">@lang('server.tasks.new.payload_help')</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer with-border" id="chainLastSegment">
|
||||
<div class="box box-primary" id="containsTaskList">
|
||||
@include('partials.schedules.task-template')
|
||||
<div class="box-footer with-border" id="taskAppendBefore">
|
||||
<div class="pull-left">
|
||||
<p class="text-muted small">Times for chain arguments are relative to the previous argument.</p>
|
||||
<p class="text-muted small">@lang('server.schedule.task_help')</p>
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
{!! csrf_field() !!}
|
||||
<button type="button" class="btn btn-sm btn-default" data-action="add-chain"><i class="fa fa-plus"></i> New Chain Argument</button>
|
||||
<button type="submit" class="btn btn-sm btn-success">@lang('server.tasks.new.submit')</button>
|
||||
<button type="button" class="btn btn-sm btn-default" data-action="add-new-task"><i class="fa fa-plus"></i> @lang('server.schedule.task.add_more')</button>
|
||||
<button type="submit" class="btn btn-sm btn-success">@lang('server.schedule.new.submit')</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@include('partials.tasks.chain-template')
|
||||
@endsection
|
||||
|
||||
@section('footer-scripts')
|
||||
@parent
|
||||
{!! Theme::js('js/frontend/server.socket.js') !!}
|
||||
{!! Theme::js('vendor/select2/select2.full.min.js') !!}
|
||||
{!! Theme::js('js/frontend/tasks.js') !!}
|
||||
{!! Theme::js('js/frontend/tasks/view-actions.js') !!}
|
||||
@endsection
|
||||
|
|
|
@ -213,7 +213,7 @@
|
|||
@parent
|
||||
{!! Theme::js('js/frontend/server.socket.js') !!}
|
||||
{!! Theme::js('vendor/select2/select2.full.min.js') !!}
|
||||
{!! Theme::js('js/frontend/tasks.js') !!}
|
||||
{!! Theme::js('js/frontend/tasks/view-actions.js') !!}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$.each(Pterodactyl.chained, function (index, value) {
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
use Pterodactyl\Http\Middleware\Server\SubuserAccess;
|
||||
use Pterodactyl\Http\Middleware\Server\ScheduleAccess;
|
||||
|
||||
Route::get('/', 'ConsoleController@index')->name('server.index');
|
||||
Route::get('/console', 'ConsoleController@console')->name('server.console');
|
||||
|
@ -90,17 +90,17 @@ Route::group(['prefix' => 'users'], function () {
|
|||
| Endpoint: /server/{server}/tasks
|
||||
|
|
||||
*/
|
||||
Route::group(['prefix' => 'tasks'], function () {
|
||||
Route::group(['prefix' => 'schedules'], function () {
|
||||
Route::get('/', 'Tasks\TaskManagementController@index')->name('server.tasks');
|
||||
Route::get('/new', 'Tasks\TaskManagementController@create')->name('server.tasks.new');
|
||||
Route::get('/view/{task}', 'Tasks\TaskManagementController@view')->name('server.tasks.view');
|
||||
Route::get('/view/{schedule}', 'Tasks\TaskManagementController@view')->middleware(ScheduleAccess::class)->name('server.tasks.view');
|
||||
|
||||
Route::post('/new', 'Tasks\TaskManagementController@store');
|
||||
|
||||
Route::patch('/view/{task}', 'Tasks\TaskManagementController@update');
|
||||
Route::patch('/view/{task}/toggle', 'Tasks\ToggleTaskController@index')->name('server.tasks.toggle');
|
||||
Route::patch('/view/{schedule}', 'Tasks\TaskManagementController@update')->middleware(ScheduleAccess::class);
|
||||
Route::patch('/view/{schedule}/toggle', 'Tasks\TaskToggleController@index')->middleware(ScheduleAccess::class)->name('server.tasks.toggle');
|
||||
|
||||
Route::delete('/view/{task}/delete', 'Tasks\TaskManagementController@delete')->name('server.tasks.delete');
|
||||
Route::delete('/view/{schedule}/delete', 'Tasks\TaskManagementController@delete')->middleware(ScheduleAccess::class)->name('server.tasks.delete');
|
||||
});
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue