Merge branch 'develop' into dane/restore-backups
This commit is contained in:
commit
663143de0b
575 changed files with 6080 additions and 6864 deletions
|
@ -14,8 +14,6 @@ class ServerInstalled
|
|||
/**
|
||||
* Checks that the server is installed before allowing access through the route.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
@ -23,10 +21,8 @@ class ServerInstalled
|
|||
/** @var \Pterodactyl\Models\Server|null $server */
|
||||
$server = $request->route()->parameter('server');
|
||||
|
||||
if (! $server instanceof Server) {
|
||||
throw new NotFoundHttpException(
|
||||
'No server resource was located in the request parameters.'
|
||||
);
|
||||
if (!$server instanceof Server) {
|
||||
throw new NotFoundHttpException('No server resource was located in the request parameters.');
|
||||
}
|
||||
|
||||
if (! $server->isInstalled()) {
|
||||
|
|
|
@ -18,16 +18,14 @@ class AdminAuthenticate
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (! $request->user() || ! $request->user()->root_admin) {
|
||||
throw new AccessDeniedHttpException;
|
||||
if (!$request->user() || !$request->user()->root_admin) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
|
|
@ -42,7 +42,7 @@ class ApiSubstituteBindings extends SubstituteBindings
|
|||
* a 404 error if a model is not found.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
|
@ -50,7 +50,7 @@ class ApiSubstituteBindings extends SubstituteBindings
|
|||
$route = $request->route();
|
||||
|
||||
foreach (self::$mappings as $key => $model) {
|
||||
if (! is_null($this->router->getBindingCallback($key))) {
|
||||
if (!is_null($this->router->getBindingCallback($key))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,13 +12,11 @@ class AuthenticateApplicationUser
|
|||
* Authenticate that the currently authenticated user is an administrator
|
||||
* and should be allowed to proceed through the application API.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (is_null($request->user()) || ! $request->user()->root_admin) {
|
||||
if (is_null($request->user()) || !$request->user()->root_admin) {
|
||||
throw new AccessDeniedHttpException('This account does not have permission to access the API.');
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@ class AuthenticateIPAccess
|
|||
/**
|
||||
* Determine if a request IP has permission to access the API.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Pterodactyl\Http\Middleware\Api;
|
||||
|
||||
use Closure;
|
||||
use Cake\Chronos\Chronos;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\ApiKey;
|
||||
|
@ -33,10 +33,6 @@ class AuthenticateKey
|
|||
|
||||
/**
|
||||
* AuthenticateKey constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\ApiKeyRepositoryInterface $repository
|
||||
* @param \Illuminate\Auth\AuthManager $auth
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
*/
|
||||
public function __construct(ApiKeyRepositoryInterface $repository, AuthManager $auth, Encrypter $encrypter)
|
||||
{
|
||||
|
@ -49,9 +45,6 @@ class AuthenticateKey
|
|||
* Handle an API request by verifying that the provided API key
|
||||
* is in a valid format and exists in the database.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param int $keyType
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
|
@ -85,10 +78,6 @@ class AuthenticateKey
|
|||
/**
|
||||
* Authenticate an API key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param int $keyType
|
||||
* @return \Pterodactyl\Models\ApiKey
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
|
@ -103,14 +92,14 @@ class AuthenticateKey
|
|||
['key_type', '=', $keyType],
|
||||
]);
|
||||
} catch (RecordNotFoundException $exception) {
|
||||
throw new AccessDeniedHttpException;
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
if (! hash_equals($this->encrypter->decrypt($model->token), $token)) {
|
||||
throw new AccessDeniedHttpException;
|
||||
if (!hash_equals($this->encrypter->decrypt($model->token), $token)) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
$this->repository->withoutFreshModel()->update($model->id, ['last_used_at' => Chronos::now()]);
|
||||
$this->repository->withoutFreshModel()->update($model->id, ['last_used_at' => CarbonImmutable::now()]);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Middleware\Api\Client\Server;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class AllocationBelongsToServer
|
||||
{
|
||||
/**
|
||||
* Ensure that the allocation found in the URL belongs to the server being queried.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
/** @var \Pterodactyl\Models\Server $server */
|
||||
$server = $request->route()->parameter('server');
|
||||
/** @var \Pterodactyl\Models\Allocation|null $allocation */
|
||||
$allocation = $request->route()->parameter('allocation');
|
||||
|
||||
if ($allocation && $allocation->server_id !== $server->id) {
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -8,8 +8,8 @@ use Pterodactyl\Models\Server;
|
|||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Pterodactyl\Exceptions\Http\Server\ServerTransferringException;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class AuthenticateServerAccess
|
||||
{
|
||||
|
@ -29,8 +29,6 @@ class AuthenticateServerAccess
|
|||
|
||||
/**
|
||||
* AuthenticateServerAccess constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(ServerRepositoryInterface $repository)
|
||||
{
|
||||
|
@ -40,8 +38,6 @@ class AuthenticateServerAccess
|
|||
/**
|
||||
* Authenticate that this server exists and is not suspended or marked as installing.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
@ -50,39 +46,37 @@ class AuthenticateServerAccess
|
|||
$user = $request->user();
|
||||
$server = $request->route()->parameter('server');
|
||||
|
||||
if (! $server instanceof Server) {
|
||||
if (!$server instanceof Server) {
|
||||
throw new NotFoundHttpException(trans('exceptions.api.resource_not_found'));
|
||||
}
|
||||
|
||||
// At the very least, ensure that the user trying to make this request is the
|
||||
// server owner, a subuser, or a root admin. We'll leave it up to the controllers
|
||||
// to authenticate more detailed permissions if needed.
|
||||
if ($user->id !== $server->owner_id && ! $user->root_admin) {
|
||||
if ($user->id !== $server->owner_id && !$user->root_admin) {
|
||||
// Check for subuser status.
|
||||
if (! $server->subusers->contains('user_id', $user->id)) {
|
||||
if (!$server->subusers->contains('user_id', $user->id)) {
|
||||
throw new NotFoundHttpException(trans('exceptions.api.resource_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($server->isSuspended() && ! $request->routeIs('api:client:server.resources')) {
|
||||
throw new BadRequestHttpException(
|
||||
'This server is currently suspended and the functionality requested is unavailable.'
|
||||
);
|
||||
if ($server->suspended && !$request->routeIs('api:client:server.resources')) {
|
||||
throw new BadRequestHttpException('This server is currently suspended and the functionality requested is unavailable.');
|
||||
}
|
||||
|
||||
// Still allow users to get information about their server if it is installing or being transferred.
|
||||
if (! $request->routeIs('api:client:server.view')) {
|
||||
if (! $server->isInstalled()) {
|
||||
if (!$request->routeIs('api:client:server.view')) {
|
||||
if (!$server->isInstalled()) {
|
||||
// Throw an exception for all server routes; however if the user is an admin and requesting the
|
||||
// server details, don't throw the exception for them.
|
||||
if (! $user->root_admin || ($user->root_admin && ! $request->routeIs($this->except))) {
|
||||
if (!$user->root_admin || ($user->root_admin && !$request->routeIs($this->except))) {
|
||||
throw new ConflictHttpException('Server has not completed the installation process.');
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_null($server->transfer)) {
|
||||
if (! $user->root_admin || ($user->root_admin && ! $request->routeIs($this->except))) {
|
||||
throw new ServerTransferringException;
|
||||
if (!is_null($server->transfer)) {
|
||||
if (!$user->root_admin || ($user->root_admin && !$request->routeIs($this->except))) {
|
||||
throw new ServerTransferringException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Middleware\Api\Client\Server;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Task;
|
||||
use Pterodactyl\Models\User;
|
||||
use InvalidArgumentException;
|
||||
use Pterodactyl\Models\Backup;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Subuser;
|
||||
use Pterodactyl\Models\Database;
|
||||
use Pterodactyl\Models\Schedule;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ResourceBelongsToServer
|
||||
{
|
||||
/**
|
||||
* Looks at the request parameters to determine if the given resource belongs
|
||||
* to the requested server. If not, a 404 error will be returned to the caller.
|
||||
*
|
||||
* This is critical to ensuring that all subsequent logic is using exactly the
|
||||
* server that is expected, and that we're not accessing a resource completely
|
||||
* unrelated to the server provided in the request.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$params = $request->route()->parameters();
|
||||
if (is_null($params) || !$params['server'] instanceof Server) {
|
||||
throw new InvalidArgumentException('This middleware cannot be used in a context that is missing a server in the parameters.');
|
||||
}
|
||||
|
||||
/** @var \Pterodactyl\Models\Server $server */
|
||||
$server = $request->route()->parameter('server');
|
||||
$exception = new NotFoundHttpException('The requested resource was not found for this server.');
|
||||
foreach ($params as $key => $model) {
|
||||
// Specifically skip the server, we're just trying to see if all of the
|
||||
// other resources are assigned to this server. Also skip anything that
|
||||
// is not currently a Model instance since those will just end up being
|
||||
// a 404 down the road.
|
||||
if ($key === 'server' || !$model instanceof Model) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (get_class($model)) {
|
||||
// All of these models use "server_id" as the field key for the server
|
||||
// they are assigned to, so the logic is identical for them all.
|
||||
case Allocation::class:
|
||||
case Backup::class:
|
||||
case Database::class:
|
||||
case Schedule::class:
|
||||
case Subuser::class:
|
||||
if ($model->server_id !== $server->id) {
|
||||
throw $exception;
|
||||
}
|
||||
break;
|
||||
// Regular users are a special case here as we need to make sure they're
|
||||
// currently assigned as a subuser on the server.
|
||||
case User::class:
|
||||
$subuser = $server->subusers()->where('user_id', $model->id)->first();
|
||||
if (is_null($subuser)) {
|
||||
throw $exception;
|
||||
}
|
||||
// This is a special case to avoid an additional query being triggered
|
||||
// in the underlying logic.
|
||||
$request->attributes->set('subuser', $subuser);
|
||||
break;
|
||||
// Tasks are special since they're (currently) the only item in the API
|
||||
// that requires something in addition to the server in order to be accessed.
|
||||
case Task::class:
|
||||
$schedule = $request->route()->parameter('schedule');
|
||||
if ($model->schedule_id !== $schedule->id || $schedule->server_id !== $server->id) {
|
||||
throw $exception;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Don't return a 404 here since we want to make sure no one relies
|
||||
// on this middleware in a context in which it will not work. Fail safe.
|
||||
throw new InvalidArgumentException('There is no handler configured for a resource of this type: ' . get_class($model));
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Middleware\Api\Client\Server;
|
||||
|
||||
use Closure;
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ class SubstituteClientApiBindings extends ApiSubstituteBindings
|
|||
* a 404 error if a model is not found.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
|
@ -43,7 +43,7 @@ class SubstituteClientApiBindings extends ApiSubstituteBindings
|
|||
}
|
||||
});
|
||||
|
||||
$this->router->bind('database', function ($value) use ($request) {
|
||||
$this->router->bind('database', function ($value) {
|
||||
$id = Container::getInstance()->make(HashidsInterface::class)->decodeFirst($value);
|
||||
|
||||
return Database::query()->where('id', $id)->firstOrFail();
|
||||
|
|
|
@ -34,9 +34,6 @@ class DaemonAuthenticate
|
|||
|
||||
/**
|
||||
* DaemonAuthenticate constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $repository
|
||||
*/
|
||||
public function __construct(Encrypter $encrypter, NodeRepository $repository)
|
||||
{
|
||||
|
@ -47,8 +44,6 @@ class DaemonAuthenticate
|
|||
/**
|
||||
* Check if a request from the daemon can be properly attributed back to a single node instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
|
@ -60,17 +55,13 @@ class DaemonAuthenticate
|
|||
}
|
||||
|
||||
if (is_null($bearer = $request->bearerToken())) {
|
||||
throw new HttpException(
|
||||
401, 'Access this this endpoint must include an Authorization header.', null, ['WWW-Authenticate' => 'Bearer']
|
||||
);
|
||||
throw new HttpException(401, 'Access this this endpoint must include an Authorization header.', null, ['WWW-Authenticate' => 'Bearer']);
|
||||
}
|
||||
|
||||
$parts = explode('.', $bearer);
|
||||
// Ensure that all of the correct parts are provided in the header.
|
||||
if (count($parts) !== 2 || empty($parts[0]) || empty($parts[1])) {
|
||||
throw new BadRequestHttpException(
|
||||
'The Authorization header provided was not in a valid format.'
|
||||
);
|
||||
throw new BadRequestHttpException('The Authorization header provided was not in a valid format.');
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -88,8 +79,6 @@ class DaemonAuthenticate
|
|||
// Do nothing, we don't want to expose a node not existing at all.
|
||||
}
|
||||
|
||||
throw new AccessDeniedHttpException(
|
||||
'You are not authorized to access this resource.'
|
||||
);
|
||||
throw new AccessDeniedHttpException('You are not authorized to access this resource.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,23 +13,15 @@ class IsValidJson
|
|||
* parsing the data. This avoids confusing validation errors where every field is flagged and
|
||||
* it is not immediately clear that there is an issue with the JSON being passed.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($request->isJson() && ! empty($request->getContent())) {
|
||||
if ($request->isJson() && !empty($request->getContent())) {
|
||||
json_decode($request->getContent(), true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new BadRequestHttpException(
|
||||
sprintf(
|
||||
'The JSON data passed in the request appears to be malformed. err_code: %d err_message: "%s"',
|
||||
json_last_error(),
|
||||
json_last_error_msg()
|
||||
)
|
||||
);
|
||||
throw new BadRequestHttpException(sprintf('The JSON data passed in the request appears to be malformed. err_code: %d err_message: "%s"', json_last_error(), json_last_error_msg()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ class SetSessionDriver
|
|||
|
||||
/**
|
||||
* SetSessionDriver constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Config\Repository $config
|
||||
*/
|
||||
public function __construct(ConfigRepository $config)
|
||||
{
|
||||
|
@ -26,8 +24,6 @@ class SetSessionDriver
|
|||
/**
|
||||
* Set the session for API calls to only last for the one request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
|
|
@ -11,16 +11,14 @@ class Authenticate
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (! $request->user()) {
|
||||
throw new AuthenticationException;
|
||||
if (!$request->user()) {
|
||||
throw new AuthenticationException();
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
|
|
@ -15,8 +15,6 @@ class LanguageMiddleware
|
|||
|
||||
/**
|
||||
* LanguageMiddleware constructor.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
*/
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
|
@ -26,8 +24,6 @@ class LanguageMiddleware
|
|||
/**
|
||||
* Handle an incoming request and set the user's preferred language.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
|
|
|
@ -14,8 +14,6 @@ class MaintenanceMiddleware
|
|||
|
||||
/**
|
||||
* MaintenanceMiddleware constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\ResponseFactory $response
|
||||
*/
|
||||
public function __construct(ResponseFactory $response)
|
||||
{
|
||||
|
@ -26,7 +24,7 @@ class MaintenanceMiddleware
|
|||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
|
|
|
@ -15,8 +15,6 @@ class RedirectIfAuthenticated
|
|||
|
||||
/**
|
||||
* RedirectIfAuthenticated constructor.
|
||||
*
|
||||
* @param \Illuminate\Auth\AuthManager $authManager
|
||||
*/
|
||||
public function __construct(AuthManager $authManager)
|
||||
{
|
||||
|
@ -26,9 +24,6 @@ class RedirectIfAuthenticated
|
|||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, string $guard = null)
|
||||
|
|
|
@ -10,9 +10,9 @@ use Pterodactyl\Exceptions\Http\TwoFactorAuthRequiredException;
|
|||
|
||||
class RequireTwoFactorAuthentication
|
||||
{
|
||||
const LEVEL_NONE = 0;
|
||||
const LEVEL_ADMIN = 1;
|
||||
const LEVEL_ALL = 2;
|
||||
public const LEVEL_NONE = 0;
|
||||
public const LEVEL_ADMIN = 1;
|
||||
public const LEVEL_ALL = 2;
|
||||
|
||||
/**
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
|
@ -28,8 +28,6 @@ class RequireTwoFactorAuthentication
|
|||
|
||||
/**
|
||||
* RequireTwoFactorAuthentication constructor.
|
||||
*
|
||||
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||
*/
|
||||
public function __construct(AlertsMessageBag $alert)
|
||||
{
|
||||
|
@ -42,8 +40,6 @@ class RequireTwoFactorAuthentication
|
|||
* order to perform actions. If so, we check the level at which it is required (all users
|
||||
* or just admins) and then check if the user has enabled it for their account.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\TwoFactorAuthRequiredException
|
||||
|
@ -55,24 +51,24 @@ class RequireTwoFactorAuthentication
|
|||
$uri = rtrim($request->getRequestUri(), '/') . '/';
|
||||
$current = $request->route()->getName();
|
||||
|
||||
if (! $user || Str::startsWith($uri, ['/auth/']) || Str::startsWith($current, ['auth.', 'account.'])) {
|
||||
if (!$user || Str::startsWith($uri, ['/auth/']) || Str::startsWith($current, ['auth.', 'account.'])) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$level = (int)config('pterodactyl.auth.2fa_required');
|
||||
$level = (int) config('pterodactyl.auth.2fa_required');
|
||||
// If this setting is not configured, or the user is already using 2FA then we can just
|
||||
// send them right through, nothing else needs to be checked.
|
||||
//
|
||||
// If the level is set as admin and the user is not an admin, pass them through as well.
|
||||
if ($level === self::LEVEL_NONE || $user->use_totp) {
|
||||
return $next($request);
|
||||
} else if ($level === self::LEVEL_ADMIN && ! $user->root_admin) {
|
||||
} elseif ($level === self::LEVEL_ADMIN && !$user->root_admin) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// For API calls return an exception which gets rendered nicely in the API response.
|
||||
if ($request->isJson() || Str::startsWith($uri, '/api/')) {
|
||||
throw new TwoFactorAuthRequiredException;
|
||||
throw new TwoFactorAuthRequiredException();
|
||||
}
|
||||
|
||||
$this->alert->danger(trans('auth.2fa_must_be_enabled'))->flash();
|
||||
|
|
|
@ -31,10 +31,6 @@ class AccessingValidServer
|
|||
|
||||
/**
|
||||
* AccessingValidServer constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Config\Repository $config
|
||||
* @param \Illuminate\Contracts\Routing\ResponseFactory $response
|
||||
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
ConfigRepository $config,
|
||||
|
@ -49,8 +45,6 @@ class AccessingValidServer
|
|||
/**
|
||||
* Determine if a given user has permission to access a server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \Illuminate\Http\Response|mixed
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
|
@ -81,9 +75,9 @@ class AccessingValidServer
|
|||
return $this->response->view('errors.installing', [], 409);
|
||||
}
|
||||
|
||||
if (! is_null($server->transfer)) {
|
||||
if (!is_null($server->transfer)) {
|
||||
if ($isApiRequest) {
|
||||
throw new ServerTransferringException;
|
||||
throw new ServerTransferringException();
|
||||
}
|
||||
|
||||
return $this->response->view('errors.transferring', [], 409);
|
||||
|
|
|
@ -26,9 +26,6 @@ class VerifyReCaptcha
|
|||
|
||||
/**
|
||||
* VerifyReCaptcha constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
|
||||
* @param \Illuminate\Contracts\Config\Repository $config
|
||||
*/
|
||||
public function __construct(Dispatcher $dispatcher, Repository $config)
|
||||
{
|
||||
|
@ -40,12 +37,12 @@ class VerifyReCaptcha
|
|||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (! $this->config->get('recaptcha.enabled')) {
|
||||
if (!$this->config->get('recaptcha.enabled')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
@ -61,7 +58,7 @@ class VerifyReCaptcha
|
|||
if ($res->getStatusCode() === 200) {
|
||||
$result = json_decode($res->getBody());
|
||||
|
||||
if ($result->success && (! $this->config->get('recaptcha.verify_domain') || $this->isResponseVerified($result, $request))) {
|
||||
if ($result->success && (!$this->config->get('recaptcha.verify_domain') || $this->isResponseVerified($result, $request))) {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
@ -69,25 +66,20 @@ class VerifyReCaptcha
|
|||
|
||||
$this->dispatcher->dispatch(
|
||||
new FailedCaptcha(
|
||||
$request->ip(), ! empty($result) ? ($result->hostname ?? null) : null
|
||||
$request->ip(),
|
||||
!empty($result) ? ($result->hostname ?? null) : null
|
||||
)
|
||||
);
|
||||
|
||||
throw new HttpException(
|
||||
Response::HTTP_BAD_REQUEST, 'Failed to validate reCAPTCHA data.'
|
||||
);
|
||||
throw new HttpException(Response::HTTP_BAD_REQUEST, 'Failed to validate reCAPTCHA data.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the response from the recaptcha servers was valid.
|
||||
*
|
||||
* @param stdClass $result
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
private function isResponseVerified(stdClass $result, Request $request): bool
|
||||
{
|
||||
if (! $this->config->get('recaptcha.verify_domain')) {
|
||||
if (!$this->config->get('recaptcha.verify_domain')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue