GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

SubuserRepository::delete()   B
last analyzed

Complexity

Conditions 4
Paths 15

Size

Total Lines 32
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 22
nc 15
nop 1
1
<?php
2
/**
3
 * Pterodactyl - Panel
4
 * Copyright (c) 2015 - 2017 Dane Everitt <[email protected]>.
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
25
namespace Pterodactyl\Repositories;
26
27
use DB;
28
use Validator;
29
use Pterodactyl\Models\User;
30
use Pterodactyl\Models\Server;
31
use Pterodactyl\Models\Subuser;
32
use Pterodactyl\Models\Permission;
33
use Pterodactyl\Services\UuidService;
34
use GuzzleHttp\Exception\TransferException;
35
use Pterodactyl\Exceptions\DisplayException;
36
use Pterodactyl\Exceptions\DisplayValidationException;
37
38
class SubuserRepository
39
{
40
    /**
41
     * Core permissions required for every subuser on the daemon.
42
     * Without this we cannot connect the websocket or get basic
43
     * information about the server.
44
     *
45
     * @var array
46
     */
47
    protected $coreDaemonPermissions = [
48
        's:get',
49
        's:console',
50
    ];
51
52
    /**
53
     * Creates a new subuser on the server.
54
     *
55
     * @param  int    $sid
56
     * @param  array  $data
57
     * @return \Pterodactyl\Models\Subuser
58
     *
59
     * @throws \Pterodactyl\Exceptions\DisplayException
60
     * @throws \Pterodactyl\Exceptions\DisplayValidationException
61
     */
62
    public function create($sid, array $data)
63
    {
64
        $server = Server::with('node')->findOrFail($sid);
0 ignored issues
show
Bug introduced by
The method findOrFail does only exist in Illuminate\Database\Eloquent\Builder, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
65
66
        $validator = Validator::make($data, [
67
            'permissions' => 'required|array',
68
            'email' => 'required|email',
69
        ]);
70
71
        if ($validator->fails()) {
72
            throw new DisplayValidationException(json_encode($validator->errors()));
73
        }
74
75
        DB::beginTransaction();
76
77
        try {
78
            // Determine if this user exists or if we need to make them an account.
79
            $user = User::where('email', $data['email'])->first();
80
            if (! $user) {
81
                try {
82
                    $repo = new UserRepository;
83
                    $user = $repo->create([
84
                        'email' => $data['email'],
85
                        'username' => str_random(8),
86
                        'name_first' => 'Unassigned',
87
                        'name_last' => 'Name',
88
                        'root_admin' => false,
89
                    ]);
90
                } catch (\Exception $ex) {
91
                    throw $ex;
92
                }
93
            } elseif ($server->owner_id === $user->id) {
94
                throw new DisplayException('You cannot add the owner of a server as a subuser.');
95
            } elseif (Subuser::select('id')->where('user_id', $user->id)->where('server_id', $server->id)->first()) {
96
                throw new DisplayException('A subuser with that email already exists for this server.');
97
            }
98
99
            $uuid = new UuidService;
100
            $subuser = Subuser::create([
101
                'user_id' => $user->id,
102
                'server_id' => $server->id,
103
                'daemonSecret' => (string) $uuid->generate('servers', 'uuid'),
104
            ]);
105
106
            $perms = Permission::listPermissions(true);
107
            $daemonPermissions = $this->coreDaemonPermissions;
108
109 View Code Duplication
            foreach ($data['permissions'] as $permission) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
110
                if (array_key_exists($permission, $perms)) {
111
                    // Build the daemon permissions array for sending.
112
                    if (! is_null($perms[$permission])) {
113
                        array_push($daemonPermissions, $perms[$permission]);
114
                    }
115
116
                    Permission::create([
117
                        'subuser_id' => $subuser->id,
118
                        'permission' => $permission,
119
                    ]);
120
                }
121
            }
122
123
            // Contact Daemon
124
            // We contact even if they don't have any daemon permissions to overwrite
125
            // if they did have them previously.
126
127
            $server->node->guzzleClient([
128
                'X-Access-Server' => $server->uuid,
129
                'X-Access-Token' => $server->node->daemonSecret,
130
            ])->request('PATCH', '/server', [
131
                'json' => [
132
                    'keys' => [
133
                        $subuser->daemonSecret => $daemonPermissions,
134
                    ],
135
                ],
136
            ]);
137
138
            DB::commit();
139
140
            return $subuser;
141
        } catch (TransferException $ex) {
142
            DB::rollBack();
143
            throw new DisplayException('There was an error attempting to connect to the daemon to add this user.', $ex);
144
        } catch (\Exception $ex) {
145
            DB::rollBack();
146
            throw $ex;
147
        }
148
149
        return false;
0 ignored issues
show
Unused Code introduced by
return false; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
150
    }
151
152
    /**
153
     * Revokes a users permissions on a server.
154
     *
155
     * @param  int    $id
156
     * @return void
157
     *
158
     * @throws \Pterodactyl\Exceptions\DisplayException
159
     */
160
    public function delete($id)
161
    {
162
        $subuser = Subuser::with('server.node')->findOrFail($id);
0 ignored issues
show
Bug introduced by
The method findOrFail does only exist in Illuminate\Database\Eloquent\Builder, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
163
        $server = $subuser->server;
164
165
        DB::beginTransaction();
166
167
        try {
168
            $server->node->guzzleClient([
169
                'X-Access-Server' => $server->uuid,
170
                'X-Access-Token' => $server->node->daemonSecret,
171
            ])->request('PATCH', '/server', [
172
                'json' => [
173
                    'keys' => [
174
                        $subuser->daemonSecret => [],
175
                    ],
176
                ],
177
            ]);
178
179
            foreach ($subuser->permissions as &$permission) {
180
                $permission->delete();
181
            }
182
            $subuser->delete();
183
            DB::commit();
184
        } catch (TransferException $ex) {
185
            DB::rollBack();
186
            throw new DisplayException('There was an error attempting to connect to the daemon to delete this subuser.', $ex);
187
        } catch (\Exception $ex) {
188
            DB::rollBack();
189
            throw $ex;
190
        }
191
    }
192
193
    /**
194
     * Updates permissions for a given subuser.
195
     *
196
     * @param  int    $id
197
     * @param  array  $data
198
     * @return void
199
     *
200
     * @throws \Pterodactyl\Exceptions\DisplayException
201
     * @throws \Pterodactyl\Exceptions\DisplayValidationException
202
     */
203
    public function update($id, array $data)
204
    {
205
        $validator = Validator::make($data, [
206
            'permissions' => 'required|array',
207
            'user' => 'required|exists:users,id',
208
            'server' => 'required|exists:servers,id',
209
        ]);
210
211
        if ($validator->fails()) {
212
            throw new DisplayValidationException(json_encode($validator->all()));
213
        }
214
215
        $subuser = Subuser::with('server.node')->findOrFail($id);
0 ignored issues
show
Bug introduced by
The method findOrFail does only exist in Illuminate\Database\Eloquent\Builder, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
216
        $server = $subuser->server;
217
218
        DB::beginTransaction();
219
220
        try {
221
            foreach ($subuser->permissions as &$permission) {
222
                $permission->delete();
223
            }
224
225
            $perms = Permission::listPermissions(true);
226
            $daemonPermissions = $this->coreDaemonPermissions;
227
228 View Code Duplication
            foreach ($data['permissions'] as $permission) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
                if (array_key_exists($permission, $perms)) {
230
                    // Build the daemon permissions array for sending.
231
                    if (! is_null($perms[$permission])) {
232
                        array_push($daemonPermissions, $perms[$permission]);
233
                    }
234
                    Permission::create([
235
                        'subuser_id' => $subuser->id,
236
                        'permission' => $permission,
237
                    ]);
238
                }
239
            }
240
241
            // Contact Daemon
242
            // We contact even if they don't have any daemon permissions to overwrite
243
            // if they did have them previously.
244
            $server->node->guzzleClient([
245
                'X-Access-Server' => $server->uuid,
246
                'X-Access-Token' => $server->node->daemonSecret,
247
            ])->request('PATCH', '/server', [
248
                'json' => [
249
                    'keys' => [
250
                        $subuser->daemonSecret => $daemonPermissions,
251
                    ],
252
                ],
253
            ]);
254
255
            DB::commit();
256
        } catch (TransferException $ex) {
257
            DB::rollBack();
258
            throw new DisplayException('There was an error attempting to connect to the daemon to update permissions.', $ex);
259
        } catch (\Exception $ex) {
260
            DB::rollBack();
261
            throw $ex;
262
        }
263
    }
264
}
265