Merge branch 'release/v0.7.15'
This commit is contained in:
commit
bd5875084b
42 changed files with 307 additions and 193 deletions
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -3,6 +3,35 @@ This file is a running track of new features and fixes to each version of the pa
|
||||||
|
|
||||||
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
|
|
||||||
|
## v0.7.15 (Derelict Dermodactylus)
|
||||||
|
### Fixed
|
||||||
|
* Fixes support for PHP 7.3 when running `composer install` commands due to a dependency that needed updating.
|
||||||
|
* Automatic allocation field when creating a new node (or updating one) should now properly remeber its old
|
||||||
|
value when showing an error state.
|
||||||
|
* Mass deleting files now executes properly and doesn't result in a JS console error.
|
||||||
|
* Scrolling on email settings page now works.
|
||||||
|
* Database host management will now properly display an error message to the user when there is any type of MySQL related
|
||||||
|
error encountered during creation or update.
|
||||||
|
* Two-factor tokens generated when a company name has a space in it will now properly be parsed on iOS authenticator devices.
|
||||||
|
* Fixed 500 error when trying to request subuser's from a server in the application API.
|
||||||
|
* Creating a node allocation via the API no longer requires an alias field be passed through in the request.
|
||||||
|
* Bulk power management for servers via the CLI no longer fails when servers span multiple nodes.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Server listing view now displays the total used disk space for each server.
|
||||||
|
* Client API endpoint to list all servers now supports an additional `?filter=subuser-of|all|admin|owner` parameter to
|
||||||
|
return different groupings of servers. The default value is `subuser-of` which will include all of the user's servers
|
||||||
|
that they are the owner of, as well as all servers they're a subuser of.
|
||||||
|
* Added back ability to toggle OOM killer status on a per-server basis.
|
||||||
|
* Added `LOCK TABLES` permission for generated database users.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Updated Paper egg to not download `server.properties` each time. [parkervcp/eggs#260](https://github.com/parkervcp/eggs/issues/260)
|
||||||
|
* Insurgency egg now uses the proper dedicated server ID.
|
||||||
|
* Teamspeak egg updated with improved installation process and grabbing latest versions.
|
||||||
|
* OOM killer disabled by default on all new servers.
|
||||||
|
* Passwords generated for MySQL now include special characters and are 24 characters in length.
|
||||||
|
|
||||||
## v0.7.14 (Derelict Dermodactylus)
|
## v0.7.14 (Derelict Dermodactylus)
|
||||||
### Fixed
|
### Fixed
|
||||||
* **[SECURITY]** Fixes an XSS vulnerability when performing certain actions in the file manager.
|
* **[SECURITY]** Fixes an XSS vulnerability when performing certain actions in the file manager.
|
||||||
|
|
|
@ -102,7 +102,10 @@ class BulkPowerActionCommand extends Command
|
||||||
$bar->clear();
|
$bar->clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->powerRepository->setServer($server)->sendSignal($action);
|
$this->powerRepository
|
||||||
|
->setNode($server->node)
|
||||||
|
->setServer($server)
|
||||||
|
->sendSignal($action);
|
||||||
} catch (RequestException $exception) {
|
} catch (RequestException $exception) {
|
||||||
$this->output->error(trans('command/messages.server.power.action_failed', [
|
$this->output->error(trans('command/messages.server.power.action_failed', [
|
||||||
'name' => $server->name,
|
'name' => $server->name,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Controllers\Admin;
|
namespace Pterodactyl\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use PDOException;
|
use PDOException;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
use Pterodactyl\Models\DatabaseHost;
|
use Pterodactyl\Models\DatabaseHost;
|
||||||
|
@ -118,17 +119,22 @@ class DatabaseController extends Controller
|
||||||
* @param \Pterodactyl\Http\Requests\Admin\DatabaseHostFormRequest $request
|
* @param \Pterodactyl\Http\Requests\Admin\DatabaseHostFormRequest $request
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function create(DatabaseHostFormRequest $request): RedirectResponse
|
public function create(DatabaseHostFormRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$host = $this->creationService->handle($request->normalize());
|
$host = $this->creationService->handle($request->normalize());
|
||||||
} catch (PDOException $ex) {
|
} catch (Exception $exception) {
|
||||||
$this->alert->danger($ex->getMessage())->flash();
|
if ($exception instanceof PDOException || $exception->getPrevious() instanceof PDOException) {
|
||||||
|
$this->alert->danger(
|
||||||
|
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||||
|
)->flash();
|
||||||
|
|
||||||
return redirect()->route('admin.databases');
|
redirect()->route('admin.databases')->withInput($request->validated());
|
||||||
|
} else {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->alert->success('Successfully created a new database host on the system.')->flash();
|
$this->alert->success('Successfully created a new database host on the system.')->flash();
|
||||||
|
@ -143,8 +149,7 @@ class DatabaseController extends Controller
|
||||||
* @param \Pterodactyl\Models\DatabaseHost $host
|
* @param \Pterodactyl\Models\DatabaseHost $host
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function update(DatabaseHostFormRequest $request, DatabaseHost $host): RedirectResponse
|
public function update(DatabaseHostFormRequest $request, DatabaseHost $host): RedirectResponse
|
||||||
{
|
{
|
||||||
|
@ -153,9 +158,17 @@ class DatabaseController extends Controller
|
||||||
try {
|
try {
|
||||||
$this->updateService->handle($host->id, $request->normalize());
|
$this->updateService->handle($host->id, $request->normalize());
|
||||||
$this->alert->success('Database host was updated successfully.')->flash();
|
$this->alert->success('Database host was updated successfully.')->flash();
|
||||||
} catch (PDOException $ex) {
|
} catch (Exception $exception) {
|
||||||
$this->alert->danger($ex->getMessage())->flash();
|
// Catch any SQL related exceptions and display them back to the user, otherwise just
|
||||||
$redirect->withInput($request->normalize());
|
// throw the exception like normal and move on with it.
|
||||||
|
if ($exception instanceof PDOException || $exception->getPrevious() instanceof PDOException) {
|
||||||
|
$this->alert->danger(
|
||||||
|
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||||
|
)->flash();
|
||||||
|
$redirect->withInput($request->normalize());
|
||||||
|
} else {
|
||||||
|
throw $exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $redirect;
|
return $redirect;
|
||||||
|
|
|
@ -516,7 +516,7 @@ class ServersController extends Controller
|
||||||
$this->buildModificationService->handle($server, $request->only([
|
$this->buildModificationService->handle($server, $request->only([
|
||||||
'allocation_id', 'add_allocations', 'remove_allocations',
|
'allocation_id', 'add_allocations', 'remove_allocations',
|
||||||
'memory', 'swap', 'io', 'cpu', 'disk',
|
'memory', 'swap', 'io', 'cpu', 'disk',
|
||||||
'database_limit', 'allocation_limit',
|
'database_limit', 'allocation_limit', 'oom_disabled',
|
||||||
]));
|
]));
|
||||||
$this->alert->success(trans('admin/server.alerts.build_updated'))->flash();
|
$this->alert->success(trans('admin/server.alerts.build_updated'))->flash();
|
||||||
|
|
||||||
|
@ -589,8 +589,7 @@ class ServersController extends Controller
|
||||||
* @param int $server
|
* @param int $server
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
|
||||||
*/
|
*/
|
||||||
public function resetDatabasePassword(Request $request, $server)
|
public function resetDatabasePassword(Request $request, $server)
|
||||||
{
|
{
|
||||||
|
@ -599,7 +598,7 @@ class ServersController extends Controller
|
||||||
['id', '=', $request->input('database')],
|
['id', '=', $request->input('database')],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->databasePasswordService->handle($database, str_random(24));
|
$this->databasePasswordService->handle($database);
|
||||||
|
|
||||||
return response('', 204);
|
return response('', 204);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,12 +87,11 @@ class DatabaseController extends ApplicationApiController
|
||||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\Databases\ServerDatabaseWriteRequest $request
|
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\Databases\ServerDatabaseWriteRequest $request
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function resetPassword(ServerDatabaseWriteRequest $request): Response
|
public function resetPassword(ServerDatabaseWriteRequest $request): Response
|
||||||
{
|
{
|
||||||
$this->databasePasswordService->handle($request->getModel(Database::class), str_random(24));
|
$this->databasePasswordService->handle($request->getModel(Database::class));
|
||||||
|
|
||||||
return response('', 204);
|
return response('', 204);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,26 @@ class ClientController extends ClientApiController
|
||||||
*/
|
*/
|
||||||
public function index(GetServersRequest $request): array
|
public function index(GetServersRequest $request): array
|
||||||
{
|
{
|
||||||
$servers = $this->repository->filterUserAccessServers($request->user(), User::FILTER_LEVEL_SUBUSER, config('pterodactyl.paginate.frontend.servers'));
|
// Check for the filter parameter on the request.
|
||||||
|
switch ($request->input('filter')) {
|
||||||
|
case 'all':
|
||||||
|
$filter = User::FILTER_LEVEL_ALL;
|
||||||
|
break;
|
||||||
|
case 'admin':
|
||||||
|
$filter = User::FILTER_LEVEL_ADMIN;
|
||||||
|
break;
|
||||||
|
case 'owner':
|
||||||
|
$filter = User::FILTER_LEVEL_OWNER;
|
||||||
|
break;
|
||||||
|
case 'subuser-of':
|
||||||
|
default:
|
||||||
|
$filter = User::FILTER_LEVEL_SUBUSER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$servers = $this->repository->filterUserAccessServers(
|
||||||
|
$request->user(), $filter, config('pterodactyl.paginate.frontend.servers')
|
||||||
|
);
|
||||||
|
|
||||||
return $this->fractal->collection($servers)
|
return $this->fractal->collection($servers)
|
||||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||||
|
|
|
@ -135,15 +135,13 @@ class DatabaseController extends Controller
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*
|
*
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function update(Request $request): JsonResponse
|
public function update(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$this->authorize('reset-db-password', $request->attributes->get('server'));
|
$this->authorize('reset-db-password', $request->attributes->get('server'));
|
||||||
|
|
||||||
$password = str_random(24);
|
$password = $this->passwordService->handle($request->attributes->get('database'));
|
||||||
$this->passwordService->handle($request->attributes->get('database'), $password);
|
|
||||||
|
|
||||||
return response()->json(['password' => $password]);
|
return response()->json(['password' => $password]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class StoreAllocationRequest extends ApplicationApiRequest
|
||||||
return [
|
return [
|
||||||
'allocation_ip' => $data['ip'],
|
'allocation_ip' => $data['ip'],
|
||||||
'allocation_ports' => $data['ports'],
|
'allocation_ports' => $data['ports'],
|
||||||
'allocation_alias' => $data['alias'],
|
'allocation_alias' => $data['alias'] ?? null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ class StoreServerRequest extends ApplicationApiRequest
|
||||||
'startup' => $rules['startup'],
|
'startup' => $rules['startup'],
|
||||||
'environment' => 'present|array',
|
'environment' => 'present|array',
|
||||||
'skip_scripts' => 'sometimes|boolean',
|
'skip_scripts' => 'sometimes|boolean',
|
||||||
|
'oom_disabled' => 'sometimes|boolean',
|
||||||
|
|
||||||
// Resource limitations
|
// Resource limitations
|
||||||
'limits' => 'required|array',
|
'limits' => 'required|array',
|
||||||
|
|
|
@ -18,6 +18,7 @@ class UpdateServerBuildConfigurationRequest extends ServerWriteRequest
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'allocation' => $rules['allocation_id'],
|
'allocation' => $rules['allocation_id'],
|
||||||
|
'oom_disabled' => $rules['oom_disabled'],
|
||||||
|
|
||||||
'limits' => 'sometimes|array',
|
'limits' => 'sometimes|array',
|
||||||
'limits.memory' => $this->requiredToOptional('memory', $rules['memory'], true),
|
'limits.memory' => $this->requiredToOptional('memory', $rules['memory'], true),
|
||||||
|
|
|
@ -28,6 +28,16 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
*/
|
*/
|
||||||
protected $table = 'servers';
|
protected $table = 'servers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default values when creating the model. We want to switch to disabling OOM killer
|
||||||
|
* on server instances unless the user specifies otherwise in the request.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $attributes = [
|
||||||
|
'oom_disabled' => true,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be mutated to dates.
|
* The attributes that should be mutated to dates.
|
||||||
*
|
*
|
||||||
|
@ -53,6 +63,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
'swap' => 'required',
|
'swap' => 'required',
|
||||||
'io' => 'required',
|
'io' => 'required',
|
||||||
'cpu' => 'required',
|
'cpu' => 'required',
|
||||||
|
'oom_disabled' => 'sometimes',
|
||||||
'disk' => 'required',
|
'disk' => 'required',
|
||||||
'nest_id' => 'required',
|
'nest_id' => 'required',
|
||||||
'egg_id' => 'required',
|
'egg_id' => 'required',
|
||||||
|
@ -79,6 +90,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
'swap' => 'numeric|min:-1',
|
'swap' => 'numeric|min:-1',
|
||||||
'io' => 'numeric|between:10,1000',
|
'io' => 'numeric|between:10,1000',
|
||||||
'cpu' => 'numeric|min:0',
|
'cpu' => 'numeric|min:0',
|
||||||
|
'oom_disabled' => 'boolean',
|
||||||
'disk' => 'numeric|min:0',
|
'disk' => 'numeric|min:0',
|
||||||
'allocation_id' => 'bail|unique:servers|exists:allocations,id',
|
'allocation_id' => 'bail|unique:servers|exists:allocations,id',
|
||||||
'nest_id' => 'exists:nests,id',
|
'nest_id' => 'exists:nests,id',
|
||||||
|
@ -107,7 +119,7 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
'disk' => 'integer',
|
'disk' => 'integer',
|
||||||
'io' => 'integer',
|
'io' => 'integer',
|
||||||
'cpu' => 'integer',
|
'cpu' => 'integer',
|
||||||
'oom_disabled' => 'integer',
|
'oom_disabled' => 'boolean',
|
||||||
'allocation_id' => 'integer',
|
'allocation_id' => 'integer',
|
||||||
'nest_id' => 'integer',
|
'nest_id' => 'integer',
|
||||||
'egg_id' => 'integer',
|
'egg_id' => 'integer',
|
||||||
|
@ -156,11 +168,11 @@ class Server extends Model implements CleansAttributes, ValidableContract
|
||||||
/**
|
/**
|
||||||
* Gets the subusers associated with a server.
|
* Gets the subusers associated with a server.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||||
*/
|
*/
|
||||||
public function subusers()
|
public function subusers()
|
||||||
{
|
{
|
||||||
return $this->hasMany(Subuser::class);
|
return $this->hasManyThrough(User::class, Subuser::class, 'server_id', 'id', 'id', 'user_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -153,7 +153,7 @@ class DatabaseRepository extends EloquentRepository implements DatabaseRepositor
|
||||||
public function assignUserToDatabase(string $database, string $username, string $remote): bool
|
public function assignUserToDatabase(string $database, string $username, string $remote): bool
|
||||||
{
|
{
|
||||||
return $this->run(sprintf(
|
return $this->run(sprintf(
|
||||||
'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, EXECUTE ON `%s`.* TO `%s`@`%s`',
|
'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX, LOCK TABLES, EXECUTE ON `%s`.* TO `%s`@`%s`',
|
||||||
$database,
|
$database,
|
||||||
$username,
|
$username,
|
||||||
$remote
|
$remote
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Services\Databases;
|
namespace Pterodactyl\Services\Databases;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Pterodactyl\Models\Database;
|
use Pterodactyl\Models\Database;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
use Illuminate\Database\ConnectionInterface;
|
||||||
use Illuminate\Contracts\Encryption\Encrypter;
|
use Illuminate\Contracts\Encryption\Encrypter;
|
||||||
use Pterodactyl\Extensions\DynamicDatabaseConnection;
|
use Pterodactyl\Extensions\DynamicDatabaseConnection;
|
||||||
|
@ -54,33 +56,39 @@ class DatabasePasswordService
|
||||||
* Updates a password for a given database.
|
* Updates a password for a given database.
|
||||||
*
|
*
|
||||||
* @param \Pterodactyl\Models\Database|int $database
|
* @param \Pterodactyl\Models\Database|int $database
|
||||||
* @param string $password
|
* @return string
|
||||||
* @return bool
|
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function handle($database, string $password): bool
|
public function handle(Database $database): string
|
||||||
{
|
{
|
||||||
if (! $database instanceof Database) {
|
$password = str_random(24);
|
||||||
$database = $this->repository->find($database);
|
// Given a random string of characters, randomly loop through the characters and replace some
|
||||||
|
// with special characters to avoid issues with MySQL password requirements on some servers.
|
||||||
|
try {
|
||||||
|
for ($i = 0; $i < random_int(2, 6); $i++) {
|
||||||
|
$character = ['!', '@', '=', '.', '+', '^'][random_int(0, 5)];
|
||||||
|
|
||||||
|
$password = substr_replace($password, $character, random_int(0, 23), 1);
|
||||||
|
}
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
// Just log the error and hope for the best at this point.
|
||||||
|
Log::error($exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->dynamic->set('dynamic', $database->database_host_id);
|
$this->connection->transaction(function () use ($database, $password) {
|
||||||
$this->connection->beginTransaction();
|
$this->dynamic->set('dynamic', $database->database_host_id);
|
||||||
|
|
||||||
$updated = $this->repository->withoutFreshModel()->update($database->id, [
|
$this->repository->withoutFreshModel()->update($database->id, [
|
||||||
'password' => $this->encrypter->encrypt($password),
|
'password' => $this->encrypter->encrypt($password),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->repository->dropUser($database->username, $database->remote);
|
$this->repository->dropUser($database->username, $database->remote);
|
||||||
$this->repository->createUser($database->username, $database->remote, $password);
|
$this->repository->createUser($database->username, $database->remote, $password);
|
||||||
$this->repository->assignUserToDatabase($database->database, $database->username, $database->remote);
|
$this->repository->assignUserToDatabase($database->database, $database->username, $database->remote);
|
||||||
$this->repository->flush();
|
$this->repository->flush();
|
||||||
|
});
|
||||||
|
|
||||||
unset($password);
|
return $password;
|
||||||
$this->connection->commit();
|
|
||||||
|
|
||||||
return $updated;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,28 +65,26 @@ class HostCreationService
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return \Pterodactyl\Models\DatabaseHost
|
* @return \Pterodactyl\Models\DatabaseHost
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function handle(array $data): DatabaseHost
|
public function handle(array $data): DatabaseHost
|
||||||
{
|
{
|
||||||
$this->connection->beginTransaction();
|
return $this->connection->transaction(function () use ($data) {
|
||||||
|
$host = $this->repository->create([
|
||||||
|
'password' => $this->encrypter->encrypt(array_get($data, 'password')),
|
||||||
|
'name' => array_get($data, 'name'),
|
||||||
|
'host' => array_get($data, 'host'),
|
||||||
|
'port' => array_get($data, 'port'),
|
||||||
|
'username' => array_get($data, 'username'),
|
||||||
|
'max_databases' => null,
|
||||||
|
'node_id' => array_get($data, 'node_id'),
|
||||||
|
]);
|
||||||
|
|
||||||
$host = $this->repository->create([
|
// Confirm access using the provided credentials before saving data.
|
||||||
'password' => $this->encrypter->encrypt(array_get($data, 'password')),
|
$this->dynamic->set('dynamic', $host);
|
||||||
'name' => array_get($data, 'name'),
|
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
||||||
'host' => array_get($data, 'host'),
|
|
||||||
'port' => array_get($data, 'port'),
|
|
||||||
'username' => array_get($data, 'username'),
|
|
||||||
'max_databases' => null,
|
|
||||||
'node_id' => array_get($data, 'node_id'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Confirm access using the provided credentials before saving data.
|
return $host;
|
||||||
$this->dynamic->set('dynamic', $host);
|
});
|
||||||
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
|
||||||
$this->connection->commit();
|
|
||||||
|
|
||||||
return $host;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,10 +71,9 @@ class HostUpdateService
|
||||||
*
|
*
|
||||||
* @param int $hostId
|
* @param int $hostId
|
||||||
* @param array $data
|
* @param array $data
|
||||||
* @return mixed
|
* @return \Pterodactyl\Models\DatabaseHost
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
* @throws \Throwable
|
||||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
|
||||||
*/
|
*/
|
||||||
public function handle(int $hostId, array $data): DatabaseHost
|
public function handle(int $hostId, array $data): DatabaseHost
|
||||||
{
|
{
|
||||||
|
@ -84,13 +83,12 @@ class HostUpdateService
|
||||||
unset($data['password']);
|
unset($data['password']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->connection->beginTransaction();
|
return $this->connection->transaction(function () use ($data, $hostId) {
|
||||||
$host = $this->repository->update($hostId, $data);
|
$host = $this->repository->update($hostId, $data);
|
||||||
|
$this->dynamic->set('dynamic', $host);
|
||||||
|
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
||||||
|
|
||||||
$this->dynamic->set('dynamic', $host);
|
return $host;
|
||||||
$this->databaseManager->connection('dynamic')->select('SELECT 1 FROM dual');
|
});
|
||||||
$this->connection->commit();
|
|
||||||
|
|
||||||
return $host;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ class BuildModificationService
|
||||||
}
|
}
|
||||||
|
|
||||||
$server = $this->repository->withFreshModel()->update($server->id, [
|
$server = $this->repository->withFreshModel()->update($server->id, [
|
||||||
|
'oom_disabled' => array_get($data, 'oom_disabled'),
|
||||||
'memory' => array_get($data, 'memory'),
|
'memory' => array_get($data, 'memory'),
|
||||||
'swap' => array_get($data, 'swap'),
|
'swap' => array_get($data, 'swap'),
|
||||||
'io' => array_get($data, 'io'),
|
'io' => array_get($data, 'io'),
|
||||||
|
@ -97,6 +98,7 @@ class BuildModificationService
|
||||||
|
|
||||||
$allocations = $this->allocationRepository->findWhere([['server_id', '=', $server->id]]);
|
$allocations = $this->allocationRepository->findWhere([['server_id', '=', $server->id]]);
|
||||||
|
|
||||||
|
$build['oom_disabled'] = $server->oom_disabled;
|
||||||
$build['memory'] = (int) $server->memory;
|
$build['memory'] = (int) $server->memory;
|
||||||
$build['swap'] = (int) $server->swap;
|
$build['swap'] = (int) $server->swap;
|
||||||
$build['io'] = (int) $server->io;
|
$build['io'] = (int) $server->io;
|
||||||
|
|
|
@ -70,6 +70,7 @@ class ServerConfigurationStructureService
|
||||||
return $item->pluck('port');
|
return $item->pluck('port');
|
||||||
})->toArray(),
|
})->toArray(),
|
||||||
'env' => $this->environment->handle($server),
|
'env' => $this->environment->handle($server),
|
||||||
|
'oom_disabled' => $server->oom_disabled,
|
||||||
'memory' => (int) $server->memory,
|
'memory' => (int) $server->memory,
|
||||||
'swap' => (int) $server->swap,
|
'swap' => (int) $server->swap,
|
||||||
'io' => (int) $server->io,
|
'io' => (int) $server->io,
|
||||||
|
|
|
@ -227,7 +227,7 @@ class ServerCreationService
|
||||||
'disk' => array_get($data, 'disk'),
|
'disk' => array_get($data, 'disk'),
|
||||||
'io' => array_get($data, 'io'),
|
'io' => array_get($data, 'io'),
|
||||||
'cpu' => array_get($data, 'cpu'),
|
'cpu' => array_get($data, 'cpu'),
|
||||||
'oom_disabled' => false,
|
'oom_disabled' => array_get($data, 'oom_disabled', true),
|
||||||
'allocation_id' => array_get($data, 'allocation_id'),
|
'allocation_id' => array_get($data, 'allocation_id'),
|
||||||
'nest_id' => array_get($data, 'nest_id'),
|
'nest_id' => array_get($data, 'nest_id'),
|
||||||
'egg_id' => array_get($data, 'egg_id'),
|
'egg_id' => array_get($data, 'egg_id'),
|
||||||
|
|
|
@ -71,7 +71,7 @@ class TwoFactorSetupService
|
||||||
'totp_secret' => $this->encrypter->encrypt($secret),
|
'totp_secret' => $this->encrypter->encrypt($secret),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$company = $this->config->get('app.name');
|
$company = preg_replace('/\s/', '', $this->config->get('app.name'));
|
||||||
|
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'otpauth://totp/%1$s:%2$s?secret=%3$s&issuer=%1$s',
|
'otpauth://totp/%1$s:%2$s?secret=%3$s&issuer=%1$s',
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
"barryvdh/laravel-ide-helper": "^2.5",
|
"barryvdh/laravel-ide-helper": "^2.5",
|
||||||
"codedungeon/phpunit-result-printer": "^0.17.1",
|
"codedungeon/phpunit-result-printer": "^0.17.1",
|
||||||
"filp/whoops": "^2.1",
|
"filp/whoops": "^2.1",
|
||||||
"friendsofphp/php-cs-fixer": "^2.11.1",
|
"friendsofphp/php-cs-fixer": "^2.15.1",
|
||||||
"fzaninotto/faker": "^1.6",
|
"fzaninotto/faker": "^1.6",
|
||||||
"mockery/mockery": "^1.0",
|
"mockery/mockery": "^1.0",
|
||||||
"nunomaduro/collision": "^2.0",
|
"nunomaduro/collision": "^2.0",
|
||||||
|
|
59
composer.lock
generated
59
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "8a99f4996405b8080a0dcabb2609c39d",
|
"content-hash": "175a2431d23dd32f79b42bbc8030ace1",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "appstract/laravel-blade-directives",
|
"name": "appstract/laravel-blade-directives",
|
||||||
|
@ -46,9 +46,9 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Gijs Jorissen",
|
"name": "Gijs Jorissen",
|
||||||
|
"role": "Developer",
|
||||||
"email": "hello@appstract.team",
|
"email": "hello@appstract.team",
|
||||||
"homepage": "https://appstract.team",
|
"homepage": "https://appstract.team"
|
||||||
"role": "Developer"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Handy Blade directives",
|
"description": "Handy Blade directives",
|
||||||
|
@ -973,12 +973,12 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/ivanakimov/hashids.php.git",
|
"url": "https://github.com/vinkla/hashids.git",
|
||||||
"reference": "b6c61142bfe36d43740a5419d11c351dddac0458"
|
"reference": "b6c61142bfe36d43740a5419d11c351dddac0458"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/ivanakimov/hashids.php/zipball/b6c61142bfe36d43740a5419d11c351dddac0458",
|
"url": "https://api.github.com/repos/vinkla/hashids/zipball/b6c61142bfe36d43740a5419d11c351dddac0458",
|
||||||
"reference": "b6c61142bfe36d43740a5419d11c351dddac0458",
|
"reference": "b6c61142bfe36d43740a5419d11c351dddac0458",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
|
@ -2149,8 +2149,8 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Antonio Carlos Ribeiro",
|
"name": "Antonio Carlos Ribeiro",
|
||||||
"email": "acr@antoniocarlosribeiro.com",
|
"role": "Creator & Designer",
|
||||||
"role": "Creator & Designer"
|
"email": "acr@antoniocarlosribeiro.com"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A One Time Password Authentication package, compatible with Google Authenticator.",
|
"description": "A One Time Password Authentication package, compatible with Google Authenticator.",
|
||||||
|
@ -2259,9 +2259,9 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Dries Vints",
|
"name": "Dries Vints",
|
||||||
|
"role": "Maintainer",
|
||||||
"email": "dries.vints@gmail.com",
|
"email": "dries.vints@gmail.com",
|
||||||
"homepage": "http://driesvints.com",
|
"homepage": "http://driesvints.com"
|
||||||
"role": "Maintainer"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Prologue Alerts is a package that handles global site messages.",
|
"description": "Prologue Alerts is a package that handles global site messages.",
|
||||||
|
@ -2720,9 +2720,9 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Jarek Tkaczyk",
|
"name": "Jarek Tkaczyk",
|
||||||
|
"role": "Developer",
|
||||||
"email": "jarek@softonsofa.com",
|
"email": "jarek@softonsofa.com",
|
||||||
"homepage": "https://softonsofa.com/",
|
"homepage": "https://softonsofa.com/"
|
||||||
"role": "Developer"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Flexible Searchable, Mappable, Metable, Validation and more extensions for Laravel Eloquent ORM.",
|
"description": "Flexible Searchable, Mappable, Metable, Validation and more extensions for Laravel Eloquent ORM.",
|
||||||
|
@ -2822,9 +2822,9 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Jarek Tkaczyk",
|
"name": "Jarek Tkaczyk",
|
||||||
|
"role": "Developer",
|
||||||
"email": "jarek@softonsofa.com",
|
"email": "jarek@softonsofa.com",
|
||||||
"homepage": "http://softonsofa.com/",
|
"homepage": "http://softonsofa.com/"
|
||||||
"role": "Developer"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Laravel Eloquent hooks system.",
|
"description": "Laravel Eloquent hooks system.",
|
||||||
|
@ -4968,16 +4968,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v2.13.1",
|
"version": "v2.15.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||||
"reference": "54814c62d5beef3ba55297b9b3186ed8b8a1b161"
|
"reference": "20064511ab796593a3990669eff5f5b535001f7c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/54814c62d5beef3ba55297b9b3186ed8b8a1b161",
|
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/20064511ab796593a3990669eff5f5b535001f7c",
|
||||||
"reference": "54814c62d5beef3ba55297b9b3186ed8b8a1b161",
|
"reference": "20064511ab796593a3990669eff5f5b535001f7c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -4986,7 +4986,7 @@
|
||||||
"doctrine/annotations": "^1.2",
|
"doctrine/annotations": "^1.2",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-tokenizer": "*",
|
"ext-tokenizer": "*",
|
||||||
"php": "^5.6 || >=7.0 <7.3",
|
"php": "^5.6 || ^7.0",
|
||||||
"php-cs-fixer/diff": "^1.3",
|
"php-cs-fixer/diff": "^1.3",
|
||||||
"symfony/console": "^3.4.17 || ^4.1.6",
|
"symfony/console": "^3.4.17 || ^4.1.6",
|
||||||
"symfony/event-dispatcher": "^3.0 || ^4.0",
|
"symfony/event-dispatcher": "^3.0 || ^4.0",
|
||||||
|
@ -4998,21 +4998,18 @@
|
||||||
"symfony/process": "^3.0 || ^4.0",
|
"symfony/process": "^3.0 || ^4.0",
|
||||||
"symfony/stopwatch": "^3.0 || ^4.0"
|
"symfony/stopwatch": "^3.0 || ^4.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
|
||||||
"hhvm": "*"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0",
|
"johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0",
|
||||||
"justinrainbow/json-schema": "^5.0",
|
"justinrainbow/json-schema": "^5.0",
|
||||||
"keradus/cli-executor": "^1.1",
|
"keradus/cli-executor": "^1.2",
|
||||||
"mikey179/vfsstream": "^1.6",
|
"mikey179/vfsstream": "^1.6",
|
||||||
"php-coveralls/php-coveralls": "^2.1",
|
"php-coveralls/php-coveralls": "^2.1",
|
||||||
"php-cs-fixer/accessible-object": "^1.0",
|
"php-cs-fixer/accessible-object": "^1.0",
|
||||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.0.1",
|
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1",
|
||||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.0.1",
|
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1",
|
||||||
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1",
|
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1",
|
||||||
"phpunitgoodpractices/traits": "^1.5.1",
|
"phpunitgoodpractices/traits": "^1.8",
|
||||||
"symfony/phpunit-bridge": "^4.0"
|
"symfony/phpunit-bridge": "^4.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-mbstring": "For handling non-UTF8 characters in cache signature.",
|
"ext-mbstring": "For handling non-UTF8 characters in cache signature.",
|
||||||
|
@ -5055,7 +5052,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A tool to automatically fix PHP code style",
|
"description": "A tool to automatically fix PHP code style",
|
||||||
"time": "2018-10-21T00:32:10+00:00"
|
"time": "2019-06-01T10:32:12+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fzaninotto/faker",
|
"name": "fzaninotto/faker",
|
||||||
|
@ -6102,8 +6099,8 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Sebastian Bergmann",
|
"name": "Sebastian Bergmann",
|
||||||
"email": "sebastian@phpunit.de",
|
"role": "lead",
|
||||||
"role": "lead"
|
"email": "sebastian@phpunit.de"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
|
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
|
||||||
|
@ -6375,8 +6372,8 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Sebastian Bergmann",
|
"name": "Sebastian Bergmann",
|
||||||
"email": "sebastian@phpunit.de",
|
"role": "lead",
|
||||||
"role": "lead"
|
"email": "sebastian@phpunit.de"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "The PHP Unit Testing framework.",
|
"description": "The PHP Unit Testing framework.",
|
||||||
|
|
|
@ -9,7 +9,7 @@ return [
|
||||||
| change this value if you are not maintaining your own internal versions.
|
| change this value if you are not maintaining your own internal versions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'version' => '0.7.14',
|
'version' => '0.7.15',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
"meta": {
|
"meta": {
|
||||||
"version": "PTDL_v1"
|
"version": "PTDL_v1"
|
||||||
},
|
},
|
||||||
"exported_at": "2019-02-27T22:23:55-05:00",
|
"exported_at": "2019-08-01T04:49:37-04:00",
|
||||||
"name": "Paper",
|
"name": "Paper",
|
||||||
"author": "parker@pterodactyl.io",
|
"author": "parker@pterodactyl.io",
|
||||||
"description": "High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies.",
|
"description": "High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies.",
|
||||||
"image": "quay.io\/pterodactyl\/core:java",
|
"image": "quay.io\/pterodactyl\/core:java",
|
||||||
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
|
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}",
|
||||||
"config": {
|
"config": {
|
||||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||||
"startup": "{\r\n \"done\": \")! For help, type \",\r\n \"userInteraction\": [\r\n \"Go to eula.txt for more info.\"\r\n ]\r\n}",
|
"startup": "{\r\n \"done\": \")! For help, type \",\r\n \"userInteraction\": [\r\n \"Go to eula.txt for more info.\"\r\n ]\r\n}",
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"installation": {
|
"installation": {
|
||||||
"script": "#!\/bin\/ash\r\n# Paper Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk add --no-cache --update curl jq\r\n\r\nif [ -n \"${DL_PATH}\" ]; then\r\n echo -e \"using supplied download url\"\r\n DOWNLOAD_URL=`eval echo $(echo ${DL_PATH} | sed -e 's\/{{\/${\/g' -e 's\/}}\/}\/g')`\r\nelse\r\n VER_EXISTS=`curl -s https:\/\/papermc.io\/api\/v1\/paper | jq -r --arg VERSION $MINECRAFT_VERSION '.versions[] | IN($VERSION)' | grep true`\r\n LATEST_PAPER_VERSION=`curl -s https:\/\/papermc.io\/api\/v1\/paper | jq -r '.versions' | jq -r '.[0]'`\r\n \r\n if [ \"${VER_EXISTS}\" == \"true\" ]; then\r\n echo -e \"Version is valid. Using version ${MINECRAFT_VERSION}\"\r\n else\r\n echo -e \"Using the latest paper version\"\r\n MINECRAFT_VERSION=${LATEST_PAPER_VERSION}\r\n fi\r\n \r\n BUILD_EXISTS=`curl -s https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION} | jq -r --arg BUILD ${BUILD_NUMBER} '.builds.all[] | IN($BUILD)' | grep true`\r\n LATEST_PAPER_BUILD=`curl -s https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION} | jq -r '.builds.latest'`\r\n \r\n if [ \"${BUILD_EXISTS}\" == \"true\" ] || [ ${BUILD_NUMBER} == \"latest\" ]; then\r\n echo -e \"Build is valid. Using version ${BUILD_NUMBER}\"\r\n else\r\n echo -e \"Using the latest paper build\"\r\n BUILD_NUMBER=${LATEST_PAPER_BUILD}\r\n fi\r\n \r\n echo \"Version being downloaded\"\r\n echo -e \"MC Version: ${MINECRAFT_VERSION}\"\r\n echo -e \"Build: ${BUILD_NUMBER}\"\r\n DOWNLOAD_URL=https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION}\/${BUILD_NUMBER}\/download \r\nfi\r\n\r\ncd \/mnt\/server\r\n\r\necho -e \"running curl -o ${SERVER_JARFILE} ${DOWNLOAD_URL}\"\r\n\r\ncurl -o ${SERVER_JARFILE} ${DOWNLOAD_URL}\r\n\r\necho -e \"Downloading MC server.properties\"\r\ncurl -o server.properties https:\/\/raw.githubusercontent.com\/parkervcp\/eggs\/master\/minecraft_java\/server.properties",
|
"script": "#!\/bin\/ash\r\n# Paper Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk add --no-cache --update curl jq\r\n\r\nif [ -n \"${DL_PATH}\" ]; then\r\n echo -e \"using supplied download url\"\r\n DOWNLOAD_URL=`eval echo $(echo ${DL_PATH} | sed -e 's\/{{\/${\/g' -e 's\/}}\/}\/g')`\r\nelse\r\n VER_EXISTS=`curl -s https:\/\/papermc.io\/api\/v1\/paper | jq -r --arg VERSION $MINECRAFT_VERSION '.versions[] | IN($VERSION)' | grep true`\r\n LATEST_PAPER_VERSION=`curl -s https:\/\/papermc.io\/api\/v1\/paper | jq -r '.versions' | jq -r '.[0]'`\r\n \r\n if [ \"${VER_EXISTS}\" == \"true\" ]; then\r\n echo -e \"Version is valid. Using version ${MINECRAFT_VERSION}\"\r\n else\r\n echo -e \"Using the latest paper version\"\r\n MINECRAFT_VERSION=${LATEST_PAPER_VERSION}\r\n fi\r\n \r\n BUILD_EXISTS=`curl -s https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION} | jq -r --arg BUILD ${BUILD_NUMBER} '.builds.all[] | IN($BUILD)' | grep true`\r\n LATEST_PAPER_BUILD=`curl -s https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION} | jq -r '.builds.latest'`\r\n \r\n if [ \"${BUILD_EXISTS}\" == \"true\" ] || [ ${BUILD_NUMBER} == \"latest\" ]; then\r\n echo -e \"Build is valid. Using version ${BUILD_NUMBER}\"\r\n else\r\n echo -e \"Using the latest paper build\"\r\n BUILD_NUMBER=${LATEST_PAPER_BUILD}\r\n fi\r\n \r\n echo \"Version being downloaded\"\r\n echo -e \"MC Version: ${MINECRAFT_VERSION}\"\r\n echo -e \"Build: ${BUILD_NUMBER}\"\r\n DOWNLOAD_URL=https:\/\/papermc.io\/api\/v1\/paper\/${MINECRAFT_VERSION}\/${BUILD_NUMBER}\/download \r\nfi\r\n\r\ncd \/mnt\/server\r\n\r\necho -e \"running curl -o ${SERVER_JARFILE} ${DOWNLOAD_URL}\"\r\n\r\nif [ -f ${SERVER_JARFILE} ]; then\r\n mv ${SERVER_JARFILE} ${SERVER_JARFILE}.old\r\nfi\r\n\r\ncurl -o ${SERVER_JARFILE} ${DOWNLOAD_URL}\r\n\r\nif [ ! -f server.properties ]; then\r\n echo -e \"Downloading MC server.properties\"\r\n curl -o server.properties https:\/\/raw.githubusercontent.com\/parkervcp\/eggs\/master\/minecraft_java\/server.properties\r\nfi",
|
||||||
"container": "alpine:3.9",
|
"container": "alpine:3.9",
|
||||||
"entrypoint": "ash"
|
"entrypoint": "ash"
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
"author": "support@pterodactyl.io",
|
"author": "support@pterodactyl.io",
|
||||||
"description": "Garrys Mod, is a sandbox physics game created by Garry Newman, and developed by his company, Facepunch Studios.",
|
"description": "Garrys Mod, is a sandbox physics game created by Garry Newman, and developed by his company, Facepunch Studios.",
|
||||||
"image": "quay.io\/pterodactyl\/core:source",
|
"image": "quay.io\/pterodactyl\/core:source",
|
||||||
"startup": ".\/srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +host_workshop_collection {{WORKSHOP_ID}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}}",
|
"startup": ".\/srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +host_workshop_collection {{WORKSHOP_ID}} +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}}",
|
||||||
"config": {
|
"config": {
|
||||||
"files": "{}",
|
"files": "{}",
|
||||||
"startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}",
|
"startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}",
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
"name": "Game ID",
|
"name": "Game ID",
|
||||||
"description": "The ID corresponding to the game to download and run using SRCDS.",
|
"description": "The ID corresponding to the game to download and run using SRCDS.",
|
||||||
"env_variable": "SRCDS_APPID",
|
"env_variable": "SRCDS_APPID",
|
||||||
"default_value": "17705",
|
"default_value": "237410",
|
||||||
"user_viewable": 1,
|
"user_viewable": 1,
|
||||||
"user_editable": 0,
|
"user_editable": 0,
|
||||||
"rules": "required|regex:\/^(17705)$\/"
|
"rules": "required|regex:\/^(237410)$\/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Game Name",
|
"name": "Game Name",
|
||||||
|
@ -51,4 +51,4 @@
|
||||||
"rules": "required|regex:\/^(\\w{1,20})$\/"
|
"rules": "required|regex:\/^(\\w{1,20})$\/"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,21 @@
|
||||||
"meta": {
|
"meta": {
|
||||||
"version": "PTDL_v1"
|
"version": "PTDL_v1"
|
||||||
},
|
},
|
||||||
"exported_at": "2019-05-01T16:35:15+00:00",
|
"exported_at": "2019-07-05T11:59:29-04:00",
|
||||||
"name": "Teamspeak3 Server",
|
"name": "Teamspeak3 Server",
|
||||||
"author": "support@pterodactyl.io",
|
"author": "support@pterodactyl.io",
|
||||||
"description": "VoIP software designed with security in mind, featuring crystal clear voice quality, endless customization options, and scalabilty up to thousands of simultaneous users.",
|
"description": "VoIP software designed with security in mind, featuring crystal clear voice quality, endless customization options, and scalabilty up to thousands of simultaneous users.",
|
||||||
"image": "quay.io\/pterodactyl\/core:glibc",
|
"image": "quay.io/parkervcp/pterodactyl-images:base_debian",
|
||||||
"startup": ".\/ts3server_minimal_runscript.sh default_voice_port={{SERVER_PORT}} query_port={{SERVER_PORT}} license_accepted=1",
|
"startup": "./ts3server default_voice_port={{SERVER_PORT}} query_port={{SERVER_PORT}} filetransfer_ip=0.0.0.0 filetransfer_port={{FILE_TRANSFER}} license_accepted=1",
|
||||||
"config": {
|
"config": {
|
||||||
"files": "{}",
|
"files": "{}",
|
||||||
"startup": "{\"done\": \"listening on 0.0.0.0:\", \"userInteraction\": []}",
|
"startup": "{\r\n \"done\": \"listening on 0.0.0.0:\",\r\n \"userInteraction\": []\r\n}",
|
||||||
"logs": "{\"custom\": true, \"location\": \"logs\/ts3.log\"}",
|
"logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs/ts3.log\"\r\n}",
|
||||||
"stop": "^C"
|
"stop": "^C"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"installation": {
|
"installation": {
|
||||||
"script": "#!\/bin\/ash\n# TS3 Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add tar curl\n\ncd \/mnt\/server\n\ncurl http:\/\/dl.4players.de\/ts\/releases\/${TS_VERSION}\/teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2 | tar xj --strip-components=1",
|
"script": "#!/bin/ash\r\n# TS3 Installation Script\r\n#\r\n# Server Files: /mnt/server\r\napk add --no-cache tar curl jq\r\n\r\nif [ -z ${TS_VERSION} ] || [ ${TS_VERSION} == latest ]; then\r\n TS_VERSION=$(wget https://teamspeak.com/versions/server.json -qO - | jq -r '.linux.x86_64.version')\r\nfi\r\n\r\ncd /mnt/server\r\n\r\n\r\necho -e \"getting files from http://files.teamspeak-services.com/releases/server/${TS_VERSION}/teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2\"\r\ncurl http://files.teamspeak-services.com/releases/server/${TS_VERSION}/teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2 | tar xj --strip-components=1",
|
||||||
"container": "alpine:3.9",
|
"container": "alpine:3.9",
|
||||||
"entrypoint": "ash"
|
"entrypoint": "ash"
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,19 @@
|
||||||
"name": "Server Version",
|
"name": "Server Version",
|
||||||
"description": "The version of Teamspeak 3 to use when running the server.",
|
"description": "The version of Teamspeak 3 to use when running the server.",
|
||||||
"env_variable": "TS_VERSION",
|
"env_variable": "TS_VERSION",
|
||||||
"default_value": "3.7.1",
|
"default_value": "latest",
|
||||||
"user_viewable": 1,
|
"user_viewable": 1,
|
||||||
"user_editable": 1,
|
"user_editable": 1,
|
||||||
"rules": "required|regex:\/^([0-9_\\.-]{5,10})$\/"
|
"rules": "required|string|max:6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "File Transfer Port",
|
||||||
|
"description": "The Teamspeak file transfer port",
|
||||||
|
"env_variable": "FILE_TRANSFER",
|
||||||
|
"default_value": "30033",
|
||||||
|
"user_viewable": 1,
|
||||||
|
"user_editable": 0,
|
||||||
|
"rules": "required|integer|between:1,65535"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,11 +101,13 @@
|
||||||
currentCpu = parseFloat(((info.proc.cpu.total / cpuMax) * 100).toFixed(2).toString());
|
currentCpu = parseFloat(((info.proc.cpu.total / cpuMax) * 100).toFixed(2).toString());
|
||||||
}
|
}
|
||||||
element.find('[data-action="memory"]').html(parseInt(info.proc.memory.total / (1024 * 1024)));
|
element.find('[data-action="memory"]').html(parseInt(info.proc.memory.total / (1024 * 1024)));
|
||||||
|
element.find('[data-action="disk"]').html(parseInt(info.proc.disk.used));
|
||||||
element.find('[data-action="cpu"]').html(currentCpu);
|
element.find('[data-action="cpu"]').html(currentCpu);
|
||||||
} else {
|
} else {
|
||||||
element.find('[data-action="memory"]').html('--');
|
element.find('[data-action="memory"]').html('--');
|
||||||
|
element.find('[data-action="disk"]').html('--');
|
||||||
element.find('[data-action="cpu"]').html('--');
|
element.find('[data-action="cpu"]').html('--');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
})();
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -397,8 +397,10 @@ class ActionsClass {
|
||||||
{
|
{
|
||||||
let formattedItems = "";
|
let formattedItems = "";
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
let self = this;
|
||||||
|
|
||||||
$.each(selectedItems, function(key, value) {
|
$.each(selectedItems, function(key, value) {
|
||||||
formattedItems += ("<code>" + this.sanitizedString(value) + "</code>, ");
|
formattedItems += ("<code>" + self.sanitizedString(value) + "</code>, ");
|
||||||
i++;
|
i++;
|
||||||
return i < 5;
|
return i < 5;
|
||||||
});
|
});
|
||||||
|
@ -411,7 +413,7 @@ class ActionsClass {
|
||||||
swal({
|
swal({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
title: '',
|
title: '',
|
||||||
text: 'Are you sure you want to delete the following files: ' + this.sanitizedString(formattedItems) + '?',
|
text: 'Are you sure you want to delete the following files: ' + formattedItems + '?',
|
||||||
html: true,
|
html: true,
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
showConfirmButton: true,
|
showConfirmButton: true,
|
||||||
|
|
|
@ -74,9 +74,11 @@
|
||||||
}
|
}
|
||||||
element.find('[data-action="memory"]').html(parseInt(data.proc.memory.total / (1024 * 1024)));
|
element.find('[data-action="memory"]').html(parseInt(data.proc.memory.total / (1024 * 1024)));
|
||||||
element.find('[data-action="cpu"]').html(currentCpu);
|
element.find('[data-action="cpu"]').html(currentCpu);
|
||||||
|
element.find('[data-action="disk"]').html(parseInt(data.proc.disk.used));
|
||||||
} else {
|
} else {
|
||||||
element.find('[data-action="memory"]').html('--');
|
element.find('[data-action="memory"]').html('--');
|
||||||
element.find('[data-action="cpu"]').html('--');
|
element.find('[data-action="cpu"]').html('--');
|
||||||
|
element.find('[data-action="disk"]').html('--');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).fail(function (jqXHR) {
|
}).fail(function (jqXHR) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ return [
|
||||||
'connection' => 'Connection',
|
'connection' => 'Connection',
|
||||||
'memory' => 'Memory',
|
'memory' => 'Memory',
|
||||||
'cpu' => 'CPU',
|
'cpu' => 'CPU',
|
||||||
|
'disk' => 'Disk',
|
||||||
'status' => 'Status',
|
'status' => 'Status',
|
||||||
'search' => 'Search',
|
'search' => 'Search',
|
||||||
'suspended' => 'Suspended',
|
'suspended' => 'Suspended',
|
||||||
|
|
|
@ -57,10 +57,10 @@
|
||||||
<td><a href="{{ route('admin.servers.view', $server->id) }}">{{ $server->name }}</a></td>
|
<td><a href="{{ route('admin.servers.view', $server->id) }}">{{ $server->name }}</a></td>
|
||||||
<td><a href="{{ route('admin.users.view', $server->owner_id) }}">{{ $server->user->username }}</a></td>
|
<td><a href="{{ route('admin.users.view', $server->owner_id) }}">{{ $server->user->username }}</a></td>
|
||||||
<td>{{ $server->nest->name }} ({{ $server->egg->name }})</td>
|
<td>{{ $server->nest->name }} ({{ $server->egg->name }})</td>
|
||||||
<td class="text-center"><span data-action="memory">NaN</span> / {{ $server->memory === 0 ? '∞' : $server->memory }} MB</td>
|
<td class="text-center"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '∞' : $server->memory }} MB</td>
|
||||||
<td class="text-center">{{ $server->disk }} MB</td>
|
<td class="text-center"><span data-action="disk">--</span> / {{ $server->disk === 0 ? '∞' : $server->disk }} MB </td>
|
||||||
<td class="text-center"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">NaN</span> %</td>
|
<td class="text-center"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">--</span> %</td>
|
||||||
<td class="text-center" data-action="status">NaN</td>
|
<td class="text-center" data-action="status">--</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</table>
|
</table>
|
||||||
|
@ -78,4 +78,4 @@
|
||||||
@section('footer-scripts')
|
@section('footer-scripts')
|
||||||
@parent
|
@parent
|
||||||
{!! Theme::js('js/admin/node/view-servers.js') !!}
|
{!! Theme::js('js/admin/node/view-servers.js') !!}
|
||||||
@endsection
|
@endsection
|
|
@ -67,8 +67,8 @@
|
||||||
<div class="form-group col-xs-12">
|
<div class="form-group col-xs-12">
|
||||||
<label for="public" class="control-label">Allow Automatic Allocation <sup><a data-toggle="tooltip" data-placement="top" title="Allow automatic allocation to this Node?">?</a></sup></label>
|
<label for="public" class="control-label">Allow Automatic Allocation <sup><a data-toggle="tooltip" data-placement="top" title="Allow automatic allocation to this Node?">?</a></sup></label>
|
||||||
<div>
|
<div>
|
||||||
<input type="radio" name="public" value="1" {{ (old('public', $node->public) === '1') ? 'checked' : '' }} id="public_1" checked> <label for="public_1" style="padding-left:5px;">Yes</label><br />
|
<input type="radio" name="public" value="1" {{ (old('public', $node->public)) ? 'checked' : '' }} id="public_1" checked> <label for="public_1" style="padding-left:5px;">Yes</label><br />
|
||||||
<input type="radio" name="public" value="0" {{ (old('public', $node->public) === '0') ? 'checked' : '' }} id="public_0"> <label for="public_0" style="padding-left:5px;">No</label>
|
<input type="radio" name="public" value="0" {{ (old('public', $node->public)) ? '' : 'checked' }} id="public_0"> <label for="public_0" style="padding-left:5px;">No</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group col-xs-12">
|
<div class="form-group col-xs-12">
|
||||||
|
|
|
@ -85,6 +85,22 @@
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted small">This server will not be allowed to boot if it is using more than this amount of space. If a server goes over this limit while running it will be safely stopped and locked until enough space is available.</p>
|
<p class="text-muted small">This server will not be allowed to boot if it is using more than this amount of space. If a server goes over this limit while running it will be safely stopped and locked until enough space is available.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="cpu" class="control-label">OOM Killer</label>
|
||||||
|
<div>
|
||||||
|
<div class="radio radio-danger radio-inline">
|
||||||
|
<input type="radio" id="pOomKillerEnabled" value="0" name="oom_disabled" @if(!$server->oom_disabled)checked @endif>
|
||||||
|
<label for="pOomKillerEnabled">Enabled</label>
|
||||||
|
</div>
|
||||||
|
<div class="radio radio-success radio-inline">
|
||||||
|
<input type="radio" id="pOomKillerDisabled" value="1" name="oom_disabled" @if($server->oom_disabled)checked @endif>
|
||||||
|
<label for="pOomKillerDisabled">Disabled</label>
|
||||||
|
</div>
|
||||||
|
<p class="text-muted small">
|
||||||
|
Enabling OOM killer may cause server processes to exit unexpectedly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -111,10 +111,8 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('footer-scripts')
|
@section('footer-scripts')
|
||||||
{!! Theme::js('js/laroute.js?t={cache-version}') !!}
|
@parent
|
||||||
{!! Theme::js('vendor/jquery/jquery.min.js?t={cache-version}') !!}
|
|
||||||
{!! Theme::js('vendor/sweetalert/sweetalert.min.js?t={cache-version}') !!}
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
<th>@lang('strings.connection')</th>
|
<th>@lang('strings.connection')</th>
|
||||||
<th class="text-center hidden-sm hidden-xs">@lang('strings.memory')</th>
|
<th class="text-center hidden-sm hidden-xs">@lang('strings.memory')</th>
|
||||||
<th class="text-center hidden-sm hidden-xs">@lang('strings.cpu')</th>
|
<th class="text-center hidden-sm hidden-xs">@lang('strings.cpu')</th>
|
||||||
|
<th class="text-center hidden-sm hidden-xs">@lang('strings.disk')</th>
|
||||||
<th class="text-center">@lang('strings.relation')</th>
|
<th class="text-center">@lang('strings.relation')</th>
|
||||||
<th class="text-center">@lang('strings.status')</th>
|
<th class="text-center">@lang('strings.status')</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -55,6 +56,7 @@
|
||||||
<td><code>{{ $server->getRelation('allocation')->alias }}:{{ $server->getRelation('allocation')->port }}</code></td>
|
<td><code>{{ $server->getRelation('allocation')->alias }}:{{ $server->getRelation('allocation')->port }}</code></td>
|
||||||
<td class="text-center hidden-sm hidden-xs"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '∞' : $server->memory }} MB</td>
|
<td class="text-center hidden-sm hidden-xs"><span data-action="memory">--</span> / {{ $server->memory === 0 ? '∞' : $server->memory }} MB</td>
|
||||||
<td class="text-center hidden-sm hidden-xs"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">--</span> %</td>
|
<td class="text-center hidden-sm hidden-xs"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">--</span> %</td>
|
||||||
|
<td class="text-center hidden-sm hidden-xs"><span data-action="disk">--</span> / {{ $server->disk === 0 ? '∞' : $server->disk }} MB </td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
@if($server->user->id === Auth::user()->id)
|
@if($server->user->id === Auth::user()->id)
|
||||||
<span class="label bg-purple">@lang('strings.owner')</span>
|
<span class="label bg-purple">@lang('strings.owner')</span>
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
namespace Tests\Unit\Commands\Server;
|
namespace Tests\Unit\Commands\Server;
|
||||||
|
|
||||||
use Mockery as m;
|
use Mockery as m;
|
||||||
|
use Pterodactyl\Models\Node;
|
||||||
|
use GuzzleHttp\Psr7\Response;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use Illuminate\Validation\Factory;
|
use Illuminate\Validation\Factory;
|
||||||
use Tests\Unit\Commands\CommandTestCase;
|
use Tests\Unit\Commands\CommandTestCase;
|
||||||
|
@ -38,8 +40,13 @@ class BulkPowerActionCommandTest extends CommandTestCase
|
||||||
*/
|
*/
|
||||||
public function testSendAction()
|
public function testSendAction()
|
||||||
{
|
{
|
||||||
|
/** @var \Pterodactyl\Models\Server[] $servers */
|
||||||
$servers = factory(Server::class)->times(2)->make();
|
$servers = factory(Server::class)->times(2)->make();
|
||||||
|
|
||||||
|
foreach ($servers as &$server) {
|
||||||
|
$server->setRelation('node', factory(Node::class)->make());
|
||||||
|
}
|
||||||
|
|
||||||
$this->repository->shouldReceive('getServersForPowerActionCount')
|
$this->repository->shouldReceive('getServersForPowerActionCount')
|
||||||
->once()
|
->once()
|
||||||
->with([], [])
|
->with([], [])
|
||||||
|
@ -51,7 +58,7 @@ class BulkPowerActionCommandTest extends CommandTestCase
|
||||||
->andReturn($servers);
|
->andReturn($servers);
|
||||||
|
|
||||||
for ($i = 0; $i < count($servers); $i++) {
|
for ($i = 0; $i < count($servers); $i++) {
|
||||||
$this->powerRepository->shouldReceive('setServer->sendSignal')
|
$this->powerRepository->shouldReceive('setNode->setServer->sendSignal')
|
||||||
->once()
|
->once()
|
||||||
->with('kill')
|
->with('kill')
|
||||||
->andReturnNull();
|
->andReturnNull();
|
||||||
|
@ -70,6 +77,7 @@ class BulkPowerActionCommandTest extends CommandTestCase
|
||||||
public function testSendWithFilters()
|
public function testSendWithFilters()
|
||||||
{
|
{
|
||||||
$server = factory(Server::class)->make();
|
$server = factory(Server::class)->make();
|
||||||
|
$server->setRelation('node', $node = factory(Node::class)->make());
|
||||||
|
|
||||||
$this->repository->shouldReceive('getServersForPowerActionCount')
|
$this->repository->shouldReceive('getServersForPowerActionCount')
|
||||||
->once()
|
->once()
|
||||||
|
@ -81,10 +89,9 @@ class BulkPowerActionCommandTest extends CommandTestCase
|
||||||
->with([1, 2], [3, 4])
|
->with([1, 2], [3, 4])
|
||||||
->andReturn([$server]);
|
->andReturn([$server]);
|
||||||
|
|
||||||
$this->powerRepository->shouldReceive('setServer->sendSignal')
|
$this->powerRepository->expects('setNode')->with($node)->andReturnSelf();
|
||||||
->once()
|
$this->powerRepository->expects('setServer')->with($server)->andReturnSelf();
|
||||||
->with('kill')
|
$this->powerRepository->expects('sendSignal')->with('kill')->andReturn(new Response);
|
||||||
->andReturnNull();
|
|
||||||
|
|
||||||
$display = $this->runCommand($this->getCommand(), [
|
$display = $this->runCommand($this->getCommand(), [
|
||||||
'action' => 'kill',
|
'action' => 'kill',
|
||||||
|
@ -103,6 +110,7 @@ class BulkPowerActionCommandTest extends CommandTestCase
|
||||||
public function testSendWithEmptyOptions()
|
public function testSendWithEmptyOptions()
|
||||||
{
|
{
|
||||||
$server = factory(Server::class)->make();
|
$server = factory(Server::class)->make();
|
||||||
|
$server->setRelation('node', factory(Node::class)->make());
|
||||||
|
|
||||||
$this->repository->shouldReceive('getServersForPowerActionCount')
|
$this->repository->shouldReceive('getServersForPowerActionCount')
|
||||||
->once()
|
->once()
|
||||||
|
@ -110,7 +118,7 @@ class BulkPowerActionCommandTest extends CommandTestCase
|
||||||
->andReturn(1);
|
->andReturn(1);
|
||||||
|
|
||||||
$this->repository->shouldReceive('getServersForPowerAction')->once()->with([], [])->andReturn([$server]);
|
$this->repository->shouldReceive('getServersForPowerAction')->once()->with([], [])->andReturn([$server]);
|
||||||
$this->powerRepository->shouldReceive('setServer->sendSignal')->once()->with('kill')->andReturnNull();
|
$this->powerRepository->shouldReceive('setNode->setServer->sendSignal')->once()->with('kill')->andReturnNull();
|
||||||
|
|
||||||
$display = $this->runCommand($this->getCommand(), [
|
$display = $this->runCommand($this->getCommand(), [
|
||||||
'action' => 'kill',
|
'action' => 'kill',
|
||||||
|
|
|
@ -48,43 +48,35 @@ class DatabasePasswordServiceTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that a password can be updated.
|
* Test that a password can be updated.
|
||||||
*
|
|
||||||
* @dataProvider useModelDataProvider
|
|
||||||
*/
|
*/
|
||||||
public function testPasswordIsChanged(bool $useModel)
|
public function testPasswordIsChanged()
|
||||||
{
|
{
|
||||||
$model = factory(Database::class)->make();
|
$model = factory(Database::class)->make();
|
||||||
|
|
||||||
if (! $useModel) {
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->repository->shouldReceive('find')->with(1234)->once()->andReturn($model);
|
return is_null($closure());
|
||||||
}
|
}));
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model->database_host_id)->once()->andReturnNull();
|
$this->dynamic->shouldReceive('set')->with('dynamic', $model->database_host_id)->once()->andReturnNull();
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
|
||||||
$this->encrypter->shouldReceive('encrypt')->with('test123')->once()->andReturn('enc123');
|
$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->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf();
|
$this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf();
|
||||||
$this->repository->shouldReceive('update')->with($model->id, ['password' => 'enc123'])->once()->andReturn(true);
|
$this->repository->shouldReceive('update')->with($model->id, ['password' => 'enc123'])->once()->andReturn(true);
|
||||||
|
|
||||||
$this->repository->shouldReceive('dropUser')->with($model->username, $model->remote)->once()->andReturn(true);
|
$this->repository->shouldReceive('dropUser')->with($model->username, $model->remote)->once()->andReturn(true);
|
||||||
$this->repository->shouldReceive('createUser')->with($model->username, $model->remote, 'test123')->once()->andReturn(true);
|
$this->repository->shouldReceive('createUser')->with($model->username, $model->remote, m::any())->once()->andReturn(true);
|
||||||
$this->repository->shouldReceive('assignUserToDatabase')->with($model->database, $model->username, $model->remote)->once()->andReturn(true);
|
$this->repository->shouldReceive('assignUserToDatabase')->with($model->database, $model->username, $model->remote)->once()->andReturn(true);
|
||||||
$this->repository->shouldReceive('flush')->withNoArgs()->once()->andReturn(true);
|
$this->repository->shouldReceive('flush')->withNoArgs()->once()->andReturn(true);
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturn(true);
|
|
||||||
|
|
||||||
$response = $this->getService()->handle($useModel ? $model : 1234, 'test123');
|
$response = $this->getService()->handle($model);
|
||||||
$this->assertNotEmpty($response);
|
$this->assertNotEmpty($response);
|
||||||
$this->assertTrue($response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data provider to determine if a model should be passed or an int.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function useModelDataProvider(): array
|
|
||||||
{
|
|
||||||
return [[false], [true]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -60,18 +60,20 @@ class HostCreationServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$model = factory(DatabaseHost::class)->make();
|
$model = factory(DatabaseHost::class)->make();
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->encrypter->shouldReceive('encrypt')->with('test123')->once()->andReturn('enc123');
|
return ! is_null($closure());
|
||||||
$this->repository->shouldReceive('create')->with(m::subset([
|
}))->andReturn($model);
|
||||||
|
|
||||||
|
$this->encrypter->expects('encrypt')->with('test123')->andReturn('enc123');
|
||||||
|
$this->repository->expects('create')->with(m::subset([
|
||||||
'password' => 'enc123',
|
'password' => 'enc123',
|
||||||
'username' => $model->username,
|
'username' => $model->username,
|
||||||
'node_id' => $model->node_id,
|
'node_id' => $model->node_id,
|
||||||
]))->once()->andReturn($model);
|
]))->andReturn($model);
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model)->once()->andReturnNull();
|
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
||||||
$this->databaseManager->shouldReceive('connection')->with('dynamic')->once()->andReturnSelf();
|
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
||||||
$this->databaseManager->shouldReceive('select')->with('SELECT 1 FROM dual')->once()->andReturnNull();
|
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
|
||||||
|
|
||||||
$response = $this->getService()->handle([
|
$response = $this->getService()->handle([
|
||||||
'password' => 'test123',
|
'password' => 'test123',
|
||||||
|
|
|
@ -60,14 +60,15 @@ class HostUpdateServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$model = factory(DatabaseHost::class)->make();
|
$model = factory(DatabaseHost::class)->make();
|
||||||
|
|
||||||
$this->encrypter->shouldReceive('encrypt')->with('test123')->once()->andReturn('enc123');
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
return ! is_null($closure());
|
||||||
$this->repository->shouldReceive('update')->with(1234, ['password' => 'enc123'])->once()->andReturn($model);
|
}))->andReturn($model);
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model)->once()->andReturnNull();
|
$this->encrypter->expects('encrypt')->with('test123')->andReturn('enc123');
|
||||||
$this->databaseManager->shouldReceive('connection')->with('dynamic')->once()->andReturnSelf();
|
$this->repository->expects('update')->with(1234, ['password' => 'enc123'])->andReturn($model);
|
||||||
$this->databaseManager->shouldReceive('select')->with('SELECT 1 FROM dual')->once()->andReturnNull();
|
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->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']);
|
$response = $this->getService()->handle(1234, ['password' => 'test123']);
|
||||||
$this->assertNotEmpty($response);
|
$this->assertNotEmpty($response);
|
||||||
|
@ -81,13 +82,14 @@ class HostUpdateServiceTest extends TestCase
|
||||||
{
|
{
|
||||||
$model = factory(DatabaseHost::class)->make();
|
$model = factory(DatabaseHost::class)->make();
|
||||||
|
|
||||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
$this->connection->expects('transaction')->with(m::on(function ($closure) {
|
||||||
$this->repository->shouldReceive('update')->with(1234, ['username' => 'test'])->once()->andReturn($model);
|
return ! is_null($closure());
|
||||||
|
}))->andReturn($model);
|
||||||
|
|
||||||
$this->dynamic->shouldReceive('set')->with('dynamic', $model)->once()->andReturnNull();
|
$this->repository->expects('update')->with(1234, ['username' => 'test'])->andReturn($model);
|
||||||
$this->databaseManager->shouldReceive('connection')->with('dynamic')->once()->andReturnSelf();
|
$this->dynamic->expects('set')->with('dynamic', $model)->andReturnNull();
|
||||||
$this->databaseManager->shouldReceive('select')->with('SELECT 1 FROM dual')->once()->andReturnNull();
|
$this->databaseManager->expects('connection')->with('dynamic')->andReturnSelf();
|
||||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
$this->databaseManager->expects('select')->with('SELECT 1 FROM dual')->andReturnNull();
|
||||||
|
|
||||||
$response = $this->getService()->handle(1234, ['password' => '', 'username' => 'test']);
|
$response = $this->getService()->handle(1234, ['password' => '', 'username' => 'test']);
|
||||||
$this->assertNotEmpty($response);
|
$this->assertNotEmpty($response);
|
||||||
|
|
|
@ -60,7 +60,7 @@ class TwoFactorSetupServiceTest extends TestCase
|
||||||
$response = $this->getService()->handle($model);
|
$response = $this->getService()->handle($model);
|
||||||
$this->assertNotEmpty($response);
|
$this->assertNotEmpty($response);
|
||||||
|
|
||||||
$companyName = preg_quote(rawurlencode('Company Name'));
|
$companyName = preg_quote(rawurlencode('CompanyName'));
|
||||||
$email = preg_quote(rawurlencode($model->email));
|
$email = preg_quote(rawurlencode($model->email));
|
||||||
|
|
||||||
$this->assertRegExp(
|
$this->assertRegExp(
|
||||||
|
|
Loading…
Reference in a new issue