Skip to content

Commit d3c749a

Browse files
committed
Code cleanup & fix frontend searching servers; closes pterodactyl#2100
1 parent f0e18ba commit d3c749a

File tree

14 files changed

+226
-194
lines changed

14 files changed

+226
-194
lines changed

app/Contracts/Repository/ServerRepositoryInterface.php

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Pterodactyl\Contracts\Repository;
44

5-
use Pterodactyl\Models\User;
65
use Pterodactyl\Models\Server;
76
use Illuminate\Support\Collection;
87
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
@@ -107,16 +106,6 @@ public function loadDatabaseRelations(Server $server, bool $refresh = false): Se
107106
*/
108107
public function getDaemonServiceData(Server $server, bool $refresh = false): array;
109108

110-
/**
111-
* Return a paginated list of servers that a user can access at a given level.
112-
*
113-
* @param \Pterodactyl\Models\User $user
114-
* @param int $level
115-
* @param bool|int $paginate
116-
* @return \Illuminate\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Collection
117-
*/
118-
public function filterUserAccessServers(User $user, int $level, $paginate = 25);
119-
120109
/**
121110
* Return a server by UUID.
122111
*

app/Http/Controllers/Api/Client/ClientApiController.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,38 @@
1010

1111
abstract class ClientApiController extends ApplicationApiController
1212
{
13+
/**
14+
* Returns only the includes which are valid for the given transformer.
15+
*
16+
* @param \Pterodactyl\Transformers\Api\Client\BaseClientTransformer $transformer
17+
* @param array $merge
18+
* @return string[]
19+
*/
20+
protected function getIncludesForTransformer(BaseClientTransformer $transformer, array $merge = [])
21+
{
22+
$filtered = array_filter($this->parseIncludes(), function ($datum) use ($transformer) {
23+
return in_array($datum, $transformer->getAvailableIncludes());
24+
});
25+
26+
return array_merge($filtered, $merge);
27+
}
28+
29+
/**
30+
* Returns the parsed includes for this request.
31+
*/
32+
protected function parseIncludes()
33+
{
34+
$includes = $this->request->query('include');
35+
36+
if (! is_string($includes)) {
37+
return $includes;
38+
}
39+
40+
return array_map(function ($item) {
41+
return trim($item);
42+
}, explode(',', $includes));
43+
}
44+
1345
/**
1446
* Return an instance of an application transformer.
1547
*

app/Http/Controllers/Api/Client/ClientController.php

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
namespace Pterodactyl\Http\Controllers\Api\Client;
44

55
use Pterodactyl\Models\User;
6+
use Pterodactyl\Models\Server;
67
use Pterodactyl\Models\Permission;
8+
use Spatie\QueryBuilder\QueryBuilder;
79
use Pterodactyl\Repositories\Eloquent\ServerRepository;
810
use Pterodactyl\Transformers\Api\Client\ServerTransformer;
911
use Pterodactyl\Http\Requests\Api\Client\GetServersRequest;
@@ -36,32 +38,36 @@ public function __construct(ServerRepository $repository)
3638
*/
3739
public function index(GetServersRequest $request): array
3840
{
39-
// Check for the filter parameter on the request.
40-
switch ($request->input('filter')) {
41-
case 'all':
42-
$filter = User::FILTER_LEVEL_ALL;
43-
break;
44-
case 'admin':
45-
$filter = User::FILTER_LEVEL_ADMIN;
46-
break;
47-
case 'owner':
48-
$filter = User::FILTER_LEVEL_OWNER;
49-
break;
50-
case 'subuser-of':
51-
default:
52-
$filter = User::FILTER_LEVEL_SUBUSER;
53-
break;
41+
$user = $request->user();
42+
$level = $request->getFilterLevel();
43+
$transformer = $this->getTransformer(ServerTransformer::class);
44+
45+
// Start the query builder and ensure we eager load any requested relationships from the request.
46+
$builder = Server::query()->with($this->getIncludesForTransformer($transformer, ['node']));
47+
48+
if ($level === User::FILTER_LEVEL_OWNER) {
49+
$builder = $builder->where('owner_id', $request->user()->id);
50+
}
51+
// If set to all, display all servers they can access, including those they access as an
52+
// admin. If set to subuser, only return the servers they can access because they are owner,
53+
// or marked as a subuser of the server.
54+
elseif (($level === User::FILTER_LEVEL_ALL && ! $user->root_admin) || $level === User::FILTER_LEVEL_SUBUSER) {
55+
$builder = $builder->whereIn('id', $user->accessibleServers()->pluck('id')->all());
5456
}
57+
// If set to admin, only display the servers a user can access because they are an administrator.
58+
// This means only servers the user would not have access to if they were not an admin (because they
59+
// are not an owner or subuser) are returned.
60+
elseif ($level === User::FILTER_LEVEL_ADMIN && $user->root_admin) {
61+
$builder = $builder->whereNotIn('id', $user->accessibleServers()->pluck('id')->all());
62+
}
63+
64+
$builder = QueryBuilder::for($builder)->allowedFilters(
65+
'uuid', 'name', 'external_id'
66+
);
5567

56-
$servers = $this->repository
57-
->setSearchTerm($request->input('query'))
58-
->filterUserAccessServers(
59-
$request->user(), $filter, config('pterodactyl.paginate.frontend.servers')
60-
);
68+
$servers = $builder->paginate(min($request->query('per_page', 50), 100))->appends($request->query());
6169

62-
return $this->fractal->collection($servers)
63-
->transformWith($this->getTransformer(ServerTransformer::class))
64-
->toArray();
70+
return $this->fractal->transformWith($transformer)->collection($servers)->toArray();
6571
}
6672

6773
/**

app/Http/Controllers/Base/IndexController.php

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
namespace Pterodactyl\Http\Controllers\Base;
44

5-
use Illuminate\Http\Request;
6-
use Pterodactyl\Models\User;
75
use Pterodactyl\Http\Controllers\Controller;
86
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
97

@@ -27,15 +25,10 @@ public function __construct(ServerRepositoryInterface $repository)
2725
/**
2826
* Returns listing of user's servers.
2927
*
30-
* @param \Illuminate\Http\Request $request
3128
* @return \Illuminate\View\View
3229
*/
33-
public function index(Request $request)
30+
public function index()
3431
{
35-
$servers = $this->repository->setSearchTerm($request->input('query'))->filterUserAccessServers(
36-
$request->user(), User::FILTER_LEVEL_ALL, config('pterodactyl.paginate.frontend.servers')
37-
);
38-
39-
return view('templates/base.core', ['servers' => $servers]);
32+
return view('templates/base.core');
4033
}
4134
}

app/Http/Requests/Api/Client/GetServersRequest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Pterodactyl\Http\Requests\Api\Client;
44

5+
use Pterodactyl\Models\User;
6+
57
class GetServersRequest extends ClientApiRequest
68
{
79
/**
@@ -11,4 +13,28 @@ public function authorize(): bool
1113
{
1214
return true;
1315
}
16+
17+
/**
18+
* Return the filtering method for servers when the client base endpoint is requested.
19+
*
20+
* @return int
21+
*/
22+
public function getFilterLevel(): int
23+
{
24+
switch ($this->input('type')) {
25+
case 'all':
26+
return User::FILTER_LEVEL_ALL;
27+
break;
28+
case 'admin':
29+
return User::FILTER_LEVEL_ADMIN;
30+
break;
31+
case 'owner':
32+
return User::FILTER_LEVEL_OWNER;
33+
break;
34+
case 'subuser-of':
35+
default:
36+
return User::FILTER_LEVEL_SUBUSER;
37+
break;
38+
}
39+
}
1440
}

app/Http/ViewComposers/Server/ServerDataComposer.php

Lines changed: 0 additions & 38 deletions
This file was deleted.

app/Http/ViewComposers/ServerListComposer.php

Lines changed: 0 additions & 51 deletions
This file was deleted.

app/Models/User.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Validation\Rules\In;
88
use Illuminate\Auth\Authenticatable;
99
use Illuminate\Notifications\Notifiable;
10+
use Illuminate\Database\Eloquent\Builder;
1011
use Pterodactyl\Models\Traits\Searchable;
1112
use Illuminate\Auth\Passwords\CanResetPassword;
1213
use Pterodactyl\Traits\Helpers\AvailableLanguages;
@@ -260,4 +261,21 @@ public function recoveryTokens()
260261
{
261262
return $this->hasMany(RecoveryToken::class);
262263
}
264+
265+
/**
266+
* Returns all of the servers that a user can access by way of being the owner of the
267+
* server, or because they are assigned as a subuser for that server.
268+
*
269+
* @return \Illuminate\Database\Eloquent\Relations\HasMany
270+
*/
271+
public function accessibleServers()
272+
{
273+
return $this->hasMany(Server::class, 'owner_id')
274+
->select('servers.*')
275+
->leftJoin('subusers', 'subusers.server_id', '=', 'servers.id')
276+
->where(function (Builder $builder) {
277+
$builder->where('servers.owner_id', $this->id)->orWhere('subusers.user_id', $this->id);
278+
})
279+
->groupBy('servers.id');
280+
}
263281
}

app/Providers/ViewComposerServiceProvider.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Illuminate\Support\ServiceProvider;
66
use Pterodactyl\Http\ViewComposers\AssetComposer;
7-
use Pterodactyl\Http\ViewComposers\ServerListComposer;
8-
use Pterodactyl\Http\ViewComposers\Server\ServerDataComposer;
97

108
class ViewComposerServiceProvider extends ServiceProvider
119
{
@@ -15,10 +13,5 @@ class ViewComposerServiceProvider extends ServiceProvider
1513
public function boot()
1614
{
1715
$this->app->make('view')->composer('*', AssetComposer::class);
18-
19-
$this->app->make('view')->composer('server.*', ServerDataComposer::class);
20-
21-
// Add data to make the sidebar work when viewing a server.
22-
$this->app->make('view')->composer(['server.*'], ServerListComposer::class);
2316
}
2417
}

0 commit comments

Comments
 (0)