diff --git a/app/Console/Commands/RunTasks.php b/app/Console/Commands/RunTasks.php index 9524bb54a..6c3ccc6c9 100644 --- a/app/Console/Commands/RunTasks.php +++ b/app/Console/Commands/RunTasks.php @@ -25,7 +25,7 @@ namespace Pterodactyl\Console\Commands; use Carbon; -use Pterodactyl\Models; +use Pterodactyl\Models\Task; use Illuminate\Console\Command; use Pterodactyl\Jobs\SendScheduledTask; use Illuminate\Foundation\Bus\DispatchesJobs; @@ -65,14 +65,14 @@ class RunTasks extends Command */ public function handle() { - $tasks = Models\Task::where('queued', 0)->where('active', 1)->where('next_run', '<=', Carbon::now()->toAtomString())->get(); + $tasks = Task::where('queued', false)->where('active', true)->where('next_run', '<=', Carbon::now()->toAtomString())->get(); $this->info(sprintf('Preparing to queue %d tasks.', count($tasks))); $bar = $this->output->createProgressBar(count($tasks)); foreach ($tasks as &$task) { $bar->advance(); - $this->dispatch((new SendScheduledTask(Models\Server::findOrFail($task->server), $task))->onQueue(config('pterodactyl.queues.low'))); + $this->dispatch((new SendScheduledTask($task))->onQueue(config('pterodactyl.queues.low'))); } $bar->finish(); diff --git a/app/Http/Controllers/API/User/ServerController.php b/app/Http/Controllers/API/User/ServerController.php index 1c5399cf9..b802d1f36 100644 --- a/app/Http/Controllers/API/User/ServerController.php +++ b/app/Http/Controllers/API/User/ServerController.php @@ -70,7 +70,7 @@ class ServerController extends Controller $server = Server::byUuid($uuid); $request->user()->can('power-' . $request->input('action'), $server); - $repo = new PowerRepository($server); + $repo = new PowerRepository($server, $request->user()); $repo->do($request->input('action')); return response('', 204)->header('Content-Type', 'application/json'); @@ -90,7 +90,7 @@ class ServerController extends Controller $server = Server::byUuid($uuid); $request->user()->can('send-command', $server); - $repo = new CommandRepository($server); + $repo = new CommandRepository($server, $request->user()); $repo->send($request->input('command')); return response('', 204)->header('Content-Type', 'application/json'); diff --git a/app/Http/Controllers/Server/TaskController.php b/app/Http/Controllers/Server/TaskController.php index 1bd7f3244..8eebaa21d 100644 --- a/app/Http/Controllers/Server/TaskController.php +++ b/app/Http/Controllers/Server/TaskController.php @@ -26,9 +26,9 @@ namespace Pterodactyl\Http\Controllers\Server; use Log; use Alert; -use Pterodactyl\Models; use Illuminate\Http\Request; -use Pterodactyl\Repositories; +use Pterodactyl\Models\Server; +use Pterodactyl\Repositories\TaskRepository; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Exceptions\DisplayValidationException; @@ -44,7 +44,7 @@ class TaskController extends Controller */ public function index(Request $request, $uuid) { - $server = Models\Server::byUuid($uuid)->load('tasks'); + $server = Server::byUuid($uuid)->load('tasks'); $this->authorize('list-tasks', $server); $server->js(); @@ -68,7 +68,7 @@ class TaskController extends Controller */ public function create(Request $request, $uuid) { - $server = Models\Server::byUuid($uuid); + $server = Server::byUuid($uuid); $this->authorize('create-task', $server); $server->js(); @@ -87,12 +87,12 @@ class TaskController extends Controller */ public function store(Request $request, $uuid) { - $server = Models\Server::byUuid($uuid); + $server = Server::byUuid($uuid); $this->authorize('create-task', $server); + $repo = new TaskRepository; try { - $repo = new Repositories\TaskRepository; - $repo->create($server->id, $request->except([ + $repo->create($server->id, $request->user()->id, $request->except([ '_token', ])); @@ -119,7 +119,7 @@ class TaskController extends Controller */ public function delete(Request $request, $uuid, $id) { - $server = Models\Server::byUuid($uuid)->load('tasks'); + $server = Server::byUuid($uuid)->load('tasks'); $this->authorize('delete-task', $server); $task = $server->tasks->where('id', $id)->first(); @@ -129,8 +129,8 @@ class TaskController extends Controller ], 404); } + $repo = new TaskRepository; try { - $repo = new Repositories\TaskRepository; $repo->delete($id); return response()->json([], 204); @@ -153,7 +153,7 @@ class TaskController extends Controller */ public function toggle(Request $request, $uuid, $id) { - $server = Models\Server::byUuid($uuid)->load('tasks'); + $server = Server::byUuid($uuid)->load('tasks'); $this->authorize('toggle-task', $server); $task = $server->tasks->where('id', $id)->first(); @@ -163,8 +163,8 @@ class TaskController extends Controller ], 404); } + $repo = new TaskRepository; try { - $repo = new Repositories\TaskRepository; $resp = $repo->toggle($id); return response()->json([ diff --git a/app/Jobs/SendScheduledTask.php b/app/Jobs/SendScheduledTask.php index 0f50f66f5..167b8e250 100644 --- a/app/Jobs/SendScheduledTask.php +++ b/app/Jobs/SendScheduledTask.php @@ -26,7 +26,10 @@ namespace Pterodactyl\Jobs; use Cron; use Carbon; -use Pterodactyl\Models; +use Pterodactyl\Models\Task; +use Pterodactyl\Models\User; +use Pterodactyl\Models\Server; +use Pterodactyl\Models\TaskLog; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; @@ -37,11 +40,6 @@ class SendScheduledTask extends Job implements ShouldQueue { use InteractsWithQueue, SerializesModels; - /** - * @var \Pterodactyl\Models\Server - */ - protected $server; - /** * @var \Pterodactyl\Models\Task */ @@ -52,13 +50,12 @@ class SendScheduledTask extends Job implements ShouldQueue * * @return void */ - public function __construct(Models\Server $server, Models\Task $task) + public function __construct(Task $task) { - $this->server = $server; $this->task = $task; - $task->queued = 1; - $task->save(); + $this->task->queued = true; + $this->task->save(); } /** @@ -69,7 +66,7 @@ class SendScheduledTask extends Job implements ShouldQueue public function handle() { $time = Carbon::now(); - $log = new Models\TaskLog; + $log = new TaskLog; if ($this->attempts() >= 1) { // Just delete the job, we will attempt it again later anyways. @@ -78,12 +75,15 @@ class SendScheduledTask extends Job implements ShouldQueue try { if ($this->task->action === 'command') { - $repo = new CommandRepository($this->server); + $repo = new CommandRepository($this->task->server, $this->task->user); $response = $repo->send($this->task->data); - } elseif ($this->task->action === 'power') { - $repo = new PowerRepository($this->server); + } else if ($this->task->action === 'power') { + $repo = new PowerRepository($this->task->server, $this->task->user); $response = $repo->do($this->task->data); + } else { + throw new \Exception('Task type provided was not valid.'); } + $log->fill([ 'task_id' => $this->task->id, 'run_time' => $time, @@ -109,7 +109,7 @@ class SendScheduledTask extends Job implements ShouldQueue $this->task->fill([ 'last_run' => $time, 'next_run' => $cron->getNextRunDate(), - 'queued' => 0, + 'queued' => false, ]); $this->task->save(); $log->save(); diff --git a/app/Models/Server.php b/app/Models/Server.php index 1ad025ec7..921e7ad00 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -320,7 +320,7 @@ class Server extends Model */ public function tasks() { - return $this->hasMany(Task::class, 'server', 'id'); + return $this->hasMany(Task::class); } /** diff --git a/app/Models/Task.php b/app/Models/Task.php index 46123cb93..5e44a8264 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -49,8 +49,10 @@ class Task extends Model */ protected $casts = [ 'id' => 'integer', - 'server' => 'integer', - 'queued' => 'integer', + 'user_id' => 'integer', + 'server_id' => 'integer', + 'queued' => 'boolean', + 'active' => 'boolean', ]; /** @@ -59,4 +61,24 @@ class Task extends Model * @var array */ protected $dates = ['last_run', 'next_run', 'created_at', 'updated_at']; + + /** + * Gets the server associated with a task. + * + * @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); + } } diff --git a/app/Repositories/Daemon/CommandRepository.php b/app/Repositories/Daemon/CommandRepository.php index b7149b453..beb9e8530 100644 --- a/app/Repositories/Daemon/CommandRepository.php +++ b/app/Repositories/Daemon/CommandRepository.php @@ -24,7 +24,8 @@ namespace Pterodactyl\Repositories\Daemon; -use Pterodactyl\Models; +use Pterodactyl\Models\User; +use Pterodactyl\Models\Server; use GuzzleHttp\Exception\ConnectException; use Pterodactyl\Exceptions\DisplayException; @@ -37,15 +38,24 @@ class CommandRepository */ protected $server; + /** + * The Eloquent Model associated with the user to run the request as. + * + * @var \Pterodactyl\Models\User|null + */ + protected $user; + /** * Constuctor for repository. * - * @param int|\Pterodactyl\Models\Server $server + * @param \Pterodactyl\Models\Server $server + * @param \Pterodactyl\Models\User|null $user * @return void */ - public function __construct($server) + public function __construct(Server $server, User $user = null) { - $this->server = ($server instanceof Models\Server) ? $server : Models\Server::findOrFail($server); + $this->server = $server; + $this->user = $user; } /** @@ -62,7 +72,7 @@ class CommandRepository // We don't use the user's specific daemon secret here since we // are assuming that a call to this function has been validated. try { - $response = $this->server->guzzleClient()->request('PUT', '/server/command', [ + $response = $this->server->guzzleClient($this->user)->request('POST', '/server/command', [ 'http_errors' => false, 'json' => [ 'command' => $command, diff --git a/app/Repositories/Daemon/PowerRepository.php b/app/Repositories/Daemon/PowerRepository.php index bc5696986..925379096 100644 --- a/app/Repositories/Daemon/PowerRepository.php +++ b/app/Repositories/Daemon/PowerRepository.php @@ -24,7 +24,8 @@ namespace Pterodactyl\Repositories\Daemon; -use Pterodactyl\Models; +use Pterodactyl\Models\User; +use Pterodactyl\Models\Server; use GuzzleHttp\Exception\ConnectException; use Pterodactyl\Exceptions\DisplayException; @@ -37,21 +38,30 @@ class PowerRepository */ protected $server; + /** + * The Eloquent Model associated with the user to run the request as. + * + * @var \Pterodactyl\Models\User|null + */ + protected $user; + /** * Constuctor for repository. * - * @param int|\Pterodactyl\Models\Server $server + * @param \Pterodactyl\Models\Server $server + * @param \Pterodactyl\Models\User|null $user * @return void */ - public function __construct($server) + public function __construct(Server $server, User $user = null) { - $this->server = ($server instanceof Models\Server) ? $server : Models\Server::findOrFail($server); + $this->server = $server; + $this->user = $user; } /** * Sends a power option to the daemon. * - * @param string $action + * @param string $action * @return string * * @throws \GuzzleHttp\Exception\RequestException @@ -59,10 +69,8 @@ class PowerRepository */ public function do($action) { - // We don't use the user's specific daemon secret here since we - // are assuming that a call to this function has been validated. try { - $response = $this->server->guzzleClient()->request('PUT', '/server/power', [ + $response = $this->server->guzzleClient($this->user)->request('PUT', '/server/power', [ 'http_errors' => false, 'json' => [ 'action' => $action, diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php index e8aff6c45..790078c22 100644 --- a/app/Repositories/TaskRepository.php +++ b/app/Repositories/TaskRepository.php @@ -24,9 +24,12 @@ namespace Pterodactyl\Repositories; +use DB; use Cron; use Validator; -use Pterodactyl\Models; +use Pterodactyl\Models\Task; +use Pterodactyl\Models\User; +use Pterodactyl\Models\Server; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayValidationException; @@ -64,49 +67,42 @@ class TaskRepository */ public function delete($id) { - $task = Models\Task::findOrFail($id); - try { - $task->delete(); - - return true; - } catch (\Exception $ex) { - throw $ex; - } + $task = Task::findOrFail($id); + $task->delete(); } /** * Toggles a task active or inactive. * * @param int $id - * @return int + * @return bool */ public function toggle($id) { - $task = Models\Task::findOrFail($id); - try { - $task->active = ($task->active === 1) ? 0 : 1; - $task->queued = 0; - $task->save(); + $task = Task::findOrFail($id); - return $task->active; - } catch (\Exception $ex) { - throw $ex; - } + $task->active = ! $task->active; + $task->queued = false; + $task->save(); + + return $task->active; } /** * Create a new scheduled task for a given server. * - * @param int $id + * @param int $server + * @param int $user * @param array $data - * @return bool + * @return \Pterodactyl\Models\Task * * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\DisplayValidationException */ - public function create($id, $data) + public function create($server, $user, $data) { - $server = Models\Server::findOrFail($id); + $server = Server::findOrFail($server); + $user = User::findOrFail($user); $validator = Validator::make($data, [ 'action' => 'string|required', @@ -148,9 +144,9 @@ class TaskRepository throw $ex; } - $task = new Models\Task; - $task->fill([ - 'server' => $server->id, + return Task::create([ + 'user_id' => $user->id, + 'server_id' => $server->id, 'active' => 1, 'action' => $data['action'], 'data' => $data['data'], @@ -164,7 +160,5 @@ class TaskRepository 'last_run' => null, 'next_run' => $buildCron->getNextRunDate(), ]); - - return $task->save(); } } diff --git a/database/migrations/2017_04_15_125021_UpgradeTaskSystem.php b/database/migrations/2017_04_15_125021_UpgradeTaskSystem.php new file mode 100644 index 000000000..f9753fde4 --- /dev/null +++ b/database/migrations/2017_04_15_125021_UpgradeTaskSystem.php @@ -0,0 +1,43 @@ +dropForeign(['server']); + + $table->renameColumn('server', 'server_id'); + $table->unsignedInteger('user_id')->after('id'); + + $table->foreign('server_id')->references('id')->on('servers'); + $table->foreign('user_id')->references('id')->on('users'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('tasks', function (Blueprint $table) { + $table->dropForeign(['server_id', 'user_id']); + + $table->renameColumn('server_id', 'server'); + $table->dropColumn('user_id'); + + $table->foreign('server')->references('id')->on('servers'); + }); + } +} diff --git a/resources/themes/pterodactyl/layouts/master.blade.php b/resources/themes/pterodactyl/layouts/master.blade.php index 579571bc1..a2483c9fd 100644 --- a/resources/themes/pterodactyl/layouts/master.blade.php +++ b/resources/themes/pterodactyl/layouts/master.blade.php @@ -159,7 +159,7 @@ @lang('navigation.server.task_management') - {{ \Pterodactyl\Models\Task::select('id')->where('server', $server->id)->where('active', 1)->count() }} + {{ \Pterodactyl\Models\Task::select('id')->where('server_id', $server->id)->where('active', 1)->count() }} diff --git a/resources/themes/pterodactyl/server/tasks/index.blade.php b/resources/themes/pterodactyl/server/tasks/index.blade.php index 738cb8b14..5505d22ef 100644 --- a/resources/themes/pterodactyl/server/tasks/index.blade.php +++ b/resources/themes/pterodactyl/server/tasks/index.blade.php @@ -55,7 +55,7 @@
{{ $task->data }}