diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 9b959e58f..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,26 +0,0 @@ - - - -* Panel or Daemon: -* Version of Panel/Daemon: -* Server's OS: -* Your Computer's OS & Browser: - ------------------------- - - diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md new file mode 100644 index 000000000..6d69080b1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -0,0 +1,27 @@ +--- +name: "\U0001F41B Bug Report" +about: Create a report to help us resolve a bug or error + +--- + +**Background (please complete the following information):** +* Panel or Daemon: +* Version of Panel/Daemon: +* Server's OS: +* Your Computer's OS & Browser: + +**Describe the bug** +A clear and concise description of what the bug is. +Please provide additional information too, depending on what you have issues with: +Panel: `php -v` (the php version in use). +Daemon: `uname -a` and `docker info` (your kernel version and information regarding docker) + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. If applicable, add screenshots or a recording to help explain your problem. diff --git a/.github/ISSUE_TEMPLATE/---feature-request.md b/.github/ISSUE_TEMPLATE/---feature-request.md new file mode 100644 index 000000000..64fa679ba --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---feature-request.md @@ -0,0 +1,17 @@ +--- +name: "\U0001F680 Feature Request" +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/--installation-help.md b/.github/ISSUE_TEMPLATE/--installation-help.md new file mode 100644 index 000000000..fa10ca975 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/--installation-help.md @@ -0,0 +1,8 @@ +--- +name: "⛔ Installation Help" +about: 'Visit our Discord for installation help: https://pterodactyl.io/discord' + +--- + +We use GitHub issues only to discuss about Pterodactyl bugs and new features. For +this kind of questions about using Pterodactyl, please visit our Discord for assistance: https://pterodactyl.io/discord diff --git a/.travis.yml b/.travis.yml index 4ed53fd7f..ff915fa1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,17 @@ language: php dist: trusty +git: + depth: 3 + quiet: true +matrix: + fast_finish: true + allow_failures: + - env: TEST_SUITE=Coverage +env: + matrix: + - TEST_SUITE=Unit + - TEST_SUITE=Coverage + - TEST_SUITE=Integration php: - 7.2 sudo: false @@ -15,8 +27,9 @@ before_script: - cp .env.travis .env - travis_retry composer install --no-interaction --prefer-dist --no-suggest script: - - vendor/bin/phpunit --bootstrap vendor/autoload.php --coverage-clover coverage.xml tests/Unit - - vendor/bin/phpunit tests/Integration + - if [ "$TEST_SUITE" = "Unit" ]; then vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit; fi; + - if [ "$TEST_SUITE" = "Coverage" ]; then vendor/bin/phpunit --bootstrap vendor/autoload.php --coverage-clover coverage.xml tests/Unit; fi; + - if [ "$TEST_SUITE" = "Integration" ]; then vendor/bin/phpunit tests/Integration; fi; notifications: email: false webhooks: diff --git a/CHANGELOG.md b/CHANGELOG.md index 27eca5765..979dd26ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,17 +3,39 @@ 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. +## v0.7.10 (Derelict Dermodactylus) +### Fixed +* Scheduled tasks triggered manually no longer improperly change the `next_run_at` time and do not run twice in a row anymore. +* Changing the maximum web-based file upload size for a node now properly validates and updates. +* Changing configuration values for a node now correctly updates them on the daemon on the first request, rather than requiring a second request to set them. + +### Changed +* Egg and server variable values are no longer limited to 191 characters. Turns out some games require a large number of characters in these fields. + +## v0.7.9 (Derelict Dermodactylus) +### Fixed +* Fixes a two-factor authentication bypass present in the password reset process for an account. + ## v0.7.8 (Derelict Dermodactylus) ### Added * Nodes can now be put into maintenance mode to deny access to servers temporarily. * Basic statistics about your panel are now available in the Admin CP. +* Added support for using a MySQL socket location for connections rather than a TCP connection. Set a `DB_SOCKET` variable in your `.env` file to use this. ### Fixed * Hitting Ctrl+Z when editing a file on the web now works as expected. * Logo now links to the correct location on all pages. +* Permissions checking to determine if a user can see the task management page now works correctly. +* Fixed `pterodactyl.environment_variables` to be used correctly for global environment variables. The wrong config variable name was being using previously. +* Fixes tokens being sent to users when their account is created to actually work. Implements Laravel's internal token creation mechanisms rather than trying to do it custom. +* Updates some eggs to ensure they have the correct data and will continue working down the road. Fixes autoupdating on some source servers and MC related download links. +* Emails should send properly now when a server is marked as installed to let the owner know it is ready for action. +* Cancelling a file manager operation should cancel correctly across all browsers now. ### Changed * Attempting to upload a folder via the web file manager will now display a warning telling the user to use SFTP. +* Changing your account password will now log out all other sessions that currently exist for that user. +* Subusers with no permissions selected can be created. ## v0.7.7 (Derelict Dermodactylus) ### Fixed diff --git a/README.md b/README.md index 135f4d4ef..1bc66ca2c 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ [![Logo Image](https://cdn.pterodactyl.io/logos/Banner%20Logo%20Black@2x.png)](https://pterodactyl.io) -[![Build Status](https://travis-ci.org/pterodactyl/panel.svg?branch=develop)](https://travis-ci.org/pterodactyl/panel) [![StyleCI](https://styleci.io/repos/47508644/shield?branch=develop)](https://styleci.io/repos/47508644) [![codecov](https://codecov.io/gh/pterodactyl/panel/branch/develop/graph/badge.svg)](https://codecov.io/gh/Pterodactyl/Panel) +[![Build status](https://img.shields.io/travis/pterodactyl/panel/develop.svg?style=flat-square)](https://travis-ci.org/pterodactyl/panel) +[![StyleCI](https://styleci.io/repos/47508644/shield?branch=develop)](https://styleci.io/repos/47508644) +[![Codecov](https://img.shields.io/codecov/c/github/pterodactyl/panel/develop.svg?style=flat-square)](https://codecov.io/gh/Pterodactyl/Panel) +[![Discord](https://img.shields.io/discord/122900397965705216.svg?style=flat-square&label=Discord)](https://pterodactyl.io/discord) # Pterodactyl Panel + Pterodactyl is the open-source game server management panel built with PHP7, Nodejs, and Go. Designed with security in mind, Pterodactyl runs all game servers in isolated Docker containers while exposing a beautiful and intuitive UI to administrators and users. What more are you waiting for? Make game servers a first class citizen on your platform today. ![Image](https://cdn.pterodactyl.io/site-assets/mockup-macbook-grey.png) ## Support & Documentation -Support for using Pterodactyl can be found on our [Documentation Website](https://docs.pterodactyl.io), [Guides Website](https://guides.pterodactyl.io), or via our [Discord Chat](https://discord.gg/QRDZvVm). +Support for using Pterodactyl can be found on our [Documentation Website](https://pterodactyl.io/project/introduction.html), [Guides Website](https://guides.pterodactyl.io), or via our [Discord Chat](https://discord.gg/QRDZvVm). ### Supported Games We support a huge variety of games by utilizing Docker containers to isolate each instance, giving you the power to host your games across the world without having to bloat each physical machine with additional dependencies. diff --git a/app/Console/Commands/Schedule/ProcessRunnableCommand.php b/app/Console/Commands/Schedule/ProcessRunnableCommand.php index 88646c030..e5a40fb43 100644 --- a/app/Console/Commands/Schedule/ProcessRunnableCommand.php +++ b/app/Console/Commands/Schedule/ProcessRunnableCommand.php @@ -9,7 +9,7 @@ namespace Pterodactyl\Console\Commands\Schedule; -use Carbon\Carbon; +use Cake\Chronos\Chronos; use Illuminate\Console\Command; use Illuminate\Support\Collection; use Pterodactyl\Services\Schedules\ProcessScheduleService; @@ -17,11 +17,6 @@ use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; class ProcessRunnableCommand extends Command { - /** - * @var \Carbon\Carbon - */ - protected $carbon; - /** * @var string */ @@ -45,31 +40,28 @@ class ProcessRunnableCommand extends Command /** * ProcessRunnableCommand constructor. * - * @param \Carbon\Carbon $carbon * @param \Pterodactyl\Services\Schedules\ProcessScheduleService $processScheduleService * @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository */ - public function __construct( - Carbon $carbon, - ProcessScheduleService $processScheduleService, - ScheduleRepositoryInterface $repository - ) { + public function __construct(ProcessScheduleService $processScheduleService, ScheduleRepositoryInterface $repository) + { parent::__construct(); - $this->carbon = $carbon; $this->processScheduleService = $processScheduleService; $this->repository = $repository; } /** * Handle command execution. - * - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ public function handle() { - $schedules = $this->repository->getSchedulesToProcess($this->carbon->now()->toAtomString()); + $schedules = $this->repository->getSchedulesToProcess(Chronos::now()->toAtomString()); + if ($schedules->count() < 1) { + $this->line('There are no scheduled tasks for servers that need to be run.'); + + return; + } $bar = $this->output->createProgressBar(count($schedules)); $schedules->each(function ($schedule) use ($bar) { diff --git a/app/Contracts/Core/ReceivesEvents.php b/app/Contracts/Core/ReceivesEvents.php new file mode 100644 index 000000000..a6c1aa10f --- /dev/null +++ b/app/Contracts/Core/ReceivesEvents.php @@ -0,0 +1,15 @@ +server = $server; + } +} diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 2327fd88d..1ae807565 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -2,16 +2,14 @@ namespace Pterodactyl\Http\Controllers\Admin; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; -use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; -use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; -use Pterodactyl\Contracts\Repository\EggRepositoryInterface; -use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; -use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; -use Pterodactyl\Contracts\Repository\UserRepositoryInterface; use Pterodactyl\Http\Controllers\Controller; +use Pterodactyl\Contracts\Repository\EggRepositoryInterface; use Pterodactyl\Traits\Controllers\PlainJavascriptInjection; +use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; +use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; +use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; +use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; class StatisticsController extends Controller { @@ -29,15 +27,14 @@ class StatisticsController extends Controller private $userRepository; - function __construct( + public function __construct( AllocationRepositoryInterface $allocationRepository, DatabaseRepositoryInterface $databaseRepository, EggRepositoryInterface $eggRepository, NodeRepositoryInterface $nodeRepository, ServerRepositoryInterface $serverRepository, UserRepositoryInterface $userRepository - ) - { + ) { $this->allocationRepository = $allocationRepository; $this->databaseRepository = $databaseRepository; $this->eggRepository = $eggRepository; @@ -83,7 +80,7 @@ class StatisticsController extends Controller 'nodes' => $nodes, 'tokens' => $tokens, ]); - + return view('admin.statistics', [ 'servers' => $servers, 'nodes' => $nodes, @@ -97,5 +94,4 @@ class StatisticsController extends Controller 'totalAllocations' => $totalAllocations, ]); } - } diff --git a/app/Http/Controllers/Api/Application/Nodes/NodeController.php b/app/Http/Controllers/Api/Application/Nodes/NodeController.php index e9f679006..99be100ee 100644 --- a/app/Http/Controllers/Api/Application/Nodes/NodeController.php +++ b/app/Http/Controllers/Api/Application/Nodes/NodeController.php @@ -124,7 +124,7 @@ class NodeController extends ApplicationApiController */ public function update(UpdateNodeRequest $request): array { - $node = $this->updateService->returnUpdatedModel()->handle( + $node = $this->updateService->handle( $request->getModel(Node::class), $request->validated() ); diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 226958416..d1f21994f 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -2,8 +2,14 @@ namespace Pterodactyl\Http\Controllers\Auth; +use Illuminate\Support\Str; +use Prologue\Alerts\AlertsMessageBag; +use Illuminate\Contracts\Hashing\Hasher; +use Illuminate\Auth\Events\PasswordReset; +use Illuminate\Contracts\Events\Dispatcher; use Pterodactyl\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; class ResetPasswordController extends Controller { @@ -16,6 +22,47 @@ class ResetPasswordController extends Controller */ public $redirectTo = '/'; + /** + * @var bool + */ + protected $hasTwoFactor = false; + + /** + * @var \Prologue\Alerts\AlertsMessageBag + */ + private $alerts; + + /** + * @var \Illuminate\Contracts\Events\Dispatcher + */ + private $dispatcher; + + /** + * @var \Illuminate\Contracts\Hashing\Hasher + */ + private $hasher; + + /** + * @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface + */ + private $userRepository; + + /** + * ResetPasswordController constructor. + * + * @param \Prologue\Alerts\AlertsMessageBag $alerts + * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher + * @param \Illuminate\Contracts\Hashing\Hasher $hasher + * @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $userRepository + */ + public function __construct(AlertsMessageBag $alerts, Dispatcher $dispatcher, Hasher $hasher, UserRepositoryInterface $userRepository) + { + $this->alerts = $alerts; + $this->dispatcher = $dispatcher; + $this->hasher = $hasher; + $this->userRepository = $userRepository; + } + /** * Return the rules used when validating password reset. * @@ -29,4 +76,49 @@ class ResetPasswordController extends Controller 'password' => 'required|confirmed|min:8', ]; } + + /** + * Reset the given user's password. If the user has two-factor authentication enabled on their + * account do not automatically log them in. In those cases, send the user back to the login + * form with a note telling them their password was changed and to log back in. + * + * @param \Illuminate\Contracts\Auth\CanResetPassword|\Pterodactyl\Models\User $user + * @param string $password + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + */ + protected function resetPassword($user, $password) + { + $user = $this->userRepository->update($user->id, [ + 'password' => $this->hasher->make($password), + $user->getRememberTokenName() => Str::random(60), + ]); + + $this->dispatcher->dispatch(new PasswordReset($user)); + + // If the user is not using 2FA log them in, otherwise skip this step and force a + // fresh login where they'll be prompted to enter a token. + if (! $user->use_totp) { + $this->guard()->login($user); + } + + $this->hasTwoFactor = $user->use_totp; + } + + /** + * Get the response for a successful password reset. + * + * @param string $response + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + protected function sendResetResponse($response) + { + if ($this->hasTwoFactor) { + $this->alerts->success('Your password was successfully updated. Please log in to continue.')->flash(); + } + + return redirect($this->hasTwoFactor ? route('auth.login') : $this->redirectPath()) + ->with('status', trans($response)); + } } diff --git a/app/Http/Controllers/Base/AccountController.php b/app/Http/Controllers/Base/AccountController.php index c7b74a750..80811750e 100644 --- a/app/Http/Controllers/Base/AccountController.php +++ b/app/Http/Controllers/Base/AccountController.php @@ -3,7 +3,9 @@ namespace Pterodactyl\Http\Controllers\Base; use Pterodactyl\Models\User; +use Illuminate\Auth\AuthManager; use Prologue\Alerts\AlertsMessageBag; +use Illuminate\Contracts\Session\Session; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Services\Users\UserUpdateService; use Pterodactyl\Traits\Helpers\AvailableLanguages; @@ -18,6 +20,11 @@ class AccountController extends Controller */ protected $alert; + /** + * @var \Illuminate\Auth\SessionGuard + */ + protected $sessionGuard; + /** * @var \Pterodactyl\Services\Users\UserUpdateService */ @@ -27,12 +34,14 @@ class AccountController extends Controller * AccountController constructor. * * @param \Prologue\Alerts\AlertsMessageBag $alert + * @param \Illuminate\Auth\AuthManager $authManager * @param \Pterodactyl\Services\Users\UserUpdateService $updateService */ - public function __construct(AlertsMessageBag $alert, UserUpdateService $updateService) + public function __construct(AlertsMessageBag $alert, AuthManager $authManager, UserUpdateService $updateService) { $this->alert = $alert; $this->updateService = $updateService; + $this->sessionGuard = $authManager->guard(); } /** @@ -55,21 +64,26 @@ class AccountController extends Controller * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ public function update(AccountDataFormRequest $request) { - $data = []; + // Prevent logging this specific session out when the password is changed. This will + // automatically update the user's password anyways, so no need to do anything else here. if ($request->input('do_action') === 'password') { - $data['password'] = $request->input('new_password'); - } elseif ($request->input('do_action') === 'email') { - $data['email'] = $request->input('new_email'); - } elseif ($request->input('do_action') === 'identity') { - $data = $request->only(['name_first', 'name_last', 'username', 'language']); + $this->sessionGuard->logoutOtherDevices($request->input('new_password')); + } else { + if ($request->input('do_action') === 'email') { + $data = ['email' => $request->input('new_email')]; + } elseif ($request->input('do_action') === 'identity') { + $data = $request->only(['name_first', 'name_last', 'username', 'language']); + } else { + $data = []; + } + + $this->updateService->setUserLevel(User::USER_LEVEL_USER); + $this->updateService->handle($request->user(), $data); } - $this->updateService->setUserLevel(User::USER_LEVEL_USER); - $this->updateService->handle($request->user(), $data); $this->alert->success(trans('base.account.details_updated'))->flash(); return redirect()->route('account'); diff --git a/app/Http/Controllers/Daemon/ActionController.php b/app/Http/Controllers/Daemon/ActionController.php index fef0b35b7..ea4c52533 100644 --- a/app/Http/Controllers/Daemon/ActionController.php +++ b/app/Http/Controllers/Daemon/ActionController.php @@ -7,9 +7,26 @@ use Illuminate\Http\Request; use Pterodactyl\Models\Node; use Pterodactyl\Models\Server; use Pterodactyl\Http\Controllers\Controller; +use Pterodactyl\Events\Server\Installed as ServerInstalled; +use Illuminate\Contracts\Events\Dispatcher as EventDispatcher; class ActionController extends Controller { + /** + * @var \Illuminate\Contracts\Events\Dispatcher + */ + private $eventDispatcher; + + /** + * ActionController constructor. + * + * @param \Illuminate\Contracts\Events\Dispatcher $eventDispatcher + */ + public function __construct(EventDispatcher $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } + /** * Handles install toggle request from daemon. * @@ -37,6 +54,11 @@ class ActionController extends Controller $server->installed = ($status === 'installed') ? 1 : 2; $server->save(); + // Only fire event if server installed successfully. + if ($server->installed === 1) { + $this->eventDispatcher->dispatch(new ServerInstalled($server)); + } + return response()->json([]); } diff --git a/app/Http/Controllers/Server/SubuserController.php b/app/Http/Controllers/Server/SubuserController.php index b507bbb45..008cfeaa5 100644 --- a/app/Http/Controllers/Server/SubuserController.php +++ b/app/Http/Controllers/Server/SubuserController.php @@ -157,7 +157,6 @@ class SubuserController extends Controller * @return \Illuminate\Http\RedirectResponse * * @throws \Exception - * @throws \Illuminate\Auth\Access\AuthorizationException * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException * @throws \Pterodactyl\Exceptions\Service\Subuser\ServerSubuserExistsException @@ -171,7 +170,7 @@ class SubuserController extends Controller $this->alert->success(trans('server.users.user_assigned'))->flash(); return redirect()->route('server.subusers.view', [ - 'uuid' => $server->uuid, + 'uuid' => $server->uuidShort, 'id' => $subuser->hashid, ]); } diff --git a/app/Http/Controllers/Server/Tasks/ActionController.php b/app/Http/Controllers/Server/Tasks/ActionController.php index 410d7c189..498db8537 100644 --- a/app/Http/Controllers/Server/Tasks/ActionController.php +++ b/app/Http/Controllers/Server/Tasks/ActionController.php @@ -2,7 +2,6 @@ namespace Pterodactyl\Http\Controllers\Server\Tasks; -use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Http\Response; use Pterodactyl\Http\Controllers\Controller; @@ -11,12 +10,22 @@ use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; class ActionController extends Controller { + /** + * @var \Pterodactyl\Services\Schedules\ProcessScheduleService + */ private $processScheduleService; + /** * @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface */ private $repository; + /** + * ActionController constructor. + * + * @param \Pterodactyl\Services\Schedules\ProcessScheduleService $processScheduleService + * @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository + */ public function __construct(ProcessScheduleService $processScheduleService, ScheduleRepositoryInterface $repository) { $this->processScheduleService = $processScheduleService; @@ -61,7 +70,7 @@ class ActionController extends Controller $server = $request->attributes->get('server'); $this->authorize('toggle-schedule', $server); - $this->processScheduleService->setRunTimeOverride(Carbon::now())->handle( + $this->processScheduleService->handle( $request->attributes->get('schedule') ); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index d21c8d3c8..85c1190ea 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -2,7 +2,6 @@ namespace Pterodactyl\Http; -use Pterodactyl\Http\Middleware\MaintenanceMiddleware; use Pterodactyl\Models\ApiKey; use Illuminate\Auth\Middleware\Authorize; use Illuminate\Auth\Middleware\Authenticate; @@ -18,15 +17,17 @@ use Pterodactyl\Http\Middleware\LanguageMiddleware; use Illuminate\Foundation\Http\Kernel as HttpKernel; use Pterodactyl\Http\Middleware\Api\AuthenticateKey; use Illuminate\Routing\Middleware\SubstituteBindings; -use Pterodactyl\Http\Middleware\AccessingValidServer; use Pterodactyl\Http\Middleware\Api\SetSessionDriver; +use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Pterodactyl\Http\Middleware\MaintenanceMiddleware; use Pterodactyl\Http\Middleware\RedirectIfAuthenticated; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; use Pterodactyl\Http\Middleware\Api\AuthenticateIPAccess; use Pterodactyl\Http\Middleware\Api\ApiSubstituteBindings; use Illuminate\Foundation\Http\Middleware\ValidatePostSize; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; +use Pterodactyl\Http\Middleware\Server\AccessingValidServer; use Pterodactyl\Http\Middleware\Server\AuthenticateAsSubuser; use Pterodactyl\Http\Middleware\Api\Daemon\DaemonAuthenticate; use Pterodactyl\Http\Middleware\Server\SubuserBelongsToServer; @@ -64,6 +65,7 @@ class Kernel extends HttpKernel EncryptCookies::class, AddQueuedCookiesToResponse::class, StartSession::class, + AuthenticateSession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, SubstituteBindings::class, diff --git a/app/Http/Middleware/Server/AccessingValidServer.php b/app/Http/Middleware/Server/AccessingValidServer.php index ddca28251..ea29e0b99 100644 --- a/app/Http/Middleware/Server/AccessingValidServer.php +++ b/app/Http/Middleware/Server/AccessingValidServer.php @@ -1,6 +1,6 @@ getAttribute('daemonBase'); unset($response['daemon_base'], $response['daemon_listen'], $response['daemon_sftp']); diff --git a/app/Http/Requests/Server/Subuser/SubuserStoreFormRequest.php b/app/Http/Requests/Server/Subuser/SubuserStoreFormRequest.php index 0ada01675..9b7c6ce4d 100644 --- a/app/Http/Requests/Server/Subuser/SubuserStoreFormRequest.php +++ b/app/Http/Requests/Server/Subuser/SubuserStoreFormRequest.php @@ -25,7 +25,7 @@ class SubuserStoreFormRequest extends ServerFormRequest { return [ 'email' => 'required|email', - 'permissions' => 'present|array', + 'permissions' => 'sometimes|array', ]; } } diff --git a/app/Jobs/Schedule/RunTaskJob.php b/app/Jobs/Schedule/RunTaskJob.php index a7fd8486b..7f206ec8f 100644 --- a/app/Jobs/Schedule/RunTaskJob.php +++ b/app/Jobs/Schedule/RunTaskJob.php @@ -3,7 +3,7 @@ namespace Pterodactyl\Jobs\Schedule; use Exception; -use Carbon\Carbon; +use Cake\Chronos\Chronos; use Pterodactyl\Jobs\Job; use InvalidArgumentException; use Illuminate\Queue\SerializesModels; @@ -158,7 +158,7 @@ class RunTaskJob extends Job implements ShouldQueue $repository = app()->make(ScheduleRepositoryInterface::class); $repository->withoutFreshModel()->update($this->schedule, [ 'is_processing' => false, - 'last_run_at' => Carbon::now()->toDateTimeString(), + 'last_run_at' => Chronos::now()->toDateTimeString(), ]); } diff --git a/app/Listeners/.gitkeep b/app/Listeners/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/Models/Node.php b/app/Models/Node.php index 2643d062a..80c84904f 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -113,6 +113,7 @@ class Node extends Model implements CleansAttributes, ValidableContract 'daemonSFTP' => 'numeric|between:1024,65535', 'daemonListen' => 'numeric|between:1024,65535', 'maintenance_mode' => 'boolean', + 'upload_size' => 'int|between:1,1024', ]; /** diff --git a/app/Notifications/AccountCreated.php b/app/Notifications/AccountCreated.php index 29b084d5e..7dd258dd4 100644 --- a/app/Notifications/AccountCreated.php +++ b/app/Notifications/AccountCreated.php @@ -23,7 +23,7 @@ class AccountCreated extends Notification implements ShouldQueue /** * The user model for the created user. * - * @var object + * @var \Pterodactyl\Models\User */ public $user; @@ -65,7 +65,7 @@ class AccountCreated extends Notification implements ShouldQueue ->line('Email: ' . $this->user->email); if (! is_null($this->token)) { - return $message->action('Setup Your Account', url('/auth/password/reset/' . $this->token . '?email=' . $this->user->email)); + return $message->action('Setup Your Account', url('/auth/password/reset/' . $this->token . '?email=' . urlencode($this->user->email))); } return $message; diff --git a/app/Notifications/ServerInstalled.php b/app/Notifications/ServerInstalled.php new file mode 100644 index 000000000..fe9747223 --- /dev/null +++ b/app/Notifications/ServerInstalled.php @@ -0,0 +1,69 @@ +server->loadMissing('user'); + + $this->server = $event->server; + $this->user = $event->server->user; + + // Since we are calling this notification directly from an event listener we need to fire off the dispatcher + // to send the email now. Don't use send() or you'll end up firing off two different events. + Container::getInstance()->make(Dispatcher::class)->sendNow($this->user, $this); + } + + /** + * Get the notification's delivery channels. + * + * @return array + */ + public function via() + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail() + { + return (new MailMessage) + ->greeting('Hello ' . $this->user->username . '.') + ->line('Your server has finished installing and is now ready for you to use.') + ->line('Server Name: ' . $this->server->name) + ->action('Login and Begin Using', route('index')); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 2ecc663fe..5be9601d6 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,6 +2,8 @@ namespace Pterodactyl\Providers; +use Pterodactyl\Events\Server\Installed as ServerInstalledEvent; +use Pterodactyl\Notifications\ServerInstalled as ServerInstalledNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider @@ -11,5 +13,9 @@ class EventServiceProvider extends ServiceProvider * * @var array */ - protected $listen = []; + protected $listen = [ + ServerInstalledEvent::class => [ + ServerInstalledNotification::class, + ], + ]; } diff --git a/app/Repositories/Daemon/BaseRepository.php b/app/Repositories/Daemon/BaseRepository.php index e15b17ce1..186b5917d 100644 --- a/app/Repositories/Daemon/BaseRepository.php +++ b/app/Repositories/Daemon/BaseRepository.php @@ -144,6 +144,7 @@ abstract class BaseRepository implements BaseRepositoryInterface $headers['X-Access-Token'] = $this->getToken() ?? $this->getNode()->daemonSecret; return new Client([ + 'verify' => config('app.env') === 'production', 'base_uri' => sprintf('%s://%s:%s/v1/', $this->getNode()->scheme, $this->getNode()->fqdn, $this->getNode()->daemonListen), 'timeout' => config('pterodactyl.guzzle.timeout'), 'connect_timeout' => config('pterodactyl.guzzle.connect_timeout'), diff --git a/app/Repositories/Eloquent/EloquentRepository.php b/app/Repositories/Eloquent/EloquentRepository.php index 64e7cfb60..cf0931799 100644 --- a/app/Repositories/Eloquent/EloquentRepository.php +++ b/app/Repositories/Eloquent/EloquentRepository.php @@ -298,7 +298,7 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf } /** - * Get the amount of entries in the database + * Get the amount of entries in the database. * * @return int */ diff --git a/app/Repositories/Eloquent/ScheduleRepository.php b/app/Repositories/Eloquent/ScheduleRepository.php index a7b53602b..1d2dda244 100644 --- a/app/Repositories/Eloquent/ScheduleRepository.php +++ b/app/Repositories/Eloquent/ScheduleRepository.php @@ -75,6 +75,7 @@ class ScheduleRepository extends EloquentRepository implements ScheduleRepositor { return $this->getBuilder()->with('tasks') ->where('is_active', true) + ->where('is_processing', false) ->where('next_run_at', '<=', $timestamp) ->get($this->getColumns()); } diff --git a/app/Repositories/Eloquent/ServerRepository.php b/app/Repositories/Eloquent/ServerRepository.php index f448f0b78..e900c92dd 100644 --- a/app/Repositories/Eloquent/ServerRepository.php +++ b/app/Repositories/Eloquent/ServerRepository.php @@ -330,7 +330,7 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt } /** - * Get the amount of servers that are suspended + * Get the amount of servers that are suspended. * * @return int */ diff --git a/app/Services/Helpers/TemporaryPasswordService.php b/app/Services/Helpers/TemporaryPasswordService.php deleted file mode 100644 index c9ccfa5df..000000000 --- a/app/Services/Helpers/TemporaryPasswordService.php +++ /dev/null @@ -1,59 +0,0 @@ -. - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ - -namespace Pterodactyl\Services\Helpers; - -use Ramsey\Uuid\Uuid; -use Illuminate\Contracts\Hashing\Hasher; -use Illuminate\Database\ConnectionInterface; - -class TemporaryPasswordService -{ - const HMAC_ALGO = 'sha256'; - - /** - * @var \Illuminate\Database\ConnectionInterface - */ - protected $connection; - - /** - * @var \Illuminate\Contracts\Hashing\Hasher - */ - protected $hasher; - - /** - * TemporaryPasswordService constructor. - * - * @param \Illuminate\Database\ConnectionInterface $connection - * @param \Illuminate\Contracts\Hashing\Hasher $hasher - */ - public function __construct(ConnectionInterface $connection, Hasher $hasher) - { - $this->connection = $connection; - $this->hasher = $hasher; - } - - /** - * Store a password reset token for a specific email address. - * - * @param string $email - * @return string - */ - public function handle($email) - { - $token = hash_hmac(self::HMAC_ALGO, Uuid::uuid4()->toString(), config('app.key')); - - $this->connection->table('password_resets')->insert([ - 'email' => $email, - 'token' => $this->hasher->make($token), - ]); - - return $token; - } -} diff --git a/app/Services/Nodes/NodeUpdateService.php b/app/Services/Nodes/NodeUpdateService.php index ef9349a71..16cc982de 100644 --- a/app/Services/Nodes/NodeUpdateService.php +++ b/app/Services/Nodes/NodeUpdateService.php @@ -1,11 +1,4 @@ . - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ namespace Pterodactyl\Services\Nodes; @@ -13,7 +6,6 @@ use Pterodactyl\Models\Node; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\RequestException; use Illuminate\Database\ConnectionInterface; -use Pterodactyl\Traits\Services\ReturnsUpdatedModels; use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; use Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException; @@ -21,8 +13,6 @@ use Pterodactyl\Contracts\Repository\Daemon\ConfigurationRepositoryInterface; class NodeUpdateService { - use ReturnsUpdatedModels; - /** * @var \Illuminate\Database\ConnectionInterface */ @@ -60,7 +50,7 @@ class NodeUpdateService * * @param \Pterodactyl\Models\Node $node * @param array $data - * @return \Pterodactyl\Models\Node|mixed + * @return \Pterodactyl\Models\Node * * @throws \Pterodactyl\Exceptions\DisplayException * @throws \Pterodactyl\Exceptions\Model\DataValidationException @@ -74,14 +64,10 @@ class NodeUpdateService } $this->connection->beginTransaction(); - if ($this->getUpdatedModel()) { - $response = $this->repository->update($node->id, $data); - } else { - $response = $this->repository->withoutFreshModel()->update($node->id, $data); - } + $updatedModel = $this->repository->update($node->id, $data); try { - $this->configRepository->setNode($node)->update(); + $this->configRepository->setNode($updatedModel)->update(); $this->connection->commit(); } catch (RequestException $exception) { // Failed to connect to the Daemon. Let's go ahead and save the configuration @@ -95,6 +81,6 @@ class NodeUpdateService throw new DaemonConnectionException($exception); } - return $response; + return $updatedModel; } } diff --git a/app/Services/Schedules/ProcessScheduleService.php b/app/Services/Schedules/ProcessScheduleService.php index b134caa35..4ada2aee8 100644 --- a/app/Services/Schedules/ProcessScheduleService.php +++ b/app/Services/Schedules/ProcessScheduleService.php @@ -2,53 +2,45 @@ namespace Pterodactyl\Services\Schedules; -use Carbon\Carbon; use Cron\CronExpression; use Pterodactyl\Models\Schedule; -use Pterodactyl\Services\Schedules\Tasks\RunTaskService; +use Illuminate\Contracts\Bus\Dispatcher; +use Pterodactyl\Jobs\Schedule\RunTaskJob; +use Pterodactyl\Contracts\Repository\TaskRepositoryInterface; use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; class ProcessScheduleService { + /** + * @var \Illuminate\Contracts\Bus\Dispatcher + */ + private $dispatcher; + /** * @var \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface */ - private $repository; + private $scheduleRepository; /** - * @var \Pterodactyl\Services\Schedules\Tasks\RunTaskService + * @var \Pterodactyl\Contracts\Repository\TaskRepositoryInterface */ - private $runnerService; - - /** - * @var \Carbon\Carbon|null - */ - private $runTimeOverride; + private $taskRepository; /** * ProcessScheduleService constructor. * - * @param \Pterodactyl\Services\Schedules\Tasks\RunTaskService $runnerService - * @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository + * @param \Illuminate\Contracts\Bus\Dispatcher $dispatcher + * @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $scheduleRepository + * @param \Pterodactyl\Contracts\Repository\TaskRepositoryInterface $taskRepository */ - public function __construct(RunTaskService $runnerService, ScheduleRepositoryInterface $repository) - { - $this->repository = $repository; - $this->runnerService = $runnerService; - } - - /** - * Set the time that this schedule should be run at. This will override the time - * defined on the schedule itself. Useful for triggering one-off task runs. - * - * @param \Carbon\Carbon $time - * @return $this - */ - public function setRunTimeOverride(Carbon $time) - { - $this->runTimeOverride = $time; - - return $this; + public function __construct( + Dispatcher $dispatcher, + ScheduleRepositoryInterface $scheduleRepository, + TaskRepositoryInterface $taskRepository + ) { + $this->dispatcher = $dispatcher; + $this->scheduleRepository = $scheduleRepository; + $this->taskRepository = $taskRepository; } /** @@ -61,7 +53,10 @@ class ProcessScheduleService */ public function handle(Schedule $schedule) { - $this->repository->loadTasks($schedule); + $this->scheduleRepository->loadTasks($schedule); + + /** @var \Pterodactyl\Models\Task $task */ + $task = $schedule->getRelation('tasks')->where('sequence_id', 1)->first(); $formattedCron = sprintf('%s %s %s * %s', $schedule->cron_minute, @@ -70,27 +65,15 @@ class ProcessScheduleService $schedule->cron_day_of_week ); - $this->repository->update($schedule->id, [ + $this->scheduleRepository->update($schedule->id, [ 'is_processing' => true, - 'next_run_at' => $this->getRunAtTime($formattedCron), + 'next_run_at' => CronExpression::factory($formattedCron)->getNextRunDate(), ]); - $task = $schedule->getRelation('tasks')->where('sequence_id', 1)->first(); - $this->runnerService->handle($task); - } + $this->taskRepository->update($task->id, ['is_queued' => true]); - /** - * Get the timestamp to store in the database as the next_run time for a schedule. - * - * @param string $formatted - * @return \DateTime|string - */ - private function getRunAtTime(string $formatted) - { - if ($this->runTimeOverride instanceof Carbon) { - return $this->runTimeOverride->toDateTimeString(); - } - - return CronExpression::factory($formatted)->getNextRunDate(); + $this->dispatcher->dispatch( + (new RunTaskJob($task->id, $schedule->id))->delay($task->time_offset) + ); } } diff --git a/app/Services/Schedules/Tasks/RunTaskService.php b/app/Services/Schedules/Tasks/RunTaskService.php deleted file mode 100644 index 5d83db077..000000000 --- a/app/Services/Schedules/Tasks/RunTaskService.php +++ /dev/null @@ -1,53 +0,0 @@ -. - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ - -namespace Pterodactyl\Services\Schedules\Tasks; - -use Pterodactyl\Models\Task; -use Pterodactyl\Jobs\Schedule\RunTaskJob; -use Illuminate\Foundation\Bus\DispatchesJobs; -use Pterodactyl\Contracts\Repository\TaskRepositoryInterface; - -class RunTaskService -{ - use DispatchesJobs; - - /** - * @var \Pterodactyl\Contracts\Repository\TaskRepositoryInterface - */ - protected $repository; - - /** - * RunTaskService constructor. - * - * @param \Pterodactyl\Contracts\Repository\TaskRepositoryInterface $repository - */ - public function __construct(TaskRepositoryInterface $repository) - { - $this->repository = $repository; - } - - /** - * Push a single task onto the queue. - * - * @param int|\Pterodactyl\Models\Task $task - * - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function handle($task) - { - if (! $task instanceof Task) { - $task = $this->repository->find($task); - } - - $this->repository->update($task->id, ['is_queued' => true]); - $this->dispatch((new RunTaskJob($task->id, $task->schedule_id))->delay($task->time_offset)); - } -} diff --git a/app/Services/Servers/EnvironmentService.php b/app/Services/Servers/EnvironmentService.php index 85eb69bb8..b17076e07 100644 --- a/app/Services/Servers/EnvironmentService.php +++ b/app/Services/Servers/EnvironmentService.php @@ -78,7 +78,7 @@ class EnvironmentService } // Process variables set in the configuration file. - foreach ($this->config->get('pterodactyl.environment_mappings', []) as $key => $object) { + foreach ($this->config->get('pterodactyl.environment_variables', []) as $key => $object) { if (is_callable($object)) { $variables[$key] = call_user_func($object, $server); } else { diff --git a/app/Services/Subusers/PermissionCreationService.php b/app/Services/Subusers/PermissionCreationService.php index 0173e8015..074048f0a 100644 --- a/app/Services/Subusers/PermissionCreationService.php +++ b/app/Services/Subusers/PermissionCreationService.php @@ -56,6 +56,8 @@ class PermissionCreationService } } - $this->repository->withoutFreshModel()->insert($insertPermissions); + if (! empty($insertPermissions)) { + $this->repository->withoutFreshModel()->insert($insertPermissions); + } } } diff --git a/app/Services/Users/UserCreationService.php b/app/Services/Users/UserCreationService.php index f4824e48b..b54c4f2de 100644 --- a/app/Services/Users/UserCreationService.php +++ b/app/Services/Users/UserCreationService.php @@ -5,8 +5,8 @@ namespace Pterodactyl\Services\Users; use Ramsey\Uuid\Uuid; use Illuminate\Contracts\Hashing\Hasher; use Illuminate\Database\ConnectionInterface; +use Illuminate\Contracts\Auth\PasswordBroker; use Pterodactyl\Notifications\AccountCreated; -use Pterodactyl\Services\Helpers\TemporaryPasswordService; use Pterodactyl\Contracts\Repository\UserRepositoryInterface; class UserCreationService @@ -22,9 +22,9 @@ class UserCreationService private $hasher; /** - * @var \Pterodactyl\Services\Helpers\TemporaryPasswordService + * @var \Illuminate\Contracts\Auth\PasswordBroker */ - private $passwordService; + private $passwordBroker; /** * @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface @@ -36,18 +36,18 @@ class UserCreationService * * @param \Illuminate\Database\ConnectionInterface $connection * @param \Illuminate\Contracts\Hashing\Hasher $hasher - * @param \Pterodactyl\Services\Helpers\TemporaryPasswordService $passwordService + * @param \Illuminate\Contracts\Auth\PasswordBroker $passwordBroker * @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository */ public function __construct( ConnectionInterface $connection, Hasher $hasher, - TemporaryPasswordService $passwordService, + PasswordBroker $passwordBroker, UserRepositoryInterface $repository ) { $this->connection = $connection; $this->hasher = $hasher; - $this->passwordService = $passwordService; + $this->passwordBroker = $passwordBroker; $this->repository = $repository; } @@ -68,8 +68,8 @@ class UserCreationService $this->connection->beginTransaction(); if (! isset($data['password']) || empty($data['password'])) { + $generateResetToken = true; $data['password'] = $this->hasher->make(str_random(30)); - $token = $this->passwordService->handle($data['email']); } /** @var \Pterodactyl\Models\User $user */ @@ -77,6 +77,10 @@ class UserCreationService 'uuid' => Uuid::uuid4()->toString(), ]), true, true); + if (isset($generateResetToken)) { + $token = $this->passwordBroker->createToken($user); + } + $this->connection->commit(); $user->notify(new AccountCreated($user, $token ?? null)); diff --git a/app/Traits/Controllers/PlainJavascriptInjection.php b/app/Traits/Controllers/PlainJavascriptInjection.php index eae53bfbc..f514eb1af 100644 --- a/app/Traits/Controllers/PlainJavascriptInjection.php +++ b/app/Traits/Controllers/PlainJavascriptInjection.php @@ -3,7 +3,7 @@ * Created by PhpStorm. * User: Stan * Date: 26-5-2018 - * Time: 20:56 + * Time: 20:56. */ namespace Pterodactyl\Traits\Controllers; @@ -12,13 +12,11 @@ use JavaScript; trait PlainJavascriptInjection { - /** - * Injects statistics into javascript + * Injects statistics into javascript. */ public function injectJavascript($data) { Javascript::put($data); } - -} \ No newline at end of file +} diff --git a/codecov.yml b/codecov.yml index 0bcc79196..f173c829e 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,8 +1,6 @@ coverage: status: - project: - default: - target: 35 - threshold: 1 + project: off + patch: off comment: layout: "diff" diff --git a/composer.json b/composer.json index 65da6b2ce..fdc3c2821 100644 --- a/composer.json +++ b/composer.json @@ -85,6 +85,6 @@ "config": { "preferred-install": "dist", "sort-packages": true, - "optimize-autoloader": true + "optimize-autoloader": false } } diff --git a/composer.lock b/composer.lock index ea58eb51c..2c24ee8a3 100644 --- a/composer.lock +++ b/composer.lock @@ -61,16 +61,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.57.1", + "version": "3.62.6", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "795332f5f3a81474e85653e62d1d7b306bd4eeae" + "reference": "0be301c36a5c337b40e69ce3b4698cca5427e4b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/795332f5f3a81474e85653e62d1d7b306bd4eeae", - "reference": "795332f5f3a81474e85653e62d1d7b306bd4eeae", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0be301c36a5c337b40e69ce3b4698cca5427e4b9", + "reference": "0be301c36a5c337b40e69ce3b4698cca5427e4b9", "shasum": "" }, "require": { @@ -137,20 +137,20 @@ "s3", "sdk" ], - "time": "2018-05-25T21:34:30+00:00" + "time": "2018-06-29T22:12:11+00:00" }, { "name": "cakephp/chronos", - "version": "1.1.4", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/cakephp/chronos.git", - "reference": "85bcaea6a832684b32ef54b2487b0c14a172e9e6" + "reference": "243bb7bc3411b549e190703dbef49a96be5b4233" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cakephp/chronos/zipball/85bcaea6a832684b32ef54b2487b0c14a172e9e6", - "reference": "85bcaea6a832684b32ef54b2487b0c14a172e9e6", + "url": "https://api.github.com/repos/cakephp/chronos/zipball/243bb7bc3411b549e190703dbef49a96be5b4233", + "reference": "243bb7bc3411b549e190703dbef49a96be5b4233", "shasum": "" }, "require": { @@ -158,15 +158,15 @@ }, "require-dev": { "athletic/athletic": "~0.1", - "cakephp/cakephp-codesniffer": "~2.3", + "cakephp/cakephp-codesniffer": "^3.0", "phpbench/phpbench": "@dev", "phpstan/phpstan": "^0.6.4", - "phpunit/phpunit": "<6.0" + "phpunit/phpunit": "<6.0 || ^7.0" }, "type": "library", "autoload": { "psr-4": { - "Cake\\Chronos\\": "src" + "Cake\\Chronos\\": "src/" }, "files": [ "src/carbon_compat.php" @@ -194,7 +194,7 @@ "datetime", "time" ], - "time": "2018-01-13T12:19:50+00:00" + "time": "2018-06-23T01:51:58+00:00" }, { "name": "dnoegel/php-xdg-base-dir", @@ -709,16 +709,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "3f00985deec8df53d4cc1e5c33619bda1ee309a5" + "reference": "92a2c3768d50e21a1f26a53cb795ce72806266c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/3f00985deec8df53d4cc1e5c33619bda1ee309a5", - "reference": "3f00985deec8df53d4cc1e5c33619bda1ee309a5", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/92a2c3768d50e21a1f26a53cb795ce72806266c5", + "reference": "92a2c3768d50e21a1f26a53cb795ce72806266c5", "shasum": "" }, "require": { @@ -754,7 +754,7 @@ "cron", "schedule" ], - "time": "2018-04-06T15:51:55+00:00" + "time": "2018-06-06T03:12:17+00:00" }, { "name": "egulias/email-validator", @@ -1369,16 +1369,16 @@ }, { "name": "laravel/framework", - "version": "v5.6.23", + "version": "v5.6.26", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "f547f0a71a12763d1adb8493237d541c9e3a5d10" + "reference": "7047df295e77cecb6a2f84736a732af66cc6789c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/f547f0a71a12763d1adb8493237d541c9e3a5d10", - "reference": "f547f0a71a12763d1adb8493237d541c9e3a5d10", + "url": "https://api.github.com/repos/laravel/framework/zipball/7047df295e77cecb6a2f84736a732af66cc6789c", + "reference": "7047df295e77cecb6a2f84736a732af66cc6789c", "shasum": "" }, "require": { @@ -1504,7 +1504,7 @@ "framework", "laravel" ], - "time": "2018-05-22T14:55:57+00:00" + "time": "2018-06-20T14:21:11+00:00" }, { "name": "laravel/tinker", @@ -2000,16 +2000,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.0.1", + "version": "v4.0.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3" + "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3", - "reference": "e4a54fa90a5cd8e8dd3fb4099942681731c5cdd3", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/35b8caf75e791ba1b2d24fec1552168d72692b12", + "reference": "35b8caf75e791ba1b2d24fec1552168d72692b12", "shasum": "" }, "require": { @@ -2047,7 +2047,7 @@ "parser", "php" ], - "time": "2018-03-25T17:35:16+00:00" + "time": "2018-06-03T11:33:10+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -2113,16 +2113,16 @@ }, { "name": "paragonie/random_compat", - "version": "v2.0.12", + "version": "v2.0.15", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + "reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/10bcb46e8f3d365170f6de9d05245aa066b81f09", + "reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09", "shasum": "" }, "require": { @@ -2154,10 +2154,11 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2018-04-04T21:24:14+00:00" + "time": "2018-06-08T15:26:40+00:00" }, { "name": "pragmarx/google2fa", @@ -2526,16 +2527,16 @@ }, { "name": "psy/psysh", - "version": "v0.9.4", + "version": "v0.9.6", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "4d969a0e08e1e05e7207c07cb4207017ecc9a331" + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4d969a0e08e1e05e7207c07cb4207017ecc9a331", - "reference": "4d969a0e08e1e05e7207c07cb4207017ecc9a331", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4a2ce86f199d51b6e2524214dc06835e872f4fce", + "reference": "4a2ce86f199d51b6e2524214dc06835e872f4fce", "shasum": "" }, "require": { @@ -2594,7 +2595,7 @@ "interactive", "shell" ], - "time": "2018-05-22T06:48:07+00:00" + "time": "2018-06-10T17:57:20+00:00" }, { "name": "ramsey/uuid", @@ -2940,16 +2941,16 @@ }, { "name": "spatie/laravel-fractal", - "version": "5.3.1", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/spatie/laravel-fractal.git", - "reference": "e39e0865b66ca541337b45fed4ad6c22200b85d0" + "reference": "a0db87cf01593cc2cfe7aec3f82ce57c83566f3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-fractal/zipball/e39e0865b66ca541337b45fed4ad6c22200b85d0", - "reference": "e39e0865b66ca541337b45fed4ad6c22200b85d0", + "url": "https://api.github.com/repos/spatie/laravel-fractal/zipball/a0db87cf01593cc2cfe7aec3f82ce57c83566f3b", + "reference": "a0db87cf01593cc2cfe7aec3f82ce57c83566f3b", "shasum": "" }, "require": { @@ -3004,7 +3005,7 @@ "spatie", "transform" ], - "time": "2018-02-07T23:06:44+00:00" + "time": "2018-06-13T20:45:45+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -3063,16 +3064,16 @@ }, { "name": "symfony/console", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "058f120b8e06ebcd7b211de5ffae07b2db00fbdd" + "reference": "70591cda56b4b47c55776ac78e157c4bb6c8b43f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/058f120b8e06ebcd7b211de5ffae07b2db00fbdd", - "reference": "058f120b8e06ebcd7b211de5ffae07b2db00fbdd", + "url": "https://api.github.com/repos/symfony/console/zipball/70591cda56b4b47c55776ac78e157c4bb6c8b43f", + "reference": "70591cda56b4b47c55776ac78e157c4bb6c8b43f", "shasum": "" }, "require": { @@ -3100,7 +3101,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3127,20 +3128,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-05-16T09:05:32+00:00" + "time": "2018-05-31T10:17:53+00:00" }, { "name": "symfony/css-selector", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "0383a1a4eb1ffcac28719975d3e01bfa14be8ab3" + "reference": "03ac71606ecb0b0ce792faa17d74cc32c2949ef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/0383a1a4eb1ffcac28719975d3e01bfa14be8ab3", - "reference": "0383a1a4eb1ffcac28719975d3e01bfa14be8ab3", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/03ac71606ecb0b0ce792faa17d74cc32c2949ef4", + "reference": "03ac71606ecb0b0ce792faa17d74cc32c2949ef4", "shasum": "" }, "require": { @@ -3149,7 +3150,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3180,20 +3181,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-05-11T15:58:37+00:00" + "time": "2018-05-30T07:26:09+00:00" }, { "name": "symfony/debug", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "4e7c98de67cc4171d4c986554e09a511da40f3d8" + "reference": "dbe0fad88046a755dcf9379f2964c61a02f5ae3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/4e7c98de67cc4171d4c986554e09a511da40f3d8", - "reference": "4e7c98de67cc4171d4c986554e09a511da40f3d8", + "url": "https://api.github.com/repos/symfony/debug/zipball/dbe0fad88046a755dcf9379f2964c61a02f5ae3d", + "reference": "dbe0fad88046a755dcf9379f2964c61a02f5ae3d", "shasum": "" }, "require": { @@ -3209,7 +3210,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3236,20 +3237,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-05-16T09:05:32+00:00" + "time": "2018-06-08T09:39:36+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "63353a71073faf08f62caab4e6889b06a787f07b" + "reference": "2391ed210a239868e7256eb6921b1bd83f3087b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/63353a71073faf08f62caab4e6889b06a787f07b", - "reference": "63353a71073faf08f62caab4e6889b06a787f07b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2391ed210a239868e7256eb6921b1bd83f3087b5", + "reference": "2391ed210a239868e7256eb6921b1bd83f3087b5", "shasum": "" }, "require": { @@ -3272,7 +3273,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3299,20 +3300,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-04-06T07:35:43+00:00" + "time": "2018-04-06T07:35:57+00:00" }, { "name": "symfony/finder", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8c633f5a815903a1fe6e3fc135f207267a8a79af" + "reference": "84714b8417d19e4ba02ea78a41a975b3efaafddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8c633f5a815903a1fe6e3fc135f207267a8a79af", - "reference": "8c633f5a815903a1fe6e3fc135f207267a8a79af", + "url": "https://api.github.com/repos/symfony/finder/zipball/84714b8417d19e4ba02ea78a41a975b3efaafddb", + "reference": "84714b8417d19e4ba02ea78a41a975b3efaafddb", "shasum": "" }, "require": { @@ -3321,7 +3322,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3348,20 +3349,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-05-16T09:05:32+00:00" + "time": "2018-06-19T21:38:16+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "277b757a2d3960170d99d372e171a8a18916467a" + "reference": "4f9c7cf962e635b0b26b14500ac046e07dbef7f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/277b757a2d3960170d99d372e171a8a18916467a", - "reference": "277b757a2d3960170d99d372e171a8a18916467a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4f9c7cf962e635b0b26b14500ac046e07dbef7f3", + "reference": "4f9c7cf962e635b0b26b14500ac046e07dbef7f3", "shasum": "" }, "require": { @@ -3369,12 +3370,13 @@ "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { + "predis/predis": "~1.0", "symfony/expression-language": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3401,34 +3403,34 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-05-25T11:08:56+00:00" + "time": "2018-06-19T21:38:16+00:00" }, { "name": "symfony/http-kernel", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "450a1bda817f2dce25a9e13f0f011336743f2a48" + "reference": "29c094a1c4f8209b7e033f612cbbd69029e38955" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/450a1bda817f2dce25a9e13f0f011336743f2a48", - "reference": "450a1bda817f2dce25a9e13f0f011336743f2a48", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/29c094a1c4f8209b7e033f612cbbd69029e38955", + "reference": "29c094a1c4f8209b7e033f612cbbd69029e38955", "shasum": "" }, "require": { "php": "^7.1.3", "psr/log": "~1.0", "symfony/debug": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/http-foundation": "~3.4.4|~4.0.4", + "symfony/event-dispatcher": "~4.1", + "symfony/http-foundation": "^4.1.1", "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/config": "<3.4", - "symfony/dependency-injection": "<3.4.5|<4.0.5,>=4", - "symfony/var-dumper": "<3.4", + "symfony/dependency-injection": "<4.1", + "symfony/var-dumper": "<4.1.1", "twig/twig": "<1.34|<2.4,>=2" }, "provide": { @@ -3440,7 +3442,7 @@ "symfony/config": "~3.4|~4.0", "symfony/console": "~3.4|~4.0", "symfony/css-selector": "~3.4|~4.0", - "symfony/dependency-injection": "^3.4.5|^4.0.5", + "symfony/dependency-injection": "^4.1", "symfony/dom-crawler": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0", @@ -3449,7 +3451,7 @@ "symfony/stopwatch": "~3.4|~4.0", "symfony/templating": "~3.4|~4.0", "symfony/translation": "~3.4|~4.0", - "symfony/var-dumper": "~3.4|~4.0" + "symfony/var-dumper": "^4.1.1" }, "suggest": { "symfony/browser-kit": "", @@ -3461,7 +3463,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3488,7 +3490,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-05-25T13:32:52+00:00" + "time": "2018-06-25T13:06:45+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3769,16 +3771,16 @@ }, { "name": "symfony/process", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "3621fa74d0576a6f89d63bc44fabd376711bd0b0" + "reference": "1d1677391ecf00d1c5b9482d6050c0c27aa3ac3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/3621fa74d0576a6f89d63bc44fabd376711bd0b0", - "reference": "3621fa74d0576a6f89d63bc44fabd376711bd0b0", + "url": "https://api.github.com/repos/symfony/process/zipball/1d1677391ecf00d1c5b9482d6050c0c27aa3ac3a", + "reference": "1d1677391ecf00d1c5b9482d6050c0c27aa3ac3a", "shasum": "" }, "require": { @@ -3787,7 +3789,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3814,20 +3816,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-05-16T09:05:32+00:00" + "time": "2018-05-31T10:17:53+00:00" }, { "name": "symfony/routing", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e8833b64b139926cbe1610d53722185e55c18e44" + "reference": "b38b9797327b26ea2e4146a40e6e2dc9820a6932" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e8833b64b139926cbe1610d53722185e55c18e44", - "reference": "e8833b64b139926cbe1610d53722185e55c18e44", + "url": "https://api.github.com/repos/symfony/routing/zipball/b38b9797327b26ea2e4146a40e6e2dc9820a6932", + "reference": "b38b9797327b26ea2e4146a40e6e2dc9820a6932", "shasum": "" }, "require": { @@ -3840,7 +3842,6 @@ }, "require-dev": { "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", @@ -3859,7 +3860,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3892,20 +3893,20 @@ "uri", "url" ], - "time": "2018-05-16T14:21:07+00:00" + "time": "2018-06-19T21:38:16+00:00" }, { "name": "symfony/translation", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e1f5863d0a9e79cfec7f031421ced3fe1d403e66" + "reference": "b6d8164085ee0b6debcd1b7a131fd6f63bb04854" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e1f5863d0a9e79cfec7f031421ced3fe1d403e66", - "reference": "e1f5863d0a9e79cfec7f031421ced3fe1d403e66", + "url": "https://api.github.com/repos/symfony/translation/zipball/b6d8164085ee0b6debcd1b7a131fd6f63bb04854", + "reference": "b6d8164085ee0b6debcd1b7a131fd6f63bb04854", "shasum": "" }, "require": { @@ -3920,6 +3921,7 @@ "require-dev": { "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/intl": "~3.4|~4.0", @@ -3933,7 +3935,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -3960,20 +3962,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-05-21T10:09:47+00:00" + "time": "2018-06-22T08:59:39+00:00" }, { "name": "symfony/var-dumper", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "3c34cf3f4bbac9e003d9325225e9ef1a49180a18" + "reference": "b2eebaec085d1f2cafbad7644733d494a3bbbc9b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3c34cf3f4bbac9e003d9325225e9ef1a49180a18", - "reference": "3c34cf3f4bbac9e003d9325225e9ef1a49180a18", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/b2eebaec085d1f2cafbad7644733d494a3bbbc9b", + "reference": "b2eebaec085d1f2cafbad7644733d494a3bbbc9b", "shasum": "" }, "require": { @@ -3982,20 +3984,26 @@ "symfony/polyfill-php72": "~1.5" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", + "symfony/console": "<3.4" }, "require-dev": { "ext-iconv": "*", + "symfony/process": "~3.4|~4.0", "twig/twig": "~1.34|~2.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump" + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, + "bin": [ + "Resources/bin/var-dump-server" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -4029,7 +4037,7 @@ "debug", "dump" ], - "time": "2018-04-26T16:12:06+00:00" + "time": "2018-06-23T12:23:56+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -4080,28 +4088,28 @@ }, { "name": "vlucas/phpdotenv", - "version": "v2.4.0", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c" + "reference": "6ae3e2e6494bb5e58c2decadafc3de7f1453f70a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", - "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/6ae3e2e6494bb5e58c2decadafc3de7f1453f70a", + "reference": "6ae3e2e6494bb5e58c2decadafc3de7f1453f70a", "shasum": "" }, "require": { "php": ">=5.3.9" }, "require-dev": { - "phpunit/phpunit": "^4.8 || ^5.0" + "phpunit/phpunit": "^4.8.35 || ^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -4111,7 +4119,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause-Attribution" + "BSD-3-Clause" ], "authors": [ { @@ -4126,7 +4134,7 @@ "env", "environment" ], - "time": "2016-09-01T10:05:43+00:00" + "time": "2018-07-01T10:25:50+00:00" }, { "name": "webmozart/assert", @@ -4580,6 +4588,50 @@ ], "time": "2016-08-30T16:08:34+00:00" }, + { + "name": "composer/xdebug-handler", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/c919dc6c62e221fc6406f861ea13433c0aa24f08", + "reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2018-04-11T15:42:36+00:00" + }, { "name": "doctrine/instantiator", "version": "1.1.0", @@ -4636,16 +4688,16 @@ }, { "name": "filp/whoops", - "version": "2.1.14", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6" + "reference": "181c4502d8f34db7aed7bfe88d4f87875b8e947a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/c6081b8838686aa04f1e83ba7e91f78b7b2a23e6", - "reference": "c6081b8838686aa04f1e83ba7e91f78b7b2a23e6", + "url": "https://api.github.com/repos/filp/whoops/zipball/181c4502d8f34db7aed7bfe88d4f87875b8e947a", + "reference": "181c4502d8f34db7aed7bfe88d4f87875b8e947a", "shasum": "" }, "require": { @@ -4653,9 +4705,9 @@ "psr/log": "^1.0.1" }, "require-dev": { - "mockery/mockery": "0.9.*", + "mockery/mockery": "^0.9 || ^1.0", "phpunit/phpunit": "^4.8.35 || ^5.7", - "symfony/var-dumper": "^2.6 || ^3.0" + "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", @@ -4664,7 +4716,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -4693,24 +4745,25 @@ "throwable", "whoops" ], - "time": "2017-11-23T18:22:44+00:00" + "time": "2018-03-03T17:56:25+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.11.1", + "version": "v2.12.1", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "ad94441c17b8ef096e517acccdbf3238af8a2da8" + "reference": "beef6cbe6dec7205edcd143842a49f9a691859a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/ad94441c17b8ef096e517acccdbf3238af8a2da8", - "reference": "ad94441c17b8ef096e517acccdbf3238af8a2da8", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/beef6cbe6dec7205edcd143842a49f9a691859a6", + "reference": "beef6cbe6dec7205edcd143842a49f9a691859a6", "shasum": "" }, "require": { "composer/semver": "^1.4", + "composer/xdebug-handler": "^1.0", "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", @@ -4732,27 +4785,26 @@ "require-dev": { "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.0", + "keradus/cli-executor": "^1.1", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.0", + "php-coveralls/php-coveralls": "^2.1", "php-cs-fixer/accessible-object": "^1.0", - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "phpunitgoodpractices/traits": "^1.3.1", - "symfony/phpunit-bridge": "^3.2.2 || ^4.0" + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.0.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.0.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", + "phpunitgoodpractices/traits": "^1.5", + "symfony/phpunit-bridge": "^4.0" }, "suggest": { "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." }, "bin": [ "php-cs-fixer" ], "type": "application", - "extra": { - "branch-alias": { - "dev-master": "2.11-dev" - } - }, "autoload": { "psr-4": { "PhpCsFixer\\": "src/" @@ -4762,9 +4814,6 @@ "tests/Test/AbstractIntegrationCaseFactory.php", "tests/Test/AbstractIntegrationTestCase.php", "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/Constraint/SameStringsConstraint.php", - "tests/Test/Constraint/SameStringsConstraintForV5.php", - "tests/Test/Constraint/SameStringsConstraintForV7.php", "tests/Test/IntegrationCase.php", "tests/Test/IntegrationCaseFactory.php", "tests/Test/IntegrationCaseFactoryInterface.php", @@ -4787,7 +4836,7 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2018-03-21T17:41:26+00:00" + "time": "2018-06-10T08:26:56+00:00" }, { "name": "fzaninotto/faker", @@ -5073,25 +5122,28 @@ }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -5114,20 +5166,20 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "time": "2018-06-11T23:09:50+00:00" }, { "name": "nunomaduro/collision", - "version": "v2.0.2", + "version": "v2.0.3", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "245958b02c6a9edf24627380f368333ac5413a51" + "reference": "b1f606399ae77e9479b5597cd1aa3d8ea0078176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/245958b02c6a9edf24627380f368333ac5413a51", - "reference": "245958b02c6a9edf24627380f368333ac5413a51", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/b1f606399ae77e9479b5597cd1aa3d8ea0078176", + "reference": "b1f606399ae77e9479b5597cd1aa3d8ea0078176", "shasum": "" }, "require": { @@ -5138,7 +5190,8 @@ }, "require-dev": { "laravel/framework": "5.6.*", - "phpunit/phpunit": "~7.0" + "phpstan/phpstan": "^0.9.2", + "phpunit/phpunit": "~7.2" }, "type": "library", "extra": { @@ -5176,7 +5229,7 @@ "php", "symfony" ], - "time": "2018-03-21T20:11:24+00:00" + "time": "2018-06-16T22:05:52+00:00" }, { "name": "phar-io/manifest", @@ -5716,23 +5769,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.0.4", + "version": "6.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca" + "reference": "865662550c384bc1db7e51d29aeda1c2c161d69a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/52187754b0eed0b8159f62a6fa30073327e8c2ca", - "reference": "52187754b0eed0b8159f62a6fa30073327e8c2ca", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/865662550c384bc1db7e51d29aeda1c2c161d69a", + "reference": "865662550c384bc1db7e51d29aeda1c2c161d69a", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", "php": "^7.1", - "phpunit/php-file-iterator": "^1.4.2", + "phpunit/php-file-iterator": "^2.0", "phpunit/php-text-template": "^1.2.1", "phpunit/php-token-stream": "^3.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", @@ -5775,29 +5828,29 @@ "testing", "xunit" ], - "time": "2018-04-29T14:59:09+00:00" + "time": "2018-06-01T07:51:50+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cecbc684605bb0cc288828eb5d65d93d5c676d3c", + "reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -5812,7 +5865,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -5822,7 +5875,7 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "time": "2018-06-11T11:44:00+00:00" }, { "name": "phpunit/php-text-template", @@ -5965,34 +6018,34 @@ }, { "name": "phpunit/phpunit", - "version": "7.1.5", + "version": "7.2.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "ca64dba53b88aba6af32aebc6b388068db95c435" + "reference": "400a3836ee549ae6f665323ac3f21e27eac7155f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ca64dba53b88aba6af32aebc6b388068db95c435", - "reference": "ca64dba53b88aba6af32aebc6b388068db95c435", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/400a3836ee549ae6f665323ac3f21e27eac7155f", + "reference": "400a3836ee549ae6f665323ac3f21e27eac7155f", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", + "myclabs/deep-copy": "^1.7", "phar-io/manifest": "^1.0.1", "phar-io/version": "^1.0", "php": "^7.1", "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.1", - "phpunit/php-file-iterator": "^1.4.3", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^2.0", - "phpunit/phpunit-mock-objects": "^6.1.1", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", "sebastian/environment": "^3.1", @@ -6002,10 +6055,14 @@ "sebastian/resource-operations": "^1.0", "sebastian/version": "^2.0.1" }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, "require-dev": { "ext-pdo": "*" }, "suggest": { + "ext-soap": "*", "ext-xdebug": "*", "phpunit/php-invoker": "^2.0" }, @@ -6015,7 +6072,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.1-dev" + "dev-master": "7.2-dev" } }, "autoload": { @@ -6041,63 +6098,7 @@ "testing", "xunit" ], - "time": "2018-04-29T15:09:19+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "6.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/70c740bde8fd9ea9ea295be1cd875dd7b267e157", - "reference": "70c740bde8fd9ea9ea295be1cd875dd7b267e157", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.1", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2018-04-11T04:50:36+00:00" + "time": "2018-06-21T13:13:39+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -6146,16 +6147,16 @@ }, { "name": "sebastian/comparator", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "ed5fd2281113729f1ebcc64d101ad66028aeb3d5" + "reference": "591a30922f54656695e59b1f39501aec513403da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ed5fd2281113729f1ebcc64d101ad66028aeb3d5", - "reference": "ed5fd2281113729f1ebcc64d101ad66028aeb3d5", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/591a30922f54656695e59b1f39501aec513403da", + "reference": "591a30922f54656695e59b1f39501aec513403da", "shasum": "" }, "require": { @@ -6206,20 +6207,20 @@ "compare", "equality" ], - "time": "2018-04-18T13:33:00+00:00" + "time": "2018-06-14T15:05:28+00:00" }, { "name": "sebastian/diff", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8" + "reference": "366541b989927187c4ca70490a35615d3fef2dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/e09160918c66281713f1c324c1f4c4c3037ba1e8", - "reference": "e09160918c66281713f1c324c1f4c4c3037ba1e8", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", + "reference": "366541b989927187c4ca70490a35615d3fef2dce", "shasum": "" }, "require": { @@ -6262,7 +6263,7 @@ "unidiff", "unified diff" ], - "time": "2018-02-01T13:45:15+00:00" + "time": "2018-06-10T07:54:39+00:00" }, { "name": "sebastian/environment", @@ -6664,7 +6665,7 @@ }, { "name": "symfony/class-loader", - "version": "v3.4.11", + "version": "v3.4.12", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", @@ -6720,16 +6721,16 @@ }, { "name": "symfony/filesystem", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04" + "reference": "562bf7005b55fd80d26b582d28e3e10f2dd5ae9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04", - "reference": "7a69e728e9f0044958c2fd7d72bfe5e7bd1a4d04", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/562bf7005b55fd80d26b582d28e3e10f2dd5ae9c", + "reference": "562bf7005b55fd80d26b582d28e3e10f2dd5ae9c", "shasum": "" }, "require": { @@ -6739,7 +6740,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -6766,20 +6767,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-05-16T09:05:32+00:00" + "time": "2018-05-30T07:26:09+00:00" }, { "name": "symfony/options-resolver", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "ac1c3a814ddcad9d0cc2d0382e215d3bff8ae2d2" + "reference": "45cdcc8a96ef92b43a50723e6d1f5f83096e8cef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ac1c3a814ddcad9d0cc2d0382e215d3bff8ae2d2", - "reference": "ac1c3a814ddcad9d0cc2d0382e215d3bff8ae2d2", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/45cdcc8a96ef92b43a50723e6d1f5f83096e8cef", + "reference": "45cdcc8a96ef92b43a50723e6d1f5f83096e8cef", "shasum": "" }, "require": { @@ -6788,7 +6789,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -6820,7 +6821,7 @@ "configuration", "options" ], - "time": "2018-05-11T15:58:37+00:00" + "time": "2018-05-31T10:17:53+00:00" }, { "name": "symfony/polyfill-php70", @@ -6883,16 +6884,16 @@ }, { "name": "symfony/stopwatch", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "6795ffa2f8eebedac77f045aa62c0c10b2763042" + "reference": "07463bbbbbfe119045a24c4a516f92ebd2752784" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6795ffa2f8eebedac77f045aa62c0c10b2763042", - "reference": "6795ffa2f8eebedac77f045aa62c0c10b2763042", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/07463bbbbbfe119045a24c4a516f92ebd2752784", + "reference": "07463bbbbbfe119045a24c4a516f92ebd2752784", "shasum": "" }, "require": { @@ -6901,7 +6902,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -6928,20 +6929,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2018-02-19T16:50:22+00:00" + "time": "2018-02-19T16:51:42+00:00" }, { "name": "symfony/yaml", - "version": "v4.0.11", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "048b1be5fb96e73ff1d065f5e7e23f84415ac907" + "reference": "80e4bfa9685fc4a09acc4a857ec16974a9cd944e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/048b1be5fb96e73ff1d065f5e7e23f84415ac907", - "reference": "048b1be5fb96e73ff1d065f5e7e23f84415ac907", + "url": "https://api.github.com/repos/symfony/yaml/zipball/80e4bfa9685fc4a09acc4a857ec16974a9cd944e", + "reference": "80e4bfa9685fc4a09acc4a857ec16974a9cd944e", "shasum": "" }, "require": { @@ -6960,7 +6961,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.1-dev" } }, "autoload": { @@ -6987,7 +6988,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-05-07T07:12:24+00:00" + "time": "2018-05-30T07:26:09+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/database.php b/config/database.php index 7d09275df..63b0b9cb6 100644 --- a/config/database.php +++ b/config/database.php @@ -34,6 +34,7 @@ return [ 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', '127.0.0.1'), + 'unix_socket' => env('DB_SOCKET'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'panel'), 'username' => env('DB_USERNAME', 'pterodactyl'), diff --git a/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php b/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php index 799f1df23..04fdf000f 100644 --- a/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php +++ b/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php @@ -14,7 +14,7 @@ class AddMaintenanceToNodes extends Migration public function up() { Schema::table('nodes', function (Blueprint $table) { - $table->boolean('maintenance_mode')->after('behind_proxy')->default(false); + $table->boolean('maintenance_mode')->after('behind_proxy')->default(false); }); } @@ -26,7 +26,7 @@ class AddMaintenanceToNodes extends Migration public function down() { Schema::table('nodes', function (Blueprint $table) { - $table->dropColumn('maintenance_mode'); + $table->dropColumn('maintenance_mode'); }); } } diff --git a/database/migrations/2018_09_03_143756_allow_egg_variables_to_have_longer_values.php b/database/migrations/2018_09_03_143756_allow_egg_variables_to_have_longer_values.php new file mode 100644 index 000000000..199650940 --- /dev/null +++ b/database/migrations/2018_09_03_143756_allow_egg_variables_to_have_longer_values.php @@ -0,0 +1,32 @@ +text('default_value')->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('egg_variables', function (Blueprint $table) { + $table->string('default_value')->change(); + }); + } +} diff --git a/database/migrations/2018_09_03_144005_allow_server_variables_to_have_longer_values.php b/database/migrations/2018_09_03_144005_allow_server_variables_to_have_longer_values.php new file mode 100644 index 000000000..cc90e0e06 --- /dev/null +++ b/database/migrations/2018_09_03_144005_allow_server_variables_to_have_longer_values.php @@ -0,0 +1,32 @@ +text('variable_value')->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('server_variables', function (Blueprint $table) { + $table->string('variable_value')->change(); + }); + } +} diff --git a/database/seeds/eggs/minecraft/egg-forge-minecraft.json b/database/seeds/eggs/minecraft/egg-forge-minecraft.json index 731d8844c..11be0aefb 100644 --- a/database/seeds/eggs/minecraft/egg-forge-minecraft.json +++ b/database/seeds/eggs/minecraft/egg-forge-minecraft.json @@ -3,7 +3,7 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-02-27T00:57:04-06:00", + "exported_at": "2018-06-25T15:47:07-04:00", "name": "Forge Minecraft", "author": "support@pterodactyl.io", "description": "Minecraft Forge Server. Minecraft Forge is a modding API (Application Programming Interface), which makes it easier to create mods, and also make sure mods are compatible with each other.", @@ -17,7 +17,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/ash\r\n# Forge Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl\r\n\r\nGET_VERSIONS=$(curl -sl http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/ | grep -A1 Latest | grep -o -e '[1]\\.[0-9][0-9]]\\?\\.\\?[0-9]\\?[0-9] - [0-9][0-9]\\.[0-9][0-9]\\.[0-9]\\?[0-9]\\.[0-9][0-9][0-9][0-9]')\r\nLATEST_VERSION=$(echo $GET_VERSIONS | sed 's\/ \/\/g')\r\n\r\ncd \/mnt\/server\r\n\r\ncurl -sS http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$LATEST_VERSION\/forge-$LATEST_VERSION-installer.jar -o installer.jar\r\ncurl -sS http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$LATEST_VERSION\/forge-$LATEST_VERSION-universal.jar -o server.jar\r\n\r\njava -jar installer.jar --installServer\r\nrm -rf installer.jar", + "script": "#!\/bin\/ash\r\n# Forge Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl\r\n\r\nif [ -z \"$MC_VERSION\" ] || [ \"$MC_VERSION\" == \"latest\" ]; then\r\n FORGE_VERSION=$(curl -sl http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/ | grep -A1 Latest | grep -o -e '[1]\\.[0-9][0-9]]\\?\\.\\?[0-9]\\?[0-9] - [0-9][0-9]\\.[0-9][0-9]\\.[0-9]\\?[0-9]\\.[0-9][0-9][0-9][0-9]' | sed 's\/ \/\/g')\r\nelse\r\n FORGE_VERSION=$(curl -sl http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/index_$MC_VERSION.html | grep -A1 Latest | grep -o -e '[1]\\.[0-9][0-9]]\\?\\.\\?[0-9]\\?[0-9] - [0-9][0-9]\\.[0-9][0-9]\\.[0-9]\\?[0-9]\\.[0-9][0-9][0-9][0-9]' | sed 's\/ \/\/g')\r\nfi\r\n\r\ncd \/mnt\/server\r\n\r\necho -e \"\\nDownloading Forge Version $FORGE_VERSION\\n\"\r\ncurl -sS http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$FORGE_VERSION\/forge-$FORGE_VERSION-installer.jar -o installer.jar\r\ncurl -sS http:\/\/files.minecraftforge.net\/maven\/net\/minecraftforge\/forge\/$FORGE_VERSION\/forge-$FORGE_VERSION-universal.jar -o $SERVER_JARFILE\r\n\r\necho -e \"\\nInstalling forge server usint the installer jar file.\\n\"\r\njava -jar installer.jar --installServer\r\n\r\necho -e \"\\nDeleting installer jar file and cleaning up.\\n\"\r\nrm -rf installer.jar", "container": "frolvlad\/alpine-oraclejdk8:cleaned", "entrypoint": "ash" } @@ -31,6 +31,15 @@ "user_viewable": 1, "user_editable": 1, "rules": "required|regex:\/^([\\w\\d._-]+)(\\.jar)$\/" + }, + { + "name": "Minecraft version", + "description": "The version of minecraft that you want to run. Example (1.10.2).", + "env_variable": "MC_VERSION", + "default_value": "latest", + "user_viewable": 1, + "user_editable": 1, + "rules": "required|string|max:20" } ] } diff --git a/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json b/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json index 3d87b1fa2..3c71a6b2b 100644 --- a/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json +++ b/database/seeds/eggs/minecraft/egg-vanilla-minecraft.json @@ -3,7 +3,7 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2017-11-03T22:15:07-05:00", + "exported_at": "2018-06-19T17:09:18-04:00", "name": "Vanilla Minecraft", "author": "support@pterodactyl.io", "description": "Minecraft is a game about placing blocks and going on adventures. Explore randomly generated worlds and build amazing things from the simplest of homes to the grandest of castles. Play in Creative Mode with unlimited resources or mine deep in Survival Mode, crafting weapons and armor to fend off dangerous mobs. Do all this alone or with friends.", @@ -17,8 +17,8 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/ash\r\n# Vanilla MC Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl\r\n\r\ncd \/mnt\/server\r\n\r\nLATEST_VERSION=`curl -s https:\/\/s3.amazonaws.com\/Minecraft.Download\/versions\/versions.json | grep -o \"[[:digit:]]\\.[0-9]*\\.[0-9]\" | head -n 1`\r\n\r\nif [ -z \"$VANILLA_VERSION\" ] || [ \"$VANILLA_VERSION\" == \"latest\" ]; then\r\n DL_VERSION=$LATEST_VERSION\r\nelse\r\n DL_VERSION=$VANILLA_VERSION\r\nfi\r\n\r\ncurl -o ${SERVER_JARFILE} https:\/\/s3.amazonaws.com\/Minecraft.Download\/versions\/${DL_VERSION}\/minecraft_server.${DL_VERSION}.jar", - "container": "alpine:3.4", + "script": "#!\/bin\/ash\r\n# Vanilla MC Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\napk update\r\napk add curl jq\r\n\r\ncd \/mnt\/server\r\n\r\nLATEST_VERSION=`curl https:\/\/launchermeta.mojang.com\/mc\/game\/version_manifest.json | jq -r '.latest.release'`\r\n\r\nif [ -z \"$VANILLA_VERSION\" ] || [ \"$VANILLA_VERSION\" == \"latest\" ]; then\r\n MANIFEST_URL=$(curl https:\/\/launchermeta.mojang.com\/mc\/game\/version_manifest.json | jq .versions | jq -r '.[] | select(.id == \"'$LATEST_VERSION'\") | .url')\r\nelse\r\n MANIFEST_URL=$(curl https:\/\/launchermeta.mojang.com\/mc\/game\/version_manifest.json | jq .versions | jq -r '.[] | select(.id == \"'$VANILLA_VERSION'\") | .url')\r\nfi\r\n\r\nDOWNLOAD_URL=`curl $MANIFEST_URL | jq .downloads.server | jq -r '. | .url'`\r\n\r\ncurl -o ${SERVER_JARFILE} $DOWNLOAD_URL", + "container": "alpine:3.7", "entrypoint": "ash" } }, @@ -39,7 +39,7 @@ "default_value": "latest", "user_viewable": 1, "user_editable": 1, - "rules": "required|string|between:3,7" + "rules": "required|string|between:3,15" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json b/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json index 092033092..4b2ec6356 100644 --- a/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json +++ b/database/seeds/eggs/source-engine/egg-ark--survival-evolved.json @@ -3,12 +3,12 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-01-21T16:59:40-06:00", + "exported_at": "2018-07-06T11:27:32+02:00", "name": "Ark: Survival Evolved", "author": "support@pterodactyl.io", "description": "As a man or woman stranded, naked, freezing, and starving on the unforgiving shores of a mysterious island called ARK, use your skill and cunning to kill or tame and ride the plethora of leviathan dinosaurs and other primeval creatures roaming the land. Hunt, harvest resources, craft items, grow crops, research technologies, and build shelters to withstand the elements and store valuables, all while teaming up with (or preying upon) hundreds of other players to survive, dominate... and escape! \u2014 Gamepedia: ARK", "image": "quay.io\/pterodactyl\/core:source", - "startup": ".\/ShooterGame\/Binaries\/Linux\/ShooterGameServer TheIsland?listen?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{SERVER_PORT}}?MaxPlayers={{SERVER_MAX_PLAYERS}}", + "startup": ".\/ShooterGame\/Binaries\/Linux\/ShooterGameServer {{SERVER_MAP}}?listen?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{SERVER_PORT}}?MaxPlayers={{SERVER_MAX_PLAYERS}}", "config": { "files": "{}", "startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}", @@ -49,6 +49,15 @@ "user_viewable": 1, "user_editable": 1, "rules": "required|numeric|digits_between:1,4" + }, + { + "name": "Server Map", + "description": "Available Maps: TheIsland, TheCenter, Ragnarok, ScorchedEarth_P, Aberration_P", + "env_variable": "SERVER_MAP", + "default_value": "TheIsland", + "user_viewable": 1, + "user_editable": 1, + "rules": "required|string|max:20" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/source-engine/egg-counter--strike--global-offensive.json b/database/seeds/eggs/source-engine/egg-counter--strike--global-offensive.json index 3c1ae8e56..ad9210256 100644 --- a/database/seeds/eggs/source-engine/egg-counter--strike--global-offensive.json +++ b/database/seeds/eggs/source-engine/egg-counter--strike--global-offensive.json @@ -3,7 +3,7 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-01-21T16:59:47-06:00", + "exported_at": "2018-06-19T07:46:06-04:00", "name": "Counter-Strike: Global Offensive", "author": "support@pterodactyl.io", "description": "Counter-Strike: Global Offensive is a multiplayer first-person shooter video game developed by Hidden Path Entertainment and Valve Corporation.", @@ -11,7 +11,7 @@ "startup": ".\/srcds_run -game csgo -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}", "config": { "files": "{}", - "startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}", + "startup": "{\r\n \"done\": \"Connection to Steam servers successful\",\r\n \"userInteraction\": []\r\n}", "logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs\/latest.log\"\r\n}", "stop": "quit" }, @@ -40,6 +40,15 @@ "user_viewable": 1, "user_editable": 1, "rules": "required|string|alpha_num|size:32" + }, + { + "name": "Source AppID", + "description": "Required for game to update on server restart. Do not modify this.", + "env_variable": "SRCDS_APPID", + "default_value": "740", + "user_viewable": 0, + "user_editable": 0, + "rules": "required|string|max:20" } ] -} \ No newline at end of file +} diff --git a/database/seeds/eggs/source-engine/egg-garrys-mod.json b/database/seeds/eggs/source-engine/egg-garrys-mod.json index c8f3ebb84..0bfdc0a07 100644 --- a/database/seeds/eggs/source-engine/egg-garrys-mod.json +++ b/database/seeds/eggs/source-engine/egg-garrys-mod.json @@ -3,7 +3,7 @@ "meta": { "version": "PTDL_v1" }, - "exported_at": "2018-01-21T16:59:47-06:00", + "exported_at": "2018-06-19T07:46:27-04:00", "name": "Garrys Mod", "author": "support@pterodactyl.io", "description": "Garrys Mod, is a sandbox physics game created by Garry Newman, and developed by his company, Facepunch Studios.", @@ -40,6 +40,15 @@ "user_viewable": 1, "user_editable": 1, "rules": "required|string|alpha_num|size:32" + }, + { + "name": "Source AppID", + "description": "Required for game to update on server restart. Do not modify this.", + "env_variable": "SRCDS_APPID", + "default_value": "4020", + "user_viewable": 0, + "user_editable": 0, + "rules": "required|string|max:20" } ] -} \ No newline at end of file +} diff --git a/public/themes/pterodactyl/css/pterodactyl.css b/public/themes/pterodactyl/css/pterodactyl.css index 41f163f3b..a4e4c4cf7 100644 --- a/public/themes/pterodactyl/css/pterodactyl.css +++ b/public/themes/pterodactyl/css/pterodactyl.css @@ -474,6 +474,11 @@ label.control-label > span.field-optional:before { width: auto; } +.search01 { + width: 30%; +} + .number-info-box-content { padding: 15px 10px 0; } + diff --git a/public/themes/pterodactyl/css/terminal.css b/public/themes/pterodactyl/css/terminal.css index ecdd10ffc..29ede479b 100644 --- a/public/themes/pterodactyl/css/terminal.css +++ b/public/themes/pterodactyl/css/terminal.css @@ -26,6 +26,7 @@ #terminal > .cmd { padding: 1px 0; + white-space: pre; } #terminal_input { diff --git a/public/themes/pterodactyl/js/frontend/files/filemanager.min.js b/public/themes/pterodactyl/js/frontend/files/filemanager.min.js index 2dc67f833..eeb7370b3 100644 --- a/public/themes/pterodactyl/js/frontend/files/filemanager.min.js +++ b/public/themes/pterodactyl/js/frontend/files/filemanager.min.js @@ -1,4 +1,4 @@ -'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i\n \n ';nameBlock.html(attachEditor);var inputField=nameBlock.find('input');var inputLoader=nameBlock.find('.input-loader');inputField.focus();inputField.on('blur keydown',function(e){if(e.type==='keydown'&&e.which===27||e.type==='blur'||e.type==='keydown'&&e.which===13&¤tName===inputField.val()){if(!_.isEmpty(currentLink)){nameBlock.html(currentLink)}else{nameBlock.html(currentName)}inputField.remove();ContextMenu.unbind().run();return}if(e.type==='keydown'&&e.which!==13)return;inputLoader.show();var currentPath=decodeURIComponent(nameBlock.data('path'));$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/rename',timeout:10000,data:JSON.stringify({from:''+currentPath+currentName,to:''+currentPath+inputField.val()})}).done(function(data){nameBlock.attr('data-name',inputField.val());if(!_.isEmpty(currentLink)){var newLink=currentLink.attr('href');if(nameBlock.parent().data('type')!=='folder'){newLink=newLink.substr(0,newLink.lastIndexOf('/'))+'/'+inputField.val()}currentLink.attr('href',newLink);nameBlock.html(currentLink.html(inputField.val()))}else{nameBlock.html(inputField.val())}inputField.remove()}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}nameBlock.addClass('has-error').delay(2000).queue(function(){nameBlock.removeClass('has-error').dequeue()});inputField.popover({animation:true,placement:'top',content:error,title:'Save Error'}).popover('show')}).always(function(){inputLoader.remove();ContextMenu.unbind().run()})})}},{key:'copy',value:function copy(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var currentName=decodeURIComponent(nameBlock.attr('data-name'));var currentPath=decodeURIComponent(nameBlock.data('path'));swal({type:'input',title:'Copy File',text:'Please enter the new path for the copied file below.',showCancelButton:true,showConfirmButton:true,closeOnConfirm:false,showLoaderOnConfirm:true,inputValue:''+currentPath+currentName},function(val){$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/copy',timeout:10000,data:JSON.stringify({from:''+currentPath+currentName,to:''+val})}).done(function(data){swal({type:'success',title:'',text:'File successfully copied.'});Files.list()}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}swal({type:'error',title:'',text:error})})})}},{key:'download',value:function download(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var fileName=decodeURIComponent(nameBlock.attr('data-name'));var filePath=decodeURIComponent(nameBlock.data('path'));window.location='/server/'+Pterodactyl.server.uuidShort+'/files/download/'+filePath+fileName}},{key:'delete',value:function _delete(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var delPath=decodeURIComponent(nameBlock.data('path'));var delName=decodeURIComponent(nameBlock.data('name'));swal({type:'warning',title:'',text:'Are you sure you want to delete '+delName+'?',html:true,showCancelButton:true,showConfirmButton:true,closeOnConfirm:false,showLoaderOnConfirm:true},function(){$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/delete',timeout:10000,data:JSON.stringify({items:[''+delPath+delName]})}).done(function(data){nameBlock.parent().addClass('warning').delay(200).fadeOut();swal({type:'success',title:'File Deleted'})}).fail(function(jqXHR){console.error(jqXHR);swal({type:'error',title:'Whoops!',html:true,text:'An error occurred while attempting to delete this file. Please try again.'})})})}},{key:'toggleMassActions',value:function toggleMassActions(){if($('#file_listing input[type="checkbox"]:checked').length){$('#mass_actions').removeClass('disabled')}else{$('#mass_actions').addClass('disabled')}}},{key:'toggleHighlight',value:function toggleHighlight(event){var parent=$(event.currentTarget);var item=$(event.currentTarget).find('input');if($(item).is(':checked')){$(item).prop('checked',false);parent.removeClass('warning').delay(200)}else{$(item).prop('checked',true);parent.addClass('warning').delay(200)}}},{key:'highlightAll',value:function highlightAll(event){var parent=void 0;var item=$(event.currentTarget).find('input');if($(item).is(':checked')){$('#file_listing input[type=checkbox]').prop('checked',false);$('#file_listing input[data-action="addSelection"]').each(function(){parent=$(this).closest('tr');parent.removeClass('warning').delay(200)})}else{$('#file_listing input[type=checkbox]').prop('checked',true);$('#file_listing input[data-action="addSelection"]').each(function(){parent=$(this).closest('tr');parent.addClass('warning').delay(200)})}}},{key:'deleteSelected',value:function deleteSelected(){var selectedItems=[];var selectedItemsElements=[];var parent=void 0;var nameBlock=void 0;var delLocation=void 0;$('#file_listing input[data-action="addSelection"]:checked').each(function(){parent=$(this).closest('tr');nameBlock=$(parent).find('td[data-identifier="name"]');delLocation=decodeURIComponent(nameBlock.data('path'))+decodeURIComponent(nameBlock.data('name'));selectedItems.push(delLocation);selectedItemsElements.push(parent)});if(selectedItems.length!=0){var formattedItems='';var i=0;$.each(selectedItems,function(key,value){formattedItems+=''+value+', ';i++;return i<5});formattedItems=formattedItems.slice(0,-2);if(selectedItems.length>5){formattedItems+=', and '+(selectedItems.length-5)+' other(s)'}swal({type:'warning',title:'',text:'Are you sure you want to delete the following files: '+formattedItems+'?',html:true,showCancelButton:true,showConfirmButton:true,closeOnConfirm:false,showLoaderOnConfirm:true},function(){$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/delete',timeout:10000,data:JSON.stringify({items:selectedItems})}).done(function(data){$('#file_listing input:checked').each(function(){$(this).prop('checked',false)});$.each(selectedItemsElements,function(){$(this).addClass('warning').delay(200).fadeOut()});swal({type:'success',title:'Files Deleted'})}).fail(function(jqXHR){console.error(jqXHR);swal({type:'error',title:'Whoops!',html:true,text:'An error occurred while attempting to delete these files. Please try again.'})})})}else{swal({type:'warning',title:'',text:'Please select files/folders to delete.'})}}},{key:'decompress',value:function decompress(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var compPath=decodeURIComponent(nameBlock.data('path'));var compName=decodeURIComponent(nameBlock.data('name'));swal({title:' Decompressing...',text:'This might take a few seconds to complete.',html:true,allowOutsideClick:false,allowEscapeKey:false,showConfirmButton:false});$.ajax({type:'POST',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/decompress',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',data:JSON.stringify({files:''+compPath+compName})}).done(function(data){swal.close();Files.list(compPath)}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}swal({type:'error',title:'Whoops!',html:true,text:error})})}},{key:'compress',value:function compress(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var compPath=decodeURIComponent(nameBlock.data('path'));var compName=decodeURIComponent(nameBlock.data('name'));$.ajax({type:'POST',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/compress',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',data:JSON.stringify({files:''+compPath+compName,to:compPath.toString()})}).done(function(data){Files.list(compPath,function(err){if(err)return;var fileListing=$('#file_listing').find('[data-name="'+data.saved_as+'"]').parent();fileListing.addClass('success pulsate').delay(3000).queue(function(){fileListing.removeClass('success pulsate').dequeue()})})}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}swal({type:'error',title:'Whoops!',html:true,text:error})})}}]);return ActionsClass}(); +'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i\n \n ';nameBlock.html(attachEditor);var inputField=nameBlock.find('input');var inputLoader=nameBlock.find('.input-loader');inputField.focus();inputField.on('blur keydown',function(e){if(e.type==='keydown'&&e.which===27||e.type==='blur'||e.type==='keydown'&&e.which===13&¤tName===inputField.val()){if(!_.isEmpty(currentLink)){nameBlock.html(currentLink)}else{nameBlock.html(currentName)}inputField.remove();ContextMenu.unbind().run();return}if(e.type==='keydown'&&e.which!==13)return;inputLoader.show();var currentPath=decodeURIComponent(nameBlock.data('path'));$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/rename',timeout:10000,data:JSON.stringify({from:''+currentPath+currentName,to:''+currentPath+inputField.val()})}).done(function(data){nameBlock.attr('data-name',inputField.val());if(!_.isEmpty(currentLink)){var newLink=currentLink.attr('href');if(nameBlock.parent().data('type')!=='folder'){newLink=newLink.substr(0,newLink.lastIndexOf('/'))+'/'+inputField.val()}currentLink.attr('href',newLink);nameBlock.html(currentLink.html(inputField.val()))}else{nameBlock.html(inputField.val())}inputField.remove()}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}nameBlock.addClass('has-error').delay(2000).queue(function(){nameBlock.removeClass('has-error').dequeue()});inputField.popover({animation:true,placement:'top',content:error,title:'Save Error'}).popover('show')}).always(function(){inputLoader.remove();ContextMenu.unbind().run()})})}},{key:'copy',value:function copy(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var currentName=decodeURIComponent(nameBlock.attr('data-name'));var currentPath=decodeURIComponent(nameBlock.data('path'));swal({type:'input',title:'Copy File',text:'Please enter the new path for the copied file below.',showCancelButton:true,showConfirmButton:true,closeOnConfirm:false,showLoaderOnConfirm:true,inputValue:''+currentPath+currentName},function(val){if(val===false){return false}$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/copy',timeout:10000,data:JSON.stringify({from:''+currentPath+currentName,to:''+val})}).done(function(data){swal({type:'success',title:'',text:'File successfully copied.'});Files.list()}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}swal({type:'error',title:'',text:error})})})}},{key:'download',value:function download(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var fileName=decodeURIComponent(nameBlock.attr('data-name'));var filePath=decodeURIComponent(nameBlock.data('path'));window.location='/server/'+Pterodactyl.server.uuidShort+'/files/download/'+filePath+fileName}},{key:'delete',value:function _delete(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var delPath=decodeURIComponent(nameBlock.data('path'));var delName=decodeURIComponent(nameBlock.data('name'));swal({type:'warning',title:'',text:'Are you sure you want to delete '+delName+'?',html:true,showCancelButton:true,showConfirmButton:true,closeOnConfirm:false,showLoaderOnConfirm:true},function(){$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/delete',timeout:10000,data:JSON.stringify({items:[''+delPath+delName]})}).done(function(data){nameBlock.parent().addClass('warning').delay(200).fadeOut();swal({type:'success',title:'File Deleted'})}).fail(function(jqXHR){console.error(jqXHR);swal({type:'error',title:'Whoops!',html:true,text:'An error occurred while attempting to delete this file. Please try again.'})})})}},{key:'toggleMassActions',value:function toggleMassActions(){if($('#file_listing input[type="checkbox"]:checked').length){$('#mass_actions').removeClass('disabled')}else{$('#mass_actions').addClass('disabled')}}},{key:'toggleHighlight',value:function toggleHighlight(event){var parent=$(event.currentTarget);var item=$(event.currentTarget).find('input');if($(item).is(':checked')){$(item).prop('checked',false);parent.removeClass('warning').delay(200)}else{$(item).prop('checked',true);parent.addClass('warning').delay(200)}}},{key:'highlightAll',value:function highlightAll(event){var parent=void 0;var item=$(event.currentTarget).find('input');if($(item).is(':checked')){$('#file_listing input[type=checkbox]').prop('checked',false);$('#file_listing input[data-action="addSelection"]').each(function(){parent=$(this).closest('tr');parent.removeClass('warning').delay(200)})}else{$('#file_listing input[type=checkbox]').prop('checked',true);$('#file_listing input[data-action="addSelection"]').each(function(){parent=$(this).closest('tr');parent.addClass('warning').delay(200)})}}},{key:'deleteSelected',value:function deleteSelected(){var selectedItems=[];var selectedItemsElements=[];var parent=void 0;var nameBlock=void 0;var delLocation=void 0;$('#file_listing input[data-action="addSelection"]:checked').each(function(){parent=$(this).closest('tr');nameBlock=$(parent).find('td[data-identifier="name"]');delLocation=decodeURIComponent(nameBlock.data('path'))+decodeURIComponent(nameBlock.data('name'));selectedItems.push(delLocation);selectedItemsElements.push(parent)});if(selectedItems.length!=0){var formattedItems='';var i=0;$.each(selectedItems,function(key,value){formattedItems+=''+value+', ';i++;return i<5});formattedItems=formattedItems.slice(0,-2);if(selectedItems.length>5){formattedItems+=', and '+(selectedItems.length-5)+' other(s)'}swal({type:'warning',title:'',text:'Are you sure you want to delete the following files: '+formattedItems+'?',html:true,showCancelButton:true,showConfirmButton:true,closeOnConfirm:false,showLoaderOnConfirm:true},function(){$.ajax({type:'POST',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/delete',timeout:10000,data:JSON.stringify({items:selectedItems})}).done(function(data){$('#file_listing input:checked').each(function(){$(this).prop('checked',false)});$.each(selectedItemsElements,function(){$(this).addClass('warning').delay(200).fadeOut()});swal({type:'success',title:'Files Deleted'})}).fail(function(jqXHR){console.error(jqXHR);swal({type:'error',title:'Whoops!',html:true,text:'An error occurred while attempting to delete these files. Please try again.'})})})}else{swal({type:'warning',title:'',text:'Please select files/folders to delete.'})}}},{key:'decompress',value:function decompress(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var compPath=decodeURIComponent(nameBlock.data('path'));var compName=decodeURIComponent(nameBlock.data('name'));swal({title:' Decompressing...',text:'This might take a few seconds to complete.',html:true,allowOutsideClick:false,allowEscapeKey:false,showConfirmButton:false});$.ajax({type:'POST',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/decompress',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',data:JSON.stringify({files:''+compPath+compName})}).done(function(data){swal.close();Files.list(compPath)}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}swal({type:'error',title:'Whoops!',html:true,text:error})})}},{key:'compress',value:function compress(){var nameBlock=$(this.element).find('td[data-identifier="name"]');var compPath=decodeURIComponent(nameBlock.data('path'));var compName=decodeURIComponent(nameBlock.data('name'));$.ajax({type:'POST',url:Pterodactyl.node.scheme+'://'+Pterodactyl.node.fqdn+':'+Pterodactyl.node.daemonListen+'/v1/server/file/compress',headers:{'X-Access-Token':Pterodactyl.server.daemonSecret,'X-Access-Server':Pterodactyl.server.uuid},contentType:'application/json; charset=utf-8',data:JSON.stringify({files:''+compPath+compName,to:compPath.toString()})}).done(function(data){Files.list(compPath,function(err){if(err)return;var fileListing=$('#file_listing').find('[data-name="'+data.saved_as+'"]').parent();fileListing.addClass('success pulsate').delay(3000).queue(function(){fileListing.removeClass('success pulsate').dequeue()})})}).fail(function(jqXHR){console.error(jqXHR);var error='An error occurred while trying to process this request.';if(typeof jqXHR.responseJSON!=='undefined'&&typeof jqXHR.responseJSON.error!=='undefined'){error=jqXHR.responseJSON.error}swal({type:'error',title:'Whoops!',html:true,text:error})})}}]);return ActionsClass}(); 'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i New File
  • New Folder
  • '}if(Pterodactyl.permissions.downloadFiles||Pterodactyl.permissions.deleteFiles){buildMenu+='
  • '}if(Pterodactyl.permissions.downloadFiles){buildMenu+=''}if(Pterodactyl.permissions.deleteFiles){buildMenu+='
  • Delete
  • '}buildMenu+='';return buildMenu}},{key:'rightClick',value:function rightClick(){var _this=this;$('[data-action="toggleMenu"]').on('mousedown',function(event){event.preventDefault();if($(document).find('#fileOptionMenu').is(':visible')){$('body').trigger('click');return}_this.showMenu(event)});$('#file_listing > tbody td').on('contextmenu',function(event){_this.showMenu(event)})}},{key:'showMenu',value:function showMenu(event){var _this2=this;var parent=$(event.target).closest('tr');var menu=$(this.makeMenu(parent));if(parent.data('type')==='disabled')return;event.preventDefault();$(menu).appendTo('body');$(menu).data('invokedOn',$(event.target)).show().css({position:'absolute',left:event.pageX-150,top:event.pageY});this.activeLine=parent;this.activeLine.addClass('active');var Actions=new ActionsClass(parent,menu);if(Pterodactyl.permissions.moveFiles){$(menu).find('li[data-action="move"]').unbind().on('click',function(e){e.preventDefault();Actions.move()});$(menu).find('li[data-action="rename"]').unbind().on('click',function(e){e.preventDefault();Actions.rename()})}if(Pterodactyl.permissions.copyFiles){$(menu).find('li[data-action="copy"]').unbind().on('click',function(e){e.preventDefault();Actions.copy()})}if(Pterodactyl.permissions.compressFiles){if(parent.data('type')==='folder'){$(menu).find('li[data-action="compress"]').removeClass('hidden')}$(menu).find('li[data-action="compress"]').unbind().on('click',function(e){e.preventDefault();Actions.compress()})}if(Pterodactyl.permissions.decompressFiles){if(_.without(['application/zip','application/gzip','application/x-gzip'],parent.data('mime')).length<3){$(menu).find('li[data-action="decompress"]').removeClass('hidden')}$(menu).find('li[data-action="decompress"]').unbind().on('click',function(e){e.preventDefault();Actions.decompress()})}if(Pterodactyl.permissions.createFiles){$(menu).find('li[data-action="folder"]').unbind().on('click',function(e){e.preventDefault();Actions.folder()})}if(Pterodactyl.permissions.downloadFiles){if(parent.data('type')==='file'){$(menu).find('li[data-action="download"]').removeClass('hidden')}$(menu).find('li[data-action="download"]').unbind().on('click',function(e){e.preventDefault();Actions.download()})}if(Pterodactyl.permissions.deleteFiles){$(menu).find('li[data-action="delete"]').unbind().on('click',function(e){e.preventDefault();Actions.delete()})}$(window).unbind().on('click',function(event){if($(event.target).is('.disable-menu-hide')){event.preventDefault();return}$(menu).unbind().remove();if(!_.isNull(_this2.activeLine))_this2.activeLine.removeClass('active')})}},{key:'directoryClick',value:function directoryClick(){$('a[data-action="directory-view"]').on('click',function(event){event.preventDefault();var path=$(this).parent().data('path')||'';var name=$(this).parent().data('name')||'';window.location.hash=encodeURIComponent(path+name);Files.list()})}}]);return ContextMenuClass}();window.ContextMenu=new ContextMenuClass; 'use strict';var _typeof=typeof Symbol==='function'&&typeof Symbol.iterator==='symbol'?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==='function'&&obj.constructor===Symbol&&obj!==Symbol.prototype?'symbol':typeof obj};var _createClass=function(){function defineProperties(target,props){for(var i=0;i\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\nclass ActionsClass {\n constructor(element, menu) {\n this.element = element;\n this.menu = menu;\n }\n\n destroy() {\n this.element = undefined;\n }\n\n folder(path) {\n let inputValue\n if (path) {\n inputValue = path\n } else {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.data('name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n if ($(this.element).data('type') === 'file') {\n inputValue = currentPath;\n } else {\n inputValue = `${currentPath}${currentName}/`;\n }\n }\n\n swal({\n type: 'input',\n title: 'Create Folder',\n text: 'Please enter the path and folder name below.',\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n inputValue: inputValue\n }, (val) => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/folder`,\n timeout: 10000,\n data: JSON.stringify({\n path: val,\n }),\n }).done(data => {\n swal.close();\n Files.list();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: '',\n text: error,\n });\n });\n });\n }\n\n move() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n swal({\n type: 'input',\n title: 'Move File',\n text: 'Please enter the new path for the file below.',\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n inputValue: `${currentPath}${currentName}`,\n }, (val) => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/move`,\n timeout: 10000,\n data: JSON.stringify({\n from: `${currentPath}${currentName}`,\n to: `${val}`,\n }),\n }).done(data => {\n nameBlock.parent().addClass('warning').delay(200).fadeOut();\n swal.close();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: '',\n text: error,\n });\n });\n });\n\n }\n\n rename() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentLink = nameBlock.find('a');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const attachEditor = `\n \n \n `;\n\n nameBlock.html(attachEditor);\n const inputField = nameBlock.find('input');\n const inputLoader = nameBlock.find('.input-loader');\n\n inputField.focus();\n inputField.on('blur keydown', e => {\n // Save Field\n if (\n (e.type === 'keydown' && e.which === 27)\n || e.type === 'blur'\n || (e.type === 'keydown' && e.which === 13 && currentName === inputField.val())\n ) {\n if (!_.isEmpty(currentLink)) {\n nameBlock.html(currentLink);\n } else {\n nameBlock.html(currentName);\n }\n inputField.remove();\n ContextMenu.unbind().run();\n return;\n }\n\n if (e.type === 'keydown' && e.which !== 13) return;\n\n inputLoader.show();\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/rename`,\n timeout: 10000,\n data: JSON.stringify({\n from: `${currentPath}${currentName}`,\n to: `${currentPath}${inputField.val()}`,\n }),\n }).done(data => {\n nameBlock.attr('data-name', inputField.val());\n if (!_.isEmpty(currentLink)) {\n let newLink = currentLink.attr('href');\n if (nameBlock.parent().data('type') !== 'folder') {\n newLink = newLink.substr(0, newLink.lastIndexOf('/')) + '/' + inputField.val();\n }\n currentLink.attr('href', newLink);\n nameBlock.html(\n currentLink.html(inputField.val())\n );\n } else {\n nameBlock.html(inputField.val());\n }\n inputField.remove();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n nameBlock.addClass('has-error').delay(2000).queue(() => {\n nameBlock.removeClass('has-error').dequeue();\n });\n inputField.popover({\n animation: true,\n placement: 'top',\n content: error,\n title: 'Save Error'\n }).popover('show');\n }).always(() => {\n inputLoader.remove();\n ContextMenu.unbind().run();\n });\n });\n }\n\n copy() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n swal({\n type: 'input',\n title: 'Copy File',\n text: 'Please enter the new path for the copied file below.',\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n inputValue: `${currentPath}${currentName}`,\n }, (val) => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/copy`,\n timeout: 10000,\n data: JSON.stringify({\n from: `${currentPath}${currentName}`,\n to: `${val}`,\n }),\n }).done(data => {\n swal({\n type: 'success',\n title: '',\n text: 'File successfully copied.'\n });\n Files.list();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: '',\n text: error,\n });\n });\n });\n }\n\n download() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const fileName = decodeURIComponent(nameBlock.attr('data-name'));\n const filePath = decodeURIComponent(nameBlock.data('path'));\n\n window.location = `/server/${Pterodactyl.server.uuidShort}/files/download/${filePath}${fileName}`;\n }\n\n delete() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const delPath = decodeURIComponent(nameBlock.data('path'));\n const delName = decodeURIComponent(nameBlock.data('name'));\n\n swal({\n type: 'warning',\n title: '',\n text: 'Are you sure you want to delete ' + delName + '?',\n html: true,\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true\n }, () => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/delete`,\n timeout: 10000,\n data: JSON.stringify({\n items: [`${delPath}${delName}`]\n }),\n }).done(data => {\n nameBlock.parent().addClass('warning').delay(200).fadeOut();\n swal({\n type: 'success',\n title: 'File Deleted'\n });\n }).fail(jqXHR => {\n console.error(jqXHR);\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: 'An error occurred while attempting to delete this file. Please try again.',\n });\n });\n });\n }\n\n toggleMassActions() {\n if ($('#file_listing input[type=\"checkbox\"]:checked').length) {\n $('#mass_actions').removeClass('disabled');\n } else {\n $('#mass_actions').addClass('disabled');\n }\n }\n\n toggleHighlight(event) {\n const parent = $(event.currentTarget);\n const item = $(event.currentTarget).find('input');\n\n if($(item).is(':checked')) {\n $(item).prop('checked', false);\n parent.removeClass('warning').delay(200);\n } else {\n $(item).prop('checked', true);\n parent.addClass('warning').delay(200);\n }\n }\n\n highlightAll(event) {\n let parent;\n const item = $(event.currentTarget).find('input');\n\n if($(item).is(':checked')) {\n $('#file_listing input[type=checkbox]').prop('checked', false);\n $('#file_listing input[data-action=\"addSelection\"]').each(function() {\n parent = $(this).closest('tr');\n parent.removeClass('warning').delay(200);\n });\n } else {\n $('#file_listing input[type=checkbox]').prop('checked', true);\n $('#file_listing input[data-action=\"addSelection\"]').each(function() {\n parent = $(this).closest('tr');\n parent.addClass('warning').delay(200);\n });\n }\n }\n\n deleteSelected() {\n let selectedItems = [];\n let selectedItemsElements = [];\n let parent;\n let nameBlock;\n let delLocation;\n\n $('#file_listing input[data-action=\"addSelection\"]:checked').each(function() {\n parent = $(this).closest('tr');\n nameBlock = $(parent).find('td[data-identifier=\"name\"]');\n delLocation = decodeURIComponent(nameBlock.data('path')) + decodeURIComponent(nameBlock.data('name'));\n\n selectedItems.push(delLocation);\n selectedItemsElements.push(parent);\n });\n\n if (selectedItems.length != 0)\n {\n let formattedItems = \"\";\n let i = 0;\n $.each(selectedItems, function(key, value) {\n formattedItems += (\"\" + value + \", \");\n i++;\n return i < 5;\n });\n\n formattedItems = formattedItems.slice(0, -2);\n if (selectedItems.length > 5) {\n formattedItems += ', and ' + (selectedItems.length - 5) + ' other(s)';\n }\n\n swal({\n type: 'warning',\n title: '',\n text: 'Are you sure you want to delete the following files: ' + formattedItems + '?',\n html: true,\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true\n }, () => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/delete`,\n timeout: 10000,\n data: JSON.stringify({\n items: selectedItems\n }),\n }).done(data => {\n $('#file_listing input:checked').each(function() {\n $(this).prop('checked', false);\n });\n\n $.each(selectedItemsElements, function() {\n $(this).addClass('warning').delay(200).fadeOut();\n })\n\n swal({\n type: 'success',\n title: 'Files Deleted'\n });\n }).fail(jqXHR => {\n console.error(jqXHR);\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: 'An error occurred while attempting to delete these files. Please try again.',\n });\n });\n });\n } else {\n swal({\n type: 'warning',\n title: '',\n text: 'Please select files/folders to delete.',\n });\n }\n }\n\n decompress() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const compPath = decodeURIComponent(nameBlock.data('path'));\n const compName = decodeURIComponent(nameBlock.data('name'));\n\n swal({\n title: ' Decompressing...',\n text: 'This might take a few seconds to complete.',\n html: true,\n allowOutsideClick: false,\n allowEscapeKey: false,\n showConfirmButton: false,\n });\n\n $.ajax({\n type: 'POST',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/decompress`,\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n data: JSON.stringify({\n files: `${compPath}${compName}`\n })\n }).done(data => {\n swal.close();\n Files.list(compPath);\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: error\n });\n });\n }\n\n compress() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const compPath = decodeURIComponent(nameBlock.data('path'));\n const compName = decodeURIComponent(nameBlock.data('name'));\n\n $.ajax({\n type: 'POST',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/compress`,\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n data: JSON.stringify({\n files: `${compPath}${compName}`,\n to: compPath.toString()\n })\n }).done(data => {\n Files.list(compPath, err => {\n if (err) return;\n const fileListing = $('#file_listing').find(`[data-name=\"${data.saved_as}\"]`).parent();\n fileListing.addClass('success pulsate').delay(3000).queue(() => {\n fileListing.removeClass('success pulsate').dequeue();\n });\n });\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: error\n });\n });\n }\n}\n","\"use strict\";\n\n// Copyright (c) 2015 - 2017 Dane Everitt \n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\nclass ContextMenuClass {\n constructor() {\n this.activeLine = null;\n }\n\n run() {\n this.directoryClick();\n this.rightClick();\n }\n\n makeMenu(parent) {\n $(document).find('#fileOptionMenu').remove();\n if (!_.isNull(this.activeLine)) this.activeLine.removeClass('active');\n\n let newFilePath = $('#file_listing').data('current-dir');\n if (parent.data('type') === 'folder') {\n const nameBlock = parent.find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n newFilePath = `${currentPath}${currentName}`;\n }\n\n let buildMenu = '
      ';\n\n if (Pterodactyl.permissions.moveFiles) {\n buildMenu += '
    • Rename
    • \\\n
    • Move
    • ';\n }\n\n if (Pterodactyl.permissions.copyFiles) {\n buildMenu += '
    • Copy
    • ';\n }\n\n if (Pterodactyl.permissions.compressFiles) {\n buildMenu += '
    • Compress
    • ';\n }\n\n if (Pterodactyl.permissions.decompressFiles) {\n buildMenu += '
    • Decompress
    • ';\n }\n\n if (Pterodactyl.permissions.createFiles) {\n buildMenu += '
    • \\\n
    • New File
    • \\\n
    • New Folder
    • ';\n }\n\n if (Pterodactyl.permissions.downloadFiles || Pterodactyl.permissions.deleteFiles) {\n buildMenu += '
    • ';\n }\n\n if (Pterodactyl.permissions.downloadFiles) {\n buildMenu += '
    • Download
    • ';\n }\n\n if (Pterodactyl.permissions.deleteFiles) {\n buildMenu += '
    • Delete
    • ';\n }\n\n buildMenu += '
    ';\n return buildMenu;\n }\n\n rightClick() {\n $('[data-action=\"toggleMenu\"]').on('mousedown', event => {\n event.preventDefault();\n if ($(document).find('#fileOptionMenu').is(':visible')) {\n $('body').trigger('click');\n return;\n }\n this.showMenu(event);\n });\n $('#file_listing > tbody td').on('contextmenu', event => {\n this.showMenu(event);\n });\n }\n\n showMenu(event) {\n const parent = $(event.target).closest('tr');\n const menu = $(this.makeMenu(parent));\n\n if (parent.data('type') === 'disabled') return;\n event.preventDefault();\n\n $(menu).appendTo('body');\n $(menu).data('invokedOn', $(event.target)).show().css({\n position: 'absolute',\n left: event.pageX - 150,\n top: event.pageY,\n });\n\n this.activeLine = parent;\n this.activeLine.addClass('active');\n\n // Handle Events\n const Actions = new ActionsClass(parent, menu);\n if (Pterodactyl.permissions.moveFiles) {\n $(menu).find('li[data-action=\"move\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.move();\n });\n $(menu).find('li[data-action=\"rename\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.rename();\n });\n }\n\n if (Pterodactyl.permissions.copyFiles) {\n $(menu).find('li[data-action=\"copy\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.copy();\n });\n }\n\n if (Pterodactyl.permissions.compressFiles) {\n if (parent.data('type') === 'folder') {\n $(menu).find('li[data-action=\"compress\"]').removeClass('hidden');\n }\n $(menu).find('li[data-action=\"compress\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.compress();\n });\n }\n\n if (Pterodactyl.permissions.decompressFiles) {\n if (_.without(['application/zip', 'application/gzip', 'application/x-gzip'], parent.data('mime')).length < 3) {\n $(menu).find('li[data-action=\"decompress\"]').removeClass('hidden');\n }\n $(menu).find('li[data-action=\"decompress\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.decompress();\n });\n }\n\n if (Pterodactyl.permissions.createFiles) {\n $(menu).find('li[data-action=\"folder\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.folder();\n });\n }\n\n if (Pterodactyl.permissions.downloadFiles) {\n if (parent.data('type') === 'file') {\n $(menu).find('li[data-action=\"download\"]').removeClass('hidden');\n }\n $(menu).find('li[data-action=\"download\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.download();\n });\n }\n\n if (Pterodactyl.permissions.deleteFiles) {\n $(menu).find('li[data-action=\"delete\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.delete();\n });\n }\n\n $(window).unbind().on('click', event => {\n if($(event.target).is('.disable-menu-hide')) {\n event.preventDefault();\n return;\n }\n $(menu).unbind().remove();\n if(!_.isNull(this.activeLine)) this.activeLine.removeClass('active');\n });\n }\n\n directoryClick() {\n $('a[data-action=\"directory-view\"]').on('click', function (event) {\n event.preventDefault();\n\n const path = $(this).parent().data('path') || '';\n const name = $(this).parent().data('name') || '';\n\n window.location.hash = encodeURIComponent(path + name);\n Files.list();\n });\n }\n}\n\nwindow.ContextMenu = new ContextMenuClass;\n","\"use strict\";\n\n// Copyright (c) 2015 - 2017 Dane Everitt \n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\nclass FileManager {\n constructor() {\n this.list(this.decodeHash());\n }\n\n list(path, next) {\n if (_.isUndefined(path)) {\n path = this.decodeHash();\n }\n\n this.loader(true);\n $.ajax({\n type: 'POST',\n url: Pterodactyl.meta.directoryList,\n headers: {\n 'X-CSRF-Token': Pterodactyl.meta.csrftoken,\n },\n data: {\n directory: path,\n },\n }).done(data => {\n this.loader(false);\n $('#load_files').slideUp(10).html(data).slideDown(10, () => {\n ContextMenu.run();\n this.reloadFilesButton();\n this.addFolderButton();\n this.selectItem();\n this.selectAll();\n this.selectiveDeletion();\n this.selectRow();\n if (_.isFunction(next)) {\n return next();\n }\n });\n $('#internal_alert').slideUp();\n\n if (typeof Siofu === 'object') {\n Siofu.listenOnInput(document.getElementById(\"files_touch_target\"));\n }\n }).fail(jqXHR => {\n this.loader(false);\n if (_.isFunction(next)) {\n return next(new Error('Failed to load file listing.'));\n }\n\n if ((path !== '' && path !== '/') && jqXHR.status === 404) {\n return this.list('', next);\n }\n\n swal({\n type: 'error',\n title: 'File Error',\n text: jqXHR.responseJSON.errors[0].detail || 'An error occurred while attempting to process this request. Please try again.',\n });\n console.error(jqXHR);\n });\n }\n\n loader(show) {\n if (show){\n $('.file-overlay').fadeIn(100);\n } else {\n $('.file-overlay').fadeOut(100);\n }\n }\n\n reloadFilesButton() {\n $('i[data-action=\"reload-files\"]').unbind().on('click', () => {\n $('i[data-action=\"reload-files\"]').addClass('fa-spin');\n this.list();\n });\n }\n\n selectItem() {\n $('[data-action=\"addSelection\"]').on('click', event => {\n event.preventDefault();\n });\n }\n\n selectAll() {\n $('[data-action=\"selectAll\"]').on('click', event => {\n event.preventDefault();\n });\n }\n\n selectiveDeletion() {\n $('[data-action=\"selective-deletion\"]').on('mousedown', event => {\n new ActionsClass().deleteSelected();\n });\n }\n\n addFolderButton() {\n $('[data-action=\"add-folder\"]').unbind().on('click', () => {\n new ActionsClass().folder($('#file_listing').data('current-dir') || '/');\n })\n }\n\n selectRow() {\n $('#file_listing tr').on('mousedown', event => {\n if (event.which === 1) {\n if ($(event.target).is('th') || $(event.target).is('input[data-action=\"selectAll\"]')) {\n new ActionsClass().highlightAll(event);\n } else if ($(event.target).is('td') || $(event.target).is('input[data-action=\"addSelection\"]')) {\n new ActionsClass().toggleHighlight(event);\n }\n\n new ActionsClass().toggleMassActions();\n }\n });\n }\n\n decodeHash() {\n return decodeURIComponent(window.location.hash.substring(1));\n }\n\n}\n\nwindow.Files = new FileManager;\n"]} \ No newline at end of file +{"version":3,"sources":["src/actions.js","src/contextmenu.js","src/index.js"],"names":[],"mappings":"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","file":"filemanager.min.js","sourcesContent":["\"use strict\";\n\n// Copyright (c) 2015 - 2017 Dane Everitt \n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\nclass ActionsClass {\n constructor(element, menu) {\n this.element = element;\n this.menu = menu;\n }\n\n destroy() {\n this.element = undefined;\n }\n\n folder(path) {\n let inputValue\n if (path) {\n inputValue = path\n } else {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.data('name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n if ($(this.element).data('type') === 'file') {\n inputValue = currentPath;\n } else {\n inputValue = `${currentPath}${currentName}/`;\n }\n }\n\n swal({\n type: 'input',\n title: 'Create Folder',\n text: 'Please enter the path and folder name below.',\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n inputValue: inputValue\n }, (val) => {\n if (val === false) {\n return false;\n }\n\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/folder`,\n timeout: 10000,\n data: JSON.stringify({\n path: val,\n }),\n }).done(data => {\n swal.close();\n Files.list();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: '',\n text: error,\n });\n });\n });\n }\n\n move() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n swal({\n type: 'input',\n title: 'Move File',\n text: 'Please enter the new path for the file below.',\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n inputValue: `${currentPath}${currentName}`,\n }, (val) => {\n if (val === false) {\n return false;\n }\n\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/move`,\n timeout: 10000,\n data: JSON.stringify({\n from: `${currentPath}${currentName}`,\n to: `${val}`,\n }),\n }).done(data => {\n nameBlock.parent().addClass('warning').delay(200).fadeOut();\n swal.close();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: '',\n text: error,\n });\n });\n });\n\n }\n\n rename() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentLink = nameBlock.find('a');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const attachEditor = `\n \n \n `;\n\n nameBlock.html(attachEditor);\n const inputField = nameBlock.find('input');\n const inputLoader = nameBlock.find('.input-loader');\n\n inputField.focus();\n inputField.on('blur keydown', e => {\n // Save Field\n if (\n (e.type === 'keydown' && e.which === 27)\n || e.type === 'blur'\n || (e.type === 'keydown' && e.which === 13 && currentName === inputField.val())\n ) {\n if (!_.isEmpty(currentLink)) {\n nameBlock.html(currentLink);\n } else {\n nameBlock.html(currentName);\n }\n inputField.remove();\n ContextMenu.unbind().run();\n return;\n }\n\n if (e.type === 'keydown' && e.which !== 13) return;\n\n inputLoader.show();\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/rename`,\n timeout: 10000,\n data: JSON.stringify({\n from: `${currentPath}${currentName}`,\n to: `${currentPath}${inputField.val()}`,\n }),\n }).done(data => {\n nameBlock.attr('data-name', inputField.val());\n if (!_.isEmpty(currentLink)) {\n let newLink = currentLink.attr('href');\n if (nameBlock.parent().data('type') !== 'folder') {\n newLink = newLink.substr(0, newLink.lastIndexOf('/')) + '/' + inputField.val();\n }\n currentLink.attr('href', newLink);\n nameBlock.html(\n currentLink.html(inputField.val())\n );\n } else {\n nameBlock.html(inputField.val());\n }\n inputField.remove();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n nameBlock.addClass('has-error').delay(2000).queue(() => {\n nameBlock.removeClass('has-error').dequeue();\n });\n inputField.popover({\n animation: true,\n placement: 'top',\n content: error,\n title: 'Save Error'\n }).popover('show');\n }).always(() => {\n inputLoader.remove();\n ContextMenu.unbind().run();\n });\n });\n }\n\n copy() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n\n swal({\n type: 'input',\n title: 'Copy File',\n text: 'Please enter the new path for the copied file below.',\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true,\n inputValue: `${currentPath}${currentName}`,\n }, (val) => {\n if (val === false) {\n return false;\n }\n\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/copy`,\n timeout: 10000,\n data: JSON.stringify({\n from: `${currentPath}${currentName}`,\n to: `${val}`,\n }),\n }).done(data => {\n swal({\n type: 'success',\n title: '',\n text: 'File successfully copied.'\n });\n Files.list();\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: '',\n text: error,\n });\n });\n });\n }\n\n download() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const fileName = decodeURIComponent(nameBlock.attr('data-name'));\n const filePath = decodeURIComponent(nameBlock.data('path'));\n\n window.location = `/server/${Pterodactyl.server.uuidShort}/files/download/${filePath}${fileName}`;\n }\n\n delete() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const delPath = decodeURIComponent(nameBlock.data('path'));\n const delName = decodeURIComponent(nameBlock.data('name'));\n\n swal({\n type: 'warning',\n title: '',\n text: 'Are you sure you want to delete ' + delName + '?',\n html: true,\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true\n }, () => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/delete`,\n timeout: 10000,\n data: JSON.stringify({\n items: [`${delPath}${delName}`]\n }),\n }).done(data => {\n nameBlock.parent().addClass('warning').delay(200).fadeOut();\n swal({\n type: 'success',\n title: 'File Deleted'\n });\n }).fail(jqXHR => {\n console.error(jqXHR);\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: 'An error occurred while attempting to delete this file. Please try again.',\n });\n });\n });\n }\n\n toggleMassActions() {\n if ($('#file_listing input[type=\"checkbox\"]:checked').length) {\n $('#mass_actions').removeClass('disabled');\n } else {\n $('#mass_actions').addClass('disabled');\n }\n }\n\n toggleHighlight(event) {\n const parent = $(event.currentTarget);\n const item = $(event.currentTarget).find('input');\n\n if($(item).is(':checked')) {\n $(item).prop('checked', false);\n parent.removeClass('warning').delay(200);\n } else {\n $(item).prop('checked', true);\n parent.addClass('warning').delay(200);\n }\n }\n\n highlightAll(event) {\n let parent;\n const item = $(event.currentTarget).find('input');\n\n if($(item).is(':checked')) {\n $('#file_listing input[type=checkbox]').prop('checked', false);\n $('#file_listing input[data-action=\"addSelection\"]').each(function() {\n parent = $(this).closest('tr');\n parent.removeClass('warning').delay(200);\n });\n } else {\n $('#file_listing input[type=checkbox]').prop('checked', true);\n $('#file_listing input[data-action=\"addSelection\"]').each(function() {\n parent = $(this).closest('tr');\n parent.addClass('warning').delay(200);\n });\n }\n }\n\n deleteSelected() {\n let selectedItems = [];\n let selectedItemsElements = [];\n let parent;\n let nameBlock;\n let delLocation;\n\n $('#file_listing input[data-action=\"addSelection\"]:checked').each(function() {\n parent = $(this).closest('tr');\n nameBlock = $(parent).find('td[data-identifier=\"name\"]');\n delLocation = decodeURIComponent(nameBlock.data('path')) + decodeURIComponent(nameBlock.data('name'));\n\n selectedItems.push(delLocation);\n selectedItemsElements.push(parent);\n });\n\n if (selectedItems.length != 0)\n {\n let formattedItems = \"\";\n let i = 0;\n $.each(selectedItems, function(key, value) {\n formattedItems += (\"\" + value + \", \");\n i++;\n return i < 5;\n });\n\n formattedItems = formattedItems.slice(0, -2);\n if (selectedItems.length > 5) {\n formattedItems += ', and ' + (selectedItems.length - 5) + ' other(s)';\n }\n\n swal({\n type: 'warning',\n title: '',\n text: 'Are you sure you want to delete the following files: ' + formattedItems + '?',\n html: true,\n showCancelButton: true,\n showConfirmButton: true,\n closeOnConfirm: false,\n showLoaderOnConfirm: true\n }, () => {\n $.ajax({\n type: 'POST',\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/delete`,\n timeout: 10000,\n data: JSON.stringify({\n items: selectedItems\n }),\n }).done(data => {\n $('#file_listing input:checked').each(function() {\n $(this).prop('checked', false);\n });\n\n $.each(selectedItemsElements, function() {\n $(this).addClass('warning').delay(200).fadeOut();\n })\n\n swal({\n type: 'success',\n title: 'Files Deleted'\n });\n }).fail(jqXHR => {\n console.error(jqXHR);\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: 'An error occurred while attempting to delete these files. Please try again.',\n });\n });\n });\n } else {\n swal({\n type: 'warning',\n title: '',\n text: 'Please select files/folders to delete.',\n });\n }\n }\n\n decompress() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const compPath = decodeURIComponent(nameBlock.data('path'));\n const compName = decodeURIComponent(nameBlock.data('name'));\n\n swal({\n title: ' Decompressing...',\n text: 'This might take a few seconds to complete.',\n html: true,\n allowOutsideClick: false,\n allowEscapeKey: false,\n showConfirmButton: false,\n });\n\n $.ajax({\n type: 'POST',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/decompress`,\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n data: JSON.stringify({\n files: `${compPath}${compName}`\n })\n }).done(data => {\n swal.close();\n Files.list(compPath);\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: error\n });\n });\n }\n\n compress() {\n const nameBlock = $(this.element).find('td[data-identifier=\"name\"]');\n const compPath = decodeURIComponent(nameBlock.data('path'));\n const compName = decodeURIComponent(nameBlock.data('name'));\n\n $.ajax({\n type: 'POST',\n url: `${Pterodactyl.node.scheme}://${Pterodactyl.node.fqdn}:${Pterodactyl.node.daemonListen}/v1/server/file/compress`,\n headers: {\n 'X-Access-Token': Pterodactyl.server.daemonSecret,\n 'X-Access-Server': Pterodactyl.server.uuid,\n },\n contentType: 'application/json; charset=utf-8',\n data: JSON.stringify({\n files: `${compPath}${compName}`,\n to: compPath.toString()\n })\n }).done(data => {\n Files.list(compPath, err => {\n if (err) return;\n const fileListing = $('#file_listing').find(`[data-name=\"${data.saved_as}\"]`).parent();\n fileListing.addClass('success pulsate').delay(3000).queue(() => {\n fileListing.removeClass('success pulsate').dequeue();\n });\n });\n }).fail(jqXHR => {\n console.error(jqXHR);\n var error = 'An error occurred while trying to process this request.';\n if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {\n error = jqXHR.responseJSON.error;\n }\n swal({\n type: 'error',\n title: 'Whoops!',\n html: true,\n text: error\n });\n });\n }\n}\n","\"use strict\";\n\n// Copyright (c) 2015 - 2017 Dane Everitt \n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\nclass ContextMenuClass {\n constructor() {\n this.activeLine = null;\n }\n\n run() {\n this.directoryClick();\n this.rightClick();\n }\n\n makeMenu(parent) {\n $(document).find('#fileOptionMenu').remove();\n if (!_.isNull(this.activeLine)) this.activeLine.removeClass('active');\n\n let newFilePath = $('#file_listing').data('current-dir');\n if (parent.data('type') === 'folder') {\n const nameBlock = parent.find('td[data-identifier=\"name\"]');\n const currentName = decodeURIComponent(nameBlock.attr('data-name'));\n const currentPath = decodeURIComponent(nameBlock.data('path'));\n newFilePath = `${currentPath}${currentName}`;\n }\n\n let buildMenu = '
      ';\n\n if (Pterodactyl.permissions.moveFiles) {\n buildMenu += '
    • Rename
    • \\\n
    • Move
    • ';\n }\n\n if (Pterodactyl.permissions.copyFiles) {\n buildMenu += '
    • Copy
    • ';\n }\n\n if (Pterodactyl.permissions.compressFiles) {\n buildMenu += '
    • Compress
    • ';\n }\n\n if (Pterodactyl.permissions.decompressFiles) {\n buildMenu += '
    • Decompress
    • ';\n }\n\n if (Pterodactyl.permissions.createFiles) {\n buildMenu += '
    • \\\n
    • New File
    • \\\n
    • New Folder
    • ';\n }\n\n if (Pterodactyl.permissions.downloadFiles || Pterodactyl.permissions.deleteFiles) {\n buildMenu += '
    • ';\n }\n\n if (Pterodactyl.permissions.downloadFiles) {\n buildMenu += '
    • Download
    • ';\n }\n\n if (Pterodactyl.permissions.deleteFiles) {\n buildMenu += '
    • Delete
    • ';\n }\n\n buildMenu += '
    ';\n return buildMenu;\n }\n\n rightClick() {\n $('[data-action=\"toggleMenu\"]').on('mousedown', event => {\n event.preventDefault();\n if ($(document).find('#fileOptionMenu').is(':visible')) {\n $('body').trigger('click');\n return;\n }\n this.showMenu(event);\n });\n $('#file_listing > tbody td').on('contextmenu', event => {\n this.showMenu(event);\n });\n }\n\n showMenu(event) {\n const parent = $(event.target).closest('tr');\n const menu = $(this.makeMenu(parent));\n\n if (parent.data('type') === 'disabled') return;\n event.preventDefault();\n\n $(menu).appendTo('body');\n $(menu).data('invokedOn', $(event.target)).show().css({\n position: 'absolute',\n left: event.pageX - 150,\n top: event.pageY,\n });\n\n this.activeLine = parent;\n this.activeLine.addClass('active');\n\n // Handle Events\n const Actions = new ActionsClass(parent, menu);\n if (Pterodactyl.permissions.moveFiles) {\n $(menu).find('li[data-action=\"move\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.move();\n });\n $(menu).find('li[data-action=\"rename\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.rename();\n });\n }\n\n if (Pterodactyl.permissions.copyFiles) {\n $(menu).find('li[data-action=\"copy\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.copy();\n });\n }\n\n if (Pterodactyl.permissions.compressFiles) {\n if (parent.data('type') === 'folder') {\n $(menu).find('li[data-action=\"compress\"]').removeClass('hidden');\n }\n $(menu).find('li[data-action=\"compress\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.compress();\n });\n }\n\n if (Pterodactyl.permissions.decompressFiles) {\n if (_.without(['application/zip', 'application/gzip', 'application/x-gzip'], parent.data('mime')).length < 3) {\n $(menu).find('li[data-action=\"decompress\"]').removeClass('hidden');\n }\n $(menu).find('li[data-action=\"decompress\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.decompress();\n });\n }\n\n if (Pterodactyl.permissions.createFiles) {\n $(menu).find('li[data-action=\"folder\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.folder();\n });\n }\n\n if (Pterodactyl.permissions.downloadFiles) {\n if (parent.data('type') === 'file') {\n $(menu).find('li[data-action=\"download\"]').removeClass('hidden');\n }\n $(menu).find('li[data-action=\"download\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.download();\n });\n }\n\n if (Pterodactyl.permissions.deleteFiles) {\n $(menu).find('li[data-action=\"delete\"]').unbind().on('click', e => {\n e.preventDefault();\n Actions.delete();\n });\n }\n\n $(window).unbind().on('click', event => {\n if($(event.target).is('.disable-menu-hide')) {\n event.preventDefault();\n return;\n }\n $(menu).unbind().remove();\n if(!_.isNull(this.activeLine)) this.activeLine.removeClass('active');\n });\n }\n\n directoryClick() {\n $('a[data-action=\"directory-view\"]').on('click', function (event) {\n event.preventDefault();\n\n const path = $(this).parent().data('path') || '';\n const name = $(this).parent().data('name') || '';\n\n window.location.hash = encodeURIComponent(path + name);\n Files.list();\n });\n }\n}\n\nwindow.ContextMenu = new ContextMenuClass;\n","\"use strict\";\n\n// Copyright (c) 2015 - 2017 Dane Everitt \n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\nclass FileManager {\n constructor() {\n this.list(this.decodeHash());\n }\n\n list(path, next) {\n if (_.isUndefined(path)) {\n path = this.decodeHash();\n }\n\n this.loader(true);\n $.ajax({\n type: 'POST',\n url: Pterodactyl.meta.directoryList,\n headers: {\n 'X-CSRF-Token': Pterodactyl.meta.csrftoken,\n },\n data: {\n directory: path,\n },\n }).done(data => {\n this.loader(false);\n $('#load_files').slideUp(10).html(data).slideDown(10, () => {\n ContextMenu.run();\n this.reloadFilesButton();\n this.addFolderButton();\n this.selectItem();\n this.selectAll();\n this.selectiveDeletion();\n this.selectRow();\n if (_.isFunction(next)) {\n return next();\n }\n });\n $('#internal_alert').slideUp();\n\n if (typeof Siofu === 'object') {\n Siofu.listenOnInput(document.getElementById(\"files_touch_target\"));\n }\n }).fail(jqXHR => {\n this.loader(false);\n if (_.isFunction(next)) {\n return next(new Error('Failed to load file listing.'));\n }\n\n if ((path !== '' && path !== '/') && jqXHR.status === 404) {\n return this.list('', next);\n }\n\n swal({\n type: 'error',\n title: 'File Error',\n text: jqXHR.responseJSON.errors[0].detail || 'An error occurred while attempting to process this request. Please try again.',\n });\n console.error(jqXHR);\n });\n }\n\n loader(show) {\n if (show){\n $('.file-overlay').fadeIn(100);\n } else {\n $('.file-overlay').fadeOut(100);\n }\n }\n\n reloadFilesButton() {\n $('i[data-action=\"reload-files\"]').unbind().on('click', () => {\n $('i[data-action=\"reload-files\"]').addClass('fa-spin');\n this.list();\n });\n }\n\n selectItem() {\n $('[data-action=\"addSelection\"]').on('click', event => {\n event.preventDefault();\n });\n }\n\n selectAll() {\n $('[data-action=\"selectAll\"]').on('click', event => {\n event.preventDefault();\n });\n }\n\n selectiveDeletion() {\n $('[data-action=\"selective-deletion\"]').on('mousedown', event => {\n new ActionsClass().deleteSelected();\n });\n }\n\n addFolderButton() {\n $('[data-action=\"add-folder\"]').unbind().on('click', () => {\n new ActionsClass().folder($('#file_listing').data('current-dir') || '/');\n })\n }\n\n selectRow() {\n $('#file_listing tr').on('mousedown', event => {\n if (event.which === 1) {\n if ($(event.target).is('th') || $(event.target).is('input[data-action=\"selectAll\"]')) {\n new ActionsClass().highlightAll(event);\n } else if ($(event.target).is('td') || $(event.target).is('input[data-action=\"addSelection\"]')) {\n new ActionsClass().toggleHighlight(event);\n }\n\n new ActionsClass().toggleMassActions();\n }\n });\n }\n\n decodeHash() {\n return decodeURIComponent(window.location.hash.substring(1));\n }\n\n}\n\nwindow.Files = new FileManager;\n"]} \ No newline at end of file diff --git a/public/themes/pterodactyl/js/frontend/files/src/actions.js b/public/themes/pterodactyl/js/frontend/files/src/actions.js index d2d6f42e2..0c3b839d6 100644 --- a/public/themes/pterodactyl/js/frontend/files/src/actions.js +++ b/public/themes/pterodactyl/js/frontend/files/src/actions.js @@ -55,6 +55,10 @@ class ActionsClass { showLoaderOnConfirm: true, inputValue: inputValue }, (val) => { + if (val === false) { + return false; + } + $.ajax({ type: 'POST', headers: { @@ -100,6 +104,10 @@ class ActionsClass { showLoaderOnConfirm: true, inputValue: `${currentPath}${currentName}`, }, (val) => { + if (val === false) { + return false; + } + $.ajax({ type: 'POST', headers: { @@ -233,6 +241,10 @@ class ActionsClass { showLoaderOnConfirm: true, inputValue: `${currentPath}${currentName}`, }, (val) => { + if (val === false) { + return false; + } + $.ajax({ type: 'POST', headers: { diff --git a/resources/lang/cn/admin/nests.php b/resources/lang/cn/admin/nests.php new file mode 100644 index 000000000..d5e2a511b --- /dev/null +++ b/resources/lang/cn/admin/nests.php @@ -0,0 +1,33 @@ +. + * + * This software is licensed under the terms of the MIT license. + * https://opensource.org/licenses/MIT + */ + +return [ + 'notices' => [ + 'created' => '一个新的管理模块, :name, 已成功创建。', + 'deleted' => '成功从面板删除指定的管理模块。', + 'updated' => '成功更新管理模块的选项。', + ], + 'eggs' => [ + 'notices' => [ + 'imported' => '成功导入一个管理模板。', + 'updated_via_import' => '该管理模板已按照上传的文件完成更新。', + 'deleted' => '成功删除指定的管路模板。', + 'updated' => '成功更新管理模板的配置。', + 'script_updated' => '管理模板的安装脚本已经成功更新并且会在安装新服务器时被执行。', + 'egg_created' => '一个管理模板已经成功创建. 你需要重启所有正在运行的节点受控端来使该模板生效。', + ], + ], + 'variables' => [ + 'notices' => [ + 'variable_deleted' => '参数 ":variable" 已被移除,在服务器重装之后将不在有效。', + 'variable_updated' => '参数 ":variable" 已更新。 你需要重装所有服务器来使该参数生效.', + 'variable_created' => '新的参数已经创建并被赋值,该操作会影响此管理模板下的所有服务器', + ], + ], +]; diff --git a/resources/lang/cn/admin/node.php b/resources/lang/cn/admin/node.php new file mode 100644 index 000000000..e2b9984aa --- /dev/null +++ b/resources/lang/cn/admin/node.php @@ -0,0 +1,23 @@ +. + * + * This software is licensed under the terms of the MIT license. + * https://opensource.org/licenses/MIT + */ + +return [ + 'validation' => [ + 'fqdn_not_resolvable' => '提供的域名或地址没有解析到一个合法的IP地址.', + 'fqdn_required_for_ssl' => '这个节点要求解析到一个公共IP的域名必须使用SSL', + ], + 'notices' => [ + 'allocations_added' => '配额已经成功的被添加到这个节点.', + 'node_deleted' => '节点成功从面板中移除.', + 'location_required' => '在你可以添加一个节点之前必须至少有一个可用区配置。', + 'node_created' => '节点新建成功! 使用 \'Configuration\' 标签,你可以在此节点上自动配置受控端. 在你可以创建服务器之前,你必须至少分配一个IP和端口', + 'node_updated' => '节点信息更新成功!如果任何节点受控端的设置更改了,您需要重启受控端来使设置生效.', + 'unallocated_deleted' => '已删除 :ip 上的所有未分配的端口', + ], +]; diff --git a/resources/lang/cn/admin/pack.php b/resources/lang/cn/admin/pack.php new file mode 100644 index 000000000..1d95dc074 --- /dev/null +++ b/resources/lang/cn/admin/pack.php @@ -0,0 +1,16 @@ +. + * + * This software is licensed under the terms of the MIT license. + * https://opensource.org/licenses/MIT + */ + +return [ + 'notices' => [ + 'pack_updated' => '整合包已经被更新。', + 'pack_deleted' => '成功删除整合包: ":name" 。', + 'pack_created' => '一个整合包已被成功创建,现在可以用它来部署服务器了。', + ], +]; diff --git a/resources/lang/cn/admin/server.php b/resources/lang/cn/admin/server.php new file mode 100644 index 000000000..c850b2735 --- /dev/null +++ b/resources/lang/cn/admin/server.php @@ -0,0 +1,31 @@ +. + * + * This software is licensed under the terms of the MIT license. + * https://opensource.org/licenses/MIT + */ + +return [ + 'exceptions' => [ + 'no_new_default_allocation' => '你正在尝试删除此服务器的默认配额,但是该服务器没有足够的后备配额。', + 'marked_as_failed' => '这个服务器目前被标记为安装失败。 当前状态不能改变为此状态。', + 'bad_variable' => '变量 :name 有一个已确认的错误 。', + 'daemon_exception' => '连接受控端时发生意外 返回错误码 HTTP/:code response code. 此错误已被记录。', + 'default_allocation_not_found' => '请求的默认配额没有在这台服务器上找到。', + ], + 'alerts' => [ + 'startup_changed' => '该服务器的启动配置已被更新. 如果此服务器所属的管理模块或管理模板更改,此时将发生一次配置重设', + 'server_deleted' => '成功从系统中删除服务器', + 'server_created' => '创建服务器成功。 请稍后几分钟,受控端将尽快完成服务器安装', + 'build_updated' => '启动参数已更改。 一些修改需要重启该服务器后生效。', + 'suspension_toggled' => '服务器状态已更改为 :status.', + 'rebuild_on_boot' => '此服务器已被标记为需要在Docker容器中启动。 此操作会在下次重启后生效。', + 'install_toggled' => '此服务器的安装状态已被更改', + 'server_reinstalled' => '此服务器目前已置于重装队列中,即将开始重装', + 'details_updated' => '服务器信息成功被更新', + 'docker_image_updated' => '成功更改用于该服务器的默认的Docker镜像。 此操作需要重启后生效', + 'node_required' => '你需要至少一个节点才能开始添加服务器', + ], +]; diff --git a/resources/lang/cn/admin/user.php b/resources/lang/cn/admin/user.php new file mode 100644 index 000000000..1250cdae7 --- /dev/null +++ b/resources/lang/cn/admin/user.php @@ -0,0 +1,18 @@ +. + * + * This software is licensed under the terms of the MIT license. + * https://opensource.org/licenses/MIT + */ + +return [ + 'exceptions' => [ + 'user_has_servers' => '无法删除一个拥有活动状态服务器的用户. 请在继续此操作前删除他的服务器', + ], + 'notices' => [ + 'account_created' => '成功创建用户', + 'account_updated' => '成功更新用户', + ], +]; diff --git a/resources/lang/cn/auth.php b/resources/lang/cn/auth.php new file mode 100644 index 000000000..6758f8238 --- /dev/null +++ b/resources/lang/cn/auth.php @@ -0,0 +1,22 @@ + '您无权执行此操作。', + 'auth_error' => '尝试登录时发生错误.', + 'authentication_required' => '需要认证才能继续操作', + 'remember_me' => '记住我', + 'sign_in' => '登陆', + 'forgot_password' => '忘记密码', + 'request_reset_text' => '忘记密码? 请在下方填入您的Email.', + 'reset_password_text' => '重设您账户的密码.', + 'reset_password' => '重设密码', + 'email_sent' => '一封帮助您重置密码的电子邮件已发出,请查收并按提示操作(如未收到请检查垃圾箱)', + 'failed' => '用户名或密码错误, 或者两步验证失败.', + 'throttle' => '太多次登陆失败. 请在 :seconds 秒后尝试', + 'password_requirements' => '密码至少包含大写字母,小写字母,数字,并且在8位以上.', + 'request_reset' => '查找账户', + '2fa_required' => '两步验证', + '2fa_failed' => '两步验证密码错误', + 'totp_failed' => '错误的TOTP验证.', + '2fa_must_be_enabled' => '管理员要求您的账户必须开启两步验证才能使用此面板.', +]; diff --git a/resources/lang/cn/base.php b/resources/lang/cn/base.php new file mode 100644 index 000000000..528e07f1c --- /dev/null +++ b/resources/lang/cn/base.php @@ -0,0 +1,88 @@ + '请求中有一个或多个字段出错', + 'errors' => [ + 'return' => '返回上一个页面', + 'home' => '返回主页', + '403' => [ + 'header' => '禁止访问', + 'desc' => '您没有权限访问此服务器上的资源.', + ], + '404' => [ + 'header' => 'Not Found', + 'desc' => '未找到资源.', + ], + 'installing' => [ + 'header' => '服务器正在安装', + 'desc' => '请求的服务器仍然在部署中,请稍等几分钟,完成后您将收到一封电子邮件', + ], + 'suspended' => [ + 'header' => '服务器已暂停', + 'desc' => '此服务器已被暂停,无法访问,请联系管理员', + ], + 'maintenance' => [ + 'header' => '节点维护中', + 'title' => '暂时不可用', + 'desc' => '此节点正在维护,当前无法访问.', + ], + ], + 'index' => [ + 'header' => '您的服务器', + 'header_sub' => '您当前可访问的服务器.', + 'list' => '服务器列表', + ], + 'api' => [ + 'index' => [ + 'list' => '您的密钥', + 'header' => '账户 API', + 'header_sub' => '管理访问密钥允许您使用API操作面板.', + 'create_new' => '新建 API 密钥', + 'keypair_created' => '新建API密钥成功.', + ], + 'new' => [ + 'header' => '新建 API 密钥', + 'header_sub' => '创建一个新的账户API密钥.', + 'form_title' => '选项', + 'descriptive_memo' => [ + 'title' => '描述', + 'description' => '添加一个关于此密钥的描述.', + ], + 'allowed_ips' => [ + 'title' => '允许的IP', + 'description' => '添加IP地址限制来保护API安全. CIDR 标记是被允许的. 留空将允许所有IP.', + ], + ], + ], + 'account' => [ + 'details_updated' => '您账户的信息成功更新.', + 'invalid_password' => '您提供的密码不正确.', + 'header' => '您的账户', + 'header_sub' => '管理您的账户信息.', + 'update_pass' => '修改密码', + 'update_email' => '修改 Email 地址', + 'current_password' => '当前密码', + 'new_password' => '新密码', + 'new_password_again' => '重复密码', + 'new_email' => '新 Email 地址', + 'first_name' => '姓', + 'last_name' => '名', + 'update_identity' => '更新个人信息', + 'username_help' => '您的用户名必须唯一(未被使用),并满足以下要求: :requirements.', + ], + 'security' => [ + 'session_mgmt_disabled' => '为了安全原因,您的此次会话无法访问用户管理.', + 'header' => '账户安全', + 'header_sub' => '管理活动会话和两步认证.', + 'sessions' => '活动中的会话', + '2fa_header' => '两步验证', + '2fa_token_help' => '填入您两步验证生成器生成的密码 (Google Authenticator, Authy, etc.).', + 'disable_2fa' => '关闭两步验证', + '2fa_enabled' => '两步验证已开启,在您登陆面板时会要求两步验证.如果您想关闭两步验证,只需输入两步验证的密码即可', + '2fa_disabled' => '两步验证已关闭! 您应该开启两步验证将其作为您账户的额外防护', + 'enable_2fa' => '开启两步验证', + '2fa_qr' => '在您的设备上上配置两步验证', + '2fa_checkpoint_help' => '使用两步验证需要用您的应用扫左侧二维码, 或手动输入下方的代码.完成后请将生成的密码输入下方方框.', + '2fa_disable_error' => '两步验证密码错误. 关闭两步验证失败.', + ], +]; diff --git a/resources/lang/cn/command/messages.php b/resources/lang/cn/command/messages.php new file mode 100644 index 000000000..11081a7e9 --- /dev/null +++ b/resources/lang/cn/command/messages.php @@ -0,0 +1,97 @@ + [ + 'warning' => '貌似您已经拥有一个应用加密密钥了. 继续操作会导致之前的密钥被覆盖,所有的加密文件都将损坏。 !!!危险操作,请注意文件安全!!!', + 'confirm' => '我已了解此操作的后果,可以承受丢失文件的风险,请继续。', + 'final_confirm' => '确定继续操作? 更改应用加密密钥 !!将会导致数据丢失!!.', + ], + 'location' => [ + 'no_location_found' => '可用区ID错误:无发找到该可用区', + 'ask_short' => '可用区ID', + 'ask_long' => '可用区描述', + 'created' => '成功创建可用区 (:name) ,可用区ID: :id.', + 'deleted' => '成功删除指定的可用区。', + ], + 'user' => [ + 'search_users' => '输入用户名, UUID, 或 Email 地址', + 'select_search_user' => '要删除的用户ID (键入 \'0\' 来重新搜索)', + 'deleted' => '成功删除用户。', + 'confirm_delete' => '确定要删除此用户吗', + 'no_users_found' => '未找到指定的用户', + 'multiple_found' => '找到多个用户, 无法删除用户,原因: --no-interaction 参数。', + 'ask_admin' => '此用户是管理员吗?', + 'ask_email' => '电子邮件地址', + 'ask_username' => '用户名', + 'ask_name_first' => '姓', + 'ask_name_last' => '名', + 'ask_password' => '密码', + 'ask_password_tip' => '如果您想创建一个随机密码的用户,请重新执行指令(CTRL+C) 并输入 `--no-password` 参数.', + 'ask_password_help' => '密码至少8位,并包含一个字母和数字', + '2fa_help_text' => [ + '此命令会关闭一个用户的两步验证(如果他打开了). 此命令应仅用于用户恢复或解锁(两步验证无法成功情况下)。', + '如果您不想这么做, 情书用 CTRL+C 退出此操作。', + ], + '2fa_disabled' => '已成功禁用以下账户的两步验证: :email.', + ], + 'schedule' => [ + 'output_line' => '第一次任务已计划于 `:schedule` (:hash).', + ], + 'maintenance' => [ + 'deleting_service_backup' => '正在删除服务备份文件 :file.', + ], + 'server' => [ + 'rebuild_failed' => '重构操作 ":name" (#:id) ,位于节点 ":node" 失败,错误信息: :message', + 'power' => [ + 'confirm' => '您即将执行 :action 在 :count 个服务器. 是否继续?', + 'action_failed' => '电源命令 ":name" (#:id) 位于节点 ":node" 失败,错误信息: :message', + ], + ], + 'environment' => [ + 'mail' => [ + 'ask_smtp_host' => 'SMTP 主机 (e.g. smtp.gmail.com)', + 'ask_smtp_port' => 'SMTP 端口', + 'ask_smtp_username' => 'SMTP 用户名', + 'ask_smtp_password' => 'SMTP 密码', + 'ask_mailgun_domain' => 'Mailgun 域名', + 'ask_mailgun_secret' => 'Mailgun 密钥', + 'ask_mandrill_secret' => 'Mandrill 密钥', + 'ask_postmark_username' => 'Postmark API 密钥', + 'ask_driver' => '哪个引擎应该用于发送邮件?', + 'ask_mail_from' => 'Email来自哪个邮箱', + 'ask_mail_name' => 'Email应该由谁发送(发送者姓名)?', + 'ask_encryption' => '应该使用的加密方法', + ], + 'database' => [ + 'host_warning' => '极度推荐不使用localhost作为主机地址(可能有bug). 如果确实要使用本机作为MySQL地址,请使用 "127.0.0.1".', + 'host' => '数据库主机', + 'port' => '数据库端口', + 'database' => '数据库名', + 'username_warning' => '使用 "root" 账户会导致安全漏洞, 翼龙面板不允许此账户作为面板数据库账户. 你应该为此程序创建MySQL庄户', + 'username' => '数据库用户名', + 'password_defined' => '您似乎已经指定了MySQL连接密码,你想更改它吗', + 'password' => '数据库密码', + 'connection_error' => '无法连接数据库. 返回错误: ":error".', + 'creds_not_saved' => '您的数据库访问信息未保存. 在继续之前您将需要提供有效的信息', + 'try_again' => '返回再试一次?', + ], + 'app' => [ + 'settings' => '启用基于UI的设置编辑器?', + 'author' => '管理模板作者Email', + 'author_help' => '提供此面板到处的管理模板作者的电子邮件地址. 这应该是一个合法的电子邮件地址', + 'app_url_help' => '这个应用的URL必须以 https:// or http:// 开头(取决于是否启用SSL). 如果不包含这些您的电子邮件地址和其他内容可能会指向错误的地址.', + 'app_url' => '应用 URL', + 'timezone_help' => '设置的时区应该满足PHP支持的时区. 如果您不确定,请参阅 http://php.net/manual/en/timezones.php.', + 'timezone' => '应用时区', + 'cache_driver' => 'Cache Driver', + 'session_driver' => 'Session Driver', + 'queue_driver' => 'Queue Driver', + 'using_redis' => '如果您选择使用Redis, 请在下方提供有效的连接信息. 一般使用默认信息即可,除非您更改过设置.', + 'redis_host' => 'Redis 主机', + 'redis_password' => 'Redis 密码', + 'redis_pass_help' => '默认情况下,Redis数据库不需要密码,且仅运行于本地. 这种情况下,您什么都不用填.', + 'redis_port' => 'Redis 端口', + 'redis_pass_defined' => '似乎您已经设置过Redis密码了,您需要更改吗?', + ], + ], +]; diff --git a/resources/lang/cn/exceptions.php b/resources/lang/cn/exceptions.php new file mode 100644 index 000000000..4fd745aaf --- /dev/null +++ b/resources/lang/cn/exceptions.php @@ -0,0 +1,68 @@ + '连接受控端时发生意外 返回错误码 HTTP/:code response code. 此错误已被记录', + 'node' => [ + 'servers_attached' => '节点删除必须按先移除其所有的服务器.', + 'daemon_off_config_updated' => '受控端配置 已被更新, 但是自动更新受控端上的配置文件时发生错误. 你需要手动将配置文件 (core.json) 更新至受控端来完成更新.', + ], + 'allocations' => [ + 'server_using' => '一个服务器已分配该地址. 一个地址只有在无服务器使用时才能删除.', + 'too_many_ports' => '一次添加1000个以上的端口是不被支持的.', + 'invalid_mapping' => '提供的端口: :port 无效,无法继续操作.', + 'cidr_out_of_range' => 'CIDR 标记 只允许掩码在 /25 到 /32之间。', + 'port_out_of_range' => '端口超过范围,范围必须在 1024 到 65535 之间.', + ], + 'nest' => [ + 'delete_has_servers' => '活动服务器使用的管理模块不能被删除.', + 'egg' => [ + 'delete_has_servers' => '活动服务器使用的管理模板不能被删除.', + 'invalid_copy_id' => '管理模板复制的脚本ID无效.', + 'must_be_child' => ' "复制设置自"选项指定的目标必须是管理模块的附属.', + 'has_children' => '此管理模版附属有一个或多个管理模板. 在删除之前请先删除所有附属.', + ], + 'variables' => [ + 'env_not_unique' => '环境变量 :name 必须唯一.', + 'reserved_name' => '环境变量 :name 是被保护的,无法指定为变量.', + 'bad_validation_rule' => '环境变量规则 ":rule" 对于这个应用不是一个有效的规则.', + ], + 'importer' => [ + 'json_error' => '尝试导入JSON 文件时发生错误: :error.', + 'file_error' => '提供的JSON文件不合法.', + 'invalid_json_provided' => '提供的JSON文件格式不正确,无法被解析。', + ], + ], + 'packs' => [ + 'delete_has_servers' => '活动服务器使用的整合包不能被删除', + 'update_has_servers' => '当前有服务器附属于包时无法修改关联选项的ID.', + 'invalid_upload' => '上传的文件不合法.', + 'invalid_mime' => '上传的文件不符合要求的文件类型 :type', + 'unreadable' => '服务器无法打开该压缩包.', + 'zip_extraction' => '解压时发生错误.', + 'invalid_archive_exception' => '压缩包缺失archive.tar.gz 或 import.json 文件在根目录.', + ], + 'subusers' => [ + 'editing_self' => '编辑您自己的子用户时不被允许的.', + 'user_is_owner' => '子用户无法添加服主.', + 'subuser_exists' => '那个电子邮件的用户已经是此服务器的子用户了.', + ], + 'databases' => [ + 'delete_has_databases' => '无法删除一个拥有活跃数据库的数据库服务器.', + ], + 'tasks' => [ + 'chain_interval_too_long' => '链接任务的最大间隔时间为15分钟。', + ], + 'locations' => [ + 'has_nodes' => '活动节点附属的可用区无法被删除.', + ], + 'users' => [ + 'node_revocation_failed' => '吊销密钥失败 节点 #:node. :error', + ], + 'deployment' => [ + 'no_viable_nodes' => '没有合适的节点来自动部署服务器', + 'no_viable_allocations' => '没有合适的地址来自动部署服务器', + ], + 'api' => [ + 'resource_not_found' => '需求的资源未找到.', + ], +]; diff --git a/resources/lang/cn/navigation.php b/resources/lang/cn/navigation.php new file mode 100644 index 000000000..aebcd0fd0 --- /dev/null +++ b/resources/lang/cn/navigation.php @@ -0,0 +1,32 @@ + '主页', + 'account' => [ + 'header' => '账户管理', + 'my_account' => '我的账户', + 'security_controls' => '安全控制', + 'api_access' => 'API', + 'my_servers' => '我的服务器', + ], + 'server' => [ + 'header' => '服务器管理', + 'console' => '控制台', + 'console-pop' => '全屏控制台', + 'file_management' => '文件管理', + 'file_browser' => '文件浏览器', + 'create_file' => '新建文件', + 'upload_files' => '上传文件', + 'subusers' => '子用户', + 'schedules' => '计划任务', + 'configuration' => '配置', + 'port_allocations' => '地址设置', + 'sftp_settings' => 'SFTP 设置', + 'startup_parameters' => '启动参数', + 'databases' => '数据库', + 'edit_file' => '编辑文件', + 'admin_header' => '管理', + 'admin' => '服务器配置', + 'server_name' => '服务器名', + ], +]; diff --git a/resources/lang/cn/pagination.php b/resources/lang/cn/pagination.php new file mode 100644 index 000000000..67e361e02 --- /dev/null +++ b/resources/lang/cn/pagination.php @@ -0,0 +1,17 @@ + '« 上一步', + 'next' => '下一步 »', +]; diff --git a/resources/lang/cn/passwords.php b/resources/lang/cn/passwords.php new file mode 100644 index 000000000..3c471ae73 --- /dev/null +++ b/resources/lang/cn/passwords.php @@ -0,0 +1,19 @@ + '密码至少六位数,并且两次输入的密码一致.', + 'reset' => '您的密码已重设!', + 'sent' => '我们已发送密码重设电子邮件!', + 'token' => '此密码重设连接的令牌已过期.', + 'user' => '无法找到此Email的用户.', +]; diff --git a/resources/lang/cn/server.php b/resources/lang/cn/server.php new file mode 100644 index 000000000..296eb05c8 --- /dev/null +++ b/resources/lang/cn/server.php @@ -0,0 +1,330 @@ + [ + 'title' => '服务器状态 :name', + 'header' => '服务器控制台', + 'header_sub' => '实时控制您的服务器.', + ], + 'schedule' => [ + 'header' => '计划任务', + 'header_sub' => '在一处,轻松管理服务器任务.', + 'current' => '当前计划', + 'new' => [ + 'header' => '创建新任务', + 'header_sub' => '创建一个新的定时任务.', + 'submit' => '创建任务', + ], + 'manage' => [ + 'header' => '管理任务', + 'submit' => '修改任务', + 'delete' => '删除任务', + ], + 'task' => [ + 'time' => '在。。。之后', + 'action' => '执行操作', + 'payload' => '任务内容', + 'add_more' => '添加另一个任务', + ], + 'actions' => [ + 'command' => '发送命令', + 'power' => '电源命令', + ], + 'toggle' => '更改状态', + 'run_now' => '触发任务(现在)', + 'schedule_created' => '成功在服务器上创建一个计划任务.', + 'schedule_updated' => '任务已被更新.', + 'unnamed' => '未命名任务', + 'setup' => '任务创建', + 'day_of_week' => '星期', + 'day_of_month' => '日', + 'hour' => '小时', + 'minute' => '分钟', + 'time_help' => '任务系统在定义任务应该何时开始运行时支持使用Cronjob语法。 使用上面的字段指定何时应开始运行这些任务,或从多个选择菜单中选择选项。', + 'task_help' => '任务的时间与先前定义的任务相关。 每个计划任务可能分配的任务不超过5个,任务可能不会超过15分钟的时间安排。', + ], + 'tasks' => [ + 'task_created' => '成功在面板上创建一个新任务', + 'task_updated' => '任务成功被更新. 列表中的所有任务会被取消,并在下一次设定的时间运行.', + 'header' => '计划的任务', + 'header_sub' => '自动化你的服务器.', + 'current' => '当前计划的任务', + 'actions' => [ + 'command' => '发送命令', + 'power' => '发送电源命令', + ], + 'new_task' => '添加新任务', + 'toggle' => '更改状态', + 'new' => [ + 'header' => '新任务', + 'header_sub' => '为这个服务器创建一个新任务。', + 'task_name' => '任务名', + 'day_of_week' => '星期', + 'custom' => '自定义', + 'day_of_month' => '日', + 'hour' => '小时', + 'minute' => '分', + 'sun' => '周日', + 'mon' => '周一', + 'tues' => '周二', + 'wed' => '周三', + 'thurs' => '周四', + 'fri' => '周五', + 'sat' => '周六', + 'submit' => '创建任务', + 'type' => '任务类型', + 'chain_then' => '然后, 之后', + 'chain_do' => '执行', + 'chain_arguments' => '参数', + 'payload' => '任务内容', + 'payload_help' => '例如, 如果你选择 发送命令 ,就在此处填写要发送的命令. 如果您选择 发送电源命令 在这里填入电源命令 (e.g. restart).', + ], + 'edit' => [ + 'header' => '任务管理', + 'submit' => '更新任务', + ], + ], + 'users' => [ + 'header' => '用户管理', + 'header_sub' => '控制访问你服务器的用户.', + 'configure' => '配置权限', + 'list' => '有权限的用户列表', + 'add' => '添加一个新的子用户', + 'update' => '修改子用户', + 'user_assigned' => '成功连接到一个子用户连接到服务器.', + 'user_updated' => '成功更新权限.', + 'edit' => [ + 'header' => '编辑子用户', + 'header_sub' => '管理用户在此服务器的访问权限.', + ], + 'new' => [ + 'header' => '添加新用户', + 'header_sub' => '添加一个允许访问此服务器的用户.', + 'email' => 'Email 地址', + 'email_help' => '填入你希望邀请的协助您管理服务器的人的Email地址.', + 'power_header' => '电源管理', + 'file_header' => '文件管理', + 'subuser_header' => '子用户管理', + 'server_header' => '服务器管理', + 'task_header' => '计划任务管理', + 'database_header' => '数据库管理', + 'power_start' => [ + 'title' => '启动服务器', + 'description' => '允许该用户启动服务器.', + ], + 'power_stop' => [ + 'title' => '停止服务器', + 'description' => '允许该用户停止服务器.', + ], + 'power_restart' => [ + 'title' => '重新启动服务器', + 'description' => '允许该用户重新启动服务器', + ], + 'power_kill' => [ + 'title' => '强制结束服务器', + 'description' => '允许该用户强行关闭服务器', + ], + 'send_command' => [ + 'title' => '发送控制台命令', + 'description' => '允许用户发送控制台. 如果用户没有"停止服务器"权限,那么他无法使用stop命令', + ], + 'access_sftp' => [ + 'title' => 'SFTP 权限', + 'description' => '允许用户连接到受控端提供的SFTP服务器.', + ], + 'list_files' => [ + 'title' => '列出文件', + 'description' => '允许用户列出所有文件及文件夹列表,但是无权访问文件.', + ], + 'edit_files' => [ + 'title' => '编辑文件', + 'description' => '允许用户访问文件内容(但更改后无法保存). SFTP 不受此权限影响.', + ], + 'save_files' => [ + 'title' => 'Save Files', + 'description' => '允许用户保存文件(和编辑文件权限联动). SFTP 不受此权限影响.', + ], + 'move_files' => [ + 'title' => '重命名和移动文件', + 'description' => '允许用户在文件系统中重命名和移动文件及文件夹.', + ], + 'copy_files' => [ + 'title' => '复制文件', + 'description' => '允许用户在文件系统中复制文件及文件夹.', + ], + 'compress_files' => [ + 'title' => '压缩文件', + 'description' => '允许用户在文件系统中压缩文件及文件夹', + ], + 'decompress_files' => [ + 'title' => '解压文件', + 'description' => '允许用户解压 .zip 和 .tar(.gz) 压缩文件.', + ], + 'create_files' => [ + 'title' => '创建文件', + 'description' => '允许用户通过面板创建文件.', + ], + 'upload_files' => [ + 'title' => '上传文件', + 'description' => '允许用户通过文件管理上传文件.', + ], + 'delete_files' => [ + 'title' => '删除文件', + 'description' => '允许用户在文件系统中删除文件.', + ], + 'download_files' => [ + 'title' => '下载文件s', + 'description' => '允许用户下载文件. 如果为用户分配该权限,那么他将自动拥有下载和查看文件内容的权限.', + ], + 'list_subusers' => [ + 'title' => '列出子用户', + 'description' => '允许用户访问此服务器的子用户列表.', + ], + 'view_subuser' => [ + 'title' => '访问子用户', + 'description' => '允许用户查看子用户的权限.', + ], + 'edit_subuser' => [ + 'title' => '编辑子用户', + 'description' => '允许用户编辑此服务器上的子用户权限.', + ], + 'create_subuser' => [ + 'title' => '创建子用户', + 'description' => '允许用户在此服务器上添加子用户.', + ], + 'delete_subuser' => [ + 'title' => '删除子用户', + 'description' => '允许用户删除此服务器上的子用户.', + ], + 'view_allocations' => [ + 'title' => '访问分配表', + 'description' => '允许用户访问所有分配到此服务器上的IP和端口列表.', + ], + 'edit_allocation' => [ + 'title' => '编辑默认连接', + 'description' => '允许用户更改连接到此服务器的默认连接地址.', + ], + 'view_startup' => [ + 'title' => '访问启动参数', + 'description' => '允许用户访问服务器的启动参数和变量.', + ], + 'edit_startup' => [ + 'title' => '编辑启动参数', + 'description' => '允许用户更改服务器的启动参数和变量.', + ], + 'list_schedules' => [ + 'title' => '列出计划任务', + 'description' => '允许用户列出服务器上的所有计划任务 (无论是否启用) .', + ], + 'view_schedule' => [ + 'title' => '访问计划任务', + 'description' => '允许用户查看一个计划任务的具体信息,包括其执行的时间和命令.', + ], + 'toggle_schedule' => [ + 'title' => '开关计划任务', + 'description' => '允许用户更改计划任务的启用或禁用状态.', + ], + 'queue_schedule' => [ + 'title' => '队列化计划任务', + 'description' => '允许用户将一个计划任务队列,以便在下一个周期执行.', + ], + 'edit_schedule' => [ + 'title' => '编辑计划任务', + 'description' => '允许用户编辑计划任务. 此权限允许用户删除所有的执行任务,但无法删除计划任务本身.', + ], + 'create_schedule' => [ + 'title' => '创建计划任务', + 'description' => '允许用户创建一个计划任务.', + ], + 'delete_schedule' => [ + 'title' => '删除计划任务', + 'description' => '允许用户从服务器删除一个计划任务.', + ], + 'view_databases' => [ + 'title' => '访问数据库信息', + 'description' => '允许用户访问附属于此服务器的数据库信息,包含数据库的地址,用户名和密码', + ], + 'reset_db_password' => [ + 'title' => '重设数据库', + 'description' => '允许用户重新设置服务器数据库的密码.', + ], + 'delete_database' => [ + 'title' => '删除数据库', + 'description' => '允许用户从面板删除此服务器的数据库.', + ], + 'create_database' => [ + 'title' => '新建数据库', + 'description' => '允许用户为这个服务器创建一个数据库.', + ], + ], + ], + 'files' => [ + 'exceptions' => [ + 'invalid_mime' => '这种类型的文件无法使用面板内建编辑器编辑.', + 'max_size' => '此文件太大,无法使用面板内建编辑器编辑.', + ], + 'header' => '文件管理', + 'header_sub' => '从网页直接管理您所有的文件.', + 'loading' => '正在加载初始文件结构,这可能需要几秒钟.', + 'path' => '当你在配置任何插件或服务器设置的文件路径时 :path 应该为您的根目录. 此节点的网页上传最大文件限制为 :size.', + 'seconds_ago' => '几秒之前', + 'file_name' => '文件名', + 'size' => '大小', + 'last_modified' => '最后修改', + 'add_new' => '新建文件', + 'add_folder' => '新建文件夹', + 'mass_actions' => '更多操作', + 'delete' => '删除文件', + 'edit' => [ + 'header' => '编辑文件', + 'header_sub' => '从网页更改一个文件.', + 'save' => '保存文件', + 'return' => '返回文件管理', + ], + 'add' => [ + 'header' => '新建文件', + 'header_sub' => '在您服务器上创建一个新文件.', + 'name' => '文件名', + 'create' => '创建文件', + ], + ], + 'config' => [ + 'name' => [ + 'header' => '服务器名', + 'header_sub' => '更改您服务器的名称。', + 'details' => '此服务器名只是为了让你更好的管理服务器,并不会对服务器内的玩家有所影响.', + ], + 'startup' => [ + 'header' => '启动配置', + 'header_sub' => '控制服务器的启动参数.', + 'command' => '启动命令', + 'edit_params' => '编辑参数', + 'update' => '更新启动参数', + 'startup_regex' => '输入规则', + 'edited' => '启动参数已成功更新. 更新的内容会在下一次启动时生效.', + ], + 'sftp' => [ + 'header' => 'SFTP 配置', + 'header_sub' => 'SFTP 连接所需要的信息.', + 'details' => 'SFTP 信息', + 'conn_addr' => '连接地址', + 'warning' => 'SFTP密码就是您的用户密码. 请确认你使用的时SFTP,不是FTP,也不是FTPS, 这些都是不同的协议.', + ], + 'database' => [ + 'header' => '数据库', + 'header_sub' => '此服务器可用的数据库.', + 'your_dbs' => '已配置的数据库', + 'host' => 'MySQL 主机', + 'reset_password' => '重设密码', + 'no_dbs' => '没有此服务器可用的数据库.', + 'add_db' => '创建一个新数据库.', + ], + 'allocation' => [ + 'header' => '服务器连接信息', + 'header_sub' => '控制此服务器可用的IP和端口.', + 'available' => '可用的连接信息', + 'help' => '连接信息版主', + 'help_text' => '左边列出的所有IP和端口都是开放的,是您连接到您服务器的地址', + ], + ], +]; diff --git a/resources/lang/cn/strings.php b/resources/lang/cn/strings.php new file mode 100644 index 000000000..50bc70697 --- /dev/null +++ b/resources/lang/cn/strings.php @@ -0,0 +1,88 @@ + 'Email', + 'user_identifier' => '用户名 或 Email', + 'password' => '密码', + 'confirm_password' => '确认密码', + 'login' => '登陆', + 'home' => '主页', + 'servers' => '服务器', + 'id' => 'ID', + 'name' => '名称', + 'node' => '节点', + 'connection' => '连接', + 'memory' => '内存', + 'cpu' => 'CPU', + 'status' => '状态', + 'search' => '搜索', + 'suspended' => '已暂停', + 'account' => '用户', + 'security' => '安全', + 'ip' => 'IP 地址', + 'last_activity' => '上次活动', + 'revoke' => '吊销', + '2fa_token' => '认证密钥', + 'submit' => '确认', + 'close' => '关闭', + 'settings' => '设置', + 'configuration' => '配置', + 'sftp' => 'SFTP', + 'databases' => '数据库', + 'memo' => 'Memo', + 'created' => '已创建', + 'expires' => '过期', + 'public_key' => '令牌', + 'api_access' => 'Api 访问', + 'never' => '从未', + 'sign_out' => '登出', + 'admin_control' => '管理员面板', + 'required' => '需要', + 'port' => '端口', + 'username' => '用户名', + 'database' => '数据库', + 'new' => '新', + 'danger' => '危险', + 'create' => '创建', + 'select_all' => '全选', + 'select_none' => '反选', + 'alias' => '别名', + 'primary' => '主要', + 'make_primary' => '设置为主要', + 'none' => '无', + 'cancel' => '取消', + 'created_at' => '创建于', + 'action' => '操作', + 'data' => '数据', + 'queued' => '队列', + 'last_run' => '上次运行', + 'next_run' => '下次运行', + 'not_run_yet' => '从未允许', + 'yes' => '是', + 'no' => '否', + 'delete' => '删除', + '2fa' => '两步验证', + 'logout' => '登出', + 'admin_cp' => '管理员控制面板', + 'optional' => '可选的', + 'read_only' => '只读', + 'relation' => '关系', + 'owner' => '所有者', + 'admin' => '管理员', + 'subuser' => '子用户', + 'captcha_invalid' => '输入的验证码错误.', + 'tasks' => '任务', + 'seconds' => '秒', + 'minutes' => '分', + 'under_maintenance' => '维护中', + 'days' => [ + 'sun' => '周日', + 'mon' => '周一', + 'tues' => '周二', + 'wed' => '周三', + 'thurs' => '周四', + 'fri' => '周五', + 'sat' => '周六', + ], + 'last_used' => '上次使用', +]; diff --git a/resources/lang/cn/validation.php b/resources/lang/cn/validation.php new file mode 100644 index 000000000..932a39479 --- /dev/null +++ b/resources/lang/cn/validation.php @@ -0,0 +1,105 @@ + ' :attribute 被接受.', + 'active_url' => ' :attribute 不是一个有效的URL.', + 'after' => ' :attribute 必须是一个位于 :date 之后的日期.', + 'after_or_equal' => ' :attribute 必须是 :date 之后或同样的日期.', + 'alpha' => ' :attribute 只能含有字母.', + 'alpha_dash' => ':attribute 只能含有数字字母和分隔线.', + 'alpha_num' => ' :attribute 只能含有数字和字母.', + 'array' => ' :attribute 必须是个数组.', + 'before' => ' :attribute 必须是一个位于 :date 之前的日前.', + 'before_or_equal' => ' :attribute 必须是 :date 之前或同样的日期.', + 'between' => [ + 'numeric' => ' :attribute 必须在 :min 到 :max 之间.', + 'file' => ' :attribute 必须在 :min 到 :max KB 之间.', + 'string' => ' :attribute m必须在 :min 到 :max 个字符之间.', + 'array' => ' :attribute 必须在 :min 到 :max 个项目之间.', + ], + 'boolean' => ' :attribute 填入的必须为 true 或 false.', + 'confirmed' => ' :attribute 确认不匹配.', + 'date' => ' :attribute 不是一个合法的日期.', + 'date_format' => ' :attribute 不是正确的格式: :format.', + 'different' => ' :attribute 和 :other 必须不同.', + 'digits' => ' :attribute 必须为 :digits 个数字.', + 'digits_between' => ' :attribute 必须在 :min 到 :max 个数字间.', + 'dimensions' => ' :attribute 有一个非法的镜像大小.', + 'distinct' => ' :attribute 填入了一个重复的值.', + 'email' => ' :attribute 必须是一个合法的Email地址.', + 'exists' => '所选择的 :attribute 无效.', + 'file' => ' :attribute 必须为一个文件.', + 'filled' => ' :attribute 为必填项目.', + 'image' => ' :attribute 必须是一个镜像.', + 'in' => '所选择的 :attribute 无效.', + 'in_array' => ' :attribute 填入的信息在 :other 不存在.', + 'integer' => ' :attribute 必须是一个整数.', + 'ip' => ' :attribute 必须是一个合法的IP地址.', + 'json' => ' :attribute 必须是一个合法的JSON字符串.', + 'max' => [ + 'numeric' => ' :attribute 不能大于 :max.', + 'file' => ' :attribute 不能大于 :max KB.', + 'string' => ' :attribute 不能多于 :max 个字符.', + 'array' => ' :attribute 不能多于 :max 个项目.', + ], + 'mimes' => ' :attribute 文件类型必须为: :values.', + 'mimetypes' => ' :attribute 文件类型必须为: :values.', + 'min' => [ + 'numeric' => ' :attribute 至少应在 :min.', + 'file' => ' :attribute 至少应在 :min KB.', + 'string' => ' :attribute 至少应在 :min 个字符.', + 'array' => ' :attribute 至少应有 :min 个项目.', + ], + 'not_in' => '所选择的 :attribute 不正确.', + 'numeric' => ' :attribute 必须是个数字.', + 'present' => ' :attribute 填入的必须存在.', + 'regex' => ' :attribute 格式不正确.', + 'required' => ' :attribute 为必填.', + 'required_if' => ' :attribute 被要求填入, 当 :other 为 :value 的时候.', + 'required_unless' => ' :attribute 被要求填入,除非 :other 为 :values.', + 'required_with' => ' :attribute 被要求填入,当 :values 存在的时候.', + 'required_with_all' => ' :attribute 被要求填入,当 :values 存在.', + 'required_without' => ' :attribute 被要求填入,当 :values 不存在.', + 'required_without_all' => ' :attribute 被要求填入,当 :values 都不存在.', + 'same' => ' :attribute 和 :other 必须相同.', + 'size' => [ + 'numeric' => ' :attribute 必须为 :size.', + 'file' => ' :attribute 必须为 :size KB.', + 'string' => ' :attribute 必须为 :size 个字符.', + 'array' => ' :attribute 必须包含 :size 个项目.', + ], + 'string' => ' :attribute 必须为字符串.', + 'timezone' => ' :attribute 必须是一个有效的时区.', + 'unique' => ' :attribute 已经被使用.', + 'uploaded' => ' :attribute 上传失败.', + 'url' => ' :attribute 格式不合法.', + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap attribute place-holders + | with something more reader friendly such as E-Mail Address instead + | of "email". This simply helps us make messages a little cleaner. + | + */ + + 'attributes' => [], + + // Internal validation logic for Pterodactyl + 'internal' => [ + 'variable_value' => ':env variable', + ], +]; diff --git a/resources/lang/de/command/messages.php b/resources/lang/de/command/messages.php index 142ba4742..e3733935f 100644 --- a/resources/lang/de/command/messages.php +++ b/resources/lang/de/command/messages.php @@ -40,7 +40,7 @@ return [ ], 'environment' => [ 'mail' => [ - 'ask_smtp_host' => 'SMTP Host (e.g. smtp.google.com)', + 'ask_smtp_host' => 'SMTP Host (e.g. smtp.gmail.com)', 'ask_smtp_port' => 'SMTP Port', 'ask_smtp_username' => 'SMTP Benutzername', 'ask_smtp_password' => 'SMTP Password', diff --git a/resources/lang/de/strings.php b/resources/lang/de/strings.php index 2e2f2a751..299a7d67e 100644 --- a/resources/lang/de/strings.php +++ b/resources/lang/de/strings.php @@ -48,7 +48,7 @@ return [ 'select_none' => 'Alles abwählen', 'alias' => 'Alias', 'primary' => 'Primär', - 'make_primary' => 'Primät machen', + 'make_primary' => 'Primär machen', 'none' => 'Nichts', 'cancel' => 'Abbrechen', 'created_at' => 'Erstellt am', diff --git a/resources/lang/en/command/messages.php b/resources/lang/en/command/messages.php index 68d172896..8741fc424 100644 --- a/resources/lang/en/command/messages.php +++ b/resources/lang/en/command/messages.php @@ -49,7 +49,7 @@ return [ ], 'environment' => [ 'mail' => [ - 'ask_smtp_host' => 'SMTP Host (e.g. smtp.google.com)', + 'ask_smtp_host' => 'SMTP Host (e.g. smtp.gmail.com)', 'ask_smtp_port' => 'SMTP Port', 'ask_smtp_username' => 'SMTP Username', 'ask_smtp_password' => 'SMTP Password', diff --git a/resources/lang/es/command/messages.php b/resources/lang/es/command/messages.php index 6e8c3e95b..7fcc74578 100644 --- a/resources/lang/es/command/messages.php +++ b/resources/lang/es/command/messages.php @@ -47,7 +47,7 @@ return [ ], 'environment' => [ 'mail' => [ - 'ask_smtp_host' => 'Host SMTP (e.g. smtp.google.com)', + 'ask_smtp_host' => 'Host SMTP (e.g. smtp.gmail.com)', 'ask_smtp_port' => 'Puerto SMTP', 'ask_smtp_username' => 'El nombre de Usuario SMTP', 'ask_smtp_password' => 'Contraseña SMTP', diff --git a/resources/themes/pterodactyl/admin/api/index.blade.php b/resources/themes/pterodactyl/admin/api/index.blade.php index 9abcc2003..7d82b3292 100644 --- a/resources/themes/pterodactyl/admin/api/index.blade.php +++ b/resources/themes/pterodactyl/admin/api/index.blade.php @@ -5,7 +5,7 @@ @endsection @section('content-header') -

    Application APIControl access credentials for manging this Panel via the API.

    +

    Application APIControl access credentials for managing this Panel via the API.