Code cleanup for subuser API endpoints; closes #2247
This commit is contained in:
parent
57bb652d81
commit
61e9771333
9 changed files with 94 additions and 104 deletions
|
@ -3,7 +3,9 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Subuser;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Models\Permission;
|
||||
use Pterodactyl\Repositories\Eloquent\SubuserRepository;
|
||||
|
@ -57,6 +59,21 @@ class SubuserController extends ClientApiController
|
|||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single subuser associated with this server instance.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\GetSubuserRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function view(GetSubuserRequest $request)
|
||||
{
|
||||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
return $this->fractal->item($subuser)
|
||||
->transformWith($this->getTransformer(SubuserTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subuser for the given server.
|
||||
*
|
||||
|
@ -84,15 +101,16 @@ class SubuserController extends ClientApiController
|
|||
* Update a given subuser in the system for the server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\UpdateSubuserRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return array
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(UpdateSubuserRequest $request, Server $server): array
|
||||
public function update(UpdateSubuserRequest $request): array
|
||||
{
|
||||
$subuser = $request->endpointSubuser();
|
||||
/** @var \Pterodactyl\Models\Subuser $subuser */
|
||||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
$this->repository->update($subuser->id, [
|
||||
'permissions' => $this->getDefaultPermissions($request),
|
||||
]);
|
||||
|
@ -106,14 +124,16 @@ class SubuserController extends ClientApiController
|
|||
* Removes a subusers from a server's assignment.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Subusers\DeleteSubuserRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function delete(DeleteSubuserRequest $request, Server $server)
|
||||
public function delete(DeleteSubuserRequest $request)
|
||||
{
|
||||
$this->repository->delete($request->endpointSubuser()->id);
|
||||
/** @var \Pterodactyl\Models\Subuser $subuser */
|
||||
$subuser = $request->attributes->get('subuser');
|
||||
|
||||
return JsonResponse::create([], JsonResponse::HTTP_NO_CONTENT);
|
||||
$this->repository->delete($subuser->id);
|
||||
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Middleware\Api\Client\Server;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SubuserBelongsToServer
|
||||
{
|
||||
/**
|
||||
* Ensure that the user being accessed in the request is a user that is currently assigned
|
||||
* as a subuser for this server instance. We'll let the requests themselves handle wether or
|
||||
* not the user making the request can actually modify or delete the subuser record.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
/** @var \Pterodactyl\Models\Server $server */
|
||||
$server = $request->route()->parameter('server');
|
||||
/** @var \Pterodactyl\Models\User $user */
|
||||
$user = $request->route()->parameter('user');
|
||||
|
||||
// Don't do anything if there isn't a user present in the request.
|
||||
if (is_null($user)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$request->attributes->set('subuser', $server->subusers()->where('user_id', $user->id)->firstOrFail());
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Pterodactyl\Http\Middleware\Api\Client;
|
||||
|
||||
use Closure;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Backup;
|
||||
use Pterodactyl\Models\Database;
|
||||
use Illuminate\Container\Container;
|
||||
|
@ -52,6 +53,10 @@ class SubstituteClientApiBindings extends ApiSubstituteBindings
|
|||
return Backup::query()->where('uuid', $value)->firstOrFail();
|
||||
});
|
||||
|
||||
$this->router->model('user', User::class, function ($value) {
|
||||
return User::query()->where('uuid', $value)->firstOrFail();
|
||||
});
|
||||
|
||||
return parent::handle($request, $next);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Subusers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Exceptions\Http\HttpForbiddenException;
|
||||
use Pterodactyl\Repositories\Eloquent\SubuserRepository;
|
||||
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
|
||||
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Pterodactyl\Services\Servers\GetUserPermissionsService;
|
||||
|
||||
abstract class SubuserRequest extends ClientApiRequest
|
||||
{
|
||||
|
@ -30,10 +28,10 @@ abstract class SubuserRequest extends ClientApiRequest
|
|||
return false;
|
||||
}
|
||||
|
||||
// If there is a subuser present in the URL, validate that it is not the same as the
|
||||
// current request user. You're not allowed to modify yourself.
|
||||
if ($this->route()->hasParameter('subuser')) {
|
||||
if ($this->endpointSubuser()->user_id === $this->user()->id) {
|
||||
$user = $this->route()->parameter('user');
|
||||
// Don't allow a user to edit themselves on the server.
|
||||
if ($user instanceof User) {
|
||||
if ($user->uuid === $this->user()->uuid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -71,68 +69,14 @@ abstract class SubuserRequest extends ClientApiRequest
|
|||
// Otherwise, get the current subuser's permission set, and ensure that the
|
||||
// permissions they are trying to assign are not _more_ than the ones they
|
||||
// already have.
|
||||
if (count(array_diff($permissions, $this->currentUserPermissions())) > 0) {
|
||||
/** @var \Pterodactyl\Models\Subuser|null $subuser */
|
||||
/** @var \Pterodactyl\Services\Servers\GetUserPermissionsService $service */
|
||||
$service = $this->container->make(GetUserPermissionsService::class);
|
||||
|
||||
if (count(array_diff($permissions, $service->handle($server, $user))) > 0) {
|
||||
throw new HttpForbiddenException(
|
||||
'Cannot assign permissions to a subuser that your account does not actively possess.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently authenticated user's permissions.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function currentUserPermissions(): array
|
||||
{
|
||||
/** @var \Pterodactyl\Repositories\Eloquent\SubuserRepository $repository */
|
||||
$repository = $this->container->make(SubuserRepository::class);
|
||||
|
||||
/* @var \Pterodactyl\Models\Subuser $model */
|
||||
try {
|
||||
$model = $repository->findFirstWhere([
|
||||
['server_id', $this->route()->parameter('server')->id],
|
||||
['user_id', $this->user()->id],
|
||||
]);
|
||||
} catch (RecordNotFoundException $exception) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $model->permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the subuser model for the given request which can then be validated. If
|
||||
* required request parameters are missing a 404 error will be returned, otherwise
|
||||
* a model exception will be returned if the model is not found.
|
||||
*
|
||||
* This returns the subuser based on the endpoint being hit, not the actual subuser
|
||||
* for the account making the request.
|
||||
*
|
||||
* @return \Pterodactyl\Models\Subuser
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
public function endpointSubuser()
|
||||
{
|
||||
/** @var \Pterodactyl\Repositories\Eloquent\SubuserRepository $repository */
|
||||
$repository = $this->container->make(SubuserRepository::class);
|
||||
|
||||
$parameters = $this->route()->parameters();
|
||||
if (
|
||||
! isset($parameters['server'], $parameters['server'])
|
||||
|| ! is_string($parameters['subuser'])
|
||||
|| ! $parameters['server'] instanceof Server
|
||||
) {
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
return $this->model ?: $this->model = $repository->getUserForServer(
|
||||
$parameters['server']->id, $parameters['subuser']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue