Skip to content

Commit c80c856

Browse files
committed
Switch file manager listing to use panel API endpoint
1 parent e87c5f6 commit c80c856

File tree

8 files changed

+156
-8
lines changed

8 files changed

+156
-8
lines changed

app/Http/Controllers/Api/Client/Servers/FileController.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
use Ramsey\Uuid\Uuid;
77
use Pterodactyl\Models\Server;
88
use Illuminate\Http\JsonResponse;
9-
use Illuminate\Contracts\Cache\Repository;
9+
use Illuminate\Contracts\Cache\Repository as CacheRepository;
1010
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
11+
use Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface;
12+
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest;
1113
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DownloadFileRequest;
1214

1315
class FileController extends ClientApiController
@@ -17,16 +19,38 @@ class FileController extends ClientApiController
1719
*/
1820
private $cache;
1921

22+
/**
23+
* @var \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface
24+
*/
25+
private $fileRepository;
26+
2027
/**
2128
* FileController constructor.
2229
*
23-
* @param \Illuminate\Contracts\Cache\Repository $cache
30+
* @param \Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface $fileRepository
31+
* @param \Illuminate\Contracts\Cache\Repository $cache
2432
*/
25-
public function __construct(Repository $cache)
33+
public function __construct(FileRepositoryInterface $fileRepository, CacheRepository $cache)
2634
{
2735
parent::__construct();
2836

2937
$this->cache = $cache;
38+
$this->fileRepository = $fileRepository;
39+
}
40+
41+
/**
42+
* Returns a listing of files in a given directory.
43+
*
44+
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest $request
45+
* @return \Illuminate\Http\JsonResponse
46+
*/
47+
public function listDirectory(ListFilesRequest $request): JsonResponse
48+
{
49+
return JsonResponse::create([
50+
'contents' => $this->fileRepository->setServer($request->getModel(Server::class))->getDirectory(
51+
$request->get('directory') ?? '/'
52+
),
53+
]);
3054
}
3155

3256
/**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
4+
5+
use Pterodactyl\Models\Server;
6+
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
7+
8+
class ListFilesRequest extends ClientApiRequest
9+
{
10+
/**
11+
* Check that the user making this request to the API is authorized to list all
12+
* of the files that exist for a given server.
13+
*
14+
* @return bool
15+
*/
16+
public function authorize(): bool
17+
{
18+
return $this->user()->can('list-files', $this->getModel(Server::class));
19+
}
20+
}

app/Providers/RepositoryServiceProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Pterodactyl\Providers;
44

55
use Illuminate\Support\ServiceProvider;
6-
use Pterodactyl\Repositories\Daemon\FileRepository;
6+
use Pterodactyl\Repositories\Wings\FileRepository;
77
use Pterodactyl\Repositories\Daemon\PowerRepository;
88
use Pterodactyl\Repositories\Eloquent\EggRepository;
99
use Pterodactyl\Repositories\Eloquent\NestRepository;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Pterodactyl\Repositories\Wings;
4+
5+
use GuzzleHttp\Client;
6+
use Pterodactyl\Repositories\Daemon\BaseRepository;
7+
use Pterodactyl\Contracts\Repository\Daemon\BaseRepositoryInterface;
8+
9+
abstract class BaseWingsRepository extends BaseRepository implements BaseRepositoryInterface
10+
{
11+
/**
12+
* Return an instance of the Guzzle HTTP Client to be used for requests.
13+
*
14+
* @param array $headers
15+
* @return \GuzzleHttp\Client
16+
*/
17+
public function getHttpClient(array $headers = []): Client
18+
{
19+
// We're just going to extend the parent client here since that logic is already quite
20+
// sound and does everything we need it to aside from provide the correct base URL
21+
// and authentication headers.
22+
$client = parent::getHttpClient($headers);
23+
24+
return new Client(array_merge($client->getConfig(), [
25+
'base_uri' => $this->getNode()->getConnectionAddress(),
26+
'headers' => [
27+
'Authorization' => 'Bearer ' . ($this->getToken() ?? $this->getNode()->daemonSecret),
28+
'Accept' => 'application/json',
29+
'Content-Type' => 'application/json',
30+
],
31+
]));
32+
}
33+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Pterodactyl\Repositories\Wings;
4+
5+
use stdClass;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Pterodactyl\Contracts\Repository\Daemon\FileRepositoryInterface;
8+
9+
class FileRepository extends BaseWingsRepository implements FileRepositoryInterface
10+
{
11+
/**
12+
* Return stat information for a given file.
13+
*
14+
* @param string $path
15+
* @return \stdClass
16+
*
17+
* @throws \GuzzleHttp\Exception\TransferException
18+
*/
19+
public function getFileStat(string $path): stdClass
20+
{
21+
// TODO: Implement getFileStat() method.
22+
}
23+
24+
/**
25+
* Return the contents of a given file if it can be edited in the Panel.
26+
*
27+
* @param string $path
28+
* @return string
29+
*
30+
* @throws \GuzzleHttp\Exception\TransferException
31+
*/
32+
public function getContent(string $path): string
33+
{
34+
// TODO: Implement getContent() method.
35+
}
36+
37+
/**
38+
* Save new contents to a given file.
39+
*
40+
* @param string $path
41+
* @param string $content
42+
* @return \Psr\Http\Message\ResponseInterface
43+
*
44+
* @throws \GuzzleHttp\Exception\TransferException
45+
*/
46+
public function putContent(string $path, string $content): ResponseInterface
47+
{
48+
// TODO: Implement putContent() method.
49+
}
50+
51+
/**
52+
* Return a directory listing for a given path.
53+
*
54+
* @param string $path
55+
* @return array
56+
*
57+
* @throws \GuzzleHttp\Exception\TransferException
58+
*/
59+
public function getDirectory(string $path): array
60+
{
61+
$response = $this->getHttpClient()->get(
62+
// Reason for the path check is because it is unnecessary on the Daemon but we need
63+
// to respect the interface.
64+
sprintf('/api/servers/%s/files/list/%s', $this->getServer()->uuid, $path === '/' ? '' : $path)
65+
);
66+
67+
return json_decode($response->getBody(), true);
68+
}
69+
}

resources/assets/scripts/api/server/getDirectoryContents.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import http from '../http';
22
import {filter, isObject} from 'lodash';
3-
// @ts-ignore
4-
import route from '../../../../../vendor/tightenco/ziggy/src/js/route';
53
import {DirectoryContentObject, DirectoryContents} from "./types";
64

75
/**
86
* Get the contents of a specific directory for a given server.
97
*/
108
export function getDirectoryContents(server: string, directory: string): Promise<DirectoryContents> {
119
return new Promise((resolve, reject) => {
12-
http.get(route('server.files', {server, directory}))
10+
http.get(`/api/client/servers/${server}/files/list`, {
11+
params: {directory}
12+
})
1313
.then((response) => {
1414
return resolve({
1515
files: filter(response.data.contents, function (o: DirectoryContentObject) {

resources/assets/scripts/api/server/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type DirectoryContentObject = {
88
name: string,
99
created: string,
1010
modified: string,
11-
mode: number,
11+
mode: string,
1212
size: number,
1313
directory: boolean,
1414
file: boolean,

routes/api-client.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
});
4343

4444
Route::group(['prefix' => '/files'], function () {
45+
Route::get('/list', 'Servers\FileController@listDirectory')->name('api.client.servers.files.list');
46+
4547
Route::post('/download/{file}', 'Servers\FileController@download')
4648
->where('file', '.*')
4749
->name('api.client.servers.files.download');

0 commit comments

Comments
 (0)