diff --git a/app/Http/Controllers/Api/Client/Servers/DownloadBackupController.php b/app/Http/Controllers/Api/Client/Servers/DownloadBackupController.php index 1d22b7c35..4c8b16a25 100644 --- a/app/Http/Controllers/Api/Client/Servers/DownloadBackupController.php +++ b/app/Http/Controllers/Api/Client/Servers/DownloadBackupController.php @@ -82,7 +82,7 @@ class DownloadBackupController extends ClientApiController throw new BadRequestHttpException; } - return JsonResponse::create([ + return new JsonResponse([ 'object' => 'signed_url', 'attributes' => [ 'url' => $url, diff --git a/app/Http/Controllers/Api/Client/Servers/FileUploadController.php b/app/Http/Controllers/Api/Client/Servers/FileUploadController.php new file mode 100644 index 000000000..e8f5ad080 --- /dev/null +++ b/app/Http/Controllers/Api/Client/Servers/FileUploadController.php @@ -0,0 +1,73 @@ +jwtService = $jwtService; + } + + /** + * Returns a url where files can be uploaded to. + * + * @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\UploadFileRequest $request + * @param \Pterodactyl\Models\Server $server + * + * @return \Illuminate\Http\JsonResponse + */ + public function __invoke(UploadFileRequest $request, Server $server) + { + return new JsonResponse([ + 'object' => 'signed_url', + 'attributes' => [ + 'url' => $this->getUploadUrl($server, $request->user()), + ], + ]); + } + + /** + * Returns a url where files can be uploaded to. + * + * @param \Pterodactyl\Models\Server $server + * @param \Pterodactyl\Models\User $user + * @return string + */ + protected function getUploadUrl(Server $server, User $user) + { + $token = $this->jwtService + ->setExpiresAt(CarbonImmutable::now()->addMinutes(15)) + ->setClaims([ + 'server_uuid' => $server->uuid, + ]) + ->handle($server->node, $user->id . $server->uuid); + + return sprintf( + '%s/upload/file?token=%s', + $server->node->getConnectionAddress(), + $token->__toString() + ); + } +} diff --git a/app/Http/Requests/Api/Client/Servers/Files/UploadFileRequest.php b/app/Http/Requests/Api/Client/Servers/Files/UploadFileRequest.php new file mode 100644 index 000000000..6808a5497 --- /dev/null +++ b/app/Http/Requests/Api/Client/Servers/Files/UploadFileRequest.php @@ -0,0 +1,17 @@ + => { + return new Promise((resolve, reject) => { + http.get(`/api/client/servers/${uuid}/files/upload`) + .then(({ data }) => resolve(data.attributes.url)) + .catch(reject); + }); +}; diff --git a/resources/scripts/components/server/files/UploadButton.tsx b/resources/scripts/components/server/files/UploadButton.tsx index 16a44d39d..c3cc78355 100644 --- a/resources/scripts/components/server/files/UploadButton.tsx +++ b/resources/scripts/components/server/files/UploadButton.tsx @@ -1,6 +1,9 @@ +import axios from 'axios'; +import getFileUploadUrl from '@/api/server/files/getFileUploadUrl'; +import useServer from '@/plugins/useServer'; import tw from 'twin.macro'; import Button from '@/components/elements/Button'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import styled from 'styled-components/macro'; const ModalMask = styled.div` @@ -9,31 +12,71 @@ const ModalMask = styled.div` `; export default () => { + const { uuid } = useServer(); const [ visible, setVisible ] = useState(false); + const handleEscapeEvent = (e: KeyboardEvent) => { + setVisible(false); + }; + + useEffect(() => { + window.addEventListener('keydown', handleEscapeEvent); + + return () => window.removeEventListener('keydown', handleEscapeEvent); + }, [ visible ]); + const onDragOver = (e: any) => { e.preventDefault(); - - //console.log(e); }; const onDragEnter = (e: any) => { e.preventDefault(); - - //console.log(e); }; const onDragLeave = (e: any) => { e.preventDefault(); - - //console.log(e); }; const onFileDrop = (e: any) => { e.preventDefault(); - const files = e.dataTransfer.files; + if (e.dataTransfer === undefined || e.dataTransfer === null) { + return; + } + + const files: FileList = e.dataTransfer.files; console.log(files); + + const formData = new FormData(); + + for (let i = 0; i < files.length; i++) { + console.log(files[i]); + // @ts-ignore + formData.append('files', files[i]); + } + + console.log('getFileUploadUrl'); + getFileUploadUrl(uuid) + .then(url => { + console.log(url); + + // `${url}&directory=` + axios.post(url, formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }) + .then(res => { + console.log(res); + setVisible(false); + }) + .catch(error => { + console.error(error); + }); + }) + .catch(error => { + console.error(error); + }); }; return ( diff --git a/routes/api-client.php b/routes/api-client.php index 9b57cf0c4..eb01ed85f 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -62,6 +62,7 @@ Route::group(['prefix' => '/servers/{server}', 'middleware' => [AuthenticateServ Route::post('/compress', 'Servers\FileController@compress'); Route::post('/delete', 'Servers\FileController@delete'); Route::post('/create-folder', 'Servers\FileController@create'); + Route::get('/upload', 'Servers\FileUploadController'); }); Route::group(['prefix' => '/schedules'], function () {