Skip to content

Commit 698c121

Browse files
committed
First round of API additions
1 parent bf9708f commit 698c121

File tree

8 files changed

+229
-142
lines changed

8 files changed

+229
-142
lines changed

app/Contracts/Repository/RepositoryInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,10 @@ public function massUpdate(array $where, array $fields);
168168
/**
169169
* Return all records from the model.
170170
*
171+
* @param null $paginate
171172
* @return mixed
172173
*/
173-
public function all();
174+
public function all($paginate = null);
174175

175176
/**
176177
* Insert a single or multiple records into the database at once skipping
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Controllers\API\Admin\Users;
4+
5+
use Spatie\Fractal\Fractal;
6+
use Illuminate\Http\Request;
7+
use Pterodactyl\Http\Controllers\Controller;
8+
use Pterodactyl\Transformers\Admin\UserTransformer;
9+
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
10+
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
11+
use Illuminate\Contracts\Config\Repository as ConfigRepository;
12+
13+
/**
14+
* @SWG\Swagger(
15+
* schemes={"https"},
16+
* basePath="/api/admin/users"
17+
* )
18+
*/
19+
class UserController extends Controller
20+
{
21+
/**
22+
* @var \Spatie\Fractal\Fractal
23+
*/
24+
private $fractal;
25+
26+
/**
27+
* @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface
28+
*/
29+
private $repository;
30+
/**
31+
* @var \Illuminate\Contracts\Config\Repository
32+
*/
33+
private $config;
34+
35+
/**
36+
* UserController constructor.
37+
*
38+
* @param \Illuminate\Contracts\Config\Repository $config
39+
* @param \Spatie\Fractal\Fractal $fractal
40+
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository
41+
*/
42+
public function __construct(
43+
ConfigRepository $config,
44+
Fractal $fractal,
45+
UserRepositoryInterface $repository
46+
) {
47+
$this->fractal = $fractal;
48+
$this->repository = $repository;
49+
$this->config = $config;
50+
}
51+
52+
/**
53+
* Handle request to list all users on the panel.
54+
*
55+
* @param \Illuminate\Http\Request $request
56+
* @return array
57+
*/
58+
public function index(Request $request)
59+
{
60+
$users = $this->repository->all($this->config->get('pterodactyl.paginate.api.users'));
61+
62+
$fractal = $this->fractal->collection($users)
63+
->transformWith(new UserTransformer($request))
64+
->withResourceName('user')
65+
->paginateWith(new IlluminatePaginatorAdapter($users));
66+
67+
if ($this->config->get('pterodactyl.api.include_on_list') && $request->input('include')) {
68+
$fractal->parseIncludes(explode(',', $request->input('include')));
69+
}
70+
71+
return $fractal->toArray();
72+
}
73+
}

app/Models/User.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class User extends Model implements
8989
*
9090
* @var array
9191
*/
92-
protected $hidden = ['password', 'remember_token', 'totp_secret'];
92+
protected $hidden = ['password', 'remember_token', 'totp_secret', 'totp_authenticated_at'];
9393

9494
/**
9595
* Parameters for search querying.

app/Repositories/Eloquent/EloquentRepository.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,20 @@ public function massUpdate(array $where, array $fields)
184184
/**
185185
* {@inheritdoc}
186186
*/
187-
public function all()
187+
public function all($paginate = null)
188188
{
189+
Assert::nullOrIntegerish($paginate, 'First argument passed to all must be null or integer, received %s.');
190+
189191
$instance = $this->getBuilder();
190192
if (is_subclass_of(get_called_class(), SearchableInterface::class)) {
191193
$instance = $instance->search($this->searchTerm);
192194
}
193195

194-
return $instance->get($this->getColumns());
196+
if (is_null($paginate)) {
197+
return $instance->get($this->getColumns());
198+
}
199+
200+
return $instance->paginate($paginate, $this->getColumns());
195201
}
196202

197203
/**
Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,59 @@
11
<?php
2-
/**
3-
* Pterodactyl - Panel
4-
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5-
*
6-
* This software is licensed under the terms of the MIT license.
7-
* https://opensource.org/licenses/MIT
8-
*/
92

103
namespace Pterodactyl\Transformers\Admin;
114

125
use Illuminate\Http\Request;
136
use Pterodactyl\Models\User;
14-
use League\Fractal\TransformerAbstract;
7+
use Pterodactyl\Transformers\ApiTransformer;
158

16-
class UserTransformer extends TransformerAbstract
9+
class UserTransformer extends ApiTransformer
1710
{
1811
/**
1912
* List of resources that can be included.
2013
*
2114
* @var array
2215
*/
23-
protected $availableIncludes = [
24-
'access',
25-
'servers',
26-
];
27-
28-
/**
29-
* The Illuminate Request object if provided.
30-
*
31-
* @var \Illuminate\Http\Request|bool
32-
*/
33-
protected $request;
16+
protected $availableIncludes = ['servers'];
3417

3518
/**
3619
* Setup request object for transformer.
3720
*
38-
* @param \Illuminate\Http\Request|bool $request
21+
* @param \Illuminate\Http\Request $request
3922
*/
40-
public function __construct($request = false)
23+
public function __construct(Request $request)
4124
{
42-
if (! $request instanceof Request && $request !== false) {
43-
throw new DisplayException('Request passed to constructor must be of type Request or false.');
44-
}
45-
4625
$this->request = $request;
4726
}
4827

4928
/**
5029
* Return a generic transformed subuser array.
5130
*
31+
* @param \Pterodactyl\Models\User $user
5232
* @return array
5333
*/
54-
public function transform(User $user)
34+
public function transform(User $user): array
5535
{
5636
return $user->toArray();
5737
}
5838

5939
/**
6040
* Return the servers associated with this user.
6141
*
62-
* @return \Leauge\Fractal\Resource\Collection
42+
* @param \Pterodactyl\Models\User $user
43+
* @return bool|\League\Fractal\Resource\Collection
44+
*
45+
* @throws \Pterodactyl\Exceptions\PterodactylException
6346
*/
6447
public function includeServers(User $user)
6548
{
66-
if ($this->request && ! $this->request->apiKeyHasPermission('server-list')) {
67-
return;
49+
if ($this->authorize('server-list')) {
50+
return false;
6851
}
6952

70-
return $this->collection($user->servers, new ServerTransformer($this->request), 'server');
71-
}
72-
73-
/**
74-
* Return the servers that this user can access.
75-
*
76-
* @return \Leauge\Fractal\Resource\Collection
77-
*/
78-
public function includeAccess(User $user)
79-
{
80-
if ($this->request && ! $this->request->apiKeyHasPermission('server-list')) {
81-
return;
53+
if (! $user->relationLoaded('servers')) {
54+
$user->load('servers');
8255
}
8356

84-
return $this->collection($user->access()->get(), new ServerTransformer($this->request), 'server');
57+
return $this->collection($user->getRelation('servers'), new ServerTransformer($this->request), 'server');
8558
}
8659
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Pterodactyl\Transformers;
4+
5+
use League\Fractal\TransformerAbstract;
6+
use Pterodactyl\Exceptions\PterodactylException;
7+
8+
abstract class ApiTransformer extends TransformerAbstract
9+
{
10+
/**
11+
* @var \Illuminate\Http\Request
12+
*/
13+
protected $request;
14+
15+
/**
16+
* Determine if an API key from the request has permission to access
17+
* a resource. This is used when loading includes on the transformed
18+
* models.
19+
*
20+
* @param string $permission
21+
* @return bool
22+
*
23+
* @throws \Pterodactyl\Exceptions\PterodactylException
24+
*/
25+
protected function authorize(string $permission): bool
26+
{
27+
/** @var \Pterodactyl\Models\APIKey $model */
28+
$model = $this->request->attributes->get('api_key');
29+
if (! $model->relationLoaded('permissions')) {
30+
throw new PterodactylException('Permissions must be loaded onto a model before passing to transformer authorize function.');
31+
}
32+
33+
$count = $model->getRelation('permissions')->filter(function ($model) use ($permission) {
34+
return $model->permission === $permission;
35+
})->count();
36+
37+
return $count > 0;
38+
}
39+
}

routes/api-admin.php

Lines changed: 17 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,19 @@
11
<?php
2+
23
/*
3-
* Pterodactyl - Panel
4-
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5-
*
6-
* This software is licensed under the terms of the MIT license.
7-
* https://opensource.org/licenses/MIT
8-
*/
9-
//Route::get('/', 'CoreController@index');
10-
//
11-
///*
12-
//|--------------------------------------------------------------------------
13-
//| Server Controller Routes
14-
//|--------------------------------------------------------------------------
15-
//|
16-
//| Endpoint: /api/admin/servers
17-
//|
18-
//*/
19-
//Route::group(['prefix' => '/servers'], function () {
20-
// Route::get('/', 'ServerController@index');
21-
// Route::get('/{id}', 'ServerController@view');
22-
//
23-
// Route::post('/', 'ServerController@store');
24-
//
25-
// Route::put('/{id}/details', 'ServerController@details');
26-
// Route::put('/{id}/container', 'ServerController@container');
27-
// Route::put('/{id}/build', 'ServerController@build');
28-
// Route::put('/{id}/startup', 'ServerController@startup');
29-
//
30-
// Route::patch('/{id}/install', 'ServerController@install');
31-
// Route::patch('/{id}/rebuild', 'ServerController@rebuild');
32-
// Route::patch('/{id}/suspend', 'ServerController@suspend');
33-
//
34-
// Route::delete('/{id}', 'ServerController@delete');
35-
//});
36-
//
37-
///*
38-
//|--------------------------------------------------------------------------
39-
//| Location Controller Routes
40-
//|--------------------------------------------------------------------------
41-
//|
42-
//| Endpoint: /api/admin/locations
43-
//|
44-
//*/
45-
//Route::group(['prefix' => '/locations'], function () {
46-
// Route::get('/', 'LocationController@index');
47-
//});
48-
//
49-
///*
50-
//|--------------------------------------------------------------------------
51-
//| Node Controller Routes
52-
//|--------------------------------------------------------------------------
53-
//|
54-
//| Endpoint: /api/admin/nodes
55-
//|
56-
//*/
57-
//Route::group(['prefix' => '/nodes'], function () {
58-
// Route::get('/', 'NodeController@index');
59-
// Route::get('/{id}', 'NodeController@view');
60-
// Route::get('/{id}/config', 'NodeController@viewConfig');
61-
//
62-
// Route::post('/', 'NodeController@store');
63-
//
64-
// Route::delete('/{id}', 'NodeController@delete');
65-
//});
66-
//
67-
///*
68-
//|--------------------------------------------------------------------------
69-
//| User Controller Routes
70-
//|--------------------------------------------------------------------------
71-
//|
72-
//| Endpoint: /api/admin/users
73-
//|
74-
//*/
75-
//Route::group(['prefix' => '/users'], function () {
76-
// Route::get('/', 'UserController@index');
77-
// Route::get('/{id}', 'UserController@view');
78-
//
79-
// Route::post('/', 'UserController@store');
80-
//
81-
// Route::put('/{id}', 'UserController@update');
82-
//
83-
// Route::delete('/{id}', 'UserController@delete');
84-
//});
85-
//
86-
///*
87-
//|--------------------------------------------------------------------------
88-
//| Service Controller Routes
89-
//|--------------------------------------------------------------------------
90-
//|
91-
//| Endpoint: /api/admin/services
92-
//|
93-
//*/
94-
//Route::group(['prefix' => '/services'], function () {
95-
// Route::get('/', 'ServiceController@index');
96-
// Route::get('/{id}', 'ServiceController@view');
97-
//});
4+
|--------------------------------------------------------------------------
5+
| User Controller Routes
6+
|--------------------------------------------------------------------------
7+
|
8+
| Endpoint: /api/admin/users
9+
|
10+
*/
11+
Route::group(['prefix' => '/users'], function () {
12+
Route::get('/', 'Users\UserController@index')->name('api.admin.user.list');
13+
Route::get('/{id}', 'Users\UserController@view');
14+
15+
Route::post('/', 'Users\UserController@store');
16+
Route::put('/{id}', 'Users\UserController@update');
17+
18+
Route::delete('/{id}', 'Users\UserController@delete');
19+
});

0 commit comments

Comments
 (0)