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;
use Pterodactyl\Models\ApiKey;
use Pterodactyl\Services\Acl\Api\AdminAcl;
use Illuminate\Foundation\Http\FormRequest;
use Pterodactyl\Exceptions\PterodactylException;
use Pterodactyl\Http\Middleware\Api\ApiSubstituteBindings;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Exception\InvalidParameterException;
@ -19,38 +17,12 @@ abstract class ApplicationApiRequest extends FormRequest
private bool $hasValidated = false;
/**
* The resource that should be checked when performing the authorization
* function for this request.
*
* @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
* Determine if the current user is authorized to perform the requested
* action against the API.
*/
public function authorize(): bool
{
if (is_null($this->resource)) {
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);
return false;
}
/**

View file

@ -3,9 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Account;
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
{

View file

@ -3,9 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Account;
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
{

View file

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

View file

@ -2,20 +2,16 @@
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;
class UpdatePasswordRequest extends ClientApiRequest
class UpdatePasswordRequest extends AccountApiRequest
{
/**
* @throws \Pterodactyl\Exceptions\Http\Base\InvalidPasswordProvidedException
*/
public function authorize(): bool
{
if (!parent::authorize()) {
return false;
}
// Verify password matches when changing password or email.
if (!password_verify($this->input('current_password'), $this->user()->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,28 +6,22 @@ use Pterodactyl\Models\Server;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Application\ApplicationApiRequest;
/**
* @method \Pterodactyl\Models\User user($guard = null)
*/
class ClientApiRequest extends ApplicationApiRequest
abstract class ClientApiRequest extends ApplicationApiRequest implements ClientPermissionsRequest
{
/**
* 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
{
if ($this instanceof ClientPermissionsRequest || method_exists($this, 'permission')) {
$server = $this->route()->parameter('server');
$server = $this->route()->parameter('server');
if ($server instanceof Server) {
return $this->user()->can($this->permission(), $server);
}
// If there is no server available on the reqest, trigger a failure since
// we expect there to be one at this point.
return false;
if ($server instanceof Server) {
return $this->user()->can($this->permission(), $server);
}
return true;
// If there is no server available on the reqest, trigger a failure since
// we expect there to be one at this point.
return false;
}
}

View file

@ -2,10 +2,6 @@
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
{
/**
* @return string
*/
public function permission()
public function permission(): string
{
return Permission::ACTION_BACKUP_CREATE;
}

View file

@ -2,21 +2,13 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Databases;
use Pterodactyl\Models\Server;
use Pterodactyl\Models\Database;
use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class DeleteDatabaseRequest extends ClientApiRequest implements ClientPermissionsRequest
class DeleteDatabaseRequest extends ClientApiRequest
{
public function permission(): string
{
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;
use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class GetDatabasesRequest extends ClientApiRequest implements ClientPermissionsRequest
class GetDatabasesRequest extends ClientApiRequest
{
public function permission(): string
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class DeleteFileRequest extends ClientApiRequest implements ClientPermissionsRequest
class DeleteFileRequest extends ClientApiRequest
{
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;
use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
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
{
return Permission::ACTION_FILE_READ_CONTENT;

View file

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

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
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

View file

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

View file

@ -3,10 +3,9 @@
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
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

View file

@ -2,17 +2,8 @@
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
{
/**
* @return string
*/
public function permission()
public function permission(): string
{
return Permission::ACTION_SETTINGS_REINSTALL;
}

View file

@ -7,7 +7,7 @@ use Pterodactyl\Models\Permission;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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