First round of changes to API to support simpler permissions.
This commit is contained in:
parent
0e24c669c4
commit
a31e5875dc
21 changed files with 403 additions and 169 deletions
|
@ -15,6 +15,8 @@ use Pterodactyl\Http\Requests\Admin\UserFormRequest;
|
|||
use Pterodactyl\Transformers\Api\Admin\UserTransformer;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
||||
use Pterodactyl\Http\Requests\API\Admin\Users\GetUserRequest;
|
||||
use Pterodactyl\Http\Requests\API\Admin\Users\GetUsersRequest;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
|
@ -67,19 +69,19 @@ class UserController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Handle request to list all users on the panel. Returns a JSONAPI representation
|
||||
* Handle request to list all users on the panel. Returns a JSON-API representation
|
||||
* of a collection of users including any defined relations passed in
|
||||
* the request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Http\Requests\API\Admin\Users\GetUsersRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function index(Request $request): array
|
||||
public function index(GetUsersRequest $request): array
|
||||
{
|
||||
$users = $this->repository->paginated(100);
|
||||
|
||||
return $this->fractal->collection($users)
|
||||
->transformWith(new UserTransformer($request))
|
||||
->transformWith((new UserTransformer)->setKey($request->key()))
|
||||
->withResourceName('user')
|
||||
->paginateWith(new IlluminatePaginatorAdapter($users))
|
||||
->toArray();
|
||||
|
@ -89,14 +91,14 @@ class UserController extends Controller
|
|||
* Handle a request to view a single user. Includes any relations that
|
||||
* were defined in the request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\User $user
|
||||
* @param \Pterodactyl\Http\Requests\API\Admin\Users\GetUserRequest $request
|
||||
* @param \Pterodactyl\Models\User $user
|
||||
* @return array
|
||||
*/
|
||||
public function view(Request $request, User $user): array
|
||||
public function view(GetUserRequest $request, User $user): array
|
||||
{
|
||||
return $this->fractal->item($user)
|
||||
->transformWith(new UserTransformer($request))
|
||||
->transformWith((new UserTransformer)->setKey($request->key()))
|
||||
->withResourceName('user')
|
||||
->toArray();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ use Pterodactyl\Http\Middleware\API\AuthenticateIPAccess;
|
|||
use Pterodactyl\Http\Middleware\Daemon\DaemonAuthenticate;
|
||||
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Pterodactyl\Http\Middleware\API\HasPermissionToResource;
|
||||
use Pterodactyl\Http\Middleware\Server\AuthenticateAsSubuser;
|
||||
use Pterodactyl\Http\Middleware\Server\SubuserBelongsToServer;
|
||||
use Pterodactyl\Http\Middleware\RequireTwoFactorAuthentication;
|
||||
|
@ -98,9 +97,6 @@ class Kernel extends HttpKernel
|
|||
'bindings' => SubstituteBindings::class,
|
||||
'recaptcha' => VerifyReCaptcha::class,
|
||||
|
||||
// API specific middleware.
|
||||
'api..user_level' => HasPermissionToResource::class,
|
||||
|
||||
// Server specific middleware (used for authenticating access to resources)
|
||||
//
|
||||
// These are only used for individual server authentication, and not gloabl
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Middleware\API;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
class HasPermissionToResource
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* HasPermissionToResource constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(ApiKeyRepositoryInterface $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an API key has permission to access the given route.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $role
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, string $role = 'admin')
|
||||
{
|
||||
/** @var \Pterodactyl\Models\APIKey $model */
|
||||
$model = $request->attributes->get('api_key');
|
||||
|
||||
if ($role === 'admin' && ! $request->user()->root_admin) {
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
$this->repository->loadPermissions($model);
|
||||
$routeKey = str_replace(['api.', 'admin.'], '', $request->route()->getName());
|
||||
|
||||
$count = $model->getRelation('permissions')->filter(function ($permission) use ($routeKey) {
|
||||
return $routeKey === str_replace('-', '.', $permission->permission);
|
||||
})->count();
|
||||
|
||||
if ($count === 1) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException('Cannot access resource without required `' . $routeKey . '` permission.');
|
||||
}
|
||||
}
|
98
app/Http/Requests/API/Admin/ApiAdminRequest.php
Normal file
98
app/Http/Requests/API/Admin/ApiAdminRequest.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Requests\API\Admin;
|
||||
|
||||
use Pterodactyl\Models\APIKey;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Pterodactyl\Exceptions\PterodactylException;
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl as Acl;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
abstract class ApiAdminRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* The resource that should be checked when performing the authorization
|
||||
* function for this request.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $resource;
|
||||
|
||||
/**
|
||||
* The permission level that a given API key should have for accessing
|
||||
* the defined $resource during the request cycle.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $permission = Acl::NONE;
|
||||
|
||||
/**
|
||||
* Determine if the current user is authorized to perform
|
||||
* the requested action aganist the API.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\PterodactylException
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
if (is_null($this->resource)) {
|
||||
throw new PterodactylException('An ACL resource must be defined on API requests.');
|
||||
}
|
||||
|
||||
return Acl::check($this->key(), $this->resource, $this->permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the requested resource exists on the server.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function resourceExists(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default set of rules to apply to API requests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the API key being used for the request.
|
||||
*
|
||||
* @return \Pterodactyl\Models\APIKey
|
||||
*/
|
||||
public function key(): APIKey
|
||||
{
|
||||
return $this->attributes->get('api_key');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request passes the authorization check as well
|
||||
* as the exists check.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
protected function passesAuthorization()
|
||||
{
|
||||
$passes = parent::passesAuthorization();
|
||||
|
||||
// Only let the user know that a resource does not exist if they are
|
||||
// authenticated to access the endpoint. This avoids exposing that
|
||||
// an item exists (or does not exist) to the user until they can prove
|
||||
// that they have permission to know about it.
|
||||
if ($passes && ! $this->resourceExists()) {
|
||||
throw new NotFoundHttpException('The requested resource does not exist on this server.');
|
||||
}
|
||||
|
||||
return $passes;
|
||||
}
|
||||
}
|
32
app/Http/Requests/API/Admin/Users/GetUserRequest.php
Normal file
32
app/Http/Requests/API/Admin/Users/GetUserRequest.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Requests\API\Admin\Users;
|
||||
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
use Pterodactyl\Http\Requests\API\Admin\ApiAdminRequest;
|
||||
|
||||
class GetUserRequest extends ApiAdminRequest
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $resource = AdminAcl::RESOURCE_USERS;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $permission = AdminAcl::READ;
|
||||
|
||||
/**
|
||||
* Determine if the requested user exists on the Panel.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function resourceExists(): bool
|
||||
{
|
||||
$user = $this->route()->parameter('user');
|
||||
|
||||
return $user instanceof User && $user->exists;
|
||||
}
|
||||
}
|
19
app/Http/Requests/API/Admin/Users/GetUsersRequest.php
Normal file
19
app/Http/Requests/API/Admin/Users/GetUsersRequest.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Requests\API\Admin\Users;
|
||||
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl as Acl;
|
||||
use Pterodactyl\Http\Requests\API\Admin\ApiAdminRequest;
|
||||
|
||||
class GetUsersRequest extends ApiAdminRequest
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $resource = Acl::RESOURCE_USERS;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $permission = Acl::READ;
|
||||
}
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace Pterodactyl\Http\Requests\API\Remote;
|
||||
|
||||
use Pterodactyl\Http\Requests\Request;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class SftpAuthenticationFormRequest extends Request
|
||||
class SftpAuthenticationFormRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Authenticate the request.
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
abstract class Request extends FormRequest
|
||||
{
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue