Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Http/Controllers/Api/Client/Servers/SubuserController.php
14056 views
1
<?php
2
3
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
4
5
use Illuminate\Http\Request;
6
use Pterodactyl\Models\Server;
7
use Illuminate\Http\JsonResponse;
8
use Pterodactyl\Facades\Activity;
9
use Pterodactyl\Models\Permission;
10
use Pterodactyl\Jobs\RevokeSftpAccessJob;
11
use Pterodactyl\Repositories\Eloquent\SubuserRepository;
12
use Pterodactyl\Services\Subusers\SubuserCreationService;
13
use Pterodactyl\Transformers\Api\Client\SubuserTransformer;
14
use Pterodactyl\Repositories\Wings\DaemonRevocationRepository;
15
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
16
use Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\GetSubuserRequest;
17
use Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\StoreSubuserRequest;
18
use Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\DeleteSubuserRequest;
19
use Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\UpdateSubuserRequest;
20
21
class SubuserController extends ClientApiController
22
{
23
/**
24
* SubuserController constructor.
25
*/
26
public function __construct(
27
private SubuserRepository $repository,
28
private SubuserCreationService $creationService,
29
private DaemonRevocationRepository $revocationRepository,
30
) {
31
parent::__construct();
32
}
33
34
/**
35
* Return the users associated with this server instance.
36
*/
37
public function index(GetSubuserRequest $request, Server $server): array
38
{
39
return $this->fractal->collection($server->subusers)
40
->transformWith($this->getTransformer(SubuserTransformer::class))
41
->toArray();
42
}
43
44
/**
45
* Returns a single subuser associated with this server instance.
46
*/
47
public function view(GetSubuserRequest $request): array
48
{
49
$subuser = $request->attributes->get('subuser');
50
51
return $this->fractal->item($subuser)
52
->transformWith($this->getTransformer(SubuserTransformer::class))
53
->toArray();
54
}
55
56
/**
57
* Create a new subuser for the given server.
58
*
59
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
60
* @throws \Pterodactyl\Exceptions\Service\Subuser\ServerSubuserExistsException
61
* @throws \Pterodactyl\Exceptions\Service\Subuser\UserIsServerOwnerException
62
* @throws \Throwable
63
*/
64
public function store(StoreSubuserRequest $request, Server $server): array
65
{
66
$response = $this->creationService->handle(
67
$server,
68
$request->input('email'),
69
$this->getDefaultPermissions($request)
70
);
71
72
Activity::event('server:subuser.create')
73
->subject($response->user)
74
->property(['email' => $request->input('email'), 'permissions' => $this->getDefaultPermissions($request)])
75
->log();
76
77
return $this->fractal->item($response)
78
->transformWith($this->getTransformer(SubuserTransformer::class))
79
->toArray();
80
}
81
82
/**
83
* Update a given subuser in the system for the server.
84
*
85
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
86
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
87
*/
88
public function update(UpdateSubuserRequest $request, Server $server): array
89
{
90
/** @var \Pterodactyl\Models\Subuser $subuser */
91
$subuser = $request->attributes->get('subuser');
92
93
$permissions = $this->getDefaultPermissions($request);
94
$current = $subuser->permissions;
95
96
sort($permissions);
97
sort($current);
98
99
$log = Activity::event('server:subuser.update')
100
->subject($subuser->user)
101
->property([
102
'email' => $subuser->user->email,
103
'old' => $current,
104
'new' => $permissions,
105
'revoked' => true,
106
]);
107
108
// Only update the database and hit up the Wings instance to invalidate JTI's if the permissions
109
// have actually changed for the user.
110
if ($permissions !== $current) {
111
$log->transaction(function () use ($request, $subuser, $server) {
112
$this->repository->update($subuser->id, [
113
'permissions' => $this->getDefaultPermissions($request),
114
]);
115
116
RevokeSftpAccessJob::dispatch($subuser->user->uuid, $server);
117
});
118
}
119
120
$log->reset();
121
122
return $this->fractal->item($subuser->refresh())
123
->transformWith($this->getTransformer(SubuserTransformer::class))
124
->toArray();
125
}
126
127
/**
128
* Removes a subusers from a server's assignment.
129
*/
130
public function delete(DeleteSubuserRequest $request, Server $server): JsonResponse
131
{
132
/** @var \Pterodactyl\Models\Subuser $subuser */
133
$subuser = $request->attributes->get('subuser');
134
135
$log = Activity::event('server:subuser.delete')
136
->subject($subuser->user)
137
->property('email', $subuser->user->email)
138
->property('revoked', true);
139
140
$log->transaction(function () use ($server, $subuser) {
141
$subuser->delete();
142
143
RevokeSftpAccessJob::dispatch($subuser->user->uuid, $server);
144
});
145
146
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
147
}
148
149
/**
150
* Returns the default permissions for subusers and parses out any permissions
151
* that were passed that do not also exist in the internally tracked list of
152
* permissions.
153
*/
154
protected function getDefaultPermissions(Request $request): array
155
{
156
$allowed = Permission::permissions()
157
->map(function ($value, $prefix) {
158
return array_map(function ($value) use ($prefix) {
159
return "$prefix.$value";
160
}, array_keys($value['keys']));
161
})
162
->flatten()
163
->all();
164
165
$cleaned = array_intersect($request->input('permissions') ?? [], $allowed);
166
167
return array_unique(array_merge($cleaned, [Permission::ACTION_WEBSOCKET_CONNECT]));
168
}
169
}
170
171