Skip to content

Commit 67d9f9f

Browse files
committed
Improve scheduled task layout and data handling
1 parent c1301c7 commit 67d9f9f

File tree

11 files changed

+639
-0
lines changed

11 files changed

+639
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Http\Controllers\Server;
25+
26+
use Alert;
27+
use Log;
28+
use Cron;
29+
30+
use Pterodactyl\Models;
31+
use Pterodactyl\Exceptions\DisplayException;
32+
use Pterodactyl\Exceptions\DisplayValidationException;
33+
34+
use Pterodactyl\Http\Controllers\Controller;
35+
use Illuminate\Http\Request;
36+
37+
class TaskController extends Controller
38+
{
39+
public function __constructor()
40+
{
41+
//
42+
}
43+
44+
public function getIndex(Request $request, $uuid)
45+
{
46+
$server = Models\Server::getByUUID($uuid);
47+
$this->authorize('list-tasks', $server);
48+
49+
return view('server.tasks.index', [
50+
'server' => $server,
51+
'node' => Models\Node::findOrFail($server->node),
52+
'tasks' => Models\Task::where('server', $server->id)->get(),
53+
'actions' => [
54+
'command' => 'Send Command',
55+
'power' => 'Set Power Status'
56+
]
57+
]);
58+
}
59+
60+
public function getNew(Request $request, $uuid)
61+
{
62+
$server = Models\Server::getByUUID($uuid);
63+
$this->authorize('create-task', $server);
64+
65+
return view('server.tasks.new', [
66+
'server' => $server,
67+
'node' => Models\Node::findOrFail($server->node)
68+
]);
69+
}
70+
71+
public function postNew(Request $request, $uuid)
72+
{
73+
dd($request->input());
74+
}
75+
76+
public function getView(Request $request, $uuid, $id)
77+
{
78+
$server = Models\Server::getByUUID($uuid);
79+
$this->authorize('view-task', $server);
80+
81+
return view('server.tasks.view', [
82+
'server' => $server,
83+
'node' => Models\Node::findOrFail($server->node),
84+
'task' => Models\Task::where('id', $id)->where('server', $server->id)->firstOrFail()
85+
]);
86+
}
87+
}

app/Http/Routes/ServerRoutes.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,30 @@ public function map(Router $router) {
117117
'uses' => 'Server\SubuserController@deleteSubuser'
118118
]);
119119

120+
$router->get('tasks/', [
121+
'as' => 'server.tasks',
122+
'uses' => 'Server\TaskController@getIndex'
123+
]);
124+
125+
$router->get('tasks/view/{id}', [
126+
'as' => 'server.tasks.view',
127+
'uses' => 'Server\TaskController@getView'
128+
]);
129+
130+
$router->get('tasks/new', [
131+
'as' => 'server.tasks.new',
132+
'uses' => 'Server\TaskController@getNew'
133+
]);
134+
135+
$router->post('tasks/new', [
136+
'uses' => 'Server\TaskController@postNew'
137+
]);
138+
139+
$router->delete('tasks/delete/{id}', [
140+
'as' => 'server.tasks.delete',
141+
'uses' => 'Server\TaskController@deleteTask'
142+
]);
143+
120144
// Assorted AJAX Routes
121145
$router->group(['prefix' => 'ajax'], function ($server) use ($router) {
122146
// Returns Server Status

app/Policies/ServerPolicy.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,4 +450,100 @@ public function viewDatabases(User $user, Server $server)
450450
return $user->permissions()->server($server)->permission('view-databases')->exists();
451451
}
452452

453+
/**
454+
* Check if user has permission to view all tasks for a server.
455+
*
456+
* @param Pterodactyl\Models\User $user
457+
* @param Pterodactyl\Models\Server $server
458+
* @return boolean
459+
*/
460+
public function listTasks(User $user, Server $server)
461+
{
462+
if ($this->isOwner($user, $server)) {
463+
return true;
464+
}
465+
466+
return $user->permissions()->server($server)->permission('list-tasks')->exists();
467+
}
468+
469+
/**
470+
* Check if user has permission to view a specific task for a server.
471+
*
472+
* @param Pterodactyl\Models\User $user
473+
* @param Pterodactyl\Models\Server $server
474+
* @return boolean
475+
*/
476+
public function viewTask(User $user, Server $server)
477+
{
478+
if ($this->isOwner($user, $server)) {
479+
return true;
480+
}
481+
482+
return $user->permissions()->server($server)->permission('view-task')->exists();
483+
}
484+
485+
/**
486+
* Check if user has permission to view a toggle a task for a server.
487+
*
488+
* @param Pterodactyl\Models\User $user
489+
* @param Pterodactyl\Models\Server $server
490+
* @return boolean
491+
*/
492+
public function toggleTask(User $user, Server $server)
493+
{
494+
if ($this->isOwner($user, $server)) {
495+
return true;
496+
}
497+
498+
return $user->permissions()->server($server)->permission('toggle-task')->exists();
499+
}
500+
501+
/**
502+
* Check if user has permission to queue a task for a server.
503+
*
504+
* @param Pterodactyl\Models\User $user
505+
* @param Pterodactyl\Models\Server $server
506+
* @return boolean
507+
*/
508+
public function queueTask(User $user, Server $server)
509+
{
510+
if ($this->isOwner($user, $server)) {
511+
return true;
512+
}
513+
514+
return $user->permissions()->server($server)->permission('queue-task')->exists();
515+
}
516+
517+
/**
518+
* Check if user has permission to delete a specific task for a server.
519+
*
520+
* @param Pterodactyl\Models\User $user
521+
* @param Pterodactyl\Models\Server $server
522+
* @return boolean
523+
*/
524+
public function deleteTask(User $user, Server $server)
525+
{
526+
if ($this->isOwner($user, $server)) {
527+
return true;
528+
}
529+
530+
return $user->permissions()->server($server)->permission('delete-task')->exists();
531+
}
532+
533+
/**
534+
* Check if user has permission to create a task for a server.
535+
*
536+
* @param Pterodactyl\Models\User $user
537+
* @param Pterodactyl\Models\Server $server
538+
* @return boolean
539+
*/
540+
public function createTask(User $user, Server $server)
541+
{
542+
if ($this->isOwner($user, $server)) {
543+
return true;
544+
}
545+
546+
return $user->permissions()->server($server)->permission('create-task')->exists();
547+
}
548+
453549
}

app/Repositories/SubuserRepository.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ class SubuserRepository
7979
'create-subuser' => null,
8080
'delete-subuser' => null,
8181

82+
// Tasks
83+
'list-tasks' => null,
84+
'view-task' => null,
85+
'toggle-task' => null,
86+
'delete-task' => null,
87+
'create-task' => null,
88+
'queue-task' => null,
89+
8290
// Management
8391
'set-connection' => null,
8492
'view-startup' => null,
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
namespace Pterodactyl\Repositories;
25+
26+
use Cron;
27+
use Validator;
28+
29+
use Pterodactyl\Models;
30+
31+
use Pterodactyl\Exceptions\DisplayValidationException;
32+
use Pterodactyl\Exceptions\DisplayException;
33+
34+
class TaskRepository
35+
{
36+
37+
protected $defaults = [
38+
'year' => '*',
39+
'day_of_week' => '*',
40+
'month' => '*',
41+
'day_of_month' => '*',
42+
'hour' => '*',
43+
'minute' => '*/30',
44+
];
45+
46+
protected $actions = [
47+
'command',
48+
'power',
49+
];
50+
51+
public function __construct()
52+
{
53+
//
54+
}
55+
56+
/**
57+
* Create a new scheduled task for a given server.
58+
* @param int $id
59+
* @param array $data
60+
*
61+
* @throws DisplayException
62+
* @throws DisplayValidationException
63+
* @return void
64+
*/
65+
public function create($id, $data)
66+
{
67+
$server = Models\Server::findOrFail($id);
68+
69+
$validator = Validator::make($data, [
70+
'action' => 'string|required',
71+
'data' => 'string|required',
72+
'year' => 'string|sometimes|required',
73+
'day_of_week' => 'string|sometimes|required',
74+
'month' => 'string|sometimes|required',
75+
'day_of_month' => 'string|sometimes|required',
76+
'hour' => 'string|sometimes|required',
77+
'minute' => 'string|sometimes|required'
78+
]);
79+
80+
if ($validator->fails()) {
81+
throw new DisplayValidationException(json_encode($validator->errors()));
82+
}
83+
84+
if (!in_array($data['action'], $this->actions)) {
85+
throw new DisplayException('The action provided is not valid.');
86+
}
87+
88+
$cron = $this->defaults;
89+
foreach ($this->defaults as $setting => $value) {
90+
if (array_key_exists($setting, $data)) {
91+
$cron[$setting] = $data[$setting];
92+
}
93+
}
94+
95+
// Check that is this a valid Cron Entry
96+
try {
97+
$buildCron = Cron::factory(sprintf('%s %s %s %s %s %s',
98+
$cron['minute'],
99+
$cron['hour'],
100+
$cron['day_of_month'],
101+
$cron['month'],
102+
$cron['day_of_week'],
103+
$cron['year']
104+
));
105+
} catch (\Exception $ex) {
106+
throw new DisplayException($ex);
107+
}
108+
109+
$task = new Models\Task;
110+
$task->fill([
111+
'server' => $server->id,
112+
'active' => 1,
113+
'action' => $data['action'],
114+
'data' => $data['data'],
115+
'queued' => 0,
116+
'year' => $cron['year'],
117+
'day_of_week' => $cron['day_of_week'],
118+
'month' => $cron['month'],
119+
'day_of_month' => $cron['day_of_month'],
120+
'hour' => $cron['hour'],
121+
'minute' => $cron['minute'],
122+
'last_run' => null,
123+
'next_run' => $buildCron->getNextRunDate()
124+
]);
125+
126+
return $task->save();
127+
128+
}
129+
130+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use Illuminate\Database\Schema\Blueprint;
4+
use Illuminate\Database\Migrations\Migration;
5+
6+
class AddNullableFieldLastrun extends Migration
7+
{
8+
/**
9+
* Run the migrations.
10+
*
11+
* @return void
12+
*/
13+
public function up()
14+
{
15+
$table = DB::getQueryGrammar()->wrapTable('tasks');
16+
DB::statement('ALTER TABLE '.$table.' CHANGE `last_run` `last_run` TIMESTAMP NULL;');
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*
22+
* @return void
23+
*/
24+
public function down()
25+
{
26+
$table = DB::getQueryGrammar()->wrapTable('tasks');
27+
DB::statement('ALTER TABLE '.$table.' CHANGE `last_run` `last_run` TIMESTAMP;');
28+
}
29+
}

0 commit comments

Comments
 (0)