Switch file manager listing to use panel API endpoint
This commit is contained in:
parent
e87c5f6657
commit
c80c8564b8
8 changed files with 156 additions and 8 deletions
|
@ -6,8 +6,10 @@ use Carbon\Carbon;
|
||||||
use Ramsey\Uuid\Uuid;
|
use Ramsey\Uuid\Uuid;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use Illuminate\Http\JsonResponse;
|
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\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;
|
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DownloadFileRequest;
|
||||||
|
|
||||||
class FileController extends ClientApiController
|
class FileController extends ClientApiController
|
||||||
|
@ -17,16 +19,38 @@ class FileController extends ClientApiController
|
||||||
*/
|
*/
|
||||||
private $cache;
|
private $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface
|
||||||
|
*/
|
||||||
|
private $fileRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FileController constructor.
|
* FileController constructor.
|
||||||
*
|
*
|
||||||
|
* @param \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface $fileRepository
|
||||||
* @param \Illuminate\Contracts\Cache\Repository $cache
|
* @param \Illuminate\Contracts\Cache\Repository $cache
|
||||||
*/
|
*/
|
||||||
public function __construct(Repository $cache)
|
public function __construct(FileRepositoryInterface $fileRepository, CacheRepository $cache)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->cache = $cache;
|
$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') ?? '/'
|
||||||
|
),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
|
||||||
|
|
||||||
|
use Pterodactyl\Models\Server;
|
||||||
|
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
|
||||||
|
|
||||||
|
class ListFilesRequest extends ClientApiRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check that the user making this request to the API is authorized to list all
|
||||||
|
* of the files that exist for a given server.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return $this->user()->can('list-files', $this->getModel(Server::class));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
namespace Pterodactyl\Providers;
|
namespace Pterodactyl\Providers;
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Pterodactyl\Repositories\Daemon\FileRepository;
|
use Pterodactyl\Repositories\Wings\FileRepository;
|
||||||
use Pterodactyl\Repositories\Daemon\PowerRepository;
|
use Pterodactyl\Repositories\Daemon\PowerRepository;
|
||||||
use Pterodactyl\Repositories\Eloquent\EggRepository;
|
use Pterodactyl\Repositories\Eloquent\EggRepository;
|
||||||
use Pterodactyl\Repositories\Eloquent\NestRepository;
|
use Pterodactyl\Repositories\Eloquent\NestRepository;
|
||||||
|
|
33
app/Repositories/Wings/BaseWingsRepository.php
Normal file
33
app/Repositories/Wings/BaseWingsRepository.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Repositories\Wings;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Pterodactyl\Repositories\Daemon\BaseRepository;
|
||||||
|
use Pterodactyl\Contracts\Repository\Daemon\BaseRepositoryInterface;
|
||||||
|
|
||||||
|
abstract class BaseWingsRepository extends BaseRepository implements BaseRepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return an instance of the Guzzle HTTP Client to be used for requests.
|
||||||
|
*
|
||||||
|
* @param array $headers
|
||||||
|
* @return \GuzzleHttp\Client
|
||||||
|
*/
|
||||||
|
public function getHttpClient(array $headers = []): Client
|
||||||
|
{
|
||||||
|
// We're just going to extend the parent client here since that logic is already quite
|
||||||
|
// sound and does everything we need it to aside from provide the correct base URL
|
||||||
|
// and authentication headers.
|
||||||
|
$client = parent::getHttpClient($headers);
|
||||||
|
|
||||||
|
return new Client(array_merge($client->getConfig(), [
|
||||||
|
'base_uri' => $this->getNode()->getConnectionAddress(),
|
||||||
|
'headers' => [
|
||||||
|
'Authorization' => 'Bearer ' . ($this->getToken() ?? $this->getNode()->daemonSecret),
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
],
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
69
app/Repositories/Wings/FileRepository.php
Normal file
69
app/Repositories/Wings/FileRepository.php
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Repositories\Wings;
|
||||||
|
|
||||||
|
use stdClass;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface;
|
||||||
|
|
||||||
|
class FileRepository extends BaseWingsRepository implements FileRepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return stat information for a given file.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @return \stdClass
|
||||||
|
*
|
||||||
|
* @throws \GuzzleHttp\Exception\TransferException
|
||||||
|
*/
|
||||||
|
public function getFileStat(string $path): stdClass
|
||||||
|
{
|
||||||
|
// TODO: Implement getFileStat() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the contents of a given file if it can be edited in the Panel.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws \GuzzleHttp\Exception\TransferException
|
||||||
|
*/
|
||||||
|
public function getContent(string $path): string
|
||||||
|
{
|
||||||
|
// TODO: Implement getContent() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save new contents to a given file.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param string $content
|
||||||
|
* @return \Psr\Http\Message\ResponseInterface
|
||||||
|
*
|
||||||
|
* @throws \GuzzleHttp\Exception\TransferException
|
||||||
|
*/
|
||||||
|
public function putContent(string $path, string $content): ResponseInterface
|
||||||
|
{
|
||||||
|
// TODO: Implement putContent() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a directory listing for a given path.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @throws \GuzzleHttp\Exception\TransferException
|
||||||
|
*/
|
||||||
|
public function getDirectory(string $path): array
|
||||||
|
{
|
||||||
|
$response = $this->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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
import http from '../http';
|
import http from '../http';
|
||||||
import {filter, isObject} from 'lodash';
|
import {filter, isObject} from 'lodash';
|
||||||
// @ts-ignore
|
|
||||||
import route from '../../../../../vendor/tightenco/ziggy/src/js/route';
|
|
||||||
import {DirectoryContentObject, DirectoryContents} from "./types";
|
import {DirectoryContentObject, DirectoryContents} from "./types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +7,9 @@ import {DirectoryContentObject, DirectoryContents} from "./types";
|
||||||
*/
|
*/
|
||||||
export function getDirectoryContents(server: string, directory: string): Promise<DirectoryContents> {
|
export function getDirectoryContents(server: string, directory: string): Promise<DirectoryContents> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
http.get(route('server.files', {server, directory}))
|
http.get(`/api/client/servers/${server}/files/list`, {
|
||||||
|
params: {directory}
|
||||||
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
return resolve({
|
return resolve({
|
||||||
files: filter(response.data.contents, function (o: DirectoryContentObject) {
|
files: filter(response.data.contents, function (o: DirectoryContentObject) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export type DirectoryContentObject = {
|
||||||
name: string,
|
name: string,
|
||||||
created: string,
|
created: string,
|
||||||
modified: string,
|
modified: string,
|
||||||
mode: number,
|
mode: string,
|
||||||
size: number,
|
size: number,
|
||||||
directory: boolean,
|
directory: boolean,
|
||||||
file: boolean,
|
file: boolean,
|
||||||
|
|
|
@ -42,6 +42,8 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['prefix' => '/files'], function () {
|
Route::group(['prefix' => '/files'], function () {
|
||||||
|
Route::get('/list', 'Servers\FileController@listDirectory')->name('api.client.servers.files.list');
|
||||||
|
|
||||||
Route::post('/download/{file}', 'Servers\FileController@download')
|
Route::post('/download/{file}', 'Servers\FileController@download')
|
||||||
->where('file', '.*')
|
->where('file', '.*')
|
||||||
->name('api.client.servers.files.download');
|
->name('api.client.servers.files.download');
|
||||||
|
|
Loading…
Reference in a new issue