diff --git a/app/Contracts/Repository/Daemon/FileRepositoryInterface.php b/app/Contracts/Repository/Daemon/FileRepositoryInterface.php index 8573daf61..66952fdab 100644 --- a/app/Contracts/Repository/Daemon/FileRepositoryInterface.php +++ b/app/Contracts/Repository/Daemon/FileRepositoryInterface.php @@ -13,7 +13,7 @@ interface FileRepositoryInterface extends BaseRepositoryInterface * @param string $path * @return \stdClass * - * @throws \GuzzleHttp\Exception\RequestException + * @throws \GuzzleHttp\Exception\TransferException */ public function getFileStat(string $path): stdClass; @@ -23,7 +23,7 @@ interface FileRepositoryInterface extends BaseRepositoryInterface * @param string $path * @return string * - * @throws \GuzzleHttp\Exception\RequestException + * @throws \GuzzleHttp\Exception\TransferException */ public function getContent(string $path): string; @@ -34,7 +34,7 @@ interface FileRepositoryInterface extends BaseRepositoryInterface * @param string $content * @return \Psr\Http\Message\ResponseInterface * - * @throws \GuzzleHttp\Exception\RequestException + * @throws \GuzzleHttp\Exception\TransferException */ public function putContent(string $path, string $content): ResponseInterface; @@ -44,7 +44,7 @@ interface FileRepositoryInterface extends BaseRepositoryInterface * @param string $path * @return array * - * @throws \GuzzleHttp\Exception\RequestException + * @throws \GuzzleHttp\Exception\TransferException */ public function getDirectory(string $path): array; } diff --git a/app/Http/Controllers/Server/ConsoleController.php b/app/Http/Controllers/Server/ConsoleController.php deleted file mode 100644 index 93d383cce..000000000 --- a/app/Http/Controllers/Server/ConsoleController.php +++ /dev/null @@ -1,73 +0,0 @@ -config = $config; - } - - /** - * Render server index page with the console and power options. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - - $this->setRequest($request)->injectJavascript([ - 'server' => [ - 'cpu' => $server->cpu, - ], - 'meta' => [ - 'saveFile' => route('server.files.save', $server->uuidShort), - 'csrfToken' => csrf_token(), - ], - 'config' => [ - 'console_count' => $this->config->get('pterodactyl.console.count'), - 'console_freq' => $this->config->get('pterodactyl.console.frequency'), - ], - ]); - - //return view('server.index'); - return view('templates/base.core'); - } - - /** - * Render a stand-alone console in the browser. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - */ - public function console(Request $request): View - { - $this->setRequest($request)->injectJavascript(['config' => [ - 'console_count' => $this->config->get('pterodactyl.console.count'), - 'console_freq' => $this->config->get('pterodactyl.console.frequency'), - ]]); - - return view('server.console'); - } -} diff --git a/app/Http/Controllers/Server/DatabaseController.php b/app/Http/Controllers/Server/DatabaseController.php deleted file mode 100644 index be7d501ba..000000000 --- a/app/Http/Controllers/Server/DatabaseController.php +++ /dev/null @@ -1,165 +0,0 @@ -alert = $alert; - $this->databaseHostRepository = $databaseHostRepository; - $this->deployServerDatabaseService = $deployServerDatabaseService; - $this->managementService = $managementService; - $this->passwordService = $passwordService; - $this->repository = $repository; - } - - /** - * Render the database listing for a server. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('view-databases', $server); - $this->setRequest($request)->injectJavascript(); - - $canCreateDatabase = config('pterodactyl.client_features.databases.enabled'); - $allowRandom = config('pterodactyl.client_features.databases.allow_random'); - - if ($this->databaseHostRepository->findCountWhere([['node_id', '=', $server->node_id]]) === 0) { - if ($canCreateDatabase && ! $allowRandom) { - $canCreateDatabase = false; - } - } - - $databases = $this->repository->getDatabasesForServer($server->id); - - return view('server.databases.index', [ - 'allowCreation' => $canCreateDatabase, - 'overLimit' => ! is_null($server->database_limit) && count($databases) >= $server->database_limit, - 'databases' => $databases, - ]); - } - - /** - * Handle a request from a user to create a new database for the server. - * - * @param \Pterodactyl\Http\Requests\Server\Database\StoreServerDatabaseRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Exception - * @throws \Pterodactyl\Exceptions\Service\Database\DatabaseClientFeatureNotEnabledException - */ - public function store(StoreServerDatabaseRequest $request): RedirectResponse - { - $this->deployServerDatabaseService->handle($request->getServer(), $request->validated()); - - $this->alert->success('Successfully created a new database.')->flash(); - - return redirect()->route('server.databases.index', $request->getServer()->uuidShort); - } - - /** - * Handle a request to update the password for a specific database. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\JsonResponse - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function update(Request $request): JsonResponse - { - $this->authorize('reset-db-password', $request->attributes->get('server')); - - $password = str_random(20); - $this->passwordService->handle($request->attributes->get('database'), $password); - - return response()->json(['password' => $password]); - } - - /** - * Delete a database for this server from the SQL server and Panel database. - * - * @param \Pterodactyl\Http\Requests\Server\Database\DeleteServerDatabaseRequest $request - * @return \Illuminate\Http\Response - * - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function delete(DeleteServerDatabaseRequest $request): Response - { - $this->managementService->delete($request->attributes->get('database')->id); - - return response('', Response::HTTP_NO_CONTENT); - } -} diff --git a/app/Http/Controllers/Server/FileController.php b/app/Http/Controllers/Server/FileController.php new file mode 100644 index 000000000..f19e5f477 --- /dev/null +++ b/app/Http/Controllers/Server/FileController.php @@ -0,0 +1,69 @@ +fileRepository = $fileRepository; + } + + /** + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\JsonResponse + * + * @throws \Illuminate\Auth\Access\AuthorizationException + * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException + */ + public function index(Request $request): JsonResponse + { + $server = $request->attributes->get('server'); + $this->authorize('list-files', $server); + + $requestDirectory = '/' . trim(urldecode($request->route()->parameter('directory', '/')), '/'); + $directory = [ + 'header' => $requestDirectory !== '/' ? $requestDirectory : '', + 'first' => $requestDirectory !== '/', + ]; + + $goBack = explode('/', trim($requestDirectory, '/')); + if (! empty(array_filter($goBack)) && count($goBack) >= 2) { + array_pop($goBack); + $directory['show'] = true; + $directory['link'] = '/' . implode('/', $goBack); + $directory['link_show'] = implode('/', $goBack) . '/'; + } + + try { + $contents = $this->fileRepository->setServer($server)->setToken( + $request->attributes->get('server_token') + )->getDirectory($requestDirectory); + } catch (TransferException $exception) { + throw new DaemonConnectionException($exception, true); + } + + return JsonResponse::create([ + 'contents' => $contents, + 'editable' => config('pterodactyl.files.editable'), + 'current_directory' => $directory, + ]); + } +} diff --git a/app/Http/Controllers/Server/Files/DownloadController.php b/app/Http/Controllers/Server/Files/DownloadController.php deleted file mode 100644 index 04b16d084..000000000 --- a/app/Http/Controllers/Server/Files/DownloadController.php +++ /dev/null @@ -1,57 +0,0 @@ -. - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ - -namespace Pterodactyl\Http\Controllers\Server\Files; - -use Ramsey\Uuid\Uuid; -use Illuminate\Http\Request; -use Illuminate\Cache\Repository; -use Illuminate\Http\RedirectResponse; -use Pterodactyl\Http\Controllers\Controller; - -class DownloadController extends Controller -{ - /** - * @var \Illuminate\Cache\Repository - */ - protected $cache; - - /** - * DownloadController constructor. - * - * @param \Illuminate\Cache\Repository $cache - */ - public function __construct(Repository $cache) - { - $this->cache = $cache; - } - - /** - * Setup a unique download link for a user to download a file from. - * - * @param \Illuminate\Http\Request $request - * @param string $uuid - * @param string $file - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request, string $uuid, string $file): RedirectResponse - { - $server = $request->attributes->get('server'); - $this->authorize('download-files', $server); - - $token = Uuid::uuid4()->toString(); - $node = $server->getRelation('node'); - - $this->cache->put('Server:Downloads:' . $token, ['server' => $server->uuid, 'path' => $file], 5); - - return redirect(sprintf('%s://%s:%s/v1/server/file/download/%s', $node->scheme, $node->fqdn, $node->daemonListen, $token)); - } -} diff --git a/app/Http/Controllers/Server/Files/FileActionsController.php b/app/Http/Controllers/Server/Files/FileActionsController.php deleted file mode 100644 index bd63009a6..000000000 --- a/app/Http/Controllers/Server/Files/FileActionsController.php +++ /dev/null @@ -1,120 +0,0 @@ -. - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ - -namespace Pterodactyl\Http\Controllers\Server\Files; - -use Illuminate\View\View; -use Illuminate\Http\Request; -use GuzzleHttp\Exception\RequestException; -use Pterodactyl\Http\Controllers\Controller; -use Pterodactyl\Traits\Controllers\JavascriptInjection; -use Pterodactyl\Http\Requests\Server\UpdateFileContentsFormRequest; -use Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface; -use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; - -class FileActionsController extends Controller -{ - use JavascriptInjection; - - /** - * @var \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface - */ - protected $repository; - - /** - * FileActionsController constructor. - * - * @param \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface $repository - */ - public function __construct(FileRepositoryInterface $repository) - { - $this->repository = $repository; - } - - /** - * Display server file index list. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('list-files', $server); - - $this->setRequest($request)->injectJavascript([ - 'meta' => [ - 'directoryList' => route('server.files.directory-list', $server->uuidShort), - 'csrftoken' => csrf_token(), - ], - 'permissions' => [ - 'moveFiles' => $request->user()->can('move-files', $server), - 'copyFiles' => $request->user()->can('copy-files', $server), - 'compressFiles' => $request->user()->can('compress-files', $server), - 'decompressFiles' => $request->user()->can('decompress-files', $server), - 'createFiles' => $request->user()->can('create-files', $server), - 'downloadFiles' => $request->user()->can('download-files', $server), - 'deleteFiles' => $request->user()->can('delete-files', $server), - ], - ]); - - return view('server.files.index'); - } - - /** - * Render page to manually create a file in the panel. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function create(Request $request): View - { - $this->authorize('create-files', $request->attributes->get('server')); - $this->setRequest($request)->injectJavascript(); - - return view('server.files.add', [ - 'directory' => (in_array($request->get('dir'), [null, '/', ''])) ? '' : trim($request->get('dir'), '/') . '/', - ]); - } - - /** - * Display a form to allow for editing of a file. - * - * @param \Pterodactyl\Http\Requests\Server\UpdateFileContentsFormRequest $request - * @param string $uuid - * @param string $file - * @return \Illuminate\View\View - * - * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException - */ - public function view(UpdateFileContentsFormRequest $request, string $uuid, string $file): View - { - $server = $request->attributes->get('server'); - - $dirname = str_replace('\\', '/', pathinfo($file, PATHINFO_DIRNAME)); - try { - $content = $this->repository->setServer($server)->setToken($request->attributes->get('server_token'))->getContent($file); - } catch (RequestException $exception) { - throw new DaemonConnectionException($exception); - } - - $this->setRequest($request)->injectJavascript(['stat' => $request->attributes->get('file_stats')]); - - return view('server.files.edit', [ - 'file' => $file, - 'stat' => $request->attributes->get('file_stats'), - 'contents' => $content, - 'directory' => (in_array($dirname, ['.', './', '/'])) ? '/' : trim($dirname, '/') . '/', - ]); - } -} diff --git a/app/Http/Controllers/Server/Files/RemoteRequestController.php b/app/Http/Controllers/Server/Files/RemoteRequestController.php deleted file mode 100644 index ab58037d0..000000000 --- a/app/Http/Controllers/Server/Files/RemoteRequestController.php +++ /dev/null @@ -1,105 +0,0 @@ -config = $config; - $this->repository = $repository; - } - - /** - * Return a listing of a servers file directory. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function directory(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('list-files', $server); - - $requestDirectory = '/' . trim(urldecode($request->input('directory', '/')), '/'); - $directory = [ - 'header' => $requestDirectory !== '/' ? $requestDirectory : '', - 'first' => $requestDirectory !== '/', - ]; - - $goBack = explode('/', trim($requestDirectory, '/')); - if (! empty(array_filter($goBack)) && count($goBack) >= 2) { - array_pop($goBack); - - $directory['show'] = true; - $directory['link'] = '/' . implode('/', $goBack); - $directory['link_show'] = implode('/', $goBack) . '/'; - } - - try { - $listing = $this->repository->setServer($server)->setToken($request->attributes->get('server_token'))->getDirectory($requestDirectory); - } catch (RequestException $exception) { - throw new DaemonConnectionException($exception, true); - } - - return view('server.files.list', [ - 'files' => $listing['files'], - 'folders' => $listing['folders'], - 'editableMime' => $this->config->get('pterodactyl.files.editable'), - 'directory' => $directory, - ]); - } - - /** - * Put the contents of a file onto the daemon. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException - */ - public function store(Request $request): Response - { - $server = $request->attributes->get('server'); - $this->authorize('save-files', $server); - - try { - $this->repository->setServer($server)->setToken($request->attributes->get('server_token')) - ->putContent($request->input('file'), $request->input('contents') ?? ''); - - return response('', 204); - } catch (RequestException $exception) { - throw new DaemonConnectionException($exception); - } - } -} diff --git a/app/Http/Controllers/Server/Settings/AllocationController.php b/app/Http/Controllers/Server/Settings/AllocationController.php deleted file mode 100644 index 21baf7c0d..000000000 --- a/app/Http/Controllers/Server/Settings/AllocationController.php +++ /dev/null @@ -1,96 +0,0 @@ -defaultAllocationService = $defaultAllocationService; - $this->hashids = $hashids; - $this->repository = $repository; - } - - /** - * Render the allocation management overview page for a server. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('view-allocations', $server); - $this->setRequest($request)->injectJavascript(); - - return view('server.settings.allocation', [ - 'allocations' => $this->repository->findWhere([['server_id', '=', $server->id]]), - ]); - } - - /** - * Update the default allocation for a server. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\JsonResponse - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function update(Request $request): JsonResponse - { - $server = $request->attributes->get('server'); - $this->authorize('edit-allocation', $server); - - $allocation = $this->hashids->decodeFirst($request->input('allocation'), 0); - - try { - $this->defaultAllocationService->handle($server->id, $allocation); - } catch (AllocationDoesNotBelongToServerException $exception) { - return response()->json(['error' => 'No matching allocation was located for this server.'], 404); - } - - return response()->json(); - } -} diff --git a/app/Http/Controllers/Server/Settings/NameController.php b/app/Http/Controllers/Server/Settings/NameController.php deleted file mode 100644 index 29cdb9ed9..000000000 --- a/app/Http/Controllers/Server/Settings/NameController.php +++ /dev/null @@ -1,59 +0,0 @@ -repository = $repository; - } - - /** - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request) - { - $this->authorize('view-name', $request->attributes->get('server')); - $this->setRequest($request)->injectJavascript(); - - return view('server.settings.name'); - } - - /** - * Update the stored name for a specific server. - * - * @param \Pterodactyl\Http\Requests\Server\Settings\ChangeServerNameRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function update(ChangeServerNameRequest $request): RedirectResponse - { - $this->repository->update($request->getServer()->id, $request->validated()); - - return redirect()->route('server.settings.name', $request->getServer()->uuidShort); - } -} diff --git a/app/Http/Controllers/Server/Settings/SftpController.php b/app/Http/Controllers/Server/Settings/SftpController.php deleted file mode 100644 index 58b110bd3..000000000 --- a/app/Http/Controllers/Server/Settings/SftpController.php +++ /dev/null @@ -1,29 +0,0 @@ -authorize('access-sftp', $request->attributes->get('server')); - $this->setRequest($request)->injectJavascript(); - - return view('server.settings.sftp'); - } -} diff --git a/app/Http/Controllers/Server/Settings/StartupController.php b/app/Http/Controllers/Server/Settings/StartupController.php deleted file mode 100644 index 8f17022b5..000000000 --- a/app/Http/Controllers/Server/Settings/StartupController.php +++ /dev/null @@ -1,96 +0,0 @@ -alert = $alert; - $this->commandViewService = $commandViewService; - $this->modificationService = $modificationService; - } - - /** - * Render the server startup page. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('view-startup', $server); - $this->setRequest($request)->injectJavascript(); - - $data = $this->commandViewService->handle($server->id); - - return view('server.settings.startup', [ - 'variables' => $data->get('variables'), - 'server_values' => $data->get('server_values'), - 'startup' => $data->get('startup'), - ]); - } - - /** - * Handle request to update the startup variables for a server. Authorization - * is handled in the form request. - * - * @param \Pterodactyl\Http\Requests\Server\UpdateStartupParametersFormRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Pterodactyl\Exceptions\DisplayException - * @throws \Illuminate\Validation\ValidationException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function update(UpdateStartupParametersFormRequest $request): RedirectResponse - { - $this->modificationService->setUserLevel(User::USER_LEVEL_USER); - $this->modificationService->handle($request->attributes->get('server'), $request->normalize()); - $this->alert->success(trans('server.config.startup.edited'))->flash(); - - return redirect()->route('server.settings.startup', ['server' => $request->attributes->get('server')->uuidShort]); - } -} diff --git a/app/Http/Controllers/Server/SubuserController.php b/app/Http/Controllers/Server/SubuserController.php deleted file mode 100644 index 008cfeaa5..000000000 --- a/app/Http/Controllers/Server/SubuserController.php +++ /dev/null @@ -1,197 +0,0 @@ -alert = $alert; - $this->repository = $repository; - $this->subuserCreationService = $subuserCreationService; - $this->subuserDeletionService = $subuserDeletionService; - $this->subuserUpdateService = $subuserUpdateService; - } - - /** - * Displays the subuser overview index. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('list-subusers', $server); - $this->setRequest($request)->injectJavascript(); - - return view('server.users.index', [ - 'subusers' => $this->repository->findWhere([['server_id', '=', $server->id]]), - ]); - } - - /** - * Displays a single subuser overview. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function view(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('view-subuser', $server); - - $subuser = $this->repository->getWithPermissions($request->attributes->get('subuser')); - $this->setRequest($request)->injectJavascript(); - - return view('server.users.view', [ - 'subuser' => $subuser, - 'permlist' => Permission::getPermissions(), - 'permissions' => $subuser->getRelation('permissions')->mapWithKeys(function ($item) { - return [$item->permission => true]; - }), - ]); - } - - /** - * Handles editing a subuser. - * - * @param \Pterodactyl\Http\Requests\Server\Subuser\SubuserUpdateFormRequest $request - * @param string $uuid - * @param string $hash - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\DisplayException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function update(SubuserUpdateFormRequest $request, string $uuid, string $hash): RedirectResponse - { - $this->subuserUpdateService->handle($request->attributes->get('subuser'), $request->input('permissions', [])); - $this->alert->success(trans('server.users.user_updated'))->flash(); - - return redirect()->route('server.subusers.view', ['uuid' => $uuid, 'subuser' => $hash]); - } - - /** - * Display new subuser creation page. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function create(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('create-subuser', $server); - $this->setRequest($request)->injectJavascript(); - - return view('server.users.new', ['permissions' => Permission::getPermissions()]); - } - - /** - * Handles creating a new subuser. - * - * @param \Pterodactyl\Http\Requests\Server\Subuser\SubuserStoreFormRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Exception - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - * @throws \Pterodactyl\Exceptions\Service\Subuser\ServerSubuserExistsException - * @throws \Pterodactyl\Exceptions\Service\Subuser\UserIsServerOwnerException - */ - public function store(SubuserStoreFormRequest $request): RedirectResponse - { - $server = $request->attributes->get('server'); - - $subuser = $this->subuserCreationService->handle($server, $request->input('email'), $request->input('permissions', [])); - $this->alert->success(trans('server.users.user_assigned'))->flash(); - - return redirect()->route('server.subusers.view', [ - 'uuid' => $server->uuidShort, - 'id' => $subuser->hashid, - ]); - } - - /** - * Handles deleting a subuser. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\DisplayException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function delete(Request $request): Response - { - $server = $request->attributes->get('server'); - $this->authorize('delete-subuser', $server); - - $this->subuserDeletionService->handle($request->attributes->get('subuser')); - - return response('', 204); - } -} diff --git a/app/Http/Controllers/Server/Tasks/ActionController.php b/app/Http/Controllers/Server/Tasks/ActionController.php deleted file mode 100644 index 410d7c189..000000000 --- a/app/Http/Controllers/Server/Tasks/ActionController.php +++ /dev/null @@ -1,70 +0,0 @@ -processScheduleService = $processScheduleService; - $this->repository = $repository; - } - - /** - * Toggle a task to be active or inactive for a given server. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function toggle(Request $request): Response - { - $server = $request->attributes->get('server'); - $schedule = $request->attributes->get('schedule'); - $this->authorize('toggle-schedule', $server); - - $this->repository->update($schedule->id, [ - 'is_active' => ! $schedule->is_active, - ]); - - return response('', 204); - } - - /** - * Trigger a schedule to run now. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - * - * @throws \Illuminate\Auth\Access\AuthorizationException - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - */ - public function trigger(Request $request): Response - { - $server = $request->attributes->get('server'); - $this->authorize('toggle-schedule', $server); - - $this->processScheduleService->setRunTimeOverride(Carbon::now())->handle( - $request->attributes->get('schedule') - ); - - return response('', 204); - } -} diff --git a/app/Http/Controllers/Server/Tasks/TaskManagementController.php b/app/Http/Controllers/Server/Tasks/TaskManagementController.php deleted file mode 100644 index 9805b5cff..000000000 --- a/app/Http/Controllers/Server/Tasks/TaskManagementController.php +++ /dev/null @@ -1,198 +0,0 @@ -alert = $alert; - $this->creationService = $creationService; - $this->hashids = $hashids; - $this->repository = $repository; - $this->updateService = $updateService; - } - - /** - * Display the task page listing. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function index(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('list-schedules', $server); - $this->setRequest($request)->injectJavascript(); - - return view('server.schedules.index', [ - 'schedules' => $this->repository->findServerSchedules($server->id), - 'actions' => [ - 'command' => trans('server.schedule.actions.command'), - 'power' => trans('server.schedule.actions.power'), - ], - ]); - } - - /** - * Display the task creation page. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function create(Request $request): View - { - $server = $request->attributes->get('server'); - $this->authorize('create-schedule', $server); - $this->setRequest($request)->injectJavascript(); - - return view('server.schedules.new'); - } - - /** - * Handle request to store a new schedule and tasks in the database. - * - * @param \Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException - */ - public function store(ScheduleCreationFormRequest $request): RedirectResponse - { - $server = $request->attributes->get('server'); - - $schedule = $this->creationService->handle($server, $request->normalize(), $request->getTasks()); - $this->alert->success(trans('server.schedule.schedule_created'))->flash(); - - return redirect()->route('server.schedules.view', [ - 'server' => $server->uuidShort, - 'schedule' => $schedule->hashid, - ]); - } - - /** - * Return a view to modify a schedule. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\View\View - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function view(Request $request): View - { - $server = $request->attributes->get('server'); - $schedule = $request->attributes->get('schedule'); - $this->authorize('view-schedule', $server); - - $this->setRequest($request)->injectJavascript([ - 'tasks' => $schedule->getRelation('tasks')->map(function ($task) { - /* @var \Pterodactyl\Models\Task $task */ - return collect($task->toArray())->only('action', 'time_offset', 'payload')->all(); - }), - ]); - - return view('server.schedules.view', ['schedule' => $schedule]); - } - - /** - * Update a specific parent task on the system. - * - * @param \Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest $request - * @return \Illuminate\Http\RedirectResponse - * - * @throws \Pterodactyl\Exceptions\Model\DataValidationException - * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException - * @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException - */ - public function update(ScheduleCreationFormRequest $request): RedirectResponse - { - $server = $request->attributes->get('server'); - $schedule = $request->attributes->get('schedule'); - - $this->updateService->handle($schedule, $request->normalize(), $request->getTasks()); - $this->alert->success(trans('server.schedule.schedule_updated'))->flash(); - - return redirect()->route('server.schedules.view', [ - 'server' => $server->uuidShort, - 'schedule' => $schedule->hashid, - ]); - } - - /** - * Delete a parent task from the Panel. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - * - * @throws \Illuminate\Auth\Access\AuthorizationException - */ - public function delete(Request $request): Response - { - $server = $request->attributes->get('server'); - $schedule = $request->attributes->get('schedule'); - $this->authorize('delete-schedule', $server); - - $this->repository->delete($schedule->id); - - return response('', 204); - } -} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index f0e978116..6e2d2dd13 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -33,9 +33,10 @@ class RouteServiceProvider extends ServiceProvider ->namespace($this->namespace . '\Auth') ->group(base_path('routes/auth.php')); - Route::middleware(['web', 'csrf', 'auth', 'server', 'subuser.auth', 'node.maintenance'])->prefix('/server/{server}') - ->namespace($this->namespace . '\Server') - ->group(base_path('routes/server.php')); + Route::middleware(['web', 'csrf', 'auth', 'server', 'subuser.auth', 'node.maintenance']) + ->prefix('/api/server/{server}') + ->namespace($this->namespace . '\Server') + ->group(base_path('routes/server.php')); Route::middleware(['api'])->prefix('/api/application') ->namespace($this->namespace . '\Api\Application') diff --git a/app/Repositories/Daemon/FileRepository.php b/app/Repositories/Daemon/FileRepository.php index 46117f3c5..da55f4c10 100644 --- a/app/Repositories/Daemon/FileRepository.php +++ b/app/Repositories/Daemon/FileRepository.php @@ -84,33 +84,6 @@ class FileRepository extends BaseRepository implements FileRepositoryInterface { $response = $this->getHttpClient()->request('GET', sprintf('server/directory/%s', rawurlencode($path))); - $contents = json_decode($response->getBody()); - $files = $folders = []; - - foreach ($contents as $value) { - if ($value->directory) { - array_push($folders, [ - 'entry' => $value->name, - 'directory' => trim($path, '/'), - 'size' => null, - 'date' => strtotime($value->modified), - 'mime' => $value->mime, - ]); - } elseif ($value->file) { - array_push($files, [ - 'entry' => $value->name, - 'directory' => trim($path, '/'), - 'extension' => str_replace('\\', '/', pathinfo($value->name, PATHINFO_EXTENSION)), - 'size' => human_readable($value->size), - 'date' => strtotime($value->modified), - 'mime' => $value->mime, - ]); - } - } - - return [ - 'files' => $files, - 'folders' => $folders, - ]; + return json_decode($response->getBody()); } } diff --git a/resources/assets/scripts/components/server/subpages/FileManager.vue b/resources/assets/scripts/components/server/subpages/FileManager.vue index 8d87e2d65..16e85f33b 100644 --- a/resources/assets/scripts/components/server/subpages/FileManager.vue +++ b/resources/assets/scripts/components/server/subpages/FileManager.vue @@ -11,14 +11,14 @@
Modified
Actions
-
+
-
{{folder.name}}
+
{{directory.name}}
-
{{formatDate(folder.modified)}}
+
{{formatDate(directory.modified)}}
-
+
@@ -46,13 +46,20 @@ ...mapState('server', ['server', 'credentials']), }, + watch: { + currentDirectory: function () { + this.listDirectory(); + }, + }, + data: function () { return { - directory: '/', + currentDirectory: '/', loading: true, + directories: [], + editableFiles: [], files: [], - folders: [], }; }, @@ -65,20 +72,22 @@ * List the contents of a directory. */ listDirectory: function () { - window.axios.get(`${this.credentials.node}/v1/server/directory/${this.directory}`, { - headers: { - 'X-Access-Server': this.server.uuid, - 'X-Access-Token': this.credentials.key, - } - }) + this.loading = true; + + window.axios.get(this.route('server.files', { + server: this.$route.params.id, + directory: this.currentDirectory, + })) .then((response) => { - this.files = filter(response.data, function (o) { + this.files = filter(response.data.contents, function (o) { return o.file; }); - this.folders = filter(response.data, function (o) { + this.directories = filter(response.data.contents, function (o) { return o.directory; }); + + this.editableFiles = response.data.editable; }) .catch(console.error) .finally(() => { @@ -86,6 +95,16 @@ }); }, + /** + * Determine if a file can be edited on the Panel. + * + * @param {Object} file + * @return {Boolean} + */ + canEdit: function (file) { + return this.editableFiles.indexOf(file.mime) >= 0; + }, + /** * Return the human readable filesize for a given number of bytes. This * uses 1024 as the base, so the response is denoted accordingly. diff --git a/resources/assets/scripts/helpers/ziggy.js b/resources/assets/scripts/helpers/ziggy.js index 3db19b314..c863c1c30 100644 --- a/resources/assets/scripts/helpers/ziggy.js +++ b/resources/assets/scripts/helpers/ziggy.js @@ -1,5 +1,5 @@ var Ziggy = { - namedRoutes: JSON.parse('{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"],"domain":null},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"],"domain":null},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"],"domain":null},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"],"domain":null},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"],"domain":null},"index":{"uri":"\/","methods":["GET","HEAD"],"domain":null},"account":{"uri":"account","methods":["GET","HEAD"],"domain":null},"account.api":{"uri":"account\/api","methods":["GET","HEAD"],"domain":null},"account.api.new":{"uri":"account\/api\/new","methods":["GET","HEAD"],"domain":null},"account.api.revoke":{"uri":"account\/api\/revoke\/{identifier}","methods":["DELETE"],"domain":null},"account.two_factor":{"uri":"account\/two_factor","methods":["GET","HEAD"],"domain":null},"account.two_factor.enable":{"uri":"account\/two_factor\/totp","methods":["POST"],"domain":null},"account.two_factor.disable":{"uri":"account\/two_factor\/totp\/disable","methods":["POST"],"domain":null},"admin.index":{"uri":"admin","methods":["GET","HEAD"],"domain":null},"admin.statistics":{"uri":"admin\/statistics","methods":["GET","HEAD"],"domain":null},"admin.api.index":{"uri":"admin\/api","methods":["GET","HEAD"],"domain":null},"admin.api.new":{"uri":"admin\/api\/new","methods":["GET","HEAD"],"domain":null},"admin.api.delete":{"uri":"admin\/api\/revoke\/{identifier}","methods":["DELETE"],"domain":null},"admin.locations":{"uri":"admin\/locations","methods":["GET","HEAD"],"domain":null},"admin.locations.view":{"uri":"admin\/locations\/view\/{location}","methods":["GET","HEAD"],"domain":null},"admin.databases":{"uri":"admin\/databases","methods":["GET","HEAD"],"domain":null},"admin.databases.view":{"uri":"admin\/databases\/view\/{host}","methods":["GET","HEAD"],"domain":null},"admin.settings":{"uri":"admin\/settings","methods":["GET","HEAD"],"domain":null},"admin.settings.mail":{"uri":"admin\/settings\/mail","methods":["GET","HEAD"],"domain":null},"admin.settings.advanced":{"uri":"admin\/settings\/advanced","methods":["GET","HEAD"],"domain":null},"admin.users":{"uri":"admin\/users","methods":["GET","HEAD"],"domain":null},"admin.users.json":{"uri":"admin\/users\/accounts.json","methods":["GET","HEAD"],"domain":null},"admin.users.new":{"uri":"admin\/users\/new","methods":["GET","HEAD"],"domain":null},"admin.users.view":{"uri":"admin\/users\/view\/{user}","methods":["GET","HEAD"],"domain":null},"admin.servers":{"uri":"admin\/servers","methods":["GET","HEAD"],"domain":null},"admin.servers.new":{"uri":"admin\/servers\/new","methods":["GET","HEAD"],"domain":null},"admin.servers.view":{"uri":"admin\/servers\/view\/{server}","methods":["GET","HEAD"],"domain":null},"admin.servers.view.details":{"uri":"admin\/servers\/view\/{server}\/details","methods":["GET","HEAD"],"domain":null},"admin.servers.view.build":{"uri":"admin\/servers\/view\/{server}\/build","methods":["GET","HEAD"],"domain":null},"admin.servers.view.startup":{"uri":"admin\/servers\/view\/{server}\/startup","methods":["GET","HEAD"],"domain":null},"admin.servers.view.database":{"uri":"admin\/servers\/view\/{server}\/database","methods":["GET","HEAD"],"domain":null},"admin.servers.view.manage":{"uri":"admin\/servers\/view\/{server}\/manage","methods":["GET","HEAD"],"domain":null},"admin.servers.view.delete":{"uri":"admin\/servers\/view\/{server}\/delete","methods":["GET","HEAD"],"domain":null},"admin.servers.view.manage.toggle":{"uri":"admin\/servers\/view\/{server}\/manage\/toggle","methods":["POST"],"domain":null},"admin.servers.view.manage.rebuild":{"uri":"admin\/servers\/view\/{server}\/manage\/rebuild","methods":["POST"],"domain":null},"admin.servers.view.manage.suspension":{"uri":"admin\/servers\/view\/{server}\/manage\/suspension","methods":["POST"],"domain":null},"admin.servers.view.manage.reinstall":{"uri":"admin\/servers\/view\/{server}\/manage\/reinstall","methods":["POST"],"domain":null},"admin.servers.view.database.delete":{"uri":"admin\/servers\/view\/{server}\/database\/{database}\/delete","methods":["DELETE"],"domain":null},"admin.nodes":{"uri":"admin\/nodes","methods":["GET","HEAD"],"domain":null},"admin.nodes.new":{"uri":"admin\/nodes\/new","methods":["GET","HEAD"],"domain":null},"admin.nodes.view":{"uri":"admin\/nodes\/view\/{node}","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.settings":{"uri":"admin\/nodes\/view\/{node}\/settings","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.configuration":{"uri":"admin\/nodes\/view\/{node}\/configuration","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.allocation":{"uri":"admin\/nodes\/view\/{node}\/allocation","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.servers":{"uri":"admin\/nodes\/view\/{node}\/servers","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.configuration.token":{"uri":"admin\/nodes\/view\/{node}\/settings\/token","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.allocation.removeBlock":{"uri":"admin\/nodes\/view\/{node}\/allocation\/remove","methods":["POST"],"domain":null},"admin.nodes.view.allocation.setAlias":{"uri":"admin\/nodes\/view\/{node}\/allocation\/alias","methods":["POST"],"domain":null},"admin.nodes.view.delete":{"uri":"admin\/nodes\/view\/{node}\/delete","methods":["DELETE"],"domain":null},"admin.nodes.view.allocation.removeSingle":{"uri":"admin\/nodes\/view\/{node}\/allocation\/remove\/{allocation}","methods":["DELETE"],"domain":null},"admin.nests":{"uri":"admin\/nests","methods":["GET","HEAD"],"domain":null},"admin.nests.new":{"uri":"admin\/nests\/new","methods":["GET","HEAD"],"domain":null},"admin.nests.view":{"uri":"admin\/nests\/view\/{nest}","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.new":{"uri":"admin\/nests\/egg\/new","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.view":{"uri":"admin\/nests\/egg\/{egg}","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.export":{"uri":"admin\/nests\/egg\/{egg}\/export","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.variables":{"uri":"admin\/nests\/egg\/{egg}\/variables","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.scripts":{"uri":"admin\/nests\/egg\/{egg}\/scripts","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.import":{"uri":"admin\/nests\/import","methods":["POST"],"domain":null},"admin.nests.egg.variables.edit":{"uri":"admin\/nests\/egg\/{egg}\/variables\/{variable}","methods":["PATCH"],"domain":null},"admin.packs":{"uri":"admin\/packs","methods":["GET","HEAD"],"domain":null},"admin.packs.new":{"uri":"admin\/packs\/new","methods":["GET","HEAD"],"domain":null},"admin.packs.new.template":{"uri":"admin\/packs\/new\/template","methods":["GET","HEAD"],"domain":null},"admin.packs.view":{"uri":"admin\/packs\/view\/{pack}","methods":["GET","HEAD"],"domain":null},"admin.packs.view.export":{"uri":"admin\/packs\/view\/{pack}\/export\/{files?}","methods":["POST"],"domain":null},"auth.login":{"uri":"auth\/login","methods":["GET","HEAD"],"domain":null},"auth.forgot-password":{"uri":"auth\/password","methods":["GET","HEAD"],"domain":null},"auth.reset":{"uri":"auth\/password\/reset\/{token}","methods":["GET","HEAD"],"domain":null},"auth.login-checkpoint":{"uri":"auth\/login\/checkpoint","methods":["POST"],"domain":null},"auth.reset-password":{"uri":"auth\/password\/reset","methods":["POST"],"domain":null},"auth.logout":{"uri":"auth\/logout","methods":["GET","HEAD"],"domain":null},"server.credentials":{"uri":"server\/{server}\/credentials","methods":["GET","HEAD"],"domain":null},"api.application.users":{"uri":"api\/application\/users","methods":["GET","HEAD"],"domain":null},"api.application.users.view":{"uri":"api\/application\/users\/{user}","methods":["GET","HEAD"],"domain":null},"api.application.users.external":{"uri":"api\/application\/users\/external\/{external_id}","methods":["GET","HEAD"],"domain":null},"api.application.nodes":{"uri":"api\/application\/nodes","methods":["GET","HEAD"],"domain":null},"api.application.nodes.view":{"uri":"api\/application\/nodes\/{node}","methods":["GET","HEAD"],"domain":null},"api.application.allocations":{"uri":"api\/application\/nodes\/{node}\/allocations","methods":["GET","HEAD"],"domain":null},"api.application.allocations.view":{"uri":"api\/application\/nodes\/{node}\/allocations\/{allocation}","methods":["DELETE"],"domain":null},"api.applications.locations":{"uri":"api\/application\/locations","methods":["GET","HEAD"],"domain":null},"api.application.locations.view":{"uri":"api\/application\/locations\/{location}","methods":["GET","HEAD"],"domain":null},"api.application.servers":{"uri":"api\/application\/servers","methods":["GET","HEAD"],"domain":null},"api.application.servers.view":{"uri":"api\/application\/servers\/{server}","methods":["GET","HEAD"],"domain":null},"api.application.servers.external":{"uri":"api\/application\/servers\/external\/{external_id}","methods":["GET","HEAD"],"domain":null},"api.application.servers.details":{"uri":"api\/application\/servers\/{server}\/details","methods":["PATCH"],"domain":null},"api.application.servers.build":{"uri":"api\/application\/servers\/{server}\/build","methods":["PATCH"],"domain":null},"api.application.servers.startup":{"uri":"api\/application\/servers\/{server}\/startup","methods":["PATCH"],"domain":null},"api.application.servers.suspend":{"uri":"api\/application\/servers\/{server}\/suspend","methods":["POST"],"domain":null},"api.application.servers.unsuspend":{"uri":"api\/application\/servers\/{server}\/unsuspend","methods":["POST"],"domain":null},"api.application.servers.reinstall":{"uri":"api\/application\/servers\/{server}\/reinstall","methods":["POST"],"domain":null},"api.application.servers.rebuild":{"uri":"api\/application\/servers\/{server}\/rebuild","methods":["POST"],"domain":null},"api.application.servers.databases":{"uri":"api\/application\/servers\/{server}\/databases","methods":["GET","HEAD"],"domain":null},"api.application.servers.databases.view":{"uri":"api\/application\/servers\/{server}\/databases\/{database}","methods":["GET","HEAD"],"domain":null},"api.application.nests":{"uri":"api\/application\/nests","methods":["GET","HEAD"],"domain":null},"api.application.nests.view":{"uri":"api\/application\/nests\/{nest}","methods":["GET","HEAD"],"domain":null},"api.application.nests.eggs":{"uri":"api\/application\/nests\/{nest}\/eggs","methods":["GET","HEAD"],"domain":null},"api.application.nests.eggs.view":{"uri":"api\/application\/nests\/{nest}\/eggs\/{egg}","methods":["GET","HEAD"],"domain":null},"api.client.index":{"uri":"api\/client","methods":["GET","HEAD"],"domain":null},"api.client.account":{"uri":"api\/client\/account","methods":["GET","HEAD"],"domain":null},"api.client.account.update-email":{"uri":"api\/client\/account\/email","methods":["PUT"],"domain":null},"api.client.account.update-password":{"uri":"api\/client\/account\/password","methods":["PUT"],"domain":null},"api.client.servers.view":{"uri":"api\/client\/servers\/{server}","methods":["GET","HEAD"],"domain":null},"api.client.servers.resources":{"uri":"api\/client\/servers\/{server}\/utilization","methods":["GET","HEAD"],"domain":null},"api.client.servers.command":{"uri":"api\/client\/servers\/{server}\/command","methods":["POST"],"domain":null},"api.client.servers.power":{"uri":"api\/client\/servers\/{server}\/power","methods":["POST"],"domain":null},"api.remote.authenticate":{"uri":"api\/remote\/authenticate\/{token}","methods":["GET","HEAD"],"domain":null},"api.remote.download_file":{"uri":"api\/remote\/download-file","methods":["POST"],"domain":null},"api.remote.eggs":{"uri":"api\/remote\/eggs","methods":["GET","HEAD"],"domain":null},"api.remote.eggs.download":{"uri":"api\/remote\/eggs\/{uuid}","methods":["GET","HEAD"],"domain":null},"api.remote.scripts":{"uri":"api\/remote\/scripts\/{uuid}","methods":["GET","HEAD"],"domain":null},"api.remote.sftp":{"uri":"api\/remote\/sftp","methods":["POST"],"domain":null},"daemon.pack.pull":{"uri":"daemon\/packs\/pull\/{uuid}","methods":["GET","HEAD"],"domain":null},"daemon.pack.hash":{"uri":"daemon\/packs\/pull\/{uuid}\/hash","methods":["GET","HEAD"],"domain":null},"daemon.configuration":{"uri":"daemon\/configure\/{token}","methods":["GET","HEAD"],"domain":null},"daemon.install":{"uri":"daemon\/install","methods":["POST"],"domain":null}}'), + namedRoutes: JSON.parse('{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"],"domain":null},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"],"domain":null},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"],"domain":null},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"],"domain":null},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"],"domain":null},"index":{"uri":"\/","methods":["GET","HEAD"],"domain":null},"account":{"uri":"account","methods":["GET","HEAD"],"domain":null},"account.api":{"uri":"account\/api","methods":["GET","HEAD"],"domain":null},"account.api.new":{"uri":"account\/api\/new","methods":["GET","HEAD"],"domain":null},"account.api.revoke":{"uri":"account\/api\/revoke\/{identifier}","methods":["DELETE"],"domain":null},"account.two_factor":{"uri":"account\/two_factor","methods":["GET","HEAD"],"domain":null},"account.two_factor.enable":{"uri":"account\/two_factor\/totp","methods":["POST"],"domain":null},"account.two_factor.disable":{"uri":"account\/two_factor\/totp\/disable","methods":["POST"],"domain":null},"admin.index":{"uri":"admin","methods":["GET","HEAD"],"domain":null},"admin.statistics":{"uri":"admin\/statistics","methods":["GET","HEAD"],"domain":null},"admin.api.index":{"uri":"admin\/api","methods":["GET","HEAD"],"domain":null},"admin.api.new":{"uri":"admin\/api\/new","methods":["GET","HEAD"],"domain":null},"admin.api.delete":{"uri":"admin\/api\/revoke\/{identifier}","methods":["DELETE"],"domain":null},"admin.locations":{"uri":"admin\/locations","methods":["GET","HEAD"],"domain":null},"admin.locations.view":{"uri":"admin\/locations\/view\/{location}","methods":["GET","HEAD"],"domain":null},"admin.databases":{"uri":"admin\/databases","methods":["GET","HEAD"],"domain":null},"admin.databases.view":{"uri":"admin\/databases\/view\/{host}","methods":["GET","HEAD"],"domain":null},"admin.settings":{"uri":"admin\/settings","methods":["GET","HEAD"],"domain":null},"admin.settings.mail":{"uri":"admin\/settings\/mail","methods":["GET","HEAD"],"domain":null},"admin.settings.advanced":{"uri":"admin\/settings\/advanced","methods":["GET","HEAD"],"domain":null},"admin.users":{"uri":"admin\/users","methods":["GET","HEAD"],"domain":null},"admin.users.json":{"uri":"admin\/users\/accounts.json","methods":["GET","HEAD"],"domain":null},"admin.users.new":{"uri":"admin\/users\/new","methods":["GET","HEAD"],"domain":null},"admin.users.view":{"uri":"admin\/users\/view\/{user}","methods":["GET","HEAD"],"domain":null},"admin.servers":{"uri":"admin\/servers","methods":["GET","HEAD"],"domain":null},"admin.servers.new":{"uri":"admin\/servers\/new","methods":["GET","HEAD"],"domain":null},"admin.servers.view":{"uri":"admin\/servers\/view\/{server}","methods":["GET","HEAD"],"domain":null},"admin.servers.view.details":{"uri":"admin\/servers\/view\/{server}\/details","methods":["GET","HEAD"],"domain":null},"admin.servers.view.build":{"uri":"admin\/servers\/view\/{server}\/build","methods":["GET","HEAD"],"domain":null},"admin.servers.view.startup":{"uri":"admin\/servers\/view\/{server}\/startup","methods":["GET","HEAD"],"domain":null},"admin.servers.view.database":{"uri":"admin\/servers\/view\/{server}\/database","methods":["GET","HEAD"],"domain":null},"admin.servers.view.manage":{"uri":"admin\/servers\/view\/{server}\/manage","methods":["GET","HEAD"],"domain":null},"admin.servers.view.delete":{"uri":"admin\/servers\/view\/{server}\/delete","methods":["GET","HEAD"],"domain":null},"admin.servers.view.manage.toggle":{"uri":"admin\/servers\/view\/{server}\/manage\/toggle","methods":["POST"],"domain":null},"admin.servers.view.manage.rebuild":{"uri":"admin\/servers\/view\/{server}\/manage\/rebuild","methods":["POST"],"domain":null},"admin.servers.view.manage.suspension":{"uri":"admin\/servers\/view\/{server}\/manage\/suspension","methods":["POST"],"domain":null},"admin.servers.view.manage.reinstall":{"uri":"admin\/servers\/view\/{server}\/manage\/reinstall","methods":["POST"],"domain":null},"admin.servers.view.database.delete":{"uri":"admin\/servers\/view\/{server}\/database\/{database}\/delete","methods":["DELETE"],"domain":null},"admin.nodes":{"uri":"admin\/nodes","methods":["GET","HEAD"],"domain":null},"admin.nodes.new":{"uri":"admin\/nodes\/new","methods":["GET","HEAD"],"domain":null},"admin.nodes.view":{"uri":"admin\/nodes\/view\/{node}","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.settings":{"uri":"admin\/nodes\/view\/{node}\/settings","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.configuration":{"uri":"admin\/nodes\/view\/{node}\/configuration","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.allocation":{"uri":"admin\/nodes\/view\/{node}\/allocation","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.servers":{"uri":"admin\/nodes\/view\/{node}\/servers","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.configuration.token":{"uri":"admin\/nodes\/view\/{node}\/settings\/token","methods":["GET","HEAD"],"domain":null},"admin.nodes.view.allocation.removeBlock":{"uri":"admin\/nodes\/view\/{node}\/allocation\/remove","methods":["POST"],"domain":null},"admin.nodes.view.allocation.setAlias":{"uri":"admin\/nodes\/view\/{node}\/allocation\/alias","methods":["POST"],"domain":null},"admin.nodes.view.delete":{"uri":"admin\/nodes\/view\/{node}\/delete","methods":["DELETE"],"domain":null},"admin.nodes.view.allocation.removeSingle":{"uri":"admin\/nodes\/view\/{node}\/allocation\/remove\/{allocation}","methods":["DELETE"],"domain":null},"admin.nests":{"uri":"admin\/nests","methods":["GET","HEAD"],"domain":null},"admin.nests.new":{"uri":"admin\/nests\/new","methods":["GET","HEAD"],"domain":null},"admin.nests.view":{"uri":"admin\/nests\/view\/{nest}","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.new":{"uri":"admin\/nests\/egg\/new","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.view":{"uri":"admin\/nests\/egg\/{egg}","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.export":{"uri":"admin\/nests\/egg\/{egg}\/export","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.variables":{"uri":"admin\/nests\/egg\/{egg}\/variables","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.scripts":{"uri":"admin\/nests\/egg\/{egg}\/scripts","methods":["GET","HEAD"],"domain":null},"admin.nests.egg.import":{"uri":"admin\/nests\/import","methods":["POST"],"domain":null},"admin.nests.egg.variables.edit":{"uri":"admin\/nests\/egg\/{egg}\/variables\/{variable}","methods":["PATCH"],"domain":null},"admin.packs":{"uri":"admin\/packs","methods":["GET","HEAD"],"domain":null},"admin.packs.new":{"uri":"admin\/packs\/new","methods":["GET","HEAD"],"domain":null},"admin.packs.new.template":{"uri":"admin\/packs\/new\/template","methods":["GET","HEAD"],"domain":null},"admin.packs.view":{"uri":"admin\/packs\/view\/{pack}","methods":["GET","HEAD"],"domain":null},"admin.packs.view.export":{"uri":"admin\/packs\/view\/{pack}\/export\/{files?}","methods":["POST"],"domain":null},"auth.login":{"uri":"auth\/login","methods":["GET","HEAD"],"domain":null},"auth.forgot-password":{"uri":"auth\/password","methods":["GET","HEAD"],"domain":null},"auth.reset":{"uri":"auth\/password\/reset\/{token}","methods":["GET","HEAD"],"domain":null},"auth.login-checkpoint":{"uri":"auth\/login\/checkpoint","methods":["POST"],"domain":null},"auth.reset-password":{"uri":"auth\/password\/reset","methods":["POST"],"domain":null},"auth.logout":{"uri":"auth\/logout","methods":["GET","HEAD"],"domain":null},"server.credentials":{"uri":"api\/server\/{server}\/credentials","methods":["GET","HEAD"],"domain":null},"server.files":{"uri":"api\/server\/{server}\/files\/{directory?}","methods":["GET","HEAD"],"domain":null},"api.application.users":{"uri":"api\/application\/users","methods":["GET","HEAD"],"domain":null},"api.application.users.view":{"uri":"api\/application\/users\/{user}","methods":["GET","HEAD"],"domain":null},"api.application.users.external":{"uri":"api\/application\/users\/external\/{external_id}","methods":["GET","HEAD"],"domain":null},"api.application.nodes":{"uri":"api\/application\/nodes","methods":["GET","HEAD"],"domain":null},"api.application.nodes.view":{"uri":"api\/application\/nodes\/{node}","methods":["GET","HEAD"],"domain":null},"api.application.allocations":{"uri":"api\/application\/nodes\/{node}\/allocations","methods":["GET","HEAD"],"domain":null},"api.application.allocations.view":{"uri":"api\/application\/nodes\/{node}\/allocations\/{allocation}","methods":["DELETE"],"domain":null},"api.applications.locations":{"uri":"api\/application\/locations","methods":["GET","HEAD"],"domain":null},"api.application.locations.view":{"uri":"api\/application\/locations\/{location}","methods":["GET","HEAD"],"domain":null},"api.application.servers":{"uri":"api\/application\/servers","methods":["GET","HEAD"],"domain":null},"api.application.servers.view":{"uri":"api\/application\/servers\/{server}","methods":["GET","HEAD"],"domain":null},"api.application.servers.external":{"uri":"api\/application\/servers\/external\/{external_id}","methods":["GET","HEAD"],"domain":null},"api.application.servers.details":{"uri":"api\/application\/servers\/{server}\/details","methods":["PATCH"],"domain":null},"api.application.servers.build":{"uri":"api\/application\/servers\/{server}\/build","methods":["PATCH"],"domain":null},"api.application.servers.startup":{"uri":"api\/application\/servers\/{server}\/startup","methods":["PATCH"],"domain":null},"api.application.servers.suspend":{"uri":"api\/application\/servers\/{server}\/suspend","methods":["POST"],"domain":null},"api.application.servers.unsuspend":{"uri":"api\/application\/servers\/{server}\/unsuspend","methods":["POST"],"domain":null},"api.application.servers.reinstall":{"uri":"api\/application\/servers\/{server}\/reinstall","methods":["POST"],"domain":null},"api.application.servers.rebuild":{"uri":"api\/application\/servers\/{server}\/rebuild","methods":["POST"],"domain":null},"api.application.servers.databases":{"uri":"api\/application\/servers\/{server}\/databases","methods":["GET","HEAD"],"domain":null},"api.application.servers.databases.view":{"uri":"api\/application\/servers\/{server}\/databases\/{database}","methods":["GET","HEAD"],"domain":null},"api.application.nests":{"uri":"api\/application\/nests","methods":["GET","HEAD"],"domain":null},"api.application.nests.view":{"uri":"api\/application\/nests\/{nest}","methods":["GET","HEAD"],"domain":null},"api.application.nests.eggs":{"uri":"api\/application\/nests\/{nest}\/eggs","methods":["GET","HEAD"],"domain":null},"api.application.nests.eggs.view":{"uri":"api\/application\/nests\/{nest}\/eggs\/{egg}","methods":["GET","HEAD"],"domain":null},"api.client.index":{"uri":"api\/client","methods":["GET","HEAD"],"domain":null},"api.client.account":{"uri":"api\/client\/account","methods":["GET","HEAD"],"domain":null},"api.client.account.update-email":{"uri":"api\/client\/account\/email","methods":["PUT"],"domain":null},"api.client.account.update-password":{"uri":"api\/client\/account\/password","methods":["PUT"],"domain":null},"api.client.servers.view":{"uri":"api\/client\/servers\/{server}","methods":["GET","HEAD"],"domain":null},"api.client.servers.resources":{"uri":"api\/client\/servers\/{server}\/utilization","methods":["GET","HEAD"],"domain":null},"api.client.servers.command":{"uri":"api\/client\/servers\/{server}\/command","methods":["POST"],"domain":null},"api.client.servers.power":{"uri":"api\/client\/servers\/{server}\/power","methods":["POST"],"domain":null},"api.remote.authenticate":{"uri":"api\/remote\/authenticate\/{token}","methods":["GET","HEAD"],"domain":null},"api.remote.download_file":{"uri":"api\/remote\/download-file","methods":["POST"],"domain":null},"api.remote.eggs":{"uri":"api\/remote\/eggs","methods":["GET","HEAD"],"domain":null},"api.remote.eggs.download":{"uri":"api\/remote\/eggs\/{uuid}","methods":["GET","HEAD"],"domain":null},"api.remote.scripts":{"uri":"api\/remote\/scripts\/{uuid}","methods":["GET","HEAD"],"domain":null},"api.remote.sftp":{"uri":"api\/remote\/sftp","methods":["POST"],"domain":null},"daemon.pack.pull":{"uri":"daemon\/packs\/pull\/{uuid}","methods":["GET","HEAD"],"domain":null},"daemon.pack.hash":{"uri":"daemon\/packs\/pull\/{uuid}\/hash","methods":["GET","HEAD"],"domain":null},"daemon.configuration":{"uri":"daemon\/configure\/{token}","methods":["GET","HEAD"],"domain":null},"daemon.install":{"uri":"daemon\/install","methods":["POST"],"domain":null}}'), baseUrl: 'http://pterodactyl.local/', baseProtocol: 'http', baseDomain: 'pterodactyl.local', diff --git a/resources/assets/styles/components/filemanager.css b/resources/assets/styles/components/filemanager.css index 0e37d2f8b..faf0c4159 100644 --- a/resources/assets/styles/components/filemanager.css +++ b/resources/assets/styles/components/filemanager.css @@ -8,14 +8,18 @@ } & > .row { - @apply .flex .text-sm .py-3 .text-sm .rounded .cursor-pointer .border .border-transparent; + @apply .flex .text-sm .py-3 .text-sm .border .border-transparent; & > div { @apply .pr-4; } - &:hover { - @apply .bg-grey-lightest .border-blue-light .text-blue-dark; + &.clickable { + @apply .rounded .cursor-pointer; + + &:hover { + @apply .bg-grey-lightest .border-blue-light .text-blue-dark; + } } & > .icon { diff --git a/routes/server.php b/routes/server.php index 880abe629..a2039677e 100644 --- a/routes/server.php +++ b/routes/server.php @@ -7,3 +7,9 @@ * https://opensource.org/licenses/MIT */ Route::get('/credentials', 'CredentialsController@index')->name('server.credentials'); + +Route::group(['prefix' => '/files'], function () { + Route::get('/{directory?}', 'FileController@index') + ->name('server.files') + ->where('directory', '.*'); +});