Skip to content

Commit 722fd61

Browse files
committed
Add new dynamic view for creating API keys
1 parent 87c09a9 commit 722fd61

File tree

10 files changed

+312
-493
lines changed

10 files changed

+312
-493
lines changed

app/Http/Controllers/API/User/CoreController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class CoreController extends Controller
3939
*/
4040
public function index(Request $request)
4141
{
42-
$this->authorize('user-server-list', $request->apiKey());
42+
$this->authorize('user.server-list', $request->apiKey());
4343

4444
$servers = $request->user()->access('service', 'node', 'allocation', 'option')->get();
4545

app/Http/Controllers/API/User/ServerController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class ServerController extends Controller
4343
*/
4444
public function index(Request $request, $uuid)
4545
{
46-
$this->authorize('user-server-view', $request->apiKey());
46+
$this->authorize('user.server-view', $request->apiKey());
4747

4848
$server = Server::byUuid($uuid);
4949
$fractal = Fractal::create()->item($server);
@@ -66,7 +66,7 @@ public function index(Request $request, $uuid)
6666
*/
6767
public function power(Request $request, $uuid)
6868
{
69-
$this->authorize('user-server-power', $request->apiKey());
69+
$this->authorize('user.server-power', $request->apiKey());
7070

7171
$server = Server::byUuid($uuid);
7272
$request->user()->can('power-' . $request->input('action'), $server);
@@ -86,7 +86,7 @@ public function power(Request $request, $uuid)
8686
*/
8787
public function command(Request $request, $uuid)
8888
{
89-
$this->authorize('user-server-command', $request->apiKey());
89+
$this->authorize('user.server-command', $request->apiKey());
9090

9191
$server = Server::byUuid($uuid);
9292
$request->user()->can('send-command', $server);

app/Http/Controllers/Base/APIController.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727

2828
use Log;
2929
use Alert;
30-
use Pterodactyl\Models;
3130
use Illuminate\Http\Request;
31+
use Pterodactyl\Models\APIKey;
32+
use Pterodactyl\Models\APIPermission;
3233
use Pterodactyl\Repositories\APIRepository;
3334
use Pterodactyl\Exceptions\DisplayException;
3435
use Pterodactyl\Http\Controllers\Controller;
@@ -45,7 +46,7 @@ class APIController extends Controller
4546
public function index(Request $request)
4647
{
4748
return view('base.api.index', [
48-
'keys' => Models\APIKey::where('user_id', $request->user()->id)->get(),
49+
'keys' => APIKey::where('user_id', $request->user()->id)->get(),
4950
]);
5051
}
5152

@@ -57,7 +58,12 @@ public function index(Request $request)
5758
*/
5859
public function create(Request $request)
5960
{
60-
return view('base.api.new');
61+
return view('base.api.new', [
62+
'permissions' => [
63+
'user' => collect(APIPermission::permissions())->pull('_user'),
64+
'admin' => collect(APIPermission::permissions())->except('_user')->toArray(),
65+
],
66+
]);
6167
}
6268

6369
/**
@@ -66,13 +72,13 @@ public function create(Request $request)
6672
* @param \Illuminate\Http\Request $request
6773
* @return \Illuminate\Http\RedirectResponse
6874
*/
69-
public function save(Request $request)
75+
public function store(Request $request)
7076
{
7177
try {
7278
$repo = new APIRepository($request->user());
7379
$secret = $repo->create($request->intersect([
7480
'memo', 'allowed_ips',
75-
'adminPermissions', 'permissions',
81+
'admin_permissions', 'permissions',
7682
]));
7783
Alert::success('An API Key-Pair has successfully been generated. The API secret for this public key is shown below and will not be shown again.<br /><br /><code>' . $secret . '</code>')->flash();
7884

app/Models/APIPermission.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,45 @@ class APIPermission extends Model
7777
// All other pemissions below are administrative actions.
7878
'server' => [
7979
'list',
80-
'view',
81-
'delete',
8280
'create',
81+
'view',
8382
'edit-details',
8483
'edit-container',
84+
'edit-build',
85+
'edit-startup',
8586
'suspend',
8687
'install',
8788
'rebuild',
88-
'edit-build',
89-
'edit-startup',
89+
'delete',
90+
],
91+
'location' => [
92+
'list',
93+
],
94+
'node' => [
95+
'list',
96+
'view',
97+
'view-config',
98+
'create',
99+
'delete',
100+
],
101+
'user' => [
102+
'list',
103+
'view',
104+
'create',
105+
'edit',
106+
'delete',
107+
],
108+
'service' => [
109+
'list',
110+
'view',
111+
],
112+
'option' => [
113+
'list',
114+
'view',
115+
],
116+
'pack' => [
117+
'list',
118+
'view',
90119
],
91120
];
92121

app/Policies/APIKeyPolicy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class APIKeyPolicy
4242
*/
4343
protected function checkPermission(User $user, Key $key, $permission)
4444
{
45+
// Non-administrative users cannot use administrative routes.
46+
if (! starts_with('user.') && ! $user->isRootAdmin()) {
47+
return false;
48+
}
49+
4550
// We don't tag this cache key with the user uuid because the key is already unique,
4651
// and multiple users are not defiend for a single key.
4752
$permissions = Cache::remember('APIKeyPolicy.' . $key->public, Carbon::now()->addSeconds(5), function () use ($key) {

app/Repositories/APIRepository.php

Lines changed: 52 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -29,65 +29,14 @@
2929
use Crypt;
3030
use Validator;
3131
use IPTools\Network;
32-
use Pterodactyl\Models;
32+
use Pterodactyl\Models\User;
33+
use Pterodactyl\Models\APIKey as Key;
34+
use Pterodactyl\Models\APIPermission as Permission;
3335
use Pterodactyl\Exceptions\DisplayException;
3436
use Pterodactyl\Exceptions\DisplayValidationException;
3537

3638
class APIRepository
3739
{
38-
/**
39-
* Valid API permissions.
40-
*
41-
* @var array
42-
*/
43-
protected $permissions = [
44-
'admin' => [
45-
'*',
46-
47-
// User Management Routes
48-
'users.list',
49-
'users.create',
50-
'users.view',
51-
'users.update',
52-
'users.delete',
53-
54-
// Server Manaement Routes
55-
'servers.list',
56-
'servers.create',
57-
'servers.view',
58-
'servers.config',
59-
'servers.build',
60-
'servers.suspend',
61-
'servers.unsuspend',
62-
'servers.delete',
63-
64-
// Node Management Routes
65-
'nodes.list',
66-
'nodes.view',
67-
'nodes.create',
68-
'nodes.allocations',
69-
'nodes.delete',
70-
71-
// Service Routes
72-
'services.list',
73-
'services.view',
74-
75-
// Location Routes
76-
'locations.list',
77-
78-
],
79-
'user' => [
80-
'*',
81-
82-
// Informational
83-
'me',
84-
85-
// Server Control
86-
'server',
87-
'server.power',
88-
],
89-
];
90-
9140
/**
9241
* Holder for listing of allowed IPs when creating a new key.
9342
*
@@ -108,11 +57,11 @@ class APIRepository
10857
* @param null|\Pterodactyl\Models\User $user
10958
* @return void
11059
*/
111-
public function __construct(Models\User $user = null)
60+
public function __construct(User $user = null)
11261
{
11362
$this->user = is_null($user) ? Auth::user() : $user;
11463
if (is_null($this->user)) {
115-
throw new \Exception('Cannot access API Repository without passing a user to constructor.');
64+
throw new \Exception('Unable to initialize user for API repository instance.');
11665
}
11766
}
11867

@@ -129,8 +78,9 @@ public function create(array $data)
12978
{
13079
$validator = Validator::make($data, [
13180
'memo' => 'string|max:500',
81+
'allowed_ips' => 'sometimes|string',
13282
'permissions' => 'sometimes|required|array',
133-
'adminPermissions' => 'sometimes|required|array',
83+
'admin_permissions' => 'sometimes|required|array',
13484
]);
13585

13686
$validator->after(function ($validator) use ($data) {
@@ -156,53 +106,69 @@ public function create(array $data)
156106
DB::beginTransaction();
157107
try {
158108
$secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7);
159-
$key = new Models\APIKey;
160-
$key->fill([
109+
$key = Key::create([
161110
'user_id' => $this->user->id,
162111
'public' => str_random(16),
163112
'secret' => Crypt::encrypt($secretKey),
164113
'allowed_ips' => empty($this->allowed) ? null : json_encode($this->allowed),
165114
'memo' => $data['memo'],
166115
'expires_at' => null,
167116
]);
168-
$key->save();
169117

170118
$totalPermissions = 0;
119+
$pNodes = Permission::permissions();
120+
171121
if (isset($data['permissions'])) {
172-
foreach ($data['permissions'] as $permNode) {
173-
if (! strpos($permNode, ':')) {
122+
foreach ($data['permissions'] as $permission) {
123+
$parts = explode('-', $permission);
124+
125+
if (count($parts) !== 2) {
126+
continue;
127+
}
128+
129+
list($block, $search) = $parts;
130+
131+
if (! array_key_exists($block, $pNodes['_user'])) {
174132
continue;
175133
}
176134

177-
list($toss, $permission) = explode(':', $permNode);
178-
if (in_array($permission, $this->permissions['user'])) {
179-
$totalPermissions++;
180-
$model = new Models\APIPermission;
181-
$model->fill([
182-
'key_id' => $key->id,
183-
'permission' => 'api.user.' . $permission,
184-
]);
185-
$model->save();
135+
if (! in_array($search, $pNodes['_user'][$block])) {
136+
continue;
186137
}
138+
139+
$totalPermissions++;
140+
Permission::create([
141+
'key_id' => $key->id,
142+
'permission' => 'user.' . $permission,
143+
]);
187144
}
188145
}
189146

190-
if ($this->user->isRootAdmin() && isset($data['adminPermissions'])) {
191-
foreach ($data['adminPermissions'] as $permNode) {
192-
if (! strpos($permNode, ':')) {
147+
if ($this->user->isRootAdmin() && isset($data['admin_permissions'])) {
148+
unset($pNodes['_user']);
149+
150+
foreach ($data['admin_permissions'] as $permNode) {
151+
$parts = explode('-', $permission);
152+
153+
if (count($parts) !== 2) {
193154
continue;
194155
}
195156

196-
list($toss, $permission) = explode(':', $permNode);
197-
if (in_array($permission, $this->permissions['admin'])) {
198-
$totalPermissions++;
199-
$model = new Models\APIPermission;
200-
$model->fill([
201-
'key_id' => $key->id,
202-
'permission' => 'api.admin.' . $permission,
203-
]);
204-
$model->save();
157+
list($block, $search) = $parts;
158+
159+
if (! array_key_exists($block, $pNodes)) {
160+
continue;
161+
}
162+
163+
if (! in_array($search, $pNodes[$block])) {
164+
continue;
205165
}
166+
167+
$totalPermissions++;
168+
Permission::create([
169+
'key_id' => $key->id,
170+
'permission' => $permission,
171+
]);
206172
}
207173
}
208174

@@ -229,20 +195,13 @@ public function create(array $data)
229195
*/
230196
public function revoke($key)
231197
{
232-
DB::beginTransaction();
233-
234-
try {
235-
$model = Models\APIKey::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
198+
DB::transaction(function () use ($key) {
199+
$model = Key::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
236200
foreach ($model->permissions as &$permission) {
237201
$permission->delete();
238202
}
239203

240204
$model->delete();
241-
242-
DB::commit();
243-
} catch (\Exception $ex) {
244-
DB::rollBack();
245-
throw $ex;
246-
}
205+
});
247206
}
248207
}

0 commit comments

Comments
 (0)