Merge branch 'develop' into matthewpi/transfer-improvements
This commit is contained in:
commit
6fa24d4979
49 changed files with 88 additions and 4473 deletions
|
@ -19,8 +19,8 @@ HASHIDS_SALT=
|
||||||
HASHIDS_LENGTH=8
|
HASHIDS_LENGTH=8
|
||||||
|
|
||||||
MAIL_DRIVER=smtp
|
MAIL_DRIVER=smtp
|
||||||
MAIL_HOST=mailtrap.io
|
MAIL_HOST=smtp.example.com
|
||||||
MAIL_PORT=2525
|
MAIL_PORT=25
|
||||||
MAIL_USERNAME=
|
MAIL_USERNAME=
|
||||||
MAIL_PASSWORD=
|
MAIL_PASSWORD=
|
||||||
MAIL_ENCRYPTION=tls
|
MAIL_ENCRYPTION=tls
|
||||||
|
|
|
@ -25,11 +25,13 @@ class Kernel extends ConsoleKernel
|
||||||
// Execute scheduled commands for servers every minute, as if there was a normal cron running.
|
// Execute scheduled commands for servers every minute, as if there was a normal cron running.
|
||||||
$schedule->command('p:schedule:process')->everyMinute()->withoutOverlapping();
|
$schedule->command('p:schedule:process')->everyMinute()->withoutOverlapping();
|
||||||
|
|
||||||
// Every 30 minutes, run the backup pruning command so that any abandoned backups can be removed
|
// Every 30 minutes, run the backup pruning command so that any abandoned backups can be deleted.
|
||||||
// from the UI view for the server.
|
$pruneAge = config('backups.prune_age', 360); // Defaults to 6 hours (time is in minuteS)
|
||||||
$schedule->command('p:maintenance:prune-backups', [
|
if ($pruneAge > 0) {
|
||||||
'--since-minutes' => '30',
|
$schedule->command('p:maintenance:prune-backups', [
|
||||||
])->everyThirtyMinutes();
|
'--since-minutes' => $pruneAge,
|
||||||
|
])->everyThirtyMinutes();
|
||||||
|
}
|
||||||
|
|
||||||
// Every day cleanup any internal backups of service files.
|
// Every day cleanup any internal backups of service files.
|
||||||
$schedule->command('p:maintenance:clean-service-backups')->daily();
|
$schedule->command('p:maintenance:clean-service-backups')->daily();
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Pterodactyl\Repositories\Wings\DaemonFileRepository;
|
||||||
use Pterodactyl\Transformers\Daemon\FileObjectTransformer;
|
use Pterodactyl\Transformers\Daemon\FileObjectTransformer;
|
||||||
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
|
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
|
||||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CopyFileRequest;
|
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CopyFileRequest;
|
||||||
|
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\PullFileRequest;
|
||||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest;
|
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest;
|
||||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DeleteFileRequest;
|
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DeleteFileRequest;
|
||||||
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\RenameFileRequest;
|
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\RenameFileRequest;
|
||||||
|
@ -143,10 +144,7 @@ class FileController extends ClientApiController
|
||||||
*/
|
*/
|
||||||
public function write(WriteFileContentRequest $request, Server $server): JsonResponse
|
public function write(WriteFileContentRequest $request, Server $server): JsonResponse
|
||||||
{
|
{
|
||||||
$this->fileRepository->setServer($server)->putContent(
|
$this->fileRepository->setServer($server)->putContent($request->get('file'), $request->getContent());
|
||||||
$this->encode($request->get('file')),
|
|
||||||
$request->getContent()
|
|
||||||
);
|
|
||||||
|
|
||||||
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
@ -284,16 +282,18 @@ class FileController extends ClientApiController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a given file name & path in a format that should work for a good majority
|
* Requests that a file be downloaded from a remote location by Wings.
|
||||||
* of file names without too much confusing logic.
|
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param $request
|
||||||
* @return string
|
* @param \Pterodactyl\Models\Server $server
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*
|
||||||
|
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||||
*/
|
*/
|
||||||
private function encode(string $path): string
|
public function pull(PullFileRequest $request, Server $server): JsonResponse
|
||||||
{
|
{
|
||||||
return Collection::make(explode('/', rawurldecode($path)))->map(function ($value) {
|
$this->fileRepository->setServer($server)->pull($request->input('url'), $request->input('directory'));
|
||||||
return rawurlencode($value);
|
|
||||||
})->join('/');
|
return new JsonResponse([], Response::HTTP_NO_CONTENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class BackupRemoteUploadController extends Controller
|
||||||
public function __invoke(Request $request, string $backup)
|
public function __invoke(Request $request, string $backup)
|
||||||
{
|
{
|
||||||
// Get the size query parameter.
|
// Get the size query parameter.
|
||||||
$size = (int)$request->query('size');
|
$size = (int) $request->query('size');
|
||||||
if (empty($size)) {
|
if (empty($size)) {
|
||||||
throw new BadRequestHttpException('A non-empty "size" query parameter must be provided.');
|
throw new BadRequestHttpException('A non-empty "size" query parameter must be provided.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function permission(): string
|
||||||
|
{
|
||||||
|
return Permission::ACTION_FILE_CREATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'url' => 'required|string|url',
|
||||||
|
'directory' => 'sometimes|nullable|string',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Repositories\Wings;
|
namespace Pterodactyl\Repositories\Wings;
|
||||||
|
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
use Webmozart\Assert\Assert;
|
use Webmozart\Assert\Assert;
|
||||||
use Pterodactyl\Models\Backup;
|
use Pterodactyl\Models\Backup;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
|
@ -48,7 +49,7 @@ class DaemonBackupRepository extends DaemonRepository
|
||||||
'json' => [
|
'json' => [
|
||||||
'adapter' => $this->adapter ?? config('backups.default'),
|
'adapter' => $this->adapter ?? config('backups.default'),
|
||||||
'uuid' => $backup->uuid,
|
'uuid' => $backup->uuid,
|
||||||
'ignored_files' => $backup->ignored_files,
|
'ignore' => implode('\n', $backup->ignored_files),
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -37,7 +37,7 @@ class DaemonFileRepository extends DaemonRepository
|
||||||
throw new DaemonConnectionException($exception);
|
throw new DaemonConnectionException($exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
$length = (int) $response->getHeader('Content-Length')[0] ?? 0;
|
$length = (int)$response->getHeader('Content-Length')[0] ?? 0;
|
||||||
|
|
||||||
if ($notLargerThan && $length > $notLargerThan) {
|
if ($notLargerThan && $length > $notLargerThan) {
|
||||||
throw new FileSizeTooLargeException;
|
throw new FileSizeTooLargeException;
|
||||||
|
@ -297,4 +297,29 @@ class DaemonFileRepository extends DaemonRepository
|
||||||
throw new DaemonConnectionException($exception);
|
throw new DaemonConnectionException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulls a file from the given URL and saves it to the disk.
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @param string|null $directory
|
||||||
|
* @return \Psr\Http\Message\ResponseInterface
|
||||||
|
*
|
||||||
|
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||||
|
*/
|
||||||
|
public function pull(string $url, ?string $directory): ResponseInterface
|
||||||
|
{
|
||||||
|
Assert::isInstanceOf($this->server, Server::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return $this->getHttpClient()->post(
|
||||||
|
sprintf('/api/servers/%s/files/pull', $this->server->uuid),
|
||||||
|
[
|
||||||
|
'json' => ['url' => $url, 'directory' => $directory ?? '/'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} catch (TransferException $exception) {
|
||||||
|
throw new DaemonConnectionException($exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,9 +117,9 @@ class InitiateBackupService
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the server has reached or exceeded it's backup limit
|
// Check if the server has reached or exceeded it's backup limit
|
||||||
if (!$server->backup_limit || $server->backups()->where('is_successful', true)->count() >= $server->backup_limit) {
|
if (! $server->backup_limit || $server->backups()->where('is_successful', true)->count() >= $server->backup_limit) {
|
||||||
// Do not allow the user to continue if this server is already at its limit and can't override.
|
// Do not allow the user to continue if this server is already at its limit and can't override.
|
||||||
if (!$override || $server->backup_limit <= 0) {
|
if (! $override || $server->backup_limit <= 0) {
|
||||||
throw new TooManyBackupsException($server->backup_limit);
|
throw new TooManyBackupsException($server->backup_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@ return [
|
||||||
// uses to upload backups to S3 storage. Value is in minutes, so this would default to an hour.
|
// uses to upload backups to S3 storage. Value is in minutes, so this would default to an hour.
|
||||||
'presigned_url_lifespan' => env('BACKUP_PRESIGNED_URL_LIFESPAN', 60),
|
'presigned_url_lifespan' => env('BACKUP_PRESIGNED_URL_LIFESPAN', 60),
|
||||||
|
|
||||||
|
// The time to wait before automatically failing a backup, time is in minutes and defaults
|
||||||
|
// to 6 hours. To disable this feature, set the value to `0`.
|
||||||
|
'prune_age' => env('BACKUP_PRUNE_AGE', 360),
|
||||||
|
|
||||||
'disks' => [
|
'disks' => [
|
||||||
// There is no configuration for the local disk for Wings. That configuration
|
// There is no configuration for the local disk for Wings. That configuration
|
||||||
// is determined by the Daemon configuration, and not the Panel.
|
// is determined by the Daemon configuration, and not the Panel.
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
"name": "Sponge Version",
|
"name": "Sponge Version",
|
||||||
"description": "The version of SpongeVanilla to download and use.",
|
"description": "The version of SpongeVanilla to download and use.",
|
||||||
"env_variable": "SPONGE_VERSION",
|
"env_variable": "SPONGE_VERSION",
|
||||||
"default_value": "1.11.2-6.1.0-BETA-21",
|
"default_value": "1.12.2-7.3.0",
|
||||||
"user_viewable": true,
|
"user_viewable": true,
|
||||||
"user_editable": false,
|
"user_editable": false,
|
||||||
"rules": "required|regex:\/^([a-zA-Z0-9.\\-_]+)$\/"
|
"rules": "required|regex:\/^([a-zA-Z0-9.\\-_]+)$\/"
|
||||||
|
|
|
@ -127,7 +127,7 @@ export default ({ database, className }: Props) => {
|
||||||
<Can action={'database.view_password'}>
|
<Can action={'database.view_password'}>
|
||||||
<div css={tw`mt-6`}>
|
<div css={tw`mt-6`}>
|
||||||
<Label>Password</Label>
|
<Label>Password</Label>
|
||||||
<CopyOnClick text={database.password?.valueOf}><Input type={'text'} readOnly value={database.password}/></CopyOnClick>
|
<CopyOnClick text={database.password}><Input type={'text'} readOnly value={database.password}/></CopyOnClick>
|
||||||
</div>
|
</div>
|
||||||
</Can>
|
</Can>
|
||||||
<div css={tw`mt-6`}>
|
<div css={tw`mt-6`}>
|
||||||
|
|
|
@ -66,6 +66,7 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ
|
||||||
Route::post('/delete', 'Servers\FileController@delete');
|
Route::post('/delete', 'Servers\FileController@delete');
|
||||||
Route::post('/create-folder', 'Servers\FileController@create');
|
Route::post('/create-folder', 'Servers\FileController@create');
|
||||||
Route::post('/chmod', 'Servers\FileController@chmod');
|
Route::post('/chmod', 'Servers\FileController@chmod');
|
||||||
|
Route::post('/pull', 'Servers\FileController@pull');
|
||||||
Route::get('/upload', 'Servers\FileUploadController');
|
Route::get('/upload', 'Servers\FileUploadController');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands;
|
|
||||||
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
|
||||||
use Symfony\Component\Console\Tester\CommandTester;
|
|
||||||
|
|
||||||
abstract class CommandTestCase extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
protected $commandIsInteractive = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a command to be non-interactive for testing purposes.
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function withoutInteraction()
|
|
||||||
{
|
|
||||||
$this->commandIsInteractive = false;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the display from running a command.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Console\Command $command
|
|
||||||
* @param array $args
|
|
||||||
* @param array $inputs
|
|
||||||
* @param array $opts
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function runCommand(Command $command, array $args = [], array $inputs = [], array $opts = [])
|
|
||||||
{
|
|
||||||
if (! $command->getLaravel() instanceof Application) {
|
|
||||||
$command->setLaravel($this->app);
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = new CommandTester($command);
|
|
||||||
$response->setInputs($inputs);
|
|
||||||
|
|
||||||
$opts = array_merge($opts, ['interactive' => $this->commandIsInteractive]);
|
|
||||||
$response->execute($args, $opts);
|
|
||||||
|
|
||||||
return $response->getDisplay();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,275 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands\Environment;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
|
||||||
use Illuminate\Contracts\Config\Repository;
|
|
||||||
use Pterodactyl\Console\Commands\Environment\EmailSettingsCommand;
|
|
||||||
|
|
||||||
class EmailSettingsCommandTest extends CommandTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Console\Commands\Environment\EmailSettingsCommand|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Config\Repository|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->config = m::mock(Repository::class);
|
|
||||||
$this->command = m::mock(EmailSettingsCommand::class . '[call, writeToEnvironment]', [$this->config]);
|
|
||||||
$this->command->setLaravel($this->app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test selection of the SMTP driver with no options passed.
|
|
||||||
*/
|
|
||||||
public function testSmtpDriverSelection()
|
|
||||||
{
|
|
||||||
// TODO(dane): fix this
|
|
||||||
$this->markTestSkipped('Skipped, GitHub actions cannot run successfully.');
|
|
||||||
// $data = [
|
|
||||||
// 'MAIL_DRIVER' => 'smtp',
|
|
||||||
// 'MAIL_HOST' => 'mail.test.com',
|
|
||||||
// 'MAIL_PORT' => '567',
|
|
||||||
// 'MAIL_USERNAME' => 'username',
|
|
||||||
// 'MAIL_PASSWORD' => 'password',
|
|
||||||
// 'MAIL_FROM' => 'mail@from.com',
|
|
||||||
// 'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
// 'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
// ];
|
|
||||||
//
|
|
||||||
// $this->setupCoreFunctions($data);
|
|
||||||
// $display = $this->runCommand($this->command, [], array_values($data));
|
|
||||||
//
|
|
||||||
// $this->assertNotEmpty($display);
|
|
||||||
// $this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the command can run when all variables are passed in as options.
|
|
||||||
*/
|
|
||||||
public function testSmtpDriverSelectionWithOptionsPassed()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'smtp',
|
|
||||||
'MAIL_HOST' => 'mail.test.com',
|
|
||||||
'MAIL_PORT' => '567',
|
|
||||||
'MAIL_USERNAME' => 'username',
|
|
||||||
'MAIL_PASSWORD' => 'password',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--driver' => $data['MAIL_DRIVER'],
|
|
||||||
'--email' => $data['MAIL_FROM'],
|
|
||||||
'--from' => $data['MAIL_FROM_NAME'],
|
|
||||||
'--encryption' => $data['MAIL_ENCRYPTION'],
|
|
||||||
'--host' => $data['MAIL_HOST'],
|
|
||||||
'--port' => $data['MAIL_PORT'],
|
|
||||||
'--username' => $data['MAIL_USERNAME'],
|
|
||||||
'--password' => $data['MAIL_PASSWORD'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test selection of PHP mail() as the driver.
|
|
||||||
*/
|
|
||||||
public function testPHPMailDriverSelection()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'mail',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
|
|
||||||
// The driver flag is passed because there seems to be some issue with the command tester
|
|
||||||
// when using a choice() method when two keys start with the same letters.
|
|
||||||
//
|
|
||||||
// In this case, mail and mailgun.
|
|
||||||
unset($data['MAIL_DRIVER']);
|
|
||||||
$display = $this->runCommand($this->command, ['--driver' => 'mail'], array_values($data));
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test selection of the Mailgun driver with no options passed.
|
|
||||||
*/
|
|
||||||
public function testMailgunDriverSelection()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'mailgun',
|
|
||||||
'MAILGUN_DOMAIN' => 'domain.com',
|
|
||||||
'MAILGUN_SECRET' => '123456',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->runCommand($this->command, [], array_values($data));
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test mailgun driver selection when variables are passed as options.
|
|
||||||
*/
|
|
||||||
public function testMailgunDriverSelectionWithOptionsPassed()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'mailgun',
|
|
||||||
'MAILGUN_DOMAIN' => 'domain.com',
|
|
||||||
'MAILGUN_SECRET' => '123456',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--driver' => $data['MAIL_DRIVER'],
|
|
||||||
'--email' => $data['MAIL_FROM'],
|
|
||||||
'--from' => $data['MAIL_FROM_NAME'],
|
|
||||||
'--encryption' => $data['MAIL_ENCRYPTION'],
|
|
||||||
'--host' => $data['MAILGUN_DOMAIN'],
|
|
||||||
'--password' => $data['MAILGUN_SECRET'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test selection of the Mandrill driver with no options passed.
|
|
||||||
*/
|
|
||||||
public function testMandrillDriverSelection()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'mandrill',
|
|
||||||
'MANDRILL_SECRET' => '123456',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->runCommand($this->command, [], array_values($data));
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test mandrill driver selection when variables are passed as options.
|
|
||||||
*/
|
|
||||||
public function testMandrillDriverSelectionWithOptionsPassed()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'mandrill',
|
|
||||||
'MANDRILL_SECRET' => '123456',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--driver' => $data['MAIL_DRIVER'],
|
|
||||||
'--email' => $data['MAIL_FROM'],
|
|
||||||
'--from' => $data['MAIL_FROM_NAME'],
|
|
||||||
'--encryption' => $data['MAIL_ENCRYPTION'],
|
|
||||||
'--password' => $data['MANDRILL_SECRET'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test selection of the Postmark driver with no options passed.
|
|
||||||
*/
|
|
||||||
public function testPostmarkDriverSelection()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'smtp',
|
|
||||||
'MAIL_HOST' => 'smtp.postmarkapp.com',
|
|
||||||
'MAIL_PORT' => '587',
|
|
||||||
'MAIL_USERNAME' => '123456',
|
|
||||||
'MAIL_PASSWORD' => '123456',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->runCommand($this->command, [], [
|
|
||||||
'postmark', '123456', $data['MAIL_FROM'], $data['MAIL_FROM_NAME'], $data['MAIL_ENCRYPTION'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test postmark driver selection when variables are passed as options.
|
|
||||||
*/
|
|
||||||
public function testPostmarkDriverSelectionWithOptionsPassed()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'MAIL_DRIVER' => 'smtp',
|
|
||||||
'MAIL_HOST' => 'smtp.postmarkapp.com',
|
|
||||||
'MAIL_PORT' => '587',
|
|
||||||
'MAIL_USERNAME' => '123456',
|
|
||||||
'MAIL_PASSWORD' => '123456',
|
|
||||||
'MAIL_FROM' => 'mail@from.com',
|
|
||||||
'MAIL_FROM_NAME' => 'MailName',
|
|
||||||
'MAIL_ENCRYPTION' => 'tls',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->setupCoreFunctions($data);
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--driver' => 'postmark',
|
|
||||||
'--email' => $data['MAIL_FROM'],
|
|
||||||
'--from' => $data['MAIL_FROM_NAME'],
|
|
||||||
'--encryption' => $data['MAIL_ENCRYPTION'],
|
|
||||||
'--username' => $data['MAIL_USERNAME'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString('Updating stored environment configuration file.', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup the core functions that are repeated across all of these tests.
|
|
||||||
*
|
|
||||||
* @param array $data
|
|
||||||
*/
|
|
||||||
private function setupCoreFunctions(array $data)
|
|
||||||
{
|
|
||||||
$this->config->shouldReceive('get')->withAnyArgs()->zeroOrMoreTimes()->andReturnNull();
|
|
||||||
$this->command->shouldReceive('writeToEnvironment')->with($data)->once()->andReturnNull();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands\Location;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Pterodactyl\Models\Location;
|
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
|
||||||
use Pterodactyl\Services\Locations\LocationDeletionService;
|
|
||||||
use Pterodactyl\Console\Commands\Location\DeleteLocationCommand;
|
|
||||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
|
||||||
|
|
||||||
class DeleteLocationCommandTest extends CommandTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Console\Commands\Location\DeleteLocationCommand
|
|
||||||
*/
|
|
||||||
protected $command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Locations\LocationDeletionService|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $deletionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->deletionService = m::mock(LocationDeletionService::class);
|
|
||||||
$this->repository = m::mock(LocationRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->command = new DeleteLocationCommand($this->deletionService, $this->repository);
|
|
||||||
$this->command->setLaravel($this->app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a location can be deleted.
|
|
||||||
*/
|
|
||||||
public function testLocationIsDeleted()
|
|
||||||
{
|
|
||||||
$locations = collect([
|
|
||||||
$location1 = factory(Location::class)->make(),
|
|
||||||
$location2 = factory(Location::class)->make(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('all')->withNoArgs()->once()->andReturn($locations);
|
|
||||||
$this->deletionService->shouldReceive('handle')->with($location2->id)->once()->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->command, [], [$location2->short]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.deleted'), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a location is deleted if passed in as an option.
|
|
||||||
*/
|
|
||||||
public function testLocationIsDeletedIfPassedInOption()
|
|
||||||
{
|
|
||||||
$locations = collect([
|
|
||||||
$location1 = factory(Location::class)->make(),
|
|
||||||
$location2 = factory(Location::class)->make(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('all')->withNoArgs()->once()->andReturn($locations);
|
|
||||||
$this->deletionService->shouldReceive('handle')->with($location2->id)->once()->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--short' => $location2->short,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.deleted'), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that prompt shows back up if the user enters the wrong parameters.
|
|
||||||
*/
|
|
||||||
public function testInteractiveEnvironmentAllowsReAttemptingSearch()
|
|
||||||
{
|
|
||||||
$locations = collect([
|
|
||||||
$location1 = factory(Location::class)->make(),
|
|
||||||
$location2 = factory(Location::class)->make(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('all')->withNoArgs()->once()->andReturn($locations);
|
|
||||||
$this->deletionService->shouldReceive('handle')->with($location2->id)->once()->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->command, [], ['123_not_exist', 'another_not_exist', $location2->short]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.no_location_found'), $display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.deleted'), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that no re-attempt is performed in a non-interactive environment.
|
|
||||||
*/
|
|
||||||
public function testNonInteractiveEnvironmentThrowsErrorIfNoLocationIsFound()
|
|
||||||
{
|
|
||||||
$locations = collect([
|
|
||||||
$location1 = factory(Location::class)->make(),
|
|
||||||
$location2 = factory(Location::class)->make(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('all')->withNoArgs()->once()->andReturn($locations);
|
|
||||||
$this->deletionService->shouldNotReceive('handle');
|
|
||||||
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, ['--short' => 'randomTestString']);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.no_location_found'), $display);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands\Location;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Pterodactyl\Models\Location;
|
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
|
||||||
use Pterodactyl\Services\Locations\LocationCreationService;
|
|
||||||
use Pterodactyl\Console\Commands\Location\MakeLocationCommand;
|
|
||||||
|
|
||||||
class MakeLocationCommandTest extends CommandTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Console\Commands\Location\MakeLocationCommand
|
|
||||||
*/
|
|
||||||
protected $command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Locations\LocationCreationService|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $creationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->creationService = m::mock(LocationCreationService::class);
|
|
||||||
|
|
||||||
$this->command = new MakeLocationCommand($this->creationService);
|
|
||||||
$this->command->setLaravel($this->app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a location can be created when no options are passed.
|
|
||||||
*/
|
|
||||||
public function testLocationIsCreatedWithNoOptionsPassed()
|
|
||||||
{
|
|
||||||
$location = factory(Location::class)->make();
|
|
||||||
|
|
||||||
$this->creationService->shouldReceive('handle')->with([
|
|
||||||
'short' => $location->short,
|
|
||||||
'long' => $location->long,
|
|
||||||
])->once()->andReturn($location);
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->command, [], [$location->short, $location->long]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.created', [
|
|
||||||
'name' => $location->short,
|
|
||||||
'id' => $location->id,
|
|
||||||
]), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a location is created when options are passed.
|
|
||||||
*/
|
|
||||||
public function testLocationIsCreatedWhenOptionsArePassed()
|
|
||||||
{
|
|
||||||
$location = factory(Location::class)->make();
|
|
||||||
|
|
||||||
$this->creationService->shouldReceive('handle')->with([
|
|
||||||
'short' => $location->short,
|
|
||||||
'long' => $location->long,
|
|
||||||
])->once()->andReturn($location);
|
|
||||||
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--short' => $location->short,
|
|
||||||
'--long' => $location->long,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.location.created', [
|
|
||||||
'name' => $location->short,
|
|
||||||
'id' => $location->id,
|
|
||||||
]), $display);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands\Maintenance;
|
|
||||||
|
|
||||||
use SplFileInfo;
|
|
||||||
use Mockery as m;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
|
||||||
use Illuminate\Contracts\Filesystem\Factory;
|
|
||||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
|
||||||
use Pterodactyl\Console\Commands\Maintenance\CleanServiceBackupFilesCommand;
|
|
||||||
|
|
||||||
class CleanServiceBackupFilesCommandTest extends CommandTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Console\Commands\Maintenance\CleanServiceBackupFilesCommand
|
|
||||||
*/
|
|
||||||
protected $command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Filesystem\Filesystem|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $disk;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Filesystem\Factory|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $filesystem;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Carbon::setTestNow(Carbon::now());
|
|
||||||
$this->disk = m::mock(Filesystem::class);
|
|
||||||
$this->filesystem = m::mock(Factory::class);
|
|
||||||
$this->filesystem->shouldReceive('disk')->withNoArgs()->once()->andReturn($this->disk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a file is deleted if it is > 5min old.
|
|
||||||
*/
|
|
||||||
public function testCommandCleansFilesMoreThan5MinutesOld()
|
|
||||||
{
|
|
||||||
$file = new SplFileInfo('testfile.txt');
|
|
||||||
|
|
||||||
$this->disk->shouldReceive('files')->with('services/.bak')->once()->andReturn([$file]);
|
|
||||||
$this->disk->shouldReceive('lastModified')->with($file->getPath())->once()->andReturn(Carbon::now()->subDays(100)->getTimestamp());
|
|
||||||
$this->disk->shouldReceive('delete')->with($file->getPath())->once()->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->getCommand());
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.maintenance.deleting_service_backup', ['file' => 'testfile.txt']), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a file isn't deleted if it is < 5min old.
|
|
||||||
*/
|
|
||||||
public function testCommandDoesNotCleanFileLessThan5MinutesOld()
|
|
||||||
{
|
|
||||||
$file = new SplFileInfo('testfile.txt');
|
|
||||||
|
|
||||||
$this->disk->shouldReceive('files')->with('services/.bak')->once()->andReturn([$file]);
|
|
||||||
$this->disk->shouldReceive('lastModified')->with($file->getPath())->once()->andReturn(Carbon::now()->getTimestamp());
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->getCommand());
|
|
||||||
|
|
||||||
$this->assertEmpty($display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the command for testing.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Console\Commands\Maintenance\CleanServiceBackupFilesCommand
|
|
||||||
*/
|
|
||||||
private function getCommand(): CleanServiceBackupFilesCommand
|
|
||||||
{
|
|
||||||
$command = new CleanServiceBackupFilesCommand($this->filesystem);
|
|
||||||
$command->setLaravel($this->app);
|
|
||||||
|
|
||||||
return $command;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands\User;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Pterodactyl\Models\User;
|
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
|
||||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
|
||||||
use Pterodactyl\Console\Commands\User\DisableTwoFactorCommand;
|
|
||||||
|
|
||||||
class DisableTwoFactorCommandTest extends CommandTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Console\Commands\User\DisableTwoFactorCommand
|
|
||||||
*/
|
|
||||||
protected $command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(UserRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->command = new DisableTwoFactorCommand($this->repository);
|
|
||||||
$this->command->setLaravel($this->app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test 2-factor auth is disabled when no option is passed.
|
|
||||||
*/
|
|
||||||
public function testTwoFactorIsDisabledWhenNoOptionIsPassed()
|
|
||||||
{
|
|
||||||
$user = factory(User::class)->make();
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('setColumns')->with(['id', 'email'])->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findFirstWhere')->with([['email', '=', $user->email]])->once()->andReturn($user);
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with($user->id, [
|
|
||||||
'use_totp' => false,
|
|
||||||
'totp_secret' => null,
|
|
||||||
])->once()->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->command, [], [$user->email]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.user.2fa_disabled', ['email' => $user->email]), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test 2-factor auth is disabled when user is passed in option.
|
|
||||||
*/
|
|
||||||
public function testTwoFactorIsDisabledWhenOptionIsPassed()
|
|
||||||
{
|
|
||||||
$user = factory(User::class)->make();
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('setColumns')->with(['id', 'email'])->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findFirstWhere')->with([['email', '=', $user->email]])->once()->andReturn($user);
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with($user->id, [
|
|
||||||
'use_totp' => false,
|
|
||||||
'totp_secret' => null,
|
|
||||||
])->once()->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, ['--email' => $user->email]);
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringContainsString(trans('command/messages.user.2fa_disabled', ['email' => $user->email]), $display);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Commands\User;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Pterodactyl\Models\User;
|
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
|
||||||
use Pterodactyl\Services\Users\UserCreationService;
|
|
||||||
use Pterodactyl\Console\Commands\User\MakeUserCommand;
|
|
||||||
|
|
||||||
class MakeUserCommandTest extends CommandTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Console\Commands\User\MakeUserCommand
|
|
||||||
*/
|
|
||||||
protected $command;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Users\UserCreationService
|
|
||||||
*/
|
|
||||||
protected $creationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->creationService = m::mock(UserCreationService::class);
|
|
||||||
|
|
||||||
$this->command = new MakeUserCommand($this->creationService);
|
|
||||||
$this->command->setLaravel($this->app);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the command executes if no options are passed.
|
|
||||||
*/
|
|
||||||
public function testCommandWithNoPassedOptions()
|
|
||||||
{
|
|
||||||
// TODO(dane): fix this
|
|
||||||
$this->markTestSkipped('Skipped, GitHub actions cannot run successfully.');
|
|
||||||
|
|
||||||
// $user = factory(User::class)->make(['root_admin' => true]);
|
|
||||||
//
|
|
||||||
// $this->creationService->shouldReceive('handle')->with([
|
|
||||||
// 'email' => $user->email,
|
|
||||||
// 'username' => $user->username,
|
|
||||||
// 'name_first' => $user->name_first,
|
|
||||||
// 'name_last' => $user->name_last,
|
|
||||||
// 'password' => 'Password123',
|
|
||||||
// 'root_admin' => $user->root_admin,
|
|
||||||
// ])->once()->andReturn($user);
|
|
||||||
//
|
|
||||||
// $display = $this->runCommand($this->command, [], [
|
|
||||||
// 'yes', $user->email, $user->username, $user->name_first, $user->name_last, 'Password123',
|
|
||||||
// ]);
|
|
||||||
//
|
|
||||||
// $this->assertNotEmpty($display);
|
|
||||||
// $this->assertStringContainsString(trans('command/messages.user.ask_password_help'), $display);
|
|
||||||
// $this->assertStringContainsString($user->uuid, $display);
|
|
||||||
// $this->assertStringContainsString($user->email, $display);
|
|
||||||
// $this->assertStringContainsString($user->username, $display);
|
|
||||||
// $this->assertStringContainsString($user->name, $display);
|
|
||||||
// $this->assertStringContainsString('Yes', $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the --no-password flag works as intended.
|
|
||||||
*/
|
|
||||||
public function testCommandWithNoPasswordOption()
|
|
||||||
{
|
|
||||||
$user = factory(User::class)->make(['root_admin' => true]);
|
|
||||||
|
|
||||||
$this->creationService->shouldReceive('handle')->with([
|
|
||||||
'email' => $user->email,
|
|
||||||
'username' => $user->username,
|
|
||||||
'name_first' => $user->name_first,
|
|
||||||
'name_last' => $user->name_last,
|
|
||||||
'password' => null,
|
|
||||||
'root_admin' => $user->root_admin,
|
|
||||||
])->once()->andReturn($user);
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->command, ['--no-password' => true], [
|
|
||||||
'yes', $user->email, $user->username, $user->name_first, $user->name_last,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringNotContainsString(trans('command/messages.user.ask_password_help'), $display);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test command when arguments are passed as flags.
|
|
||||||
*/
|
|
||||||
public function testCommandWithOptionsPassed()
|
|
||||||
{
|
|
||||||
$user = factory(User::class)->make(['root_admin' => false]);
|
|
||||||
|
|
||||||
$this->creationService->shouldReceive('handle')->with([
|
|
||||||
'email' => $user->email,
|
|
||||||
'username' => $user->username,
|
|
||||||
'name_first' => $user->name_first,
|
|
||||||
'name_last' => $user->name_last,
|
|
||||||
'password' => 'Password123',
|
|
||||||
'root_admin' => $user->root_admin,
|
|
||||||
])->once()->andReturn($user);
|
|
||||||
|
|
||||||
$display = $this->withoutInteraction()->runCommand($this->command, [
|
|
||||||
'--email' => $user->email,
|
|
||||||
'--username' => $user->username,
|
|
||||||
'--name-first' => $user->name_first,
|
|
||||||
'--name-last' => $user->name_last,
|
|
||||||
'--password' => 'Password123',
|
|
||||||
'--admin' => 0,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($display);
|
|
||||||
$this->assertStringNotContainsString(trans('command/messages.user.ask_password_help'), $display);
|
|
||||||
$this->assertStringContainsString($user->uuid, $display);
|
|
||||||
$this->assertStringContainsString($user->email, $display);
|
|
||||||
$this->assertStringContainsString($user->username, $display);
|
|
||||||
$this->assertStringContainsString($user->name, $display);
|
|
||||||
$this->assertStringContainsString('No', $display);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Http\Controllers\Admin;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\DatabaseHost;
|
|
||||||
use Prologue\Alerts\AlertsMessageBag;
|
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
|
||||||
use Tests\Assertions\ControllerAssertionsTrait;
|
|
||||||
use Pterodactyl\Http\Controllers\Admin\DatabaseController;
|
|
||||||
use Pterodactyl\Services\Databases\Hosts\HostUpdateService;
|
|
||||||
use Pterodactyl\Services\Databases\Hosts\HostCreationService;
|
|
||||||
use Pterodactyl\Services\Databases\Hosts\HostDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
|
||||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
|
||||||
|
|
||||||
class DatabaseControllerTest extends TestCase
|
|
||||||
{
|
|
||||||
use ControllerAssertionsTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Prologue\Alerts\AlertsMessageBag|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $alert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Databases\Hosts\HostCreationService|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $creationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $databaseRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Databases\Hosts\HostDeletionService|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $deletionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $locationRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Databases\Hosts\HostUpdateService|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $updateService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->alert = m::mock(AlertsMessageBag::class);
|
|
||||||
$this->creationService = m::mock(HostCreationService::class);
|
|
||||||
$this->databaseRepository = m::mock(DatabaseRepositoryInterface::class);
|
|
||||||
$this->deletionService = m::mock(HostDeletionService::class);
|
|
||||||
$this->locationRepository = m::mock(LocationRepositoryInterface::class);
|
|
||||||
$this->repository = m::mock(DatabaseHostRepositoryInterface::class);
|
|
||||||
$this->updateService = m::mock(HostUpdateService::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the index controller.
|
|
||||||
*/
|
|
||||||
public function testIndexController()
|
|
||||||
{
|
|
||||||
$this->locationRepository->shouldReceive('getAllWithNodes')->withNoArgs()->once()->andReturn(collect(['getAllWithNodes']));
|
|
||||||
$this->repository->shouldReceive('getWithViewDetails')->withNoArgs()->once()->andReturn(collect(['getWithViewDetails']));
|
|
||||||
|
|
||||||
$response = $this->getController()->index();
|
|
||||||
|
|
||||||
$this->assertIsViewResponse($response);
|
|
||||||
$this->assertViewNameEquals('admin.databases.index', $response);
|
|
||||||
$this->assertViewHasKey('locations', $response);
|
|
||||||
$this->assertViewHasKey('hosts', $response);
|
|
||||||
$this->assertViewKeyEquals('locations', collect(['getAllWithNodes']), $response);
|
|
||||||
$this->assertViewKeyEquals('hosts', collect(['getWithViewDetails']), $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the view controller for displaying a specific database host.
|
|
||||||
*/
|
|
||||||
public function testViewController()
|
|
||||||
{
|
|
||||||
$model = factory(DatabaseHost::class)->make();
|
|
||||||
$paginator = new LengthAwarePaginator([], 1, 1);
|
|
||||||
|
|
||||||
$this->locationRepository->shouldReceive('getAllWithNodes')->withNoArgs()->once()->andReturn(collect(['getAllWithNodes']));
|
|
||||||
$this->repository->shouldReceive('find')->with(1)->once()->andReturn($model);
|
|
||||||
$this->databaseRepository->shouldReceive('getDatabasesForHost')
|
|
||||||
->once()
|
|
||||||
->with(1)
|
|
||||||
->andReturn($paginator);
|
|
||||||
|
|
||||||
$response = $this->getController()->view(1);
|
|
||||||
|
|
||||||
$this->assertIsViewResponse($response);
|
|
||||||
$this->assertViewNameEquals('admin.databases.view', $response);
|
|
||||||
$this->assertViewHasKey('locations', $response);
|
|
||||||
$this->assertViewHasKey('host', $response);
|
|
||||||
$this->assertViewHasKey('databases', $response);
|
|
||||||
$this->assertViewKeyEquals('locations', collect(['getAllWithNodes']), $response);
|
|
||||||
$this->assertViewKeyEquals('host', $model, $response);
|
|
||||||
$this->assertViewKeyEquals('databases', $paginator, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the DatabaseController with mock dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Http\Controllers\Admin\DatabaseController
|
|
||||||
*/
|
|
||||||
private function getController(): DatabaseController
|
|
||||||
{
|
|
||||||
return new DatabaseController(
|
|
||||||
$this->alert,
|
|
||||||
$this->repository,
|
|
||||||
$this->databaseRepository,
|
|
||||||
$this->creationService,
|
|
||||||
$this->deletionService,
|
|
||||||
$this->updateService,
|
|
||||||
$this->locationRepository
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Http\Controllers;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Prologue\Alerts\AlertsMessageBag;
|
|
||||||
use Illuminate\Contracts\Console\Kernel;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
|
||||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
|
||||||
use Pterodactyl\Http\Controllers\Admin\Settings\MailController;
|
|
||||||
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
|
|
||||||
|
|
||||||
class MailControllerTest extends ControllerTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Prologue\Alerts\AlertsMessageBag
|
|
||||||
*/
|
|
||||||
private $alert;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Config\Repository
|
|
||||||
*/
|
|
||||||
private $configRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
|
||||||
*/
|
|
||||||
private $encrypter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Console\Kernel
|
|
||||||
*/
|
|
||||||
private $kernel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface
|
|
||||||
*/
|
|
||||||
private $settingsRepositoryInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->alert = m::mock(AlertsMessageBag::class);
|
|
||||||
$this->configRepository = m::mock(ConfigRepository::class);
|
|
||||||
$this->encrypter = m::mock(Encrypter::class);
|
|
||||||
$this->kernel = m::mock(Kernel::class);
|
|
||||||
$this->settingsRepositoryInterface = m::mock(SettingsRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the mail controller for viewing mail settings page.
|
|
||||||
*/
|
|
||||||
public function testIndex()
|
|
||||||
{
|
|
||||||
$this->configRepository->shouldReceive('get');
|
|
||||||
|
|
||||||
$response = $this->getController()->index();
|
|
||||||
|
|
||||||
$this->assertIsViewResponse($response);
|
|
||||||
$this->assertViewNameEquals('admin.settings.mail', $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare a MailController using our mocks.
|
|
||||||
*
|
|
||||||
* @return MailController
|
|
||||||
*/
|
|
||||||
public function getController()
|
|
||||||
{
|
|
||||||
return new MailController(
|
|
||||||
$this->alert,
|
|
||||||
$this->configRepository,
|
|
||||||
$this->encrypter,
|
|
||||||
$this->kernel,
|
|
||||||
$this->settingsRepositoryInterface
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Http\Controllers;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Tests\Traits\Http\RequestMockHelpers;
|
|
||||||
use Tests\Assertions\ControllerAssertionsTrait;
|
|
||||||
|
|
||||||
abstract class ControllerTestCase extends TestCase
|
|
||||||
{
|
|
||||||
use ControllerAssertionsTrait, RequestMockHelpers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Http\Controllers\Controller|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $controller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->buildRequestMock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an instance of the controller.
|
|
||||||
*
|
|
||||||
* @param \Pterodactyl\Http\Controllers\Controller|\Mockery\Mock $controller
|
|
||||||
*/
|
|
||||||
public function setControllerInstance($controller)
|
|
||||||
{
|
|
||||||
$this->controller = $controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the controller.
|
|
||||||
*
|
|
||||||
* @return \Mockery\Mock|\Pterodactyl\Http\Controllers\Controller
|
|
||||||
*/
|
|
||||||
public function getControllerInstance()
|
|
||||||
{
|
|
||||||
return $this->controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function to mock injectJavascript requests.
|
|
||||||
*
|
|
||||||
* @param array|null $args
|
|
||||||
* @param bool $subset
|
|
||||||
*/
|
|
||||||
protected function mockInjectJavascript(array $args = null, bool $subset = false)
|
|
||||||
{
|
|
||||||
$controller = $this->getControllerInstance();
|
|
||||||
|
|
||||||
$controller->shouldReceive('setRequest')->with($this->request)->once()->andReturnSelf();
|
|
||||||
if (is_null($args)) {
|
|
||||||
$controller->shouldReceive('injectJavascript')->withAnyArgs()->once()->andReturnNull();
|
|
||||||
} else {
|
|
||||||
$with = $subset ? m::subset($args) : $args;
|
|
||||||
|
|
||||||
$controller->shouldReceive('injectJavascript')->with($with)->once()->andReturnNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mocks a request input call.
|
|
||||||
*
|
|
||||||
* @param string $param
|
|
||||||
* @param mixed $return
|
|
||||||
*/
|
|
||||||
protected function mockRequestInput(string $param, $return = null)
|
|
||||||
{
|
|
||||||
$this->request->shouldReceive('input')->withArgs(function ($k) use ($param) {
|
|
||||||
return $k === $param;
|
|
||||||
})->andReturn($return);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build and return a mocked controller instance to use for testing.
|
|
||||||
*
|
|
||||||
* @param string $class
|
|
||||||
* @param array $args
|
|
||||||
* @return \Mockery\Mock|\Pterodactyl\Http\Controllers\Controller
|
|
||||||
*/
|
|
||||||
protected function buildMockedController(string $class, array $args = [])
|
|
||||||
{
|
|
||||||
$controller = m::mock($class, $args)->makePartial();
|
|
||||||
|
|
||||||
if (is_null($this->getControllerInstance())) {
|
|
||||||
$this->setControllerInstance($controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getControllerInstance();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Allocations;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Allocation;
|
|
||||||
use Pterodactyl\Services\Allocations\AllocationDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException;
|
|
||||||
|
|
||||||
class AllocationDeletionServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(AllocationRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an allocation is deleted.
|
|
||||||
*/
|
|
||||||
public function testAllocationIsDeleted()
|
|
||||||
{
|
|
||||||
$model = factory(Allocation::class)->make(['id' => 123]);
|
|
||||||
|
|
||||||
$this->repository->expects('delete')->with($model->id)->andReturns(1);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle($model);
|
|
||||||
$this->assertEquals(1, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception gets thrown if an allocation is currently assigned to a server.
|
|
||||||
*/
|
|
||||||
public function testExceptionThrownIfAssignedToServer()
|
|
||||||
{
|
|
||||||
$this->expectException(ServerUsingAllocationException::class);
|
|
||||||
|
|
||||||
$model = factory(Allocation::class)->make(['server_id' => 123]);
|
|
||||||
|
|
||||||
$this->getService()->handle($model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked injections.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Allocations\AllocationDeletionService
|
|
||||||
*/
|
|
||||||
private function getService(): AllocationDeletionService
|
|
||||||
{
|
|
||||||
return new AllocationDeletionService($this->repository);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,291 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Allocations;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Node;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Pterodactyl\Services\Allocations\AssignmentService;
|
|
||||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException;
|
|
||||||
|
|
||||||
class AssignmentServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Models\Node
|
|
||||||
*/
|
|
||||||
protected $node;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->node = factory(Node::class)->make();
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->repository = m::mock(AllocationRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test a non-CIDR notated IP address without a port range.
|
|
||||||
*/
|
|
||||||
public function testIndividualIpAddressWithoutRange()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.1',
|
|
||||||
'allocation_ports' => ['2222'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('insertIgnore')->with([
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.1',
|
|
||||||
'port' => 2222,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
])->once()->andReturn(true);
|
|
||||||
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test a non-CIDR IP address with a port range provided.
|
|
||||||
*/
|
|
||||||
public function testIndividualIpAddressWithRange()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.1',
|
|
||||||
'allocation_ports' => ['1025-1027'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('insertIgnore')->once()->with([
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.1',
|
|
||||||
'port' => 1025,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.1',
|
|
||||||
'port' => 1026,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.1',
|
|
||||||
'port' => 1027,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
])->andReturn(true);
|
|
||||||
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test a non-CIDR IP address with a single port and an alias.
|
|
||||||
*/
|
|
||||||
public function testIndividualIPAddressWithAlias()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.1',
|
|
||||||
'allocation_ports' => ['2222'],
|
|
||||||
'allocation_alias' => 'my.alias.net',
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('insertIgnore')->once()->with([
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.1',
|
|
||||||
'port' => 2222,
|
|
||||||
'ip_alias' => 'my.alias.net',
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
])->andReturn(true);
|
|
||||||
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a domain name can be passed in place of an IP address.
|
|
||||||
*/
|
|
||||||
public function testDomainNamePassedInPlaceOfIPAddress()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => 'unit-test-static.pterodactyl.io',
|
|
||||||
'allocation_ports' => ['2222'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('insertIgnore')->once()->with([
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '127.0.0.1',
|
|
||||||
'port' => 2222,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
])->andReturn(true);
|
|
||||||
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a CIDR IP address without a range works properly.
|
|
||||||
*/
|
|
||||||
public function testCIDRNotatedIPAddressWithoutRange()
|
|
||||||
{
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.100/31',
|
|
||||||
'allocation_ports' => ['2222'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('insertIgnore')->once()->with([
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.100',
|
|
||||||
'port' => 2222,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
])->andReturn(true);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('insertIgnore')->once()->with([
|
|
||||||
[
|
|
||||||
'node_id' => $this->node->id,
|
|
||||||
'ip' => '192.168.1.101',
|
|
||||||
'port' => 2222,
|
|
||||||
'ip_alias' => null,
|
|
||||||
'server_id' => null,
|
|
||||||
],
|
|
||||||
])->andReturn(true);
|
|
||||||
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a CIDR IP address with a range works properly.
|
|
||||||
*/
|
|
||||||
public function testCIDRNotatedIPAddressOutsideRangeLimit()
|
|
||||||
{
|
|
||||||
$this->expectException(CidrOutOfRangeException::class);
|
|
||||||
$this->expectExceptionMessage('CIDR notation only allows masks between /25 and /32.');
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.100/20',
|
|
||||||
'allocation_ports' => ['2222'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if there are too many ports.
|
|
||||||
*/
|
|
||||||
public function testAllocationWithPortsExceedingLimit()
|
|
||||||
{
|
|
||||||
$this->expectException(TooManyPortsInRangeException::class);
|
|
||||||
$this->expectExceptionMessage('Adding more than 1000 ports in a single range at once is not supported.');
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.1',
|
|
||||||
'allocation_ports' => ['5000-7000'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if an invalid port is provided.
|
|
||||||
*/
|
|
||||||
public function testInvalidPortProvided()
|
|
||||||
{
|
|
||||||
$this->expectException(InvalidPortMappingException::class);
|
|
||||||
$this->expectExceptionMessage('The mapping provided for test123 was invalid and could not be processed.');
|
|
||||||
|
|
||||||
$data = [
|
|
||||||
'allocation_ip' => '192.168.1.1',
|
|
||||||
'allocation_ports' => ['test123'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that ports outside of defined limits throw an error.
|
|
||||||
*
|
|
||||||
* @param array $ports
|
|
||||||
*
|
|
||||||
* @dataProvider invalidPortsDataProvider
|
|
||||||
*/
|
|
||||||
public function testPortRangeOutsideOfRangeLimits(array $ports)
|
|
||||||
{
|
|
||||||
$this->expectException(PortOutOfRangeException::class);
|
|
||||||
$this->expectExceptionMessage('Ports in an allocation must be greater than 1024 and less than or equal to 65535.');
|
|
||||||
|
|
||||||
$data = ['allocation_ip' => '192.168.1.1', 'allocation_ports' => $ports];
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs()->andReturnNull();
|
|
||||||
$this->getService()->handle($this->node, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide ports and ranges of ports that exceed the viable port limits for the software.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function invalidPortsDataProvider(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
[['65536']],
|
|
||||||
[['1024']],
|
|
||||||
[['1000']],
|
|
||||||
[['0']],
|
|
||||||
[['65530-65540']],
|
|
||||||
[['65540-65560']],
|
|
||||||
[[PHP_INT_MAX]],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an instance of the service with mocked dependencies for testing.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Allocations\AssignmentService
|
|
||||||
*/
|
|
||||||
private function getService(): AssignmentService
|
|
||||||
{
|
|
||||||
return new AssignmentService($this->repository, $this->connection);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Databases;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Database;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
|
||||||
use Pterodactyl\Extensions\DynamicDatabaseConnection;
|
|
||||||
use Pterodactyl\Services\Databases\DatabasePasswordService;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
|
||||||
|
|
||||||
class DatabasePasswordServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Extensions\DynamicDatabaseConnection|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $dynamic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Encryption\Encrypter|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $encrypter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->dynamic = m::mock(DynamicDatabaseConnection::class);
|
|
||||||
$this->encrypter = m::mock(Encrypter::class);
|
|
||||||
$this->repository = m::mock(DatabaseRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a password can be updated.
|
|
||||||
*/
|
|
||||||
public function testPasswordIsChanged()
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Database $model */
|
|
||||||
$model = factory(Database::class)->make(['max_connections' => 0]);
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
|
||||||
return is_null($closure());
|
|
||||||
}));
|
|
||||||
|
|
||||||
$this->dynamic->expects('set')->with('dynamic', $model->database_host_id)->andReturnNull();
|
|
||||||
|
|
||||||
$this->encrypter->expects('encrypt')->with(m::on(function ($string) {
|
|
||||||
preg_match_all('/[!@+=.^-]/', $string, $matches, PREG_SET_ORDER);
|
|
||||||
$this->assertTrue(count($matches) >= 2 && count($matches) <= 6, "Failed asserting that [{$string}] contains 2 to 6 special characters.");
|
|
||||||
$this->assertTrue(strlen($string) === 24, "Failed asserting that [{$string}] is 24 characters in length.");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}))->andReturn('enc123');
|
|
||||||
|
|
||||||
$this->repository->expects('withoutFreshModel')->withNoArgs()->andReturnSelf();
|
|
||||||
$this->repository->expects('update')->with($model->id, ['password' => 'enc123'])->andReturn(true);
|
|
||||||
|
|
||||||
$this->repository->expects('dropUser')->with($model->username, $model->remote)->andReturn(true);
|
|
||||||
$this->repository->expects('createUser')->with($model->username, $model->remote, m::any(), 0)->andReturn(true);
|
|
||||||
$this->repository->expects('assignUserToDatabase')->with($model->database, $model->username, $model->remote)->andReturn(true);
|
|
||||||
$this->repository->expects('flush')->withNoArgs()->andReturn(true);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle($model);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Databases\DatabasePasswordService
|
|
||||||
*/
|
|
||||||
private function getService(): DatabasePasswordService
|
|
||||||
{
|
|
||||||
return new DatabasePasswordService($this->connection, $this->repository, $this->dynamic, $this->encrypter);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Databases\Hosts;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\DatabaseHost;
|
|
||||||
use Illuminate\Database\DatabaseManager;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
|
||||||
use Pterodactyl\Extensions\DynamicDatabaseConnection;
|
|
||||||
use Pterodactyl\Services\Databases\Hosts\HostCreationService;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
|
||||||
|
|
||||||
class HostCreationServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\DatabaseManager|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $databaseManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Extensions\DynamicDatabaseConnection|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $dynamic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Encryption\Encrypter|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $encrypter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->databaseManager = m::mock(DatabaseManager::class);
|
|
||||||
$this->dynamic = m::mock(DynamicDatabaseConnection::class);
|
|
||||||
$this->encrypter = m::mock(Encrypter::class);
|
|
||||||
$this->repository = m::mock(DatabaseHostRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a database host can be created.
|
|
||||||
*/
|
|
||||||
public function testDatabaseHostIsCreated()
|
|
||||||
{
|
|
||||||
$model = factory(DatabaseHost::class)->make();
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
|
||||||
return ! is_null($closure());
|
|
||||||
}))->andReturn($model);
|
|
||||||
|
|
||||||
$this->encrypter->expects('encrypt')->with('test123')->andReturn('enc123');
|
|
||||||
$this->repository->expects('create')->with(m::subset([
|
|
||||||
'password' => 'enc123',
|
|
||||||
'username' => $model->username,
|
|
||||||
'node_id' => $model->node_id,
|
|
||||||
]))->andReturn($model);
|
|
||||||
|
|
||||||
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
|
||||||
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
|
||||||
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
|
||||||
|
|
||||||
$response = $this->getService()->handle([
|
|
||||||
'password' => 'test123',
|
|
||||||
'username' => $model->username,
|
|
||||||
'node_id' => $model->node_id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame($model, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Databases\Hosts\HostCreationService
|
|
||||||
*/
|
|
||||||
private function getService(): HostCreationService
|
|
||||||
{
|
|
||||||
return new HostCreationService(
|
|
||||||
$this->connection,
|
|
||||||
$this->databaseManager,
|
|
||||||
$this->repository,
|
|
||||||
$this->dynamic,
|
|
||||||
$this->encrypter
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Databases\Hosts;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Exceptions\PterodactylException;
|
|
||||||
use Pterodactyl\Exceptions\Service\HasActiveServersException;
|
|
||||||
use Pterodactyl\Services\Databases\Hosts\HostDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
|
||||||
|
|
||||||
class HostDeletionServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $databaseRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->databaseRepository = m::mock(DatabaseRepositoryInterface::class);
|
|
||||||
$this->repository = m::mock(DatabaseHostRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a host can be deleted.
|
|
||||||
*/
|
|
||||||
public function testHostIsDeleted()
|
|
||||||
{
|
|
||||||
$this->databaseRepository->shouldReceive('findCountWhere')->with([['database_host_id', '=', 1234]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('delete')->with(1234)->once()->andReturn(1);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle(1234);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame(1, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if a host with databases is deleted.
|
|
||||||
*
|
|
||||||
* @dataProvider databaseCountDataProvider
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfDeletingHostWithDatabases(int $count)
|
|
||||||
{
|
|
||||||
$this->databaseRepository->shouldReceive('findCountWhere')->with([['database_host_id', '=', 1234]])->once()->andReturn($count);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->getService()->handle(1234);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(HasActiveServersException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.databases.delete_has_databases'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data provider to ensure exceptions are thrown for any value > 0.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function databaseCountDataProvider(): array
|
|
||||||
{
|
|
||||||
return [[1], [2], [10]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Databases\Hosts\HostDeletionService
|
|
||||||
*/
|
|
||||||
private function getService(): HostDeletionService
|
|
||||||
{
|
|
||||||
return new HostDeletionService($this->databaseRepository, $this->repository);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Databases\Hosts;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\DatabaseHost;
|
|
||||||
use Illuminate\Database\DatabaseManager;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
|
||||||
use Pterodactyl\Extensions\DynamicDatabaseConnection;
|
|
||||||
use Pterodactyl\Services\Databases\Hosts\HostUpdateService;
|
|
||||||
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
|
|
||||||
|
|
||||||
class HostUpdateServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\DatabaseManager|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $databaseManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Extensions\DynamicDatabaseConnection|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $dynamic;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Encryption\Encrypter|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $encrypter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->databaseManager = m::mock(DatabaseManager::class);
|
|
||||||
$this->dynamic = m::mock(DynamicDatabaseConnection::class);
|
|
||||||
$this->encrypter = m::mock(Encrypter::class);
|
|
||||||
$this->repository = m::mock(DatabaseHostRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a password is encrypted before storage if provided.
|
|
||||||
*/
|
|
||||||
public function testPasswordIsEncryptedWhenProvided()
|
|
||||||
{
|
|
||||||
$model = factory(DatabaseHost::class)->make();
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
|
||||||
return ! is_null($closure());
|
|
||||||
}))->andReturn($model);
|
|
||||||
|
|
||||||
$this->encrypter->expects('encrypt')->with('test123')->andReturn('enc123');
|
|
||||||
$this->repository->expects('update')->with(1234, ['password' => 'enc123'])->andReturn($model);
|
|
||||||
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
|
||||||
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
|
||||||
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
|
||||||
|
|
||||||
$response = $this->getService()->handle(1234, ['password' => 'test123']);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame($model, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that updates still occur when no password is provided.
|
|
||||||
*/
|
|
||||||
public function testUpdateOccursWhenNoPasswordIsProvided()
|
|
||||||
{
|
|
||||||
$model = factory(DatabaseHost::class)->make();
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
|
||||||
return ! is_null($closure());
|
|
||||||
}))->andReturn($model);
|
|
||||||
|
|
||||||
$this->repository->expects('update')->with(1234, ['username' => 'test'])->andReturn($model);
|
|
||||||
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
|
||||||
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
|
||||||
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
|
||||||
|
|
||||||
$response = $this->getService()->handle(1234, ['password' => '', 'username' => 'test']);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame($model, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Databases\Hosts\HostUpdateService
|
|
||||||
*/
|
|
||||||
private function getService(): HostUpdateService
|
|
||||||
{
|
|
||||||
return new HostUpdateService(
|
|
||||||
$this->connection,
|
|
||||||
$this->databaseManager,
|
|
||||||
$this->repository,
|
|
||||||
$this->dynamic,
|
|
||||||
$this->encrypter
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,145 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Services\Options;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Tests\Traits\MocksUuids;
|
|
||||||
use Illuminate\Contracts\Config\Repository;
|
|
||||||
use Pterodactyl\Exceptions\PterodactylException;
|
|
||||||
use Pterodactyl\Services\Eggs\EggCreationService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\NoParentConfigurationFoundException;
|
|
||||||
|
|
||||||
class EggCreationServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
use MocksUuids;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Config\Repository|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Eggs\EggCreationService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->config = m::mock(Repository::class);
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new EggCreationService($this->config, $this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a new model is created when not using the config from attribute.
|
|
||||||
*/
|
|
||||||
public function testCreateNewModelWithoutUsingConfigFrom()
|
|
||||||
{
|
|
||||||
$model = factory(Egg::class)->make();
|
|
||||||
|
|
||||||
$this->config->shouldReceive('get')->with('pterodactyl.service.author')->once()->andReturn('test@example.com');
|
|
||||||
$this->repository->shouldReceive('create')->with([
|
|
||||||
'uuid' => $this->getKnownUuid(),
|
|
||||||
'author' => 'test@example.com',
|
|
||||||
'config_from' => null,
|
|
||||||
'name' => $model->name,
|
|
||||||
], true, true)->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->service->handle(['name' => $model->name]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertNull(object_get($response, 'config_from'));
|
|
||||||
$this->assertEquals($model->name, $response->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a new model is created when using the config from attribute.
|
|
||||||
*/
|
|
||||||
public function testCreateNewModelUsingConfigFrom()
|
|
||||||
{
|
|
||||||
$model = factory(Egg::class)->make();
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('findCountWhere')->with([
|
|
||||||
['nest_id', '=', $model->nest_id],
|
|
||||||
['id', '=', 12345],
|
|
||||||
])->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->config->shouldReceive('get')->with('pterodactyl.service.author')->once()->andReturn('test@example.com');
|
|
||||||
$this->repository->shouldReceive('create')->with([
|
|
||||||
'nest_id' => $model->nest_id,
|
|
||||||
'config_from' => 12345,
|
|
||||||
'uuid' => $this->getKnownUuid(),
|
|
||||||
'author' => 'test@example.com',
|
|
||||||
], true, true)->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->service->handle([
|
|
||||||
'nest_id' => $model->nest_id,
|
|
||||||
'config_from' => 12345,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertEquals($response, $model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that certain data, such as the UUID or author takes priority over data
|
|
||||||
* that is passed into the function.
|
|
||||||
*/
|
|
||||||
public function testDataProvidedByHandlerTakesPriorityOverPassedData()
|
|
||||||
{
|
|
||||||
$model = factory(Egg::class)->make();
|
|
||||||
|
|
||||||
$this->config->shouldReceive('get')->with('pterodactyl.service.author')->once()->andReturn('test@example.com');
|
|
||||||
$this->repository->shouldReceive('create')->with([
|
|
||||||
'uuid' => $this->getKnownUuid(),
|
|
||||||
'author' => 'test@example.com',
|
|
||||||
'config_from' => null,
|
|
||||||
'name' => $model->name,
|
|
||||||
], true, true)->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->service->handle(['name' => $model->name, 'uuid' => 'should-be-ignored', 'author' => 'should-be-ignored']);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertNull(object_get($response, 'config_from'));
|
|
||||||
$this->assertEquals($model->name, $response->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if no parent configuration can be located.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfNoParentConfigurationIsFound()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('findCountWhere')->with([
|
|
||||||
['nest_id', '=', null],
|
|
||||||
['id', '=', 1],
|
|
||||||
])->once()->andReturn(0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle(['config_from' => 1]);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(NoParentConfigurationFoundException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.egg.must_be_child'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Services\Options;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Exceptions\PterodactylException;
|
|
||||||
use Pterodactyl\Services\Eggs\EggDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\HasChildrenException;
|
|
||||||
use Pterodactyl\Exceptions\Service\HasActiveServersException;
|
|
||||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
|
||||||
|
|
||||||
class EggDeletionServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $serverRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Eggs\EggDeletionService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
$this->serverRepository = m::mock(ServerRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new EggDeletionService($this->serverRepository, $this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that Egg is deleted if no servers are found.
|
|
||||||
*/
|
|
||||||
public function testEggIsDeletedIfNoServersAreFound()
|
|
||||||
{
|
|
||||||
$this->serverRepository->shouldReceive('findCountWhere')->with([['egg_id', '=', 1]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('findCountWhere')->with([['config_from', '=', 1]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('delete')->with(1)->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->assertEquals(1, $this->service->handle(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that Egg is not deleted if servers are found.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfServersAreFound()
|
|
||||||
{
|
|
||||||
$this->serverRepository->shouldReceive('findCountWhere')->with([['egg_id', '=', 1]])->once()->andReturn(1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle(1);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(HasActiveServersException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.egg.delete_has_servers'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if children Eggs exist.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfChildrenArePresent()
|
|
||||||
{
|
|
||||||
$this->serverRepository->shouldReceive('findCountWhere')->with([['egg_id', '=', 1]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('findCountWhere')->with([['config_from', '=', 1]])->once()->andReturn(1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle(1);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(HasChildrenException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.egg.has_children'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Services\Options;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Pterodactyl\Services\Eggs\EggUpdateService;
|
|
||||||
use Pterodactyl\Exceptions\PterodactylException;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\NoParentConfigurationFoundException;
|
|
||||||
|
|
||||||
class EggUpdateServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Models\Egg
|
|
||||||
*/
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Eggs\EggUpdateService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->model = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new EggUpdateService($this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an Egg is updated when no config_from attribute is passed.
|
|
||||||
*/
|
|
||||||
public function testEggIsUpdatedWhenNoConfigFromIsProvided()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel->update')
|
|
||||||
->with($this->model->id, ['test_field' => 'field_value'])->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->service->handle($this->model, ['test_field' => 'field_value']);
|
|
||||||
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that Egg is updated when a valid config_from attribute is passed.
|
|
||||||
*/
|
|
||||||
public function testOptionIsUpdatedWhenValidConfigFromIsPassed()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('findCountWhere')->with([
|
|
||||||
['nest_id', '=', $this->model->nest_id],
|
|
||||||
['id', '=', 1],
|
|
||||||
])->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel->update')
|
|
||||||
->with($this->model->id, ['config_from' => 1])->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->service->handle($this->model, ['config_from' => 1]);
|
|
||||||
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if an invalid config_from attribute is passed.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfInvalidParentConfigIsPassed()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('findCountWhere')->with([
|
|
||||||
['nest_id', '=', $this->model->nest_id],
|
|
||||||
['id', '=', 1],
|
|
||||||
])->once()->andReturn(0);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle($this->model, ['config_from' => 1]);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(NoParentConfigurationFoundException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.egg.must_be_child'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Eggs\Scripts;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Pterodactyl\Services\Eggs\Scripts\InstallScriptService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\InvalidCopyFromException;
|
|
||||||
|
|
||||||
class InstallScriptServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $data = [
|
|
||||||
'script_install' => 'test-script',
|
|
||||||
'script_is_privileged' => true,
|
|
||||||
'script_entry' => '/bin/bash',
|
|
||||||
'script_container' => 'ubuntu',
|
|
||||||
'copy_script_from' => null,
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that passing a new copy_script_from attribute works properly.
|
|
||||||
*/
|
|
||||||
public function testUpdateWithValidCopyScriptFromAttribute()
|
|
||||||
{
|
|
||||||
$model = factory(Egg::class)->make(['id' => 123, 'nest_id' => 456]);
|
|
||||||
$this->data['copy_script_from'] = 1;
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('isCopyableScript')->with(1, $model->nest_id)->once()->andReturn(true);
|
|
||||||
$this->repository->expects('withoutFreshModel->update')->with($model->id, $this->data)->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($model, $this->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception gets raised when the script is not copyable.
|
|
||||||
*/
|
|
||||||
public function testUpdateWithInvalidCopyScriptFromAttribute()
|
|
||||||
{
|
|
||||||
$this->data['copy_script_from'] = 1;
|
|
||||||
|
|
||||||
$this->expectException(InvalidCopyFromException::class);
|
|
||||||
$this->expectExceptionMessage(trans('exceptions.nest.egg.invalid_copy_id'));
|
|
||||||
|
|
||||||
$model = factory(Egg::class)->make(['id' => 123, 'nest_id' => 456]);
|
|
||||||
|
|
||||||
$this->repository->expects('isCopyableScript')->with(1, $model->nest_id)->andReturn(false);
|
|
||||||
$this->getService()->handle($model, $this->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test standard functionality.
|
|
||||||
*/
|
|
||||||
public function testUpdateWithoutNewCopyScriptFromAttribute()
|
|
||||||
{
|
|
||||||
$model = factory(Egg::class)->make(['id' => 123, 'nest_id' => 456]);
|
|
||||||
|
|
||||||
$this->repository->expects('withoutFreshModel->update')->with($model->id, $this->data)->andReturnNull();
|
|
||||||
|
|
||||||
$this->getService()->handle($model, $this->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getService()
|
|
||||||
{
|
|
||||||
return new InstallScriptService($this->repository);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Eggs\Sharing;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Tests\Assertions\NestedObjectAssertionsTrait;
|
|
||||||
use Pterodactyl\Services\Eggs\Sharing\EggExporterService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
|
|
||||||
class EggExporterServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
use NestedObjectAssertionsTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Carbon::setTestNow(Carbon::now());
|
|
||||||
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a JSON structure is returned.
|
|
||||||
*/
|
|
||||||
public function testJsonStructureIsExported()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make([
|
|
||||||
'id' => 123,
|
|
||||||
'nest_id' => 456,
|
|
||||||
]);
|
|
||||||
$egg->variables = collect([$variable = factory(EggVariable::class)->make()]);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('getWithExportAttributes')->with($egg->id)->once()->andReturn($egg);
|
|
||||||
|
|
||||||
$service = new EggExporterService($this->repository);
|
|
||||||
|
|
||||||
$response = $service->handle($egg->id);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
|
|
||||||
$data = json_decode($response);
|
|
||||||
$this->assertEquals(JSON_ERROR_NONE, json_last_error());
|
|
||||||
$this->assertObjectHasNestedAttribute('meta.version', $data);
|
|
||||||
$this->assertObjectNestedValueEquals('meta.version', 'PTDL_v1', $data);
|
|
||||||
$this->assertObjectHasNestedAttribute('author', $data);
|
|
||||||
$this->assertObjectNestedValueEquals('author', $egg->author, $data);
|
|
||||||
$this->assertObjectHasNestedAttribute('exported_at', $data);
|
|
||||||
$this->assertObjectNestedValueEquals('exported_at', Carbon::now()->toIso8601String(), $data);
|
|
||||||
$this->assertObjectHasNestedAttribute('scripts.installation.script', $data);
|
|
||||||
$this->assertObjectHasNestedAttribute('scripts.installation.container', $data);
|
|
||||||
$this->assertObjectHasNestedAttribute('scripts.installation.entrypoint', $data);
|
|
||||||
$this->assertObjectHasAttribute('variables', $data);
|
|
||||||
$this->assertArrayHasKey('0', $data->variables);
|
|
||||||
$this->assertObjectHasAttribute('name', $data->variables[0]);
|
|
||||||
$this->assertObjectNestedValueEquals('name', $variable->name, $data->variables[0]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,187 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Eggs\Sharing;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Pterodactyl\Models\Nest;
|
|
||||||
use Tests\Traits\MocksUuids;
|
|
||||||
use Illuminate\Http\UploadedFile;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Pterodactyl\Services\Eggs\Sharing\EggImporterService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException;
|
|
||||||
use Pterodactyl\Exceptions\Service\InvalidFileUploadException;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
|
||||||
|
|
||||||
class EggImporterServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
use MocksUuids;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $eggVariableRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Http\UploadedFile|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $file;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $nestRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Eggs\Sharing\EggImporterService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->file = m::mock(UploadedFile::class);
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->eggVariableRepository = m::mock(EggVariableRepositoryInterface::class);
|
|
||||||
$this->nestRepository = m::mock(NestRepositoryInterface::class);
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new EggImporterService(
|
|
||||||
$this->connection, $this->repository, $this->eggVariableRepository, $this->nestRepository
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a service option can be successfully imported.
|
|
||||||
*/
|
|
||||||
public function testEggConfigurationIsImported()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
$nest = factory(Nest::class)->make(['id' => 456]);
|
|
||||||
|
|
||||||
$this->file->expects('getError')->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->expects('isFile')->andReturn(true);
|
|
||||||
$this->file->expects('getSize')->andReturn(100);
|
|
||||||
|
|
||||||
$this->file->expects('openFile->fread')->with(100)->once()->andReturn(json_encode([
|
|
||||||
'meta' => ['version' => 'PTDL_v1'],
|
|
||||||
'name' => $egg->name,
|
|
||||||
'author' => $egg->author,
|
|
||||||
'variables' => [
|
|
||||||
$variable = factory(EggVariable::class)->make(),
|
|
||||||
],
|
|
||||||
]));
|
|
||||||
$this->nestRepository->shouldReceive('getWithEggs')->with($nest->id)->once()->andReturn($nest);
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
|
||||||
'uuid' => $this->getKnownUuid(),
|
|
||||||
'nest_id' => $nest->id,
|
|
||||||
'name' => $egg->name,
|
|
||||||
]), true, true)->once()->andReturn($egg);
|
|
||||||
|
|
||||||
$this->eggVariableRepository->shouldReceive('create')->with(m::subset([
|
|
||||||
'egg_id' => $egg->id,
|
|
||||||
'env_variable' => $variable->env_variable,
|
|
||||||
]))->once()->andReturnNull();
|
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
|
||||||
|
|
||||||
$response = $this->service->handle($this->file, $nest->id);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertInstanceOf(Egg::class, $response);
|
|
||||||
$this->assertSame($egg, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if the file is invalid.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfFileIsInvalid()
|
|
||||||
{
|
|
||||||
$this->expectException(InvalidFileUploadException::class);
|
|
||||||
$this->expectExceptionMessage(
|
|
||||||
'The selected file ["test.txt"] was not in a valid format to import. (is_file: true is_valid: true err_code: 4 err: UPLOAD_ERR_NO_FILE)'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->file->expects('getFilename')->andReturns('test.txt');
|
|
||||||
$this->file->expects('isFile')->andReturns(true);
|
|
||||||
$this->file->expects('isValid')->andReturns(true);
|
|
||||||
$this->file->expects('getError')->twice()->andReturns(UPLOAD_ERR_NO_FILE);
|
|
||||||
$this->file->expects('getErrorMessage')->andReturns('UPLOAD_ERR_NO_FILE');
|
|
||||||
|
|
||||||
$this->service->handle($this->file, 1234);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if the file is not a file.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfFileIsNotAFile()
|
|
||||||
{
|
|
||||||
$this->expectException(InvalidFileUploadException::class);
|
|
||||||
$this->expectExceptionMessage(
|
|
||||||
'The selected file ["test.txt"] was not in a valid format to import. (is_file: false is_valid: true err_code: 4 err: UPLOAD_ERR_NO_FILE)'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->file->expects('getFilename')->andReturns('test.txt');
|
|
||||||
$this->file->expects('isFile')->andReturns(false);
|
|
||||||
$this->file->expects('isValid')->andReturns(true);
|
|
||||||
$this->file->expects('getError')->twice()->andReturns(UPLOAD_ERR_NO_FILE);
|
|
||||||
$this->file->expects('getErrorMessage')->andReturns('UPLOAD_ERR_NO_FILE');
|
|
||||||
|
|
||||||
$this->service->handle($this->file, 1234);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if the JSON metadata is invalid.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfJsonMetaDataIsInvalid()
|
|
||||||
{
|
|
||||||
$this->expectException(InvalidFileUploadException::class);
|
|
||||||
$this->expectExceptionMessage(trans('exceptions.nest.importer.invalid_json_provided'));
|
|
||||||
|
|
||||||
$this->file->expects('getError')->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->expects('isFile')->andReturn(true);
|
|
||||||
$this->file->expects('getSize')->andReturn(100);
|
|
||||||
|
|
||||||
$this->file->expects('openFile->fread')->with(100)->andReturn(json_encode([
|
|
||||||
'meta' => ['version' => 'hodor'],
|
|
||||||
]));
|
|
||||||
|
|
||||||
$this->service->handle($this->file, 1234);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if bad JSON is provided.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfBadJsonIsProvided()
|
|
||||||
{
|
|
||||||
$this->expectException(BadJsonFormatException::class);
|
|
||||||
$this->expectExceptionMessage(trans('exceptions.nest.importer.json_error', [
|
|
||||||
'error' => 'Syntax error',
|
|
||||||
]));
|
|
||||||
|
|
||||||
$this->file->expects('getError')->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->expects('isFile')->andReturn(true);
|
|
||||||
$this->file->expects('getSize')->andReturn(100);
|
|
||||||
$this->file->expects('openFile->fread')->with(100)->andReturn('}');
|
|
||||||
|
|
||||||
$this->service->handle($this->file, 1234);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,219 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Eggs\Sharing;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Illuminate\Http\UploadedFile;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Pterodactyl\Exceptions\PterodactylException;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException;
|
|
||||||
use Pterodactyl\Exceptions\Service\InvalidFileUploadException;
|
|
||||||
use Pterodactyl\Services\Eggs\Sharing\EggUpdateImporterService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
|
||||||
|
|
||||||
class EggUpdateImporterServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Http\UploadedFile|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $file;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Eggs\Sharing\EggUpdateImporterService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $variableRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->file = m::mock(UploadedFile::class);
|
|
||||||
$this->repository = m::mock(EggRepositoryInterface::class);
|
|
||||||
$this->variableRepository = m::mock(EggVariableRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new EggUpdateImporterService($this->connection, $this->repository, $this->variableRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an egg update is handled correctly using an uploaded file.
|
|
||||||
*/
|
|
||||||
public function testEggIsUpdated()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
$variable = factory(EggVariable::class)->make();
|
|
||||||
|
|
||||||
$this->file->shouldReceive('getError')->withNoArgs()->once()->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
|
|
||||||
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
|
|
||||||
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([
|
|
||||||
'meta' => ['version' => 'PTDL_v1'],
|
|
||||||
'name' => $egg->name,
|
|
||||||
'author' => 'newauthor@example.com',
|
|
||||||
'variables' => [$variable->toArray()],
|
|
||||||
]));
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('update')->with($egg->id, m::subset([
|
|
||||||
'author' => 'newauthor@example.com',
|
|
||||||
'name' => $egg->name,
|
|
||||||
]), true, true)->once()->andReturn($egg);
|
|
||||||
|
|
||||||
$this->variableRepository->shouldReceive('withoutFreshModel->updateOrCreate')->with([
|
|
||||||
'egg_id' => $egg->id,
|
|
||||||
'env_variable' => $variable->env_variable,
|
|
||||||
], collect($variable)->except(['egg_id', 'env_variable'])->toArray())->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->variableRepository->shouldReceive('setColumns')->with(['id', 'env_variable'])->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findWhere')->with([['egg_id', '=', $egg->id]])->once()->andReturn(collect([$variable]));
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->service->handle($egg, $this->file);
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an imported file with less variables than currently existing deletes
|
|
||||||
* the un-needed variables from the database.
|
|
||||||
*/
|
|
||||||
public function testVariablesMissingFromImportAreDeleted()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
$variable1 = factory(EggVariable::class)->make();
|
|
||||||
$variable2 = factory(EggVariable::class)->make();
|
|
||||||
|
|
||||||
$this->file->shouldReceive('getError')->withNoArgs()->once()->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
|
|
||||||
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
|
|
||||||
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([
|
|
||||||
'meta' => ['version' => 'PTDL_v1'],
|
|
||||||
'name' => $egg->name,
|
|
||||||
'author' => 'newauthor@example.com',
|
|
||||||
'variables' => [$variable1->toArray()],
|
|
||||||
]));
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
|
||||||
$this->repository->shouldReceive('update')->with($egg->id, m::subset([
|
|
||||||
'author' => 'newauthor@example.com',
|
|
||||||
'name' => $egg->name,
|
|
||||||
]), true, true)->once()->andReturn($egg);
|
|
||||||
|
|
||||||
$this->variableRepository->shouldReceive('withoutFreshModel->updateOrCreate')->with([
|
|
||||||
'egg_id' => $egg->id,
|
|
||||||
'env_variable' => $variable1->env_variable,
|
|
||||||
], collect($variable1)->except(['egg_id', 'env_variable'])->toArray())->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->variableRepository->shouldReceive('setColumns')->with(['id', 'env_variable'])->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findWhere')->with([['egg_id', '=', $egg->id]])->once()->andReturn(collect([$variable1, $variable2]));
|
|
||||||
|
|
||||||
$this->variableRepository->shouldReceive('deleteWhere')->with([
|
|
||||||
['egg_id', '=', $egg->id],
|
|
||||||
['env_variable', '=', $variable2->env_variable],
|
|
||||||
])->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->service->handle($egg, $this->file);
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if the file is invalid.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfFileIsInvalid()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
|
|
||||||
$this->expectException(InvalidFileUploadException::class);
|
|
||||||
$this->expectExceptionMessageMatches('/^The selected file \["test\.txt"\] was not in a valid format to import\./');
|
|
||||||
$file = new UploadedFile('test.txt', 'original.txt', 'application/json', UPLOAD_ERR_NO_FILE, true);
|
|
||||||
|
|
||||||
$this->service->handle($egg, $file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if the file is not a file.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfFileIsNotAFile()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
|
|
||||||
$this->expectException(InvalidFileUploadException::class);
|
|
||||||
$this->expectExceptionMessageMatches('/^The selected file \["test\.txt"\] was not in a valid format to import\./');
|
|
||||||
|
|
||||||
$file = m::mock(
|
|
||||||
new UploadedFile('test.txt', 'original.txt', 'application/json', UPLOAD_ERR_INI_SIZE, true)
|
|
||||||
)->makePartial();
|
|
||||||
|
|
||||||
$file->expects('isFile')->andReturnFalse();
|
|
||||||
|
|
||||||
$this->service->handle($egg, $file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if the JSON metadata is invalid.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfJsonMetaDataIsInvalid()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
|
|
||||||
$this->file->shouldReceive('getError')->withNoArgs()->once()->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
|
|
||||||
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
|
|
||||||
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([
|
|
||||||
'meta' => ['version' => 'hodor'],
|
|
||||||
]));
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle($egg, $this->file);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(InvalidFileUploadException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.importer.invalid_json_provided'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if bad JSON is provided.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfBadJsonIsProvided()
|
|
||||||
{
|
|
||||||
$egg = factory(Egg::class)->make(['id' => 123]);
|
|
||||||
|
|
||||||
$this->file->shouldReceive('getError')->withNoArgs()->once()->andReturn(UPLOAD_ERR_OK);
|
|
||||||
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
|
|
||||||
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
|
|
||||||
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn('}');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle($egg, $this->file);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(BadJsonFormatException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.importer.json_error', [
|
|
||||||
'error' => json_last_error_msg(),
|
|
||||||
]), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,185 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Eggs\Variables;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use BadMethodCallException;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Illuminate\Contracts\Validation\Factory;
|
|
||||||
use Pterodactyl\Services\Eggs\Variables\VariableCreationService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException;
|
|
||||||
|
|
||||||
class VariableCreationServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Validation\Factory|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(EggVariableRepositoryInterface::class);
|
|
||||||
$this->validator = m::mock(Factory::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test basic functionality, data should be stored in the database.
|
|
||||||
*/
|
|
||||||
public function testVariableIsCreatedAndStored()
|
|
||||||
{
|
|
||||||
$data = ['env_variable' => 'TEST_VAR_123', 'default_value' => 'test'];
|
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
|
||||||
'egg_id' => 1,
|
|
||||||
'default_value' => 'test',
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
'env_variable' => 'TEST_VAR_123',
|
|
||||||
]))->once()->andReturn(new EggVariable);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the option key in the data array is properly parsed.
|
|
||||||
*/
|
|
||||||
public function testOptionsPassedInArrayKeyAreParsedProperly()
|
|
||||||
{
|
|
||||||
$data = ['env_variable' => 'TEST_VAR_123', 'options' => ['user_viewable', 'user_editable']];
|
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
|
||||||
'default_value' => '',
|
|
||||||
'user_viewable' => true,
|
|
||||||
'user_editable' => true,
|
|
||||||
'env_variable' => 'TEST_VAR_123',
|
|
||||||
]))->once()->andReturn(new EggVariable);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an empty (null) value passed in the option key is handled
|
|
||||||
* properly as an array. Also tests the same case against the default_value.
|
|
||||||
*
|
|
||||||
* @see https://github.com/Pterodactyl/Panel/issues/841
|
|
||||||
* @see https://github.com/Pterodactyl/Panel/issues/943
|
|
||||||
*/
|
|
||||||
public function testNullOptionValueIsPassedAsArray()
|
|
||||||
{
|
|
||||||
$data = ['env_variable' => 'TEST_VAR_123', 'options' => null, 'default_value' => null];
|
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
|
||||||
'default_value' => '',
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
]))->once()->andReturn(new EggVariable);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that all of the reserved variables defined in the model trigger an exception.
|
|
||||||
*
|
|
||||||
* @param string $variable
|
|
||||||
*
|
|
||||||
* @dataProvider reservedNamesProvider
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable)
|
|
||||||
{
|
|
||||||
$this->expectException(ReservedVariableNameException::class);
|
|
||||||
|
|
||||||
$this->getService()->handle(1, ['env_variable' => $variable]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the egg ID applied in the function takes higher priority than an
|
|
||||||
* ID passed into the handler.
|
|
||||||
*/
|
|
||||||
public function testEggIdPassedInDataIsNotApplied()
|
|
||||||
{
|
|
||||||
$data = ['egg_id' => 123456, 'env_variable' => 'TEST_VAR_123'];
|
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
|
||||||
'egg_id' => 1,
|
|
||||||
]))->once()->andReturn(new EggVariable);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(EggVariable::class, $this->getService()->handle(1, $data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that validation errors due to invalid rules are caught and handled properly.
|
|
||||||
*/
|
|
||||||
public function testInvalidValidationRulesResultInException()
|
|
||||||
{
|
|
||||||
$this->expectException(BadValidationRuleException::class);
|
|
||||||
$this->expectExceptionMessage('The validation rule "hodor_door" is not a valid rule for this application.');
|
|
||||||
|
|
||||||
$data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string|hodorDoor'];
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('make')->once()
|
|
||||||
->with(['__TEST' => 'test'], ['__TEST' => 'string|hodorDoor'])
|
|
||||||
->andReturnSelf();
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('fails')->once()
|
|
||||||
->withNoArgs()
|
|
||||||
->andThrow(new BadMethodCallException('Method [validateHodorDoor] does not exist.'));
|
|
||||||
|
|
||||||
$this->getService()->handle(1, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception not stemming from a bad rule is not caught.
|
|
||||||
*/
|
|
||||||
public function testExceptionNotCausedByBadRuleIsNotCaught()
|
|
||||||
{
|
|
||||||
$this->expectException(BadMethodCallException::class);
|
|
||||||
$this->expectExceptionMessage('Received something, but no expectations were specified.');
|
|
||||||
|
|
||||||
$data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string'];
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('make')->once()
|
|
||||||
->with(['__TEST' => 'test'], ['__TEST' => 'string'])
|
|
||||||
->andReturnSelf();
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('fails')->once()
|
|
||||||
->withNoArgs()
|
|
||||||
->andThrow(new BadMethodCallException('Received something, but no expectations were specified.'));
|
|
||||||
|
|
||||||
$this->getService()->handle(1, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the data to be used in the tests.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function reservedNamesProvider()
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
$exploded = explode(',', EggVariable::RESERVED_ENV_NAMES);
|
|
||||||
foreach ($exploded as $e) {
|
|
||||||
$data[] = [$e];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies for testing.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Eggs\Variables\VariableCreationService
|
|
||||||
*/
|
|
||||||
private function getService(): VariableCreationService
|
|
||||||
{
|
|
||||||
return new VariableCreationService($this->repository, $this->validator);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,241 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Eggs\Variables;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use BadMethodCallException;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Illuminate\Contracts\Validation\Factory;
|
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
|
||||||
use Pterodactyl\Services\Eggs\Variables\VariableUpdateService;
|
|
||||||
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\Variable\BadValidationRuleException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Egg\Variable\ReservedVariableNameException;
|
|
||||||
|
|
||||||
class VariableUpdateServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Models\EggVariable|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Validation\Factory|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $validator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->model = factory(EggVariable::class)->make();
|
|
||||||
$this->repository = m::mock(EggVariableRepositoryInterface::class);
|
|
||||||
$this->validator = m::mock(Factory::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the function when no env_variable key is passed into the function.
|
|
||||||
*/
|
|
||||||
public function testVariableIsUpdatedWhenNoEnvironmentVariableIsPassed()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with($this->model->id, m::subset([
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
]))->once()->andReturn(true);
|
|
||||||
|
|
||||||
$this->assertTrue($this->getService()->handle($this->model, []));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a null value passed in for the default is converted to a string.
|
|
||||||
*
|
|
||||||
* @see https://github.com/Pterodactyl/Panel/issues/934
|
|
||||||
*/
|
|
||||||
public function testNullDefaultValue()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel->update')->with($this->model->id, m::subset([
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
'default_value' => '',
|
|
||||||
]))->once()->andReturn(true);
|
|
||||||
|
|
||||||
$this->assertTrue($this->getService()->handle($this->model, ['default_value' => null]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test the function when a valid env_variable key is passed into the function.
|
|
||||||
*/
|
|
||||||
public function testVariableIsUpdatedWhenValidEnvironmentVariableIsPassed()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findCountWhere')->with([
|
|
||||||
['env_variable', '=', 'TEST_VAR_123'],
|
|
||||||
['egg_id', '=', $this->model->option_id],
|
|
||||||
['id', '!=', $this->model->id],
|
|
||||||
])->once()->andReturn(0);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with($this->model->id, m::subset([
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
'env_variable' => 'TEST_VAR_123',
|
|
||||||
]))->once()->andReturn(true);
|
|
||||||
|
|
||||||
$this->assertTrue($this->getService()->handle($this->model, ['env_variable' => 'TEST_VAR_123']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an empty (null) value passed in the option key is handled
|
|
||||||
* properly as an array. Also tests that a null description is handled.
|
|
||||||
*
|
|
||||||
* @see https://github.com/Pterodactyl/Panel/issues/841
|
|
||||||
*/
|
|
||||||
public function testNullOptionValueIsPassedAsArray()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with($this->model->id, m::subset([
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
'description' => '',
|
|
||||||
]))->once()->andReturn(true);
|
|
||||||
|
|
||||||
$this->assertTrue($this->getService()->handle($this->model, ['options' => null, 'description' => null]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that data passed into the handler is overwritten inside the handler.
|
|
||||||
*/
|
|
||||||
public function testDataPassedIntoHandlerTakesLowerPriorityThanDataSet()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findCountWhere')->with([
|
|
||||||
['env_variable', '=', 'TEST_VAR_123'],
|
|
||||||
['egg_id', '=', $this->model->option_id],
|
|
||||||
['id', '!=', $this->model->id],
|
|
||||||
])->once()->andReturn(0);
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with($this->model->id, m::subset([
|
|
||||||
'user_viewable' => false,
|
|
||||||
'user_editable' => false,
|
|
||||||
'env_variable' => 'TEST_VAR_123',
|
|
||||||
]))->once()->andReturn(true);
|
|
||||||
|
|
||||||
$this->assertTrue($this->getService()->handle($this->model, ['user_viewable' => 123456, 'env_variable' => 'TEST_VAR_123']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a non-unique environment variable triggers an exception.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfEnvironmentVariableIsNotUnique()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findCountWhere')->with([
|
|
||||||
['env_variable', '=', 'TEST_VAR_123'],
|
|
||||||
['egg_id', '=', $this->model->option_id],
|
|
||||||
['id', '!=', $this->model->id],
|
|
||||||
])->once()->andReturn(1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->getService()->handle($this->model, ['env_variable' => 'TEST_VAR_123']);
|
|
||||||
} catch (Exception $exception) {
|
|
||||||
$this->assertInstanceOf(DisplayException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.service.variables.env_not_unique', [
|
|
||||||
'name' => 'TEST_VAR_123',
|
|
||||||
]), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that all of the reserved variables defined in the model trigger an exception.
|
|
||||||
*
|
|
||||||
* @dataProvider reservedNamesProvider
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable)
|
|
||||||
{
|
|
||||||
$this->expectException(ReservedVariableNameException::class);
|
|
||||||
|
|
||||||
$this->getService()->handle($this->model, ['env_variable' => $variable]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that validation errors due to invalid rules are caught and handled properly.
|
|
||||||
*/
|
|
||||||
public function testInvalidValidationRulesResultInException()
|
|
||||||
{
|
|
||||||
$this->expectException(BadValidationRuleException::class);
|
|
||||||
$this->expectExceptionMessage('The validation rule "hodor_door" is not a valid rule for this application.');
|
|
||||||
|
|
||||||
$data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string|hodorDoor'];
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('setColumns->findCountWhere')->once()->andReturn(0);
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('make')->once()
|
|
||||||
->with(['__TEST' => 'test'], ['__TEST' => 'string|hodorDoor'])
|
|
||||||
->andReturnSelf();
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('fails')->once()
|
|
||||||
->withNoArgs()
|
|
||||||
->andThrow(new BadMethodCallException('Method [validateHodorDoor] does not exist.'));
|
|
||||||
|
|
||||||
$this->getService()->handle($this->model, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception not stemming from a bad rule is not caught.
|
|
||||||
*/
|
|
||||||
public function testExceptionNotCausedByBadRuleIsNotCaught()
|
|
||||||
{
|
|
||||||
$this->expectException(BadMethodCallException::class);
|
|
||||||
$this->expectExceptionMessage('Received something, but no expectations were specified.');
|
|
||||||
|
|
||||||
$data = ['rules' => 'string'];
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('make')->once()
|
|
||||||
->with(['__TEST' => 'test'], ['__TEST' => 'string'])
|
|
||||||
->andReturnSelf();
|
|
||||||
|
|
||||||
$this->validator->shouldReceive('fails')->once()
|
|
||||||
->withNoArgs()
|
|
||||||
->andThrow(new BadMethodCallException('Received something, but no expectations were specified.'));
|
|
||||||
|
|
||||||
$this->getService()->handle($this->model, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the data to be used in the tests.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function reservedNamesProvider()
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
$exploded = explode(',', EggVariable::RESERVED_ENV_NAMES);
|
|
||||||
foreach ($exploded as $e) {
|
|
||||||
$data[] = [$e];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies for testing.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Eggs\Variables\VariableUpdateService
|
|
||||||
*/
|
|
||||||
private function getService(): VariableUpdateService
|
|
||||||
{
|
|
||||||
return new VariableUpdateService($this->repository, $this->validator);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Locations;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Location;
|
|
||||||
use Pterodactyl\Services\Locations\LocationCreationService;
|
|
||||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
|
||||||
|
|
||||||
class LocationCreationServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Locations\LocationCreationService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(LocationRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new LocationCreationService($this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a location is created.
|
|
||||||
*/
|
|
||||||
public function testLocationIsCreated()
|
|
||||||
{
|
|
||||||
$location = factory(Location::class)->make();
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('create')->with(['test_data' => 'test_value'])->once()->andReturn($location);
|
|
||||||
|
|
||||||
$response = $this->service->handle(['test_data' => 'test_value']);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertInstanceOf(Location::class, $response);
|
|
||||||
$this->assertEquals($location, $response);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Locations;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
|
||||||
use Pterodactyl\Services\Locations\LocationDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
|
||||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\Location\HasActiveNodesException;
|
|
||||||
|
|
||||||
class LocationDeletionServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\NodeRepositoryInterface
|
|
||||||
*/
|
|
||||||
protected $nodeRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Locations\LocationDeletionService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->nodeRepository = m::mock(NodeRepositoryInterface::class);
|
|
||||||
$this->repository = m::mock(LocationRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new LocationDeletionService($this->repository, $this->nodeRepository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a location is deleted.
|
|
||||||
*/
|
|
||||||
public function testLocationIsDeleted()
|
|
||||||
{
|
|
||||||
$this->nodeRepository->shouldReceive('findCountWhere')->with([['location_id', '=', 123]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('delete')->with(123)->once()->andReturn(1);
|
|
||||||
|
|
||||||
$response = $this->service->handle(123);
|
|
||||||
$this->assertEquals(1, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if nodes are attached to a location.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfNodesAreAttached()
|
|
||||||
{
|
|
||||||
$this->nodeRepository->shouldReceive('findCountWhere')->with([['location_id', '=', 123]])->once()->andReturn(1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle(123);
|
|
||||||
} catch (DisplayException $exception) {
|
|
||||||
$this->assertInstanceOf(HasActiveNodesException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.locations.has_nodes'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Locations;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Location;
|
|
||||||
use Pterodactyl\Services\Locations\LocationUpdateService;
|
|
||||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
|
||||||
|
|
||||||
class LocationUpdateServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Locations\LocationUpdateService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(LocationRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new LocationUpdateService($this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test location is updated.
|
|
||||||
*/
|
|
||||||
public function testLocationIsUpdated()
|
|
||||||
{
|
|
||||||
$model = factory(Location::class)->make(['id' => 123]);
|
|
||||||
$this->repository->shouldReceive('update')->with(123, ['test_data' => 'test_value'])->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->service->handle($model->id, ['test_data' => 'test_value']);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertInstanceOf(Location::class, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a model can be passed in place of an ID.
|
|
||||||
*/
|
|
||||||
public function testModelCanBePassedToFunction()
|
|
||||||
{
|
|
||||||
$model = factory(Location::class)->make(['id' => 123]);
|
|
||||||
$this->repository->shouldReceive('update')->with(123, ['test_data' => 'test_value'])->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->service->handle($model, ['test_data' => 'test_value']);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertInstanceOf(Location::class, $response);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Services;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Nest;
|
|
||||||
use Tests\Traits\MocksUuids;
|
|
||||||
use Illuminate\Contracts\Config\Repository;
|
|
||||||
use Pterodactyl\Services\Nests\NestCreationService;
|
|
||||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
|
||||||
|
|
||||||
class NestCreationServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
use MocksUuids;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Config\Repository|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->config = m::mock(Repository::class);
|
|
||||||
$this->repository = m::mock(NestRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a new service can be created using the correct data.
|
|
||||||
*/
|
|
||||||
public function testCreateNewService()
|
|
||||||
{
|
|
||||||
$model = factory(Nest::class)->make();
|
|
||||||
|
|
||||||
$this->config->shouldReceive('get')->with('pterodactyl.service.author')->once()->andReturn('testauthor@example.com');
|
|
||||||
$this->repository->shouldReceive('create')->with([
|
|
||||||
'uuid' => $this->getKnownUuid(),
|
|
||||||
'author' => 'testauthor@example.com',
|
|
||||||
'name' => $model->name,
|
|
||||||
'description' => $model->description,
|
|
||||||
], true, true)->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle(['name' => $model->name, 'description' => $model->description]);
|
|
||||||
$this->assertInstanceOf(Nest::class, $response);
|
|
||||||
$this->assertEquals($model, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test creation of a new nest with a defined author. This is used by seeder
|
|
||||||
* scripts which need to set a specific author for nests in order for other
|
|
||||||
* functionality to work correctly.
|
|
||||||
*/
|
|
||||||
public function testCreateServiceWithDefinedAuthor()
|
|
||||||
{
|
|
||||||
$model = factory(Nest::class)->make();
|
|
||||||
|
|
||||||
$this->repository->shouldReceive('create')->with([
|
|
||||||
'uuid' => $this->getKnownUuid(),
|
|
||||||
'author' => 'support@pterodactyl.io',
|
|
||||||
'name' => $model->name,
|
|
||||||
'description' => $model->description,
|
|
||||||
], true, true)->once()->andReturn($model);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle(['name' => $model->name, 'description' => $model->description], 'support@pterodactyl.io');
|
|
||||||
$this->assertInstanceOf(Nest::class, $response);
|
|
||||||
$this->assertEquals($model, $response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Nests\NestCreationService
|
|
||||||
*/
|
|
||||||
private function getService(): NestCreationService
|
|
||||||
{
|
|
||||||
return new NestCreationService($this->config, $this->repository);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Services;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Exceptions\PterodactylException;
|
|
||||||
use Pterodactyl\Services\Nests\NestDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
|
||||||
use Pterodactyl\Exceptions\Service\HasActiveServersException;
|
|
||||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
|
||||||
|
|
||||||
class NestDeletionServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $serverRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Nests\NestDeletionService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->serverRepository = m::mock(ServerRepositoryInterface::class);
|
|
||||||
$this->repository = m::mock(NestRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new NestDeletionService($this->serverRepository, $this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a service is deleted when there are no servers attached to a service.
|
|
||||||
*/
|
|
||||||
public function testServiceIsDeleted()
|
|
||||||
{
|
|
||||||
$this->serverRepository->shouldReceive('findCountWhere')->with([['nest_id', '=', 1]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('delete')->with(1)->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->assertEquals(1, $this->service->handle(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown when there are servers attached to a service.
|
|
||||||
*
|
|
||||||
* @dataProvider serverCountProvider
|
|
||||||
*
|
|
||||||
* @param int $count
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfServersAreAttached(int $count)
|
|
||||||
{
|
|
||||||
$this->serverRepository->shouldReceive('findCountWhere')->with([['nest_id', '=', 1]])->once()->andReturn($count);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->service->handle(1);
|
|
||||||
} catch (PterodactylException $exception) {
|
|
||||||
$this->assertInstanceOf(HasActiveServersException::class, $exception);
|
|
||||||
$this->assertEquals(trans('exceptions.nest.delete_has_servers'), $exception->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide assorted server counts to ensure that an exception is always thrown when more than 0 servers are found.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function serverCountProvider()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
[1], [2], [5], [10],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Pterodactyl - Panel
|
|
||||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
|
||||||
*
|
|
||||||
* This software is licensed under the terms of the MIT license.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Services;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Services\Nests\NestUpdateService;
|
|
||||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
|
||||||
|
|
||||||
class NestUpdateServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Nests\NestUpdateService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(NestRepositoryInterface::class);
|
|
||||||
|
|
||||||
$this->service = new NestUpdateService($this->repository);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the author key is removed from the data array before updating the record.
|
|
||||||
*/
|
|
||||||
public function testAuthorArrayKeyIsRemovedIfPassed()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with(1, ['otherfield' => 'value'])->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->service->handle(1, ['author' => 'author1', 'otherfield' => 'value']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the function continues to work when no author key is passed.
|
|
||||||
*/
|
|
||||||
public function testServiceIsUpdatedWhenNoAuthorKeyIsPassed()
|
|
||||||
{
|
|
||||||
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf()
|
|
||||||
->shouldReceive('update')->with(1, ['otherfield' => 'value'])->once()->andReturnNull();
|
|
||||||
|
|
||||||
$this->service->handle(1, ['otherfield' => 'value']);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Nodes;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Ramsey\Uuid\Uuid;
|
|
||||||
use phpmock\phpunit\PHPMock;
|
|
||||||
use Pterodactyl\Models\Node;
|
|
||||||
use Ramsey\Uuid\UuidFactory;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
|
||||||
use Pterodactyl\Services\Nodes\NodeCreationService;
|
|
||||||
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
|
||||||
|
|
||||||
class NodeCreationServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
use PHPMock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Mockery\MockInterface
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Mockery\MockInterface
|
|
||||||
*/
|
|
||||||
private $encrypter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
/* @noinspection PhpParamsInspection */
|
|
||||||
Uuid::setFactory(
|
|
||||||
m::mock(UuidFactory::class . '[uuid4]', [
|
|
||||||
'uuid4' => Uuid::fromString('00000000-0000-0000-0000-000000000000'),
|
|
||||||
])
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->repository = m::mock(NodeRepositoryInterface::class);
|
|
||||||
$this->encrypter = m::mock(Encrypter::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a node is created and a daemon secret token is created.
|
|
||||||
*/
|
|
||||||
public function testNodeIsCreatedAndDaemonSecretIsGenerated()
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Node $node */
|
|
||||||
$node = factory(Node::class)->make();
|
|
||||||
|
|
||||||
$this->encrypter->expects('encrypt')->with(m::on(function ($value) {
|
|
||||||
return strlen($value) === Node::DAEMON_TOKEN_LENGTH;
|
|
||||||
}))->andReturns('encrypted_value');
|
|
||||||
|
|
||||||
$this->repository->expects('create')->with(m::on(function ($value) {
|
|
||||||
$this->assertTrue(is_array($value));
|
|
||||||
$this->assertSame('NodeName', $value['name']);
|
|
||||||
$this->assertSame('00000000-0000-0000-0000-000000000000', $value['uuid']);
|
|
||||||
$this->assertSame('encrypted_value', $value['daemon_token']);
|
|
||||||
$this->assertTrue(strlen($value['daemon_token_id']) === Node::DAEMON_TOKEN_ID_LENGTH);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}), true, true)->andReturn($node);
|
|
||||||
|
|
||||||
$this->assertSame($node, $this->getService()->handle(['name' => 'NodeName']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Pterodactyl\Services\Nodes\NodeCreationService
|
|
||||||
*/
|
|
||||||
private function getService()
|
|
||||||
{
|
|
||||||
return new NodeCreationService($this->encrypter, $this->repository);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Nodes;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Node;
|
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
|
||||||
use Illuminate\Contracts\Translation\Translator;
|
|
||||||
use Pterodactyl\Services\Nodes\NodeDeletionService;
|
|
||||||
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
|
||||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
|
||||||
|
|
||||||
class NodeDeletionServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\NodeRepositoryInterface
|
|
||||||
*/
|
|
||||||
protected $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
|
|
||||||
*/
|
|
||||||
protected $serverRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Illuminate\Contracts\Translation\Translator
|
|
||||||
*/
|
|
||||||
protected $translator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Nodes\NodeDeletionService
|
|
||||||
*/
|
|
||||||
protected $service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(NodeRepositoryInterface::class);
|
|
||||||
$this->serverRepository = m::mock(ServerRepositoryInterface::class);
|
|
||||||
$this->translator = m::mock(Translator::class);
|
|
||||||
|
|
||||||
$this->service = new NodeDeletionService(
|
|
||||||
$this->repository,
|
|
||||||
$this->serverRepository,
|
|
||||||
$this->translator
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a node is deleted if there are no servers attached to it.
|
|
||||||
*/
|
|
||||||
public function testNodeIsDeletedIfNoServersAreAttached()
|
|
||||||
{
|
|
||||||
$this->serverRepository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findCountWhere')->with([['node_id', '=', 1]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('delete')->with(1)->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->assertEquals(1, $this->service->handle(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception is thrown if servers are attached to the node.
|
|
||||||
*/
|
|
||||||
public function testExceptionIsThrownIfServersAreAttachedToNode()
|
|
||||||
{
|
|
||||||
$this->expectException(DisplayException::class);
|
|
||||||
|
|
||||||
$this->serverRepository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findCountWhere')->with([['node_id', '=', 1]])->once()->andReturn(1);
|
|
||||||
$this->translator->shouldReceive('trans')->with('exceptions.node.servers_attached')->once()->andReturnNull();
|
|
||||||
$this->repository->shouldNotReceive('delete');
|
|
||||||
|
|
||||||
$this->service->handle(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a model can be passed into the handle function rather than an ID.
|
|
||||||
*/
|
|
||||||
public function testModelCanBePassedToFunctionInPlaceOfNodeId()
|
|
||||||
{
|
|
||||||
$node = factory(Node::class)->make(['id' => 123]);
|
|
||||||
|
|
||||||
$this->serverRepository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf()
|
|
||||||
->shouldReceive('findCountWhere')->with([['node_id', '=', $node->id]])->once()->andReturn(0);
|
|
||||||
$this->repository->shouldReceive('delete')->with($node->id)->once()->andReturn(1);
|
|
||||||
|
|
||||||
$this->assertEquals(1, $this->service->handle($node));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,241 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Nodes;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use GuzzleHttp\Psr7\Request;
|
|
||||||
use phpmock\phpunit\PHPMock;
|
|
||||||
use Pterodactyl\Models\Node;
|
|
||||||
use Tests\Traits\MocksRequestException;
|
|
||||||
use GuzzleHttp\Exception\ConnectException;
|
|
||||||
use GuzzleHttp\Exception\TransferException;
|
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
|
||||||
use Pterodactyl\Services\Nodes\NodeUpdateService;
|
|
||||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
|
||||||
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
|
|
||||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException;
|
|
||||||
|
|
||||||
class NodeUpdateServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
use PHPMock, MocksRequestException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Mockery\MockInterface
|
|
||||||
*/
|
|
||||||
private $connection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Mockery\MockInterface
|
|
||||||
*/
|
|
||||||
private $configurationRepository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Mockery\MockInterface
|
|
||||||
*/
|
|
||||||
private $encrypter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Mockery\MockInterface
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->connection = m::mock(ConnectionInterface::class);
|
|
||||||
$this->encrypter = m::mock(Encrypter::class);
|
|
||||||
$this->configurationRepository = m::mock(DaemonConfigurationRepository::class);
|
|
||||||
$this->repository = m::mock(NodeRepository::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the daemon secret is reset when `reset_secret` is passed in the data.
|
|
||||||
*/
|
|
||||||
public function testNodeIsUpdatedAndDaemonSecretIsReset()
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Node $model */
|
|
||||||
$model = factory(Node::class)->make([
|
|
||||||
'fqdn' => 'https://example.com',
|
|
||||||
]);
|
|
||||||
|
|
||||||
/** @var \Pterodactyl\Models\Node $updatedModel */
|
|
||||||
$updatedModel = factory(Node::class)->make([
|
|
||||||
'name' => 'New Name',
|
|
||||||
'fqdn' => 'https://example2.com',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) use ($updatedModel) {
|
|
||||||
$response = $closure();
|
|
||||||
|
|
||||||
$this->assertIsArray($response);
|
|
||||||
$this->assertTrue(count($response) === 2);
|
|
||||||
$this->assertSame($updatedModel, $response[0]);
|
|
||||||
$this->assertFalse($response[1]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}))->andReturns([$updatedModel, false]);
|
|
||||||
|
|
||||||
$this->encrypter->expects('encrypt')->with(m::on(function ($value) {
|
|
||||||
return strlen($value) === Node::DAEMON_TOKEN_LENGTH;
|
|
||||||
}))->andReturns('encrypted_value');
|
|
||||||
|
|
||||||
$this->repository->expects('withFreshModel->update')->with($model->id, m::on(function ($value) {
|
|
||||||
$this->assertTrue(is_array($value));
|
|
||||||
$this->assertSame('New Name', $value['name']);
|
|
||||||
$this->assertSame('encrypted_value', $value['daemon_token']);
|
|
||||||
$this->assertTrue(strlen($value['daemon_token_id']) === Node::DAEMON_TOKEN_ID_LENGTH);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}), true, true)->andReturns($updatedModel);
|
|
||||||
|
|
||||||
$this->configurationRepository->expects('setNode')->with(m::on(function ($value) use ($model, $updatedModel) {
|
|
||||||
$this->assertInstanceOf(Node::class, $value);
|
|
||||||
$this->assertSame($model->uuid, $value->uuid);
|
|
||||||
|
|
||||||
// Yes, this is correct. Always use the updated model's FQDN when making requests to
|
|
||||||
// the Daemon so that any changes to that are properly propagated down to the daemon.
|
|
||||||
//
|
|
||||||
// @see https://github.com/pterodactyl/panel/issues/1931
|
|
||||||
$this->assertSame($updatedModel->fqdn, $value->fqdn);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}))->andReturnSelf();
|
|
||||||
|
|
||||||
$this->configurationRepository->expects('update')->with($updatedModel);
|
|
||||||
|
|
||||||
$this->getService()->handle($model, [
|
|
||||||
'name' => $updatedModel->name,
|
|
||||||
], true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that daemon secret is not modified when no variable is passed in data.
|
|
||||||
*/
|
|
||||||
public function testNodeIsUpdatedAndDaemonSecretIsNotChanged()
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Node $model */
|
|
||||||
$model = factory(Node::class)->make(['fqdn' => 'https://example.com']);
|
|
||||||
|
|
||||||
/** @var \Pterodactyl\Models\Node $updatedModel */
|
|
||||||
$updatedModel = factory(Node::class)->make(['name' => 'New Name', 'fqdn' => $model->fqdn]);
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) use ($updatedModel) {
|
|
||||||
$response = $closure();
|
|
||||||
|
|
||||||
$this->assertIsArray($response);
|
|
||||||
$this->assertTrue(count($response) === 2);
|
|
||||||
$this->assertSame($updatedModel, $response[0]);
|
|
||||||
$this->assertFalse($response[1]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}))->andReturns([$updatedModel, false]);
|
|
||||||
|
|
||||||
$this->repository->expects('withFreshModel->update')->with($model->id, m::on(function ($value) {
|
|
||||||
$this->assertTrue(is_array($value));
|
|
||||||
$this->assertSame('New Name', $value['name']);
|
|
||||||
$this->assertArrayNotHasKey('daemon_token', $value);
|
|
||||||
$this->assertArrayNotHasKey('daemon_token_id', $value);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}), true, true)->andReturns($updatedModel);
|
|
||||||
|
|
||||||
$this->configurationRepository->expects('setNode->update')->with($updatedModel);
|
|
||||||
|
|
||||||
$this->getService()->handle($model, ['name' => $updatedModel->name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception caused by a connection error is handled.
|
|
||||||
*/
|
|
||||||
public function testExceptionRelatedToConnection()
|
|
||||||
{
|
|
||||||
$this->configureExceptionMock(DaemonConnectionException::class);
|
|
||||||
$this->expectException(ConfigurationNotPersistedException::class);
|
|
||||||
|
|
||||||
/** @var \Pterodactyl\Models\Node $model */
|
|
||||||
$model = factory(Node::class)->make(['fqdn' => 'https://example.com']);
|
|
||||||
|
|
||||||
/** @var \Pterodactyl\Models\Node $updatedModel */
|
|
||||||
$updatedModel = factory(Node::class)->make(['name' => 'New Name', 'fqdn' => $model->fqdn]);
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) use ($updatedModel) {
|
|
||||||
$response = $closure();
|
|
||||||
|
|
||||||
$this->assertIsArray($response);
|
|
||||||
$this->assertTrue(count($response) === 2);
|
|
||||||
$this->assertSame($updatedModel, $response[0]);
|
|
||||||
$this->assertTrue($response[1]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}))->andReturn([$updatedModel, true]);
|
|
||||||
|
|
||||||
$this->repository->expects('withFreshModel->update')->with($model->id, m::on(function ($value) {
|
|
||||||
$this->assertTrue(is_array($value));
|
|
||||||
$this->assertSame('New Name', $value['name']);
|
|
||||||
$this->assertArrayNotHasKey('daemon_token', $value);
|
|
||||||
$this->assertArrayNotHasKey('daemon_token_id', $value);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}), true, true)->andReturns($updatedModel);
|
|
||||||
|
|
||||||
$this->configurationRepository->expects('setNode->update')->with($updatedModel)->andThrow(
|
|
||||||
new DaemonConnectionException(
|
|
||||||
new ConnectException('', new Request('GET', 'Test'), new Exception)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->getService()->handle($model, ['name' => $updatedModel->name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that an exception not caused by a daemon connection error is handled.
|
|
||||||
*/
|
|
||||||
public function testExceptionNotRelatedToConnection()
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Node $model */
|
|
||||||
$model = factory(Node::class)->make(['fqdn' => 'https://example.com']);
|
|
||||||
|
|
||||||
/** @var \Pterodactyl\Models\Node $updatedModel */
|
|
||||||
$updatedModel = factory(Node::class)->make(['name' => 'New Name', 'fqdn' => $model->fqdn]);
|
|
||||||
|
|
||||||
$this->connection->expects('transaction')->with(m::on(function ($closure) use ($updatedModel) {
|
|
||||||
try {
|
|
||||||
$closure();
|
|
||||||
} catch (Exception $exception) {
|
|
||||||
$this->assertInstanceOf(Exception::class, $exception);
|
|
||||||
$this->assertSame('Foo', $exception->getMessage());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
$this->repository->expects('withFreshModel->update')->andReturns($updatedModel);
|
|
||||||
$this->configurationRepository->expects('setNode->update')->andThrow(
|
|
||||||
new Exception('Foo')
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->getService()->handle($model, ['name' => $updatedModel->name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked injections.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Nodes\NodeUpdateService
|
|
||||||
*/
|
|
||||||
private function getService(): NodeUpdateService
|
|
||||||
{
|
|
||||||
return new NodeUpdateService(
|
|
||||||
$this->connection, $this->encrypter, $this->configurationRepository, $this->repository
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,173 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Servers;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Server;
|
|
||||||
use Pterodactyl\Models\Location;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Pterodactyl\Services\Servers\EnvironmentService;
|
|
||||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
|
||||||
|
|
||||||
class EnvironmentServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
config()->set('pterodactyl.environment_variables', []);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that set environment key stores the key into a retrievable array.
|
|
||||||
*/
|
|
||||||
public function testSettingEnvironmentKeyPersistsItInArray()
|
|
||||||
{
|
|
||||||
$service = $this->getService();
|
|
||||||
|
|
||||||
$service->setEnvironmentKey('TEST_KEY', function () {
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->assertNotEmpty($service->getEnvironmentKeys());
|
|
||||||
$this->assertArrayHasKey('TEST_KEY', $service->getEnvironmentKeys());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that environment defaults are returned by the process function.
|
|
||||||
*/
|
|
||||||
public function testProcessShouldReturnDefaultEnvironmentVariablesForAServer()
|
|
||||||
{
|
|
||||||
$model = $this->getServerModel([
|
|
||||||
'TEST_VARIABLE' => factory(EggVariable::class)->make([
|
|
||||||
'id' => 987,
|
|
||||||
'env_variable' => 'TEST_VARIABLE',
|
|
||||||
'default_value' => 'Test Variable',
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle($model);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertCount(4, $response);
|
|
||||||
$this->assertArrayHasKey('TEST_VARIABLE', $response);
|
|
||||||
$this->assertSame('Test Variable', $response['TEST_VARIABLE']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that variables included at run-time are also included.
|
|
||||||
*/
|
|
||||||
public function testProcessShouldReturnKeySetAtRuntime()
|
|
||||||
{
|
|
||||||
$model = $this->getServerModel([]);
|
|
||||||
$service = $this->getService();
|
|
||||||
$service->setEnvironmentKey('TEST_VARIABLE', function ($server) {
|
|
||||||
return $server->uuidShort;
|
|
||||||
});
|
|
||||||
|
|
||||||
$response = $service->handle($model);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertArrayHasKey('TEST_VARIABLE', $response);
|
|
||||||
$this->assertSame($model->uuidShort, $response['TEST_VARIABLE']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that duplicate variables provided in config override the defaults.
|
|
||||||
*/
|
|
||||||
public function testProcessShouldAllowOverwritingVariablesWithConfigurationFile()
|
|
||||||
{
|
|
||||||
config()->set('pterodactyl.environment_variables', [
|
|
||||||
'P_SERVER_UUID' => 'name',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$model = $this->getServerModel([]);
|
|
||||||
$response = $this->getService()->handle($model);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame(3, count($response));
|
|
||||||
$this->assertArrayHasKey('P_SERVER_UUID', $response);
|
|
||||||
$this->assertSame($model->name, $response['P_SERVER_UUID']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that config based environment variables can be done using closures.
|
|
||||||
*/
|
|
||||||
public function testVariablesSetInConfigurationAllowForClosures()
|
|
||||||
{
|
|
||||||
config()->set('pterodactyl.environment_variables', [
|
|
||||||
'P_SERVER_UUID' => function ($server) {
|
|
||||||
return $server->id * 2;
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
$model = $this->getServerModel([]);
|
|
||||||
$response = $this->getService()->handle($model);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame(3, count($response));
|
|
||||||
$this->assertArrayHasKey('P_SERVER_UUID', $response);
|
|
||||||
$this->assertSame($model->id * 2, $response['P_SERVER_UUID']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that duplicate variables provided at run-time override the defaults and those
|
|
||||||
* that are defined in the configuration file.
|
|
||||||
*/
|
|
||||||
public function testProcessShouldAllowOverwritingDefaultVariablesWithRuntimeProvided()
|
|
||||||
{
|
|
||||||
config()->set('pterodactyl.environment_variables', [
|
|
||||||
'P_SERVER_UUID' => 'overwritten-config',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$model = $this->getServerModel([]);
|
|
||||||
$service = $this->getService();
|
|
||||||
$service->setEnvironmentKey('P_SERVER_UUID', function ($model) {
|
|
||||||
return 'overwritten';
|
|
||||||
});
|
|
||||||
|
|
||||||
$response = $service->handle($model);
|
|
||||||
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertSame(3, count($response));
|
|
||||||
$this->assertArrayHasKey('P_SERVER_UUID', $response);
|
|
||||||
$this->assertSame('overwritten', $response['P_SERVER_UUID']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Servers\EnvironmentService
|
|
||||||
*/
|
|
||||||
private function getService(): EnvironmentService
|
|
||||||
{
|
|
||||||
return new EnvironmentService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a server model with a location relationship to be used in the tests.
|
|
||||||
*
|
|
||||||
* @param array $variables
|
|
||||||
* @return \Pterodactyl\Models\Server
|
|
||||||
*/
|
|
||||||
private function getServerModel(array $variables): Server
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Server $server */
|
|
||||||
$server = factory(Server::class)->make([
|
|
||||||
'id' => 123,
|
|
||||||
'location' => factory(Location::class)->make(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$server->setRelation('variables', Collection::make($variables));
|
|
||||||
|
|
||||||
return $server;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Servers;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Egg;
|
|
||||||
use Pterodactyl\Models\Server;
|
|
||||||
use Pterodactyl\Models\Allocation;
|
|
||||||
use Pterodactyl\Services\Servers\EnvironmentService;
|
|
||||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
|
||||||
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
|
|
||||||
|
|
||||||
class ServerConfigurationStructureServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Services\Servers\EnvironmentService|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $environment;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->environment = m::mock(EnvironmentService::class);
|
|
||||||
$this->repository = m::mock(ServerRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a configuration is returned in the proper format when passed a
|
|
||||||
* server model that is missing required relationships.
|
|
||||||
*/
|
|
||||||
public function testCorrectStructureIsReturned()
|
|
||||||
{
|
|
||||||
/** @var \Pterodactyl\Models\Server $model */
|
|
||||||
$model = factory(Server::class)->make();
|
|
||||||
$model->setRelation('allocation', factory(Allocation::class)->make());
|
|
||||||
$model->setRelation('allocations', collect(factory(Allocation::class)->times(2)->make()));
|
|
||||||
$model->setRelation('egg', factory(Egg::class)->make());
|
|
||||||
|
|
||||||
$this->environment->expects('handle')->with($model)->andReturn(['environment_array']);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle($model);
|
|
||||||
$this->assertNotEmpty($response);
|
|
||||||
$this->assertArrayNotHasKey('user', $response);
|
|
||||||
$this->assertArrayNotHasKey('keys', $response);
|
|
||||||
|
|
||||||
$this->assertArrayHasKey('uuid', $response);
|
|
||||||
$this->assertArrayHasKey('suspended', $response);
|
|
||||||
$this->assertArrayHasKey('environment', $response);
|
|
||||||
$this->assertArrayHasKey('invocation', $response);
|
|
||||||
$this->assertArrayHasKey('skip_egg_scripts', $response);
|
|
||||||
$this->assertArrayHasKey('build', $response);
|
|
||||||
$this->assertArrayHasKey('container', $response);
|
|
||||||
$this->assertArrayHasKey('allocations', $response);
|
|
||||||
|
|
||||||
$this->assertSame([
|
|
||||||
'default' => [
|
|
||||||
'ip' => $model->allocation->ip,
|
|
||||||
'port' => $model->allocation->port,
|
|
||||||
],
|
|
||||||
'mappings' => $model->getAllocationMappings(),
|
|
||||||
], $response['allocations']);
|
|
||||||
|
|
||||||
$this->assertSame([
|
|
||||||
'memory_limit' => $model->memory,
|
|
||||||
'swap' => $model->swap,
|
|
||||||
'io_weight' => $model->io,
|
|
||||||
'cpu_limit' => $model->cpu,
|
|
||||||
'threads' => $model->threads,
|
|
||||||
'disk_space' => $model->disk,
|
|
||||||
], $response['build']);
|
|
||||||
|
|
||||||
$this->assertSame([
|
|
||||||
'image' => $model->image,
|
|
||||||
'oom_disabled' => $model->oom_disabled,
|
|
||||||
'requires_rebuild' => false,
|
|
||||||
], $response['container']);
|
|
||||||
|
|
||||||
$this->assertSame($model->uuid, $response['uuid']);
|
|
||||||
$this->assertSame($model->suspended, $response['suspended']);
|
|
||||||
$this->assertSame(['environment_array'], $response['environment']);
|
|
||||||
$this->assertSame($model->startup, $response['invocation']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Servers\ServerConfigurationStructureService
|
|
||||||
*/
|
|
||||||
private function getService(): ServerConfigurationStructureService
|
|
||||||
{
|
|
||||||
return new ServerConfigurationStructureService($this->environment);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit\Services\Servers;
|
|
||||||
|
|
||||||
use Mockery as m;
|
|
||||||
use Tests\TestCase;
|
|
||||||
use Pterodactyl\Models\Server;
|
|
||||||
use Pterodactyl\Models\Allocation;
|
|
||||||
use Pterodactyl\Models\EggVariable;
|
|
||||||
use Pterodactyl\Services\Servers\StartupCommandService;
|
|
||||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
|
||||||
|
|
||||||
class StartupCommandViewServiceTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock
|
|
||||||
*/
|
|
||||||
private $repository;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup tests.
|
|
||||||
*/
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
$this->repository = m::mock(ServerRepositoryInterface::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that the correct startup string is returned.
|
|
||||||
*/
|
|
||||||
public function testServiceResponse()
|
|
||||||
{
|
|
||||||
|
|
||||||
$server = factory(Server::class)->make([
|
|
||||||
'id' => 123,
|
|
||||||
'startup' => 'example {{SERVER_MEMORY}} {{SERVER_IP}} {{SERVER_PORT}} {{TEST_VARIABLE}} {{TEST_VARIABLE_HIDDEN}} {{UNKNOWN}}',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$variables = collect([
|
|
||||||
factory(EggVariable::class)->make([
|
|
||||||
'env_variable' => 'TEST_VARIABLE',
|
|
||||||
'server_value' => 'Test Value',
|
|
||||||
'user_viewable' => 1,
|
|
||||||
]),
|
|
||||||
factory(EggVariable::class)->make([
|
|
||||||
'env_variable' => 'TEST_VARIABLE_HIDDEN',
|
|
||||||
'server_value' => 'Hidden Value',
|
|
||||||
'user_viewable' => 0,
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$server->setRelation('variables', $variables);
|
|
||||||
$server->setRelation('allocation', $allocation = factory(Allocation::class)->make());
|
|
||||||
|
|
||||||
$response = $this->getService()->handle($server);
|
|
||||||
$this->assertSame(
|
|
||||||
sprintf('example %s %s %s %s %s {{UNKNOWN}}', $server->memory, $allocation->ip, $allocation->port, 'Test Value', '[hidden]'),
|
|
||||||
$response
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an instance of the service with mocked dependencies.
|
|
||||||
*
|
|
||||||
* @return \Pterodactyl\Services\Servers\StartupCommandService
|
|
||||||
*/
|
|
||||||
private function getService(): StartupCommandService
|
|
||||||
{
|
|
||||||
return new StartupCommandService;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue