Fix suspension/installed handling for servers
closes Pterodactyl/Panel#891
This commit is contained in:
parent
b0c8390529
commit
7a19019980
7 changed files with 71 additions and 29 deletions
|
@ -3,12 +3,13 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Remote;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
||||
use Pterodactyl\Services\Sftp\AuthenticateUsingPasswordService;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Pterodactyl\Http\Requests\Api\Remote\SftpAuthenticationFormRequest;
|
||||
|
||||
class SftpController extends Controller
|
||||
|
@ -47,7 +48,7 @@ class SftpController extends Controller
|
|||
if ($this->hasTooManyLoginAttempts($request)) {
|
||||
return response()->json([
|
||||
'error' => 'Logins throttled.',
|
||||
], 429);
|
||||
], Response::HTTP_TOO_MANY_REQUESTS);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -59,14 +60,14 @@ class SftpController extends Controller
|
|||
);
|
||||
|
||||
$this->clearLoginAttempts($request);
|
||||
} catch (AuthenticationException $exception) {
|
||||
} catch (BadRequestHttpException $exception) {
|
||||
return response()->json([
|
||||
'error' => 'Invalid credentials.',
|
||||
], 403);
|
||||
'error' => 'The server you are trying to access is not installed or is suspended.',
|
||||
], Response::HTTP_BAD_REQUEST);
|
||||
} catch (RecordNotFoundException $exception) {
|
||||
return response()->json([
|
||||
'error' => 'Invalid server.',
|
||||
], 404);
|
||||
'error' => 'Unable to locate a resource using the username and password provided.',
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
return response()->json($data);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
namespace Pterodactyl\Http\Controllers\Api\Remote;
|
||||
|
||||
use Spatie\Fractal\Fractal;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Foundation\Testing\HttpException;
|
||||
|
@ -75,12 +76,11 @@ class ValidateKeyController extends Controller
|
|||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Foundation\Testing\HttpException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function index($token)
|
||||
{
|
||||
if (! starts_with($token, DaemonKeyRepositoryInterface::INTERNAL_KEY_IDENTIFIER)) {
|
||||
throw new HttpException(501);
|
||||
throw new HttpException(Response::HTTP_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -89,6 +89,10 @@ class ValidateKeyController extends Controller
|
|||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
if ($key->getRelation('server')->suspended || $key->getRelation('server')->installed !== 1) {
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
|
||||
return $this->fractal->item($key, $this->app->make(ApiKeyTransformer::class), 'server')
|
||||
->serializeWith(JsonApiSerializer::class)
|
||||
->toArray();
|
||||
|
|
|
@ -431,7 +431,7 @@ class ServersController extends Controller
|
|||
|
||||
$this->repository->update($server->id, [
|
||||
'installed' => ! $server->installed,
|
||||
]);
|
||||
], true, true);
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.install_toggled'))->flash();
|
||||
|
||||
|
|
|
@ -108,7 +108,6 @@ class ServerController extends ApplicationApiController
|
|||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function delete(ServerWriteRequest $request, Server $server, string $force = ''): Response
|
||||
{
|
||||
|
|
|
@ -90,6 +90,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
|||
'startup' => 'string',
|
||||
'skip_scripts' => 'boolean',
|
||||
'image' => 'string|max:255',
|
||||
'installed' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace Pterodactyl\Services\Sftp;
|
||||
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
||||
use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService;
|
||||
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
class AuthenticateUsingPasswordService
|
||||
{
|
||||
|
@ -53,13 +53,13 @@ class AuthenticateUsingPasswordService
|
|||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param string|null $server
|
||||
* @param int $node
|
||||
* @param string|null $server
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
|
||||
*/
|
||||
public function handle(string $username, string $password, int $node, string $server = null): array
|
||||
{
|
||||
|
@ -67,21 +67,20 @@ class AuthenticateUsingPasswordService
|
|||
throw new RecordNotFoundException;
|
||||
}
|
||||
|
||||
try {
|
||||
$user = $this->userRepository->setColumns(['id', 'root_admin', 'password'])->findFirstWhere([['username', '=', $username]]);
|
||||
|
||||
if (! password_verify($password, $user->password)) {
|
||||
throw new AuthenticationException;
|
||||
}
|
||||
} catch (RecordNotFoundException $exception) {
|
||||
throw new AuthenticationException;
|
||||
$user = $this->userRepository->setColumns(['id', 'root_admin', 'password'])->findFirstWhere([['username', '=', $username]]);
|
||||
if (! password_verify($password, $user->password)) {
|
||||
throw new RecordNotFoundException;
|
||||
}
|
||||
|
||||
$server = $this->repository->setColumns(['id', 'node_id', 'owner_id', 'uuid'])->getByUuid($server);
|
||||
$server = $this->repository->setColumns(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->getByUuid($server);
|
||||
if ($server->node_id !== $node || (! $user->root_admin && $server->owner_id !== $user->id)) {
|
||||
throw new RecordNotFoundException;
|
||||
}
|
||||
|
||||
if ($server->installed !== 1 || $server->suspended) {
|
||||
throw new BadRequestHttpException;
|
||||
}
|
||||
|
||||
return [
|
||||
'server' => $server->uuid,
|
||||
'token' => $this->keyProviderService->handle($server, $user),
|
||||
|
|
|
@ -52,7 +52,7 @@ class AuthenticateUsingPasswordServiceTest extends TestCase
|
|||
$this->userRepository->shouldReceive('setColumns')->with(['id', 'root_admin', 'password'])->once()->andReturnSelf();
|
||||
$this->userRepository->shouldReceive('findFirstWhere')->with([['username', '=', $user->username]])->once()->andReturn($user);
|
||||
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('getByUuid')->with($server->uuidShort)->once()->andReturn($server);
|
||||
|
||||
$this->keyProviderService->shouldReceive('handle')->with($server, $user)->once()->andReturn('server_token');
|
||||
|
@ -77,7 +77,7 @@ class AuthenticateUsingPasswordServiceTest extends TestCase
|
|||
$this->userRepository->shouldReceive('setColumns')->with(['id', 'root_admin', 'password'])->once()->andReturnSelf();
|
||||
$this->userRepository->shouldReceive('findFirstWhere')->with([['username', '=', $user->username]])->once()->andReturn($user);
|
||||
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('getByUuid')->with($server->uuidShort)->once()->andReturn($server);
|
||||
|
||||
$this->keyProviderService->shouldReceive('handle')->with($server, $user)->once()->andReturn('server_token');
|
||||
|
@ -104,7 +104,7 @@ class AuthenticateUsingPasswordServiceTest extends TestCase
|
|||
* Test that an exception is thrown if the user account exists but the wrong
|
||||
* credentials are passed.
|
||||
*
|
||||
* @expectedException \Illuminate\Auth\AuthenticationException
|
||||
* @expectedException \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function testExceptionIsThrownIfUserDetailsAreIncorrect()
|
||||
{
|
||||
|
@ -119,7 +119,7 @@ class AuthenticateUsingPasswordServiceTest extends TestCase
|
|||
/**
|
||||
* Test that an exception is thrown if no user account is found.
|
||||
*
|
||||
* @expectedException \Illuminate\Auth\AuthenticationException
|
||||
* @expectedException \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function testExceptionIsThrownIfNoUserAccountIsFound()
|
||||
{
|
||||
|
@ -143,7 +143,7 @@ class AuthenticateUsingPasswordServiceTest extends TestCase
|
|||
$this->userRepository->shouldReceive('setColumns')->with(['id', 'root_admin', 'password'])->once()->andReturnSelf();
|
||||
$this->userRepository->shouldReceive('findFirstWhere')->with([['username', '=', $user->username]])->once()->andReturn($user);
|
||||
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('getByUuid')->with($server->uuidShort)->once()->andReturn($server);
|
||||
|
||||
$this->getService()->handle($user->username, 'password', 1, $server->uuidShort);
|
||||
|
@ -163,7 +163,45 @@ class AuthenticateUsingPasswordServiceTest extends TestCase
|
|||
$this->userRepository->shouldReceive('setColumns')->with(['id', 'root_admin', 'password'])->once()->andReturnSelf();
|
||||
$this->userRepository->shouldReceive('findFirstWhere')->with([['username', '=', $user->username]])->once()->andReturn($user);
|
||||
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('getByUuid')->with($server->uuidShort)->once()->andReturn($server);
|
||||
|
||||
$this->getService()->handle($user->username, 'password', 1, $server->uuidShort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a suspended server throws an exception.
|
||||
*
|
||||
* @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
|
||||
*/
|
||||
public function testSuspendedServer()
|
||||
{
|
||||
$user = factory(User::class)->make(['root_admin' => 1]);
|
||||
$server = factory(Server::class)->make(['node_id' => 1, 'owner_id' => $user->id + 1, 'suspended' => 1]);
|
||||
|
||||
$this->userRepository->shouldReceive('setColumns')->with(['id', 'root_admin', 'password'])->once()->andReturnSelf();
|
||||
$this->userRepository->shouldReceive('findFirstWhere')->with([['username', '=', $user->username]])->once()->andReturn($user);
|
||||
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('getByUuid')->with($server->uuidShort)->once()->andReturn($server);
|
||||
|
||||
$this->getService()->handle($user->username, 'password', 1, $server->uuidShort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a server that is not yet installed throws an exception.
|
||||
*
|
||||
* @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
|
||||
*/
|
||||
public function testNotInstalledServer()
|
||||
{
|
||||
$user = factory(User::class)->make(['root_admin' => 1]);
|
||||
$server = factory(Server::class)->make(['node_id' => 1, 'owner_id' => $user->id + 1, 'installed' => 0]);
|
||||
|
||||
$this->userRepository->shouldReceive('setColumns')->with(['id', 'root_admin', 'password'])->once()->andReturnSelf();
|
||||
$this->userRepository->shouldReceive('findFirstWhere')->with([['username', '=', $user->username]])->once()->andReturn($user);
|
||||
|
||||
$this->repository->shouldReceive('setColumns')->with(['id', 'node_id', 'owner_id', 'uuid', 'installed', 'suspended'])->once()->andReturnSelf();
|
||||
$this->repository->shouldReceive('getByUuid')->with($server->uuidShort)->once()->andReturn($server);
|
||||
|
||||
$this->getService()->handle($user->username, 'password', 1, $server->uuidShort);
|
||||
|
|
Loading…
Reference in a new issue