Update the client API to be consistent with how validation is handled

This commit is contained in:
Dane Everitt 2021-08-04 20:55:15 -07:00
parent b47d262ee0
commit 622d292f39
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
33 changed files with 59 additions and 172 deletions

View file

@ -3,9 +3,7 @@
namespace Pterodactyl\Http\Requests\Api\Application; namespace Pterodactyl\Http\Requests\Api\Application;
use Pterodactyl\Models\ApiKey; use Pterodactyl\Models\ApiKey;
use Pterodactyl\Services\Acl\Api\AdminAcl;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Pterodactyl\Exceptions\PterodactylException;
use Pterodactyl\Http\Middleware\Api\ApiSubstituteBindings; use Pterodactyl\Http\Middleware\Api\ApiSubstituteBindings;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\InvalidParameterException;
@ -19,38 +17,12 @@ abstract class ApplicationApiRequest extends FormRequest
private bool $hasValidated = false; private bool $hasValidated = false;
/** /**
* The resource that should be checked when performing the authorization * Determine if the current user is authorized to perform the requested
* function for this request. * action against the API.
*
* @var string|null
*/
protected string $resource;
/**
* The permission level that a given API key should have for accessing
* the defined $resource during the request cycle.
*
* @var int
*/
protected int $permission = AdminAcl::NONE;
/**
* Determine if the current user is authorized to perform
* the requested action against the API.
*
* @throws \Pterodactyl\Exceptions\PterodactylException
*/ */
public function authorize(): bool public function authorize(): bool
{ {
if (is_null($this->resource)) { return false;
throw new PterodactylException('An ACL resource must be defined on API requests.');
}
if ($this->key()->key_type === ApiKey::TYPE_ACCOUNT) {
return $this->user()->root_admin;
}
return AdminAcl::check($this->key(), $this->resource, $this->permission);
} }
/** /**

View file

@ -3,9 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Account; namespace Pterodactyl\Http\Requests\Api\Client\Account;
use Pterodactyl\Models\PersonalAccessToken; use Pterodactyl\Models\PersonalAccessToken;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\AccountApiRequest;
class StoreApiKeyRequest extends ClientApiRequest class StoreApiKeyRequest extends AccountApiRequest
{ {
public function rules(): array public function rules(): array
{ {

View file

@ -3,9 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Account; namespace Pterodactyl\Http\Requests\Api\Client\Account;
use Pterodactyl\Models\UserSSHKey; use Pterodactyl\Models\UserSSHKey;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\AccountApiRequest;
class StoreSSHKeyRequest extends ClientApiRequest class StoreSSHKeyRequest extends AccountApiRequest
{ {
public function rules(): array public function rules(): array
{ {

View file

@ -3,20 +3,16 @@
namespace Pterodactyl\Http\Requests\Api\Client\Account; namespace Pterodactyl\Http\Requests\Api\Client\Account;
use Pterodactyl\Models\User; use Pterodactyl\Models\User;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\AccountApiRequest;
use Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException; use Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException;
class UpdateEmailRequest extends ClientApiRequest class UpdateEmailRequest extends AccountApiRequest
{ {
/** /**
* @throws \Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException * @throws \Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException
*/ */
public function authorize(): bool public function authorize(): bool
{ {
if (!parent::authorize()) {
return false;
}
// Verify password matches when changing password or email. // Verify password matches when changing password or email.
if (!password_verify($this->input('password'), $this->user()->password)) { if (!password_verify($this->input('password'), $this->user()->password)) {
throw new InvalidPasswordProvidedException(trans('validation.internal.invalid_password')); throw new InvalidPasswordProvidedException(trans('validation.internal.invalid_password'));

View file

@ -2,20 +2,16 @@
namespace Pterodactyl\Http\Requests\Api\Client\Account; namespace Pterodactyl\Http\Requests\Api\Client\Account;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\AccountApiRequest;
use Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException; use Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException;
class UpdatePasswordRequest extends ClientApiRequest class UpdatePasswordRequest extends AccountApiRequest
{ {
/** /**
* @throws \Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException * @throws \Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException
*/ */
public function authorize(): bool public function authorize(): bool
{ {
if (!parent::authorize()) {
return false;
}
// Verify password matches when changing password or email. // Verify password matches when changing password or email.
if (!password_verify($this->input('current_password'), $this->user()->password)) { if (!password_verify($this->input('current_password'), $this->user()->password)) {
throw new InvalidPasswordProvidedException(trans('validation.internal.invalid_password')); throw new InvalidPasswordProvidedException(trans('validation.internal.invalid_password'));

View file

@ -0,0 +1,16 @@
<?php
namespace Pterodactyl\Http\Requests\Api\Client;
abstract class AccountApiRequest extends ClientApiRequest
{
public function permission(): string
{
return '';
}
public function authorize(): bool
{
return true;
}
}

View file

@ -6,17 +6,14 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest; use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest; use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
/** abstract class ClientApiRequest extends ApplicationApiRequest implements ClientPermissionsRequest
* @method \Pterodactyl\Models\User user($guard = null)
*/
class ClientApiRequest extends ApplicationApiRequest
{ {
/** /**
* Determine if the current user is authorized to perform the requested action against the API. * Determine if the current user is authorized to perform the requested action
* against the API.
*/ */
public function authorize(): bool public function authorize(): bool
{ {
if ($this instanceof ClientPermissionsRequest || method_exists($this, 'permission')) {
$server = $this->route()->parameter('server'); $server = $this->route()->parameter('server');
if ($server instanceof Server) { if ($server instanceof Server) {
@ -27,7 +24,4 @@ class ClientApiRequest extends ApplicationApiRequest
// we expect there to be one at this point. // we expect there to be one at this point.
return false; return false;
} }
return true;
}
} }

View file

@ -2,10 +2,6 @@
namespace Pterodactyl\Http\Requests\Api\Client; namespace Pterodactyl\Http\Requests\Api\Client;
class GetServersRequest extends ClientApiRequest class GetServersRequest extends AccountApiRequest
{ {
public function authorize(): bool
{
return true;
}
} }

View file

@ -7,10 +7,7 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class StoreBackupRequest extends ClientApiRequest class StoreBackupRequest extends ClientApiRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_BACKUP_CREATE; return Permission::ACTION_BACKUP_CREATE;
} }

View file

@ -2,21 +2,13 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Databases; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Databases;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Database;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class DeleteDatabaseRequest extends ClientApiRequest implements ClientPermissionsRequest class DeleteDatabaseRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {
return Permission::ACTION_DATABASE_DELETE; return Permission::ACTION_DATABASE_DELETE;
} }
public function resourceExists(): bool
{
return $this->getModel(Server::class)->id === $this->getModel(Database::class)->server_id;
}
} }

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Databases; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Databases;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class GetDatabasesRequest extends ClientApiRequest implements ClientPermissionsRequest class GetDatabasesRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -7,9 +7,6 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class RotatePasswordRequest extends ClientApiRequest class RotatePasswordRequest extends ClientApiRequest
{ {
/**
* Check that the user has permission to rotate the password.
*/
public function permission(): string public function permission(): string
{ {
return Permission::ACTION_DATABASE_UPDATE; return Permission::ACTION_DATABASE_UPDATE;

View file

@ -7,11 +7,10 @@ use Pterodactyl\Models\Server;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Illuminate\Database\Query\Builder; use Illuminate\Database\Query\Builder;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
use Pterodactyl\Services\Databases\DatabaseManagementService; use Pterodactyl\Services\Databases\DatabaseManagementService;
class StoreDatabaseRequest extends ClientApiRequest implements ClientPermissionsRequest class StoreDatabaseRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class ChmodFilesRequest extends ClientApiRequest implements ClientPermissionsRequest class ChmodFilesRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -7,9 +7,6 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class CompressFilesRequest extends ClientApiRequest class CompressFilesRequest extends ClientApiRequest
{ {
/**
* Checks that the authenticated user is allowed to create archives for this server.
*/
public function permission(): string public function permission(): string
{ {
return Permission::ACTION_FILE_ARCHIVE; return Permission::ACTION_FILE_ARCHIVE;

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class CopyFileRequest extends ClientApiRequest implements ClientPermissionsRequest class CopyFileRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -7,9 +7,6 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class CreateFolderRequest extends ClientApiRequest class CreateFolderRequest extends ClientApiRequest
{ {
/**
* Checks that the authenticated user is allowed to create files on the server.
*/
public function permission(): string public function permission(): string
{ {
return Permission::ACTION_FILE_CREATE; return Permission::ACTION_FILE_CREATE;

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class DeleteFileRequest extends ClientApiRequest implements ClientPermissionsRequest class DeleteFileRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -1,18 +0,0 @@
<?php
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Server;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class DownloadFileRequest extends ClientApiRequest
{
/**
* Ensure that the user making this request has permission to download files
* from this server.
*/
public function authorize(): bool
{
return $this->user()->can('file.read', $this->getModel(Server::class));
}
}

View file

@ -3,16 +3,10 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class GetFileContentsRequest extends ClientApiRequest implements ClientPermissionsRequest class GetFileContentsRequest extends ClientApiRequest
{ {
/**
* Returns the permissions string indicating which permission should be used to
* validate that the authenticated user has permission to perform this action aganist
* the given resource (server).
*/
public function permission(): string public function permission(): string
{ {
return Permission::ACTION_FILE_READ_CONTENT; return Permission::ACTION_FILE_READ_CONTENT;

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class PullFileRequest extends ClientApiRequest implements ClientPermissionsRequest class PullFileRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class RenameFileRequest extends ClientApiRequest implements ClientPermissionsRequest class RenameFileRequest extends ClientApiRequest
{ {
/** /**
* The permission the user is required to have in order to perform this * The permission the user is required to have in order to perform this

View file

@ -7,10 +7,7 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class UploadFileRequest extends ClientApiRequest class UploadFileRequest extends ClientApiRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_FILE_CREATE; return Permission::ACTION_FILE_CREATE;
} }

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files; namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class WriteFileContentRequest extends ClientApiRequest implements ClientPermissionsRequest class WriteFileContentRequest extends ClientApiRequest
{ {
/** /**
* Returns the permissions string indicating which permission should be used to * Returns the permissions string indicating which permission should be used to

View file

@ -2,17 +2,8 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers; namespace Pterodactyl\Http\Requests\Api\Client\Servers;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\AccountApiRequest;
class GetServerRequest extends ClientApiRequest class GetServerRequest extends AccountApiRequest
{ {
/**
* Determine if a client has permission to view this server on the API. This
* should never be false since this would be checking the same permission as
* resourceExists().
*/
public function authorize(): bool
{
return true;
}
} }

View file

@ -7,10 +7,7 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class ReinstallServerRequest extends ClientApiRequest class ReinstallServerRequest extends ClientApiRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_SETTINGS_REINSTALL; return Permission::ACTION_SETTINGS_REINSTALL;
} }

View file

@ -7,7 +7,7 @@ use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest; use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class RenameServerRequest extends ClientApiRequest implements ClientPermissionsRequest class RenameServerRequest extends ClientApiRequest
{ {
/** /**
* Returns the permissions string indicating which permission should be used to * Returns the permissions string indicating which permission should be used to

View file

@ -6,10 +6,9 @@ use Webmozart\Assert\Assert;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use Pterodactyl\Models\Permission; use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest; use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class SetDockerImageRequest extends ClientApiRequest implements ClientPermissionsRequest class SetDockerImageRequest extends ClientApiRequest
{ {
public function permission(): string public function permission(): string
{ {

View file

@ -7,10 +7,7 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class GetStartupRequest extends ClientApiRequest class GetStartupRequest extends ClientApiRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_STARTUP_READ; return Permission::ACTION_STARTUP_READ;
} }

View file

@ -7,10 +7,7 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class UpdateStartupVariableRequest extends ClientApiRequest class UpdateStartupVariableRequest extends ClientApiRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_STARTUP_UPDATE; return Permission::ACTION_STARTUP_UPDATE;
} }

View file

@ -6,10 +6,7 @@ use Pterodactyl\Models\Permission;
class DeleteSubuserRequest extends SubuserRequest class DeleteSubuserRequest extends SubuserRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_USER_DELETE; return Permission::ACTION_USER_DELETE;
} }

View file

@ -6,10 +6,7 @@ use Pterodactyl\Models\Permission;
class StoreSubuserRequest extends SubuserRequest class StoreSubuserRequest extends SubuserRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_USER_CREATE; return Permission::ACTION_USER_CREATE;
} }

View file

@ -6,10 +6,7 @@ use Pterodactyl\Models\Permission;
class UpdateSubuserRequest extends SubuserRequest class UpdateSubuserRequest extends SubuserRequest
{ {
/** public function permission(): string
* @return string
*/
public function permission()
{ {
return Permission::ACTION_USER_UPDATE; return Permission::ACTION_USER_UPDATE;
} }