diff --git a/app/Http/Controllers/Api/Client/Servers/FileController.php b/app/Http/Controllers/Api/Client/Servers/FileController.php index c41046c68..fd712246b 100644 --- a/app/Http/Controllers/Api/Client/Servers/FileController.php +++ b/app/Http/Controllers/Api/Client/Servers/FileController.php @@ -6,8 +6,10 @@ use Carbon\Carbon; use Ramsey\Uuid\Uuid; use Pterodactyl\Models\Server; use Illuminate\Http\JsonResponse; -use Illuminate\Contracts\Cache\Repository; +use Illuminate\Contracts\Cache\Repository as CacheRepository; use Pterodactyl\Http\Controllers\Api\Client\ClientApiController; +use Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface; +use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest; use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DownloadFileRequest; class FileController extends ClientApiController @@ -17,16 +19,38 @@ class FileController extends ClientApiController */ private $cache; + /** + * @var \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface + */ + private $fileRepository; + /** * FileController constructor. * - * @param \Illuminate\Contracts\Cache\Repository $cache + * @param \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface $fileRepository + * @param \Illuminate\Contracts\Cache\Repository $cache */ - public function __construct(Repository $cache) + public function __construct(FileRepositoryInterface $fileRepository, CacheRepository $cache) { parent::__construct(); $this->cache = $cache; + $this->fileRepository = $fileRepository; + } + + /** + * Returns a listing of files in a given directory. + * + * @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest $request + * @return \Illuminate\Http\JsonResponse + */ + public function listDirectory(ListFilesRequest $request): JsonResponse + { + return JsonResponse::create([ + 'contents' => $this->fileRepository->setServer($request->getModel(Server::class))->getDirectory( + $request->get('directory') ?? '/' + ), + ]); } /** diff --git a/app/Http/Requests/Api/Client/Servers/Files/ListFilesRequest.php b/app/Http/Requests/Api/Client/Servers/Files/ListFilesRequest.php new file mode 100644 index 000000000..ee571a076 --- /dev/null +++ b/app/Http/Requests/Api/Client/Servers/Files/ListFilesRequest.php @@ -0,0 +1,20 @@ +user()->can('list-files', $this->getModel(Server::class)); + } +} diff --git a/app/Providers/RepositoryServiceProvider.php b/app/Providers/RepositoryServiceProvider.php index aa5fbbaa5..9813baa2e 100644 --- a/app/Providers/RepositoryServiceProvider.php +++ b/app/Providers/RepositoryServiceProvider.php @@ -3,7 +3,7 @@ namespace Pterodactyl\Providers; use Illuminate\Support\ServiceProvider; -use Pterodactyl\Repositories\Daemon\FileRepository; +use Pterodactyl\Repositories\Wings\FileRepository; use Pterodactyl\Repositories\Daemon\PowerRepository; use Pterodactyl\Repositories\Eloquent\EggRepository; use Pterodactyl\Repositories\Eloquent\NestRepository; diff --git a/app/Repositories/Wings/BaseWingsRepository.php b/app/Repositories/Wings/BaseWingsRepository.php new file mode 100644 index 000000000..b22f8f8dd --- /dev/null +++ b/app/Repositories/Wings/BaseWingsRepository.php @@ -0,0 +1,33 @@ +getConfig(), [ + 'base_uri' => $this->getNode()->getConnectionAddress(), + 'headers' => [ + 'Authorization' => 'Bearer ' . ($this->getToken() ?? $this->getNode()->daemonSecret), + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + ])); + } +} diff --git a/app/Repositories/Wings/FileRepository.php b/app/Repositories/Wings/FileRepository.php new file mode 100644 index 000000000..5f2efa274 --- /dev/null +++ b/app/Repositories/Wings/FileRepository.php @@ -0,0 +1,69 @@ +getHttpClient()->get( + // Reason for the path check is because it is unnecessary on the Daemon but we need + // to respect the interface. + sprintf('/api/servers/%s/files/list/%s', $this->getServer()->uuid, $path === '/' ? '' : $path) + ); + + return json_decode($response->getBody(), true); + } +} diff --git a/resources/assets/scripts/api/server/getDirectoryContents.ts b/resources/assets/scripts/api/server/getDirectoryContents.ts index 75093ac29..6138fd62f 100644 --- a/resources/assets/scripts/api/server/getDirectoryContents.ts +++ b/resources/assets/scripts/api/server/getDirectoryContents.ts @@ -1,7 +1,5 @@ import http from '../http'; import {filter, isObject} from 'lodash'; -// @ts-ignore -import route from '../../../../../vendor/tightenco/ziggy/src/js/route'; import {DirectoryContentObject, DirectoryContents} from "./types"; /** @@ -9,7 +7,9 @@ import {DirectoryContentObject, DirectoryContents} from "./types"; */ export function getDirectoryContents(server: string, directory: string): Promise { return new Promise((resolve, reject) => { - http.get(route('server.files', {server, directory})) + http.get(`/api/client/servers/${server}/files/list`, { + params: {directory} + }) .then((response) => { return resolve({ files: filter(response.data.contents, function (o: DirectoryContentObject) { diff --git a/resources/assets/scripts/api/server/types.ts b/resources/assets/scripts/api/server/types.ts index 30d68feb1..300153897 100644 --- a/resources/assets/scripts/api/server/types.ts +++ b/resources/assets/scripts/api/server/types.ts @@ -8,7 +8,7 @@ export type DirectoryContentObject = { name: string, created: string, modified: string, - mode: number, + mode: string, size: number, directory: boolean, file: boolean, diff --git a/routes/api-client.php b/routes/api-client.php index 0738c744f..02ece8b3f 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -42,6 +42,8 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ }); Route::group(['prefix' => '/files'], function () { + Route::get('/list', 'Servers\FileController@listDirectory')->name('api.client.servers.files.list'); + Route::post('/download/{file}', 'Servers\FileController@download') ->where('file', '.*') ->name('api.client.servers.files.download');