diff --git a/CHANGELOG.md b/CHANGELOG.md index ada37ee00..18324a2c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ 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.6.0-pre.8 (Courageous Carniadactylus) +### Fixed +* `[pre.7]` — Fixes bug with subuser checkbox display. +* `[pre.7]` — Fixes bug with injected JS that was causing `` to be ignored in templates. +* `[pre.7]` — Fixes exception thrown when trying to delete a node due to a misnamed model. + +### Changed +* Subuser permissions are now stored in `Permission::list()` to make views way cleaner and make adding to views significantly cleaner. +* `[pre.7]` — Sidebar for file manager now is a single link rather than a dropdown. +* Attempting to reset a password for an account that does not exist no longer returns an error, rather it displays a success message. Failed resets trigger a `Pterodactyl\Events\Auth\FailedPasswordReset` event that can be caught if needed to perform other actions. + ## v0.6.0-pre.7 (Courageous Carniadactylus) ### Fixed * `[pre.6]` — Addresses misconfigured console queue that was still sending data way to quickly thus causing the console to explode on some devices when large amounts of data were sent. diff --git a/app/Events/Auth/FailedPasswordReset.php b/app/Events/Auth/FailedPasswordReset.php new file mode 100644 index 000000000..ec2de3b47 --- /dev/null +++ b/app/Events/Auth/FailedPasswordReset.php @@ -0,0 +1,59 @@ +. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +namespace Pterodactyl\Events\Auth; + +use Illuminate\Queue\SerializesModels; + +class FailedPasswordReset +{ + use SerializesModels; + + /** + * The IP that the request originated from. + * + * @var string + */ + public $ip; + + /** + * The email address that was used when the reset request failed. + * + * @var string + */ + public $email; + + /** + * Create a new event instance. + * + * @param string $ip + * @param string $email + * @return void + */ + public function __construct($ip, $email) + { + $this->ip = $ip; + $this->email = $email; + } +} diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 6d5f4bfa1..25a02b75c 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -1,8 +1,33 @@ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ namespace Pterodactyl\Http\Controllers\Auth; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Password; use Pterodactyl\Http\Controllers\Controller; +use Pterodactyl\Events\Auth\FailedPasswordReset; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; class ForgotPasswordController extends Controller @@ -29,4 +54,21 @@ class ForgotPasswordController extends Controller { $this->middleware('guest'); } + + /** + * Get the response for a failed password reset link. + * + * @param \Illuminate\Http\Request + * @param string $response + * @return \Illuminate\Http\RedirectResponse + */ + protected function sendResetLinkFailedResponse(Request $request, $response) + { + // As noted in #358 we will return success even if it failed + // to avoid pointing out that an account does or does not + // exist on the system. + event(new FailedPasswordReset($request->ip(), $request->only('email'))); + + return $this->sendResetLinkResponse(Password::RESET_LINK_SENT); + } } diff --git a/app/Http/Controllers/Server/SubuserController.php b/app/Http/Controllers/Server/SubuserController.php index 390f7b328..3caba0e0e 100644 --- a/app/Http/Controllers/Server/SubuserController.php +++ b/app/Http/Controllers/Server/SubuserController.php @@ -79,6 +79,7 @@ class SubuserController extends Controller 'server' => $server, 'node' => $server->node, 'subuser' => $subuser, + 'permlist' => Models\Permission::list(), 'permissions' => $subuser->permissions->mapWithKeys(function ($item, $key) { return [$item->permission => true]; }), @@ -146,6 +147,7 @@ class SubuserController extends Controller return view('server.users.new', [ 'server' => $server, + 'permissions' => Models\Permission::list(), 'node' => $server->node, ]); } diff --git a/app/Models/Permission.php b/app/Models/Permission.php index 7dfd55f3f..a2bd58a7b 100644 --- a/app/Models/Permission.php +++ b/app/Models/Permission.php @@ -58,6 +58,80 @@ class Permission extends Model 'subuser_id' => 'integer', ]; + /** + * A list of all permissions available for a user. + * + * @var array + */ + protected static $permissions = [ + 'power' => [ + 'power-start' => 's:power:start', + 'power-stop' => 's:power:stop', + 'power-restart' => 's:power:restart', + 'power-kill' => 's:power:kill', + 'send-command' => 's:command', + ], + 'subuser' => [ + 'list-subusers' => null, + 'view-subuser' => null, + 'edit-subuser' => null, + 'create-subuser' => null, + 'delete-subuser' => null, + ], + 'server' => [ + 'set-connection' => null, + 'view-startup' => null, + 'edit-startup' => null, + ], + 'sftp' => [ + 'view-sftp' => null, + 'view-sftp-password' => null, + 'reset-sftp' => 's:set-password', + ], + 'file' => [ + 'list-files' => 's:files:get', + 'edit-files' => 's:files:read', + 'save-files' => 's:files:post', + 'move-files' => 's:files:move', + 'copy-files' => 's:files:copy', + 'compress-files' => 's:files:compress', + 'decompress-files' => 's:files:decompress', + 'create-files' => 's:files:create', + 'upload-files' => 's:files:upload', + 'delete-files' => 's:files:delete', + 'download-files' => null, + ], + 'task' => [ + 'list-tasks' => null, + 'view-task' => null, + 'toggle-task' => null, + 'queue-task' => null, + 'create-task' => null, + 'delete-task' => null, + ], + 'database' => [ + 'view-databases' => null, + 'reset-db-password' => null, + ], + ]; + + /** + * Return a collection of permissions available. + * + * @param array $single + * @return \Illuminate\Support\Collection|array + */ + public static function list($single = false) + { + if ($single) { + return collect(self::$permissions)->mapWithKeys(function ($item) { + return $item; + })->all(); + } + + return collect(self::$permissions); + } + /** * Find permission by permission node. * diff --git a/app/Repositories/NodeRepository.php b/app/Repositories/NodeRepository.php index 51a91cfe3..0b361c3d5 100644 --- a/app/Repositories/NodeRepository.php +++ b/app/Repositories/NodeRepository.php @@ -277,13 +277,9 @@ class NodeRepository throw new DisplayException('You cannot delete a node with servers currently attached to it.'); } - DB::beginTransaction(); - - try { + DB::transaction(function () use ($node) { // Unlink Database Servers - Models\DatabaseServer::where('linked_node', $node->id)->update([ - 'linked_node' => null, - ]); + Models\DatabaseHost::where('node_id', $node->id)->update(['node_id' => null]); // Delete Allocations Models\Allocation::where('node_id', $node->id)->delete(); @@ -293,11 +289,6 @@ class NodeRepository // Delete Node $node->delete(); - - DB::commit(); - } catch (\Exception $ex) { - DB::rollback(); - throw $ex; - } + }); } } diff --git a/app/Repositories/SubuserRepository.php b/app/Repositories/SubuserRepository.php index 3b74ad1ad..37dd60501 100644 --- a/app/Repositories/SubuserRepository.php +++ b/app/Repositories/SubuserRepository.php @@ -45,62 +45,6 @@ class SubuserRepository 's:console', ]; - /** - * Allowed permissions and their related daemon permission. - * - * @var array - */ - protected $permissions = [ - // Power Permissions - 'power-start' => 's:power:start', - 'power-stop' => 's:power:stop', - 'power-restart' => 's:power:restart', - 'power-kill' => 's:power:kill', - - // Commands - 'send-command' => 's:command', - - // File Manager - 'list-files' => 's:files:get', - 'edit-files' => 's:files:read', - 'save-files' => 's:files:post', - 'create-files' => 's:files:create', - 'download-files' => null, - 'upload-files' => 's:files:upload', - 'delete-files' => 's:files:delete', - 'move-files' => 's:files:move', - 'copy-files' => 's:files:copy', - 'compress-files' => 's:files:compress', - 'decompress-files' => 's:files:decompress', - - // Subusers - 'list-subusers' => null, - 'view-subuser' => null, - 'edit-subuser' => null, - 'create-subuser' => null, - 'delete-subuser' => null, - - // Tasks - 'list-tasks' => null, - 'view-task' => null, - 'toggle-task' => null, - 'delete-task' => null, - 'create-task' => null, - 'queue-task' => null, - - // Management - 'set-connection' => null, - 'view-startup' => null, - 'edit-startup' => null, - 'view-sftp' => null, - 'reset-sftp' => 's:set-password', - 'view-sftp-password' => null, - - // Databases - 'view-databases' => null, - 'reset-db-password' => null, - ]; - /** * Creates a new subuser on the server. * @@ -155,12 +99,14 @@ class SubuserRepository 'daemonSecret' => (string) $uuid->generate('servers', 'uuid'), ]); + $perms = Permission::list(true); $daemonPermissions = $this->coreDaemonPermissions; + foreach ($data['permissions'] as $permission) { - if (array_key_exists($permission, $this->permissions)) { + if (array_key_exists($permission, $perms)) { // Build the daemon permissions array for sending. - if (! is_null($this->permissions[$permission])) { - array_push($daemonPermissions, $this->permissions[$permission]); + if (! is_null($perms[$permission])) { + array_push($daemonPermissions, $perms[$permission]); } Models\Permission::create([ @@ -272,12 +218,14 @@ class SubuserRepository $permission->delete(); } + $perms = Permission::list(true); $daemonPermissions = $this->coreDaemonPermissions; + foreach ($data['permissions'] as $permission) { - if (array_key_exists($permission, $this->permissions)) { + if (array_key_exists($permission, $perms)) { // Build the daemon permissions array for sending. - if (! is_null($this->permissions[$permission])) { - array_push($daemonPermissions, $this->permissions[$permission]); + if (! is_null($perms[$permission])) { + array_push($daemonPermissions, $perms[$permission]); } Models\Permission::create([ 'subuser_id' => $subuser->id, diff --git a/composer.json b/composer.json index a58fc7f82..b0779d689 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ ], "require": { "php": ">=5.6.4", - "laravel/framework": "5.3.21", + "laravel/framework": "5.3.31", "barryvdh/laravel-debugbar": "2.2.3", "doctrine/dbal": "2.5.5", "guzzlehttp/guzzle": "6.2.2", diff --git a/composer.lock b/composer.lock index 8975e85a0..51e9e8c6d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "7c01d337ebab3d47ae3479360c63e68f", - "content-hash": "c2addd888e0a4fd26518ea7c691f6f25", + "hash": "6de462d1565dfca583d5309a395e83a7", + "content-hash": "05b632a5d4b74151245bcbf0d12a1693", "packages": [ { "name": "aws/aws-sdk-php", @@ -1403,16 +1403,16 @@ }, { "name": "laravel/framework", - "version": "v5.3.21", + "version": "v5.3.31", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "140ad823863d5cc6f4580f1cdf9b18b9a6a457f4" + "reference": "e641e75fc5b26ad0ba8c19b7e83b08cad1d03b89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/140ad823863d5cc6f4580f1cdf9b18b9a6a457f4", - "reference": "140ad823863d5cc6f4580f1cdf9b18b9a6a457f4", + "url": "https://api.github.com/repos/laravel/framework/zipball/e641e75fc5b26ad0ba8c19b7e83b08cad1d03b89", + "reference": "e641e75fc5b26ad0ba8c19b7e83b08cad1d03b89", "shasum": "" }, "require": { @@ -1427,9 +1427,9 @@ "nesbot/carbon": "~1.20", "paragonie/random_compat": "~1.4|~2.0", "php": ">=5.6.4", - "psy/psysh": "0.7.*", + "psy/psysh": "0.7.*|0.8.*", "ramsey/uuid": "~3.0", - "swiftmailer/swiftmailer": "~5.1", + "swiftmailer/swiftmailer": "~5.4", "symfony/console": "3.1.*", "symfony/debug": "3.1.*", "symfony/finder": "3.1.*", @@ -1527,20 +1527,20 @@ "framework", "laravel" ], - "time": "2016-10-26 13:27:05" + "time": "2017-03-24 16:31:06" }, { "name": "league/flysystem", - "version": "1.0.35", + "version": "1.0.37", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "dda7f3ab94158a002d9846a97dc18ebfb7acc062" + "reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/dda7f3ab94158a002d9846a97dc18ebfb7acc062", - "reference": "dda7f3ab94158a002d9846a97dc18ebfb7acc062", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/78b5cc4feb61a882302df4fbaf63b7662e5e4ccd", + "reference": "78b5cc4feb61a882302df4fbaf63b7662e5e4ccd", "shasum": "" }, "require": { @@ -1610,7 +1610,7 @@ "sftp", "storage" ], - "time": "2017-02-09 11:33:58" + "time": "2017-03-22 15:43:14" }, { "name": "league/fractal", @@ -1789,16 +1789,16 @@ }, { "name": "monolog/monolog", - "version": "1.22.0", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558" + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/bad29cb8d18ab0315e6c477751418a82c850d558", - "reference": "bad29cb8d18ab0315e6c477751418a82c850d558", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", + "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", "shasum": "" }, "require": { @@ -1863,7 +1863,7 @@ "logging", "psr-3" ], - "time": "2016-11-26 00:15:39" + "time": "2017-03-13 07:08:03" }, { "name": "mtdowling/cron-expression", @@ -2059,24 +2059,24 @@ }, { "name": "nikic/php-parser", - "version": "v2.1.1", + "version": "v3.0.5", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4dd659edadffdc2143e4753df655d866dbfeedf0" + "reference": "2b9e2f71b722f7c53918ab0c25f7646c2013f17d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4dd659edadffdc2143e4753df655d866dbfeedf0", - "reference": "4dd659edadffdc2143e4753df655d866dbfeedf0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2b9e2f71b722f7c53918ab0c25f7646c2013f17d", + "reference": "2b9e2f71b722f7c53918ab0c25f7646c2013f17d", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.4" + "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.0|~5.0" }, "bin": [ "bin/php-parse" @@ -2084,7 +2084,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2106,20 +2106,20 @@ "parser", "php" ], - "time": "2016-09-16 12:04:44" + "time": "2017-03-05 18:23:57" }, { "name": "paragonie/random_compat", - "version": "v2.0.4", + "version": "v2.0.10", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e" + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", - "reference": "a9b97968bcde1c4de2a5ec6cbd06a0f6c919b46e", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", "shasum": "" }, "require": { @@ -2154,7 +2154,7 @@ "pseudorandom", "random" ], - "time": "2016-11-07 23:38:38" + "time": "2017-03-13 16:27:32" }, { "name": "phpdocumentor/reflection-common", @@ -2562,37 +2562,38 @@ }, { "name": "psy/psysh", - "version": "v0.7.2", + "version": "v0.8.3", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280" + "reference": "1dd4bbbc64d71e7ec075ffe82b42d9e096dc8d5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e64e10b20f8d229cac76399e1f3edddb57a0f280", - "reference": "e64e10b20f8d229cac76399e1f3edddb57a0f280", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1dd4bbbc64d71e7ec075ffe82b42d9e096dc8d5e", + "reference": "1dd4bbbc64d71e7ec075ffe82b42d9e096dc8d5e", "shasum": "" }, "require": { "dnoegel/php-xdg-base-dir": "0.1", "jakub-onderka/php-console-highlighter": "0.3.*", - "nikic/php-parser": "^1.2.1|~2.0", + "nikic/php-parser": "~1.3|~2.0|~3.0", "php": ">=5.3.9", "symfony/console": "~2.3.10|^2.4.2|~3.0", "symfony/var-dumper": "~2.7|~3.0" }, "require-dev": { - "fabpot/php-cs-fixer": "~1.5", - "phpunit/phpunit": "~3.7|~4.0|~5.0", - "squizlabs/php_codesniffer": "~2.0", + "friendsofphp/php-cs-fixer": "~1.11", + "hoa/console": "~3.16|~1.14", + "phpunit/phpunit": "~4.4|~5.0", "symfony/finder": "~2.1|~3.0" }, "suggest": { "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", "ext-pdo-sqlite": "The doc command requires SQLite to work.", "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", - "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.", + "hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit." }, "bin": [ "bin/psysh" @@ -2600,7 +2601,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-develop": "0.8.x-dev" + "dev-develop": "0.9.x-dev" } }, "autoload": { @@ -2630,34 +2631,34 @@ "interactive", "shell" ], - "time": "2016-03-09 05:03:14" + "time": "2017-03-19 21:40:44" }, { "name": "ramsey/uuid", - "version": "3.5.2", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "5677cfe02397dd6b58c861870dfaa5d9007d3954" + "reference": "4ae32dd9ab8860a4bbd750ad269cba7f06f7934e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/5677cfe02397dd6b58c861870dfaa5d9007d3954", - "reference": "5677cfe02397dd6b58c861870dfaa5d9007d3954", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4ae32dd9ab8860a4bbd750ad269cba7f06f7934e", + "reference": "4ae32dd9ab8860a4bbd750ad269cba7f06f7934e", "shasum": "" }, "require": { "paragonie/random_compat": "^1.0|^2.0", - "php": ">=5.4" + "php": "^5.4 || ^7.0" }, "replace": { "rhumsaa/uuid": "self.version" }, "require-dev": { "apigen/apigen": "^4.1", - "codeception/aspect-mock": "1.0.0", + "codeception/aspect-mock": "^1.0 | ^2.0", "doctrine/annotations": "~1.2.0", - "goaop/framework": "1.0.0-alpha.2", + "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ^2.1", "ircmaxell/random-lib": "^1.1", "jakub-onderka/php-parallel-lint": "^0.9.0", "mockery/mockery": "^0.9.4", @@ -2712,7 +2713,7 @@ "identifier", "uuid" ], - "time": "2016-11-22 19:21:44" + "time": "2017-03-26 20:37:53" }, { "name": "s1lentium/iptools", @@ -2766,16 +2767,16 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v5.4.5", + "version": "v5.4.6", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "cd142238a339459b10da3d8234220963f392540c" + "reference": "81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/cd142238a339459b10da3d8234220963f392540c", - "reference": "cd142238a339459b10da3d8234220963f392540c", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e", + "reference": "81fdccfaf8bdc5d5d7a1ef6bb3a61bbb1a6c4a3e", "shasum": "" }, "require": { @@ -2816,7 +2817,7 @@ "mail", "mailer" ], - "time": "2016-12-29 10:02:40" + "time": "2017-02-13 07:52:53" }, { "name": "symfony/console", @@ -2938,16 +2939,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v3.2.3", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9137eb3a3328e413212826d63eeeb0217836e2b6" + "reference": "b7a1b9e0a0f623ce43b4c8d775eb138f190c9d8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9137eb3a3328e413212826d63eeeb0217836e2b6", - "reference": "9137eb3a3328e413212826d63eeeb0217836e2b6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7a1b9e0a0f623ce43b4c8d775eb138f190c9d8d", + "reference": "b7a1b9e0a0f623ce43b4c8d775eb138f190c9d8d", "shasum": "" }, "require": { @@ -2994,7 +2995,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-01-02 20:32:22" + "time": "2017-02-21 09:12:04" }, { "name": "symfony/finder", @@ -4057,16 +4058,16 @@ }, { "name": "mockery/mockery", - "version": "0.9.8", + "version": "0.9.9", "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", - "reference": "1e5e2ffdc4d71d7358ed58a6fdd30a4a0c506855" + "reference": "6fdb61243844dc924071d3404bb23994ea0b6856" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/1e5e2ffdc4d71d7358ed58a6fdd30a4a0c506855", - "reference": "1e5e2ffdc4d71d7358ed58a6fdd30a4a0c506855", + "url": "https://api.github.com/repos/padraic/mockery/zipball/6fdb61243844dc924071d3404bb23994ea0b6856", + "reference": "6fdb61243844dc924071d3404bb23994ea0b6856", "shasum": "" }, "require": { @@ -4118,7 +4119,7 @@ "test double", "testing" ], - "time": "2017-02-09 13:29:38" + "time": "2017-02-28 12:52:32" }, { "name": "myclabs/deep-copy", @@ -4164,27 +4165,27 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", + "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "sebastian/comparator": "^1.1|^2.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", + "phpspec/phpspec": "^2.5|^3.2", "phpunit/phpunit": "^4.8 || ^5.6.5" }, "type": "library", @@ -4223,39 +4224,39 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2017-03-02 20:05:34" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.5", + "version": "4.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971" + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", - "reference": "c19cfc7cbb0e9338d8c469c7eedecc2a428b0971", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09e2277d14ea467e5a984010f501343ef29ffc69", + "reference": "09e2277d14ea467e5a984010f501343ef29ffc69", "shasum": "" }, "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "^1.4.2", - "sebastian/code-unit-reverse-lookup": "~1.0", + "phpunit/php-file-iterator": "^1.3", + "phpunit/php-text-template": "^1.2", + "phpunit/php-token-stream": "^1.4.2 || ^2.0", + "sebastian/code-unit-reverse-lookup": "^1.0", "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "~1.0|~2.0" + "sebastian/version": "^1.0 || ^2.0" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "^5.4" + "ext-xdebug": "^2.1.4", + "phpunit/phpunit": "^5.7" }, "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.4.0", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.5.1" }, "type": "library", "extra": { @@ -4286,7 +4287,7 @@ "testing", "xunit" ], - "time": "2017-01-20 15:06:43" + "time": "2017-03-01 09:12:17" }, { "name": "phpunit/php-file-iterator", @@ -4378,25 +4379,30 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -4418,20 +4424,20 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2017-02-26 11:10:40" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "1.4.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", + "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", "shasum": "" }, "require": { @@ -4467,20 +4473,20 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2017-02-27 10:12:30" }, { "name": "phpunit/phpunit", - "version": "5.7.13", + "version": "5.7.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "60ebeed87a35ea46fd7f7d8029df2d6f013ebb34" + "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60ebeed87a35ea46fd7f7d8029df2d6f013ebb34", - "reference": "60ebeed87a35ea46fd7f7d8029df2d6f013ebb34", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68752b665d3875f9a38a357e3ecb35c79f8673bf", + "reference": "68752b665d3875f9a38a357e3ecb35c79f8673bf", "shasum": "" }, "require": { @@ -4504,7 +4510,7 @@ "sebastian/global-state": "^1.1", "sebastian/object-enumerator": "~2.0", "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0|~2.0", + "sebastian/version": "~1.0.3|~2.0", "symfony/yaml": "~2.1|~3.0" }, "conflict": { @@ -4549,7 +4555,7 @@ "testing", "xunit" ], - "time": "2017-02-10 09:05:10" + "time": "2017-03-19 16:52:12" }, { "name": "phpunit/phpunit-mock-objects", @@ -4612,23 +4618,23 @@ }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { @@ -4653,7 +4659,7 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13 06:45:14" + "time": "2017-03-04 06:30:41" }, { "name": "sebastian/comparator", @@ -4941,16 +4947,16 @@ }, { "name": "sebastian/object-enumerator", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7", + "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7", "shasum": "" }, "require": { @@ -4983,7 +4989,7 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-11-19 07:35:10" + "time": "2017-02-18 15:18:39" }, { "name": "sebastian/recursion-context", @@ -5290,16 +5296,16 @@ }, { "name": "symfony/yaml", - "version": "v3.2.3", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e1718c6bf57e1efbb8793ada951584b2ab27775b" + "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e1718c6bf57e1efbb8793ada951584b2ab27775b", - "reference": "e1718c6bf57e1efbb8793ada951584b2ab27775b", + "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", + "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", "shasum": "" }, "require": { @@ -5341,7 +5347,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-01-21 17:06:35" + "time": "2017-03-07 16:47:02" } ], "aliases": [], diff --git a/config/javascript.php b/config/javascript.php index 1c2ef82dc..1aeb222e0 100644 --- a/config/javascript.php +++ b/config/javascript.php @@ -14,8 +14,7 @@ return [ | */ 'bind_js_vars_to_this_view' => [ - 'layouts.master', - 'layouts.admin', + 'layouts.scripts', ], /* diff --git a/public/themes/pterodactyl/css/pterodactyl.css b/public/themes/pterodactyl/css/pterodactyl.css index 119099b50..aca92d909 100644 --- a/public/themes/pterodactyl/css/pterodactyl.css +++ b/public/themes/pterodactyl/css/pterodactyl.css @@ -276,3 +276,7 @@ span[aria-labelledby="select2-pUserId-container"] { .btn-icon > i.fa { line-height: 1.5; } + +.strong { + font-weight: bold !important; +} diff --git a/public/themes/pterodactyl/js/frontend/server.socket.js b/public/themes/pterodactyl/js/frontend/server.socket.js index 3e97c2a62..4c0e77fa8 100644 --- a/public/themes/pterodactyl/js/frontend/server.socket.js +++ b/public/themes/pterodactyl/js/frontend/server.socket.js @@ -38,9 +38,13 @@ var Server = (function () { }, newest_on_top: true, delay: 2000, + offset: { + x: 20, + y: 60, + }, animate: { - enter: 'animated zoomInDown', - exit: 'animated zoomOutDown' + enter: 'animated bounceInUp', + exit: 'animated bounceOutDown' } }); @@ -56,7 +60,7 @@ var Server = (function () { message: 'There was an error attempting to establish a WebSocket connection to the Daemon. This panel will not work as expected.

' + err, }, { type: 'danger', - delay: 0 + delay: 0, }); } }); diff --git a/resources/lang/en/server.php b/resources/lang/en/server.php index 43913b64e..e0c34a888 100644 --- a/resources/lang/en/server.php +++ b/resources/lang/en/server.php @@ -59,24 +59,24 @@ return [ 'server_header' => 'Server Management', 'task_header' => 'Task Management', 'sftp_header' => 'SFTP Management', - 'db_header' => 'Database Management', - 'start' => [ + 'database_header' => 'Database Management', + 'power_start' => [ 'title' => 'Start Server', 'description' => 'Allows user to start the server.', ], - 'stop' => [ + 'power_stop' => [ 'title' => 'Stop Server', 'description' => 'Allows user to stop the server.', ], - 'restart' => [ + 'power_restart' => [ 'title' => 'Restart Server', 'description' => 'Allows user to restart the server.', ], - 'kill' => [ + 'power_kill' => [ 'title' => 'Kill Server', 'description' => 'Allows user to kill the server process.', ], - 'command' => [ + 'send_command' => [ 'title' => 'Send Console Command', 'description' => 'Allows sending a command from the console. If the user does not have stop or restart permissions they cannot send the application\'s stop command.', ], diff --git a/resources/themes/pterodactyl/layouts/admin.blade.php b/resources/themes/pterodactyl/layouts/admin.blade.php index f3a7920b8..910b50bcf 100644 --- a/resources/themes/pterodactyl/layouts/admin.blade.php +++ b/resources/themes/pterodactyl/layouts/admin.blade.php @@ -26,7 +26,6 @@ - @@ -36,6 +35,8 @@ + @include('layouts.scripts') + @section('scripts') {!! Theme::css('vendor/select2/select2.min.css') !!} {!! Theme::css('vendor/bootstrap/bootstrap.min.css') !!} @@ -75,13 +76,13 @@
  • - +
  • -
  • +
  • -
  • +
  • @@ -171,8 +172,8 @@ diff --git a/resources/themes/pterodactyl/layouts/master.blade.php b/resources/themes/pterodactyl/layouts/master.blade.php index 3a204523a..ac074bb30 100644 --- a/resources/themes/pterodactyl/layouts/master.blade.php +++ b/resources/themes/pterodactyl/layouts/master.blade.php @@ -35,6 +35,8 @@ + @include('layouts.scripts') + @section('scripts') {!! Theme::css('vendor/bootstrap/bootstrap.min.css') !!} {!! Theme::css('vendor/adminlte/admin.min.css') !!} @@ -73,15 +75,15 @@
  • - +
  • @if(Auth::user()->isRootAdmin())
  • -
  • +
  • @endif
  • -
  • +
  • @@ -127,24 +129,14 @@ @can('list-files', $server) -
  • - - - @lang('navigation.server.file_management') - - - + > + + @lang('navigation.server.file_management') -
  • @endcan @can('list-subusers', $server) @@ -154,7 +146,7 @@ @endif > - Subusers + @lang('navigation.server.subusers') @endcan @@ -235,8 +227,8 @@ diff --git a/resources/themes/pterodactyl/layouts/scripts.blade.php b/resources/themes/pterodactyl/layouts/scripts.blade.php new file mode 100644 index 000000000..3393bf5fe --- /dev/null +++ b/resources/themes/pterodactyl/layouts/scripts.blade.php @@ -0,0 +1 @@ +{{-- Just here as a binder for dynamically rendered content. --}} diff --git a/resources/themes/pterodactyl/server/users/new.blade.php b/resources/themes/pterodactyl/server/users/new.blade.php index 5cbe5617f..e77144232 100644 --- a/resources/themes/pterodactyl/server/users/new.blade.php +++ b/resources/themes/pterodactyl/server/users/new.blade.php @@ -60,340 +60,31 @@
    -
    - {{-- Left Side --}} -
    -
    -
    -
    -

    @lang('server.users.new.power_header')

    -
    -
    -
    - + @foreach($permissions as $block => $perms) +
    +
    +
    +

    @lang('server.users.new.' . $block . '_header')

    +
    +
    + @foreach($perms as $permission => $daemon) +
    +
    + + +
    +

    @lang('server.users.new.' . str_replace('-', '_', $permission) . '.description')

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    + @endforeach
    -
    -
    -
    -
    -

    @lang('server.users.new.subuser_header')

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.server_header')

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.sftp_header')

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    - {{-- Right Side --}} -
    -
    -
    -
    -

    @lang('server.users.new.file_header')

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.task_header')

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.db_header')

    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    -
    + @if ($loop->iteration % 2 === 0) +
    + @endif + @endforeach
    @endsection diff --git a/resources/themes/pterodactyl/server/users/view.blade.php b/resources/themes/pterodactyl/server/users/view.blade.php index fdb4e0c0d..61fd5c48a 100644 --- a/resources/themes/pterodactyl/server/users/view.blade.php +++ b/resources/themes/pterodactyl/server/users/view.blade.php @@ -62,270 +62,31 @@
    -
    - {{-- Left Side --}} -
    -
    -
    -
    -

    @lang('server.users.new.power_header')

    -
    -
    -
    - - -

    @lang('server.users.new.start.description')

    + @foreach($permlist as $block => $perms) +
    +
    +
    +

    @lang('server.users.new.' . $block . '_header')

    +
    +
    + @foreach($perms as $permission => $daemon) +
    +
    + + +
    +

    @lang('server.users.new.' . str_replace('-', '_', $permission) . '.description')

    -
    - - @lang('server.users.new.stop.title') -

    @lang('server.users.new.stop.description')

    -
    -
    - - @lang('server.users.new.restart.title') -

    @lang('server.users.new.restart.description')

    -
    -
    - - @lang('server.users.new.kill.title') -

    @lang('server.users.new.kill.description')

    -
    -
    - - @lang('server.users.new.command.title') -

    @lang('server.users.new.command.description')

    -
    -
    + @endforeach
    -
    -
    -
    -
    -

    @lang('server.users.new.subuser_header')

    -
    -
    -
    - - @lang('server.users.new.list_subusers.title') -

    @lang('server.users.new.list_subusers.description')

    -
    -
    - - @lang('server.users.new.view_subuser.title') -

    @lang('server.users.new.view_subuser.description')

    -
    -
    - - @lang('server.users.new.edit_subuser.title') -

    @lang('server.users.new.edit_subuser.description')

    -
    -
    - - @lang('server.users.new.create_subuser.title') -

    @lang('server.users.new.create_subuser.description')

    -
    -
    - - @lang('server.users.new.delete_subuser.title') -

    @lang('server.users.new.delete_subuser.description')

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.server_header')

    -
    -
    -
    - - @lang('server.users.new.set_connection.title') -

    @lang('server.users.new.set_connection.description')

    -
    -
    - - @lang('server.users.new.view_startup.title') -

    @lang('server.users.new.view_startup.description')

    -
    -
    - - @lang('server.users.new.edit_startup.title') -

    @lang('server.users.new.edit_startup.description')

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.sftp_header')

    -
    -
    -
    - - @lang('server.users.new.view_sftp.title') -

    @lang('server.users.new.view_sftp.description')

    -
    -
    - - @lang('strings.danger') - @lang('server.users.new.view_sftp_password.title') -

    @lang('server.users.new.view_sftp_password.description')

    -
    -
    - - @lang('server.users.new.reset_sftp.title') -

    @lang('server.users.new.reset_sftp.description')

    -
    -
    -
    -
    -
    -
    -
    - {{-- Right Side --}} -
    -
    -
    -
    -

    @lang('server.users.new.file_header')

    -
    -
    -
    - - @lang('server.users.new.list_files.title') -

    @lang('server.users.new.list_files.description')

    -
    -
    - - @lang('server.users.new.edit_files.title') -

    @lang('server.users.new.edit_files.description')

    -
    -
    - - @lang('server.users.new.save_files.title') -

    @lang('server.users.new.save_files.description')

    -
    -
    - - @lang('server.users.new.move_files.title') -

    @lang('server.users.new.move_files.description')

    -
    -
    - - @lang('server.users.new.copy_files.title') -

    @lang('server.users.new.copy_files.description')

    -
    -
    - - @lang('server.users.new.compress_files.title') -

    @lang('server.users.new.compress_files.description')

    -
    -
    - - @lang('server.users.new.decompress_files.title') -

    @lang('server.users.new.decompress_files.description')

    -
    -
    - - @lang('server.users.new.create_files.title') -

    @lang('server.users.new.create_files.description')

    -
    -
    - - @lang('server.users.new.upload_files.title') -

    @lang('server.users.new.upload_files.description')

    -
    -
    - - @lang('strings.danger') - @lang('server.users.new.delete_files.title') -

    @lang('server.users.new.delete_files.description')

    -
    -
    - - @lang('strings.danger') - @lang('server.users.new.download_files.title') -

    @lang('server.users.new.download_files.description')

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.task_header')

    -
    -
    -
    - - @lang('server.users.new.list_tasks.title') -

    @lang('server.users.new.list_tasks.description')

    -
    -
    - - @lang('server.users.new.view_task.title') -

    @lang('server.users.new.view_task.description')

    -
    -
    - - @lang('server.users.new.toggle_task.title') -

    @lang('server.users.new.toggle_task.description')

    -
    -
    - - @lang('server.users.new.queue_task.title') -

    @lang('server.users.new.queue_task.description')

    -
    -
    - - @lang('server.users.new.create_task.title') -

    @lang('server.users.new.create_task.description')

    -
    -
    - - @lang('strings.danger') - @lang('server.users.new.delete_task.title') -

    @lang('server.users.new.delete_task.description')

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    @lang('server.users.new.db_header')

    -
    -
    -
    - - @lang('strings.danger') - @lang('server.users.new.view_databases.title') -

    @lang('server.users.new.view_databases.description')

    -
    -
    - - @lang('strings.danger') - @lang('server.users.new.reset_db_password.title') -

    @lang('server.users.new.reset_db_password.description')

    -
    -
    -
    -
    -
    -
    + @if ($loop->iteration % 2 === 0) +
    + @endif + @endforeach
    @can('edit-subuser', $server)