From 811026895bab0a14e6e2c1e3bbc82b425db56d00 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 4 May 2019 16:04:59 -0700 Subject: [PATCH] Update support for moving/renaming files and folders --- .../Daemon/FileRepositoryInterface.php | 9 ++++++ .../Api/Client/Servers/FileController.php | 18 ++++++++++- .../Servers/Files/RenameFileRequest.php | 31 +++++++++++++++++++ app/Repositories/Wings/FileRepository.php | 24 ++++++++++++-- .../scripts/api/server/files/renameElement.ts | 23 -------------- .../scripts/api/server/files/renameFile.ts | 12 +++++++ .../filemanager/modals/MoveFileModal.vue | 9 ++---- .../filemanager/modals/RenameModal.vue | 10 ++---- routes/api-client.php | 2 +- 9 files changed, 97 insertions(+), 41 deletions(-) create mode 100644 app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php delete mode 100644 resources/assets/scripts/api/server/files/renameElement.ts create mode 100644 resources/assets/scripts/api/server/files/renameFile.ts diff --git a/app/Contracts/Repository/Daemon/FileRepositoryInterface.php b/app/Contracts/Repository/Daemon/FileRepositoryInterface.php index eab8e9f43..10206d072 100644 --- a/app/Contracts/Repository/Daemon/FileRepositoryInterface.php +++ b/app/Contracts/Repository/Daemon/FileRepositoryInterface.php @@ -56,4 +56,13 @@ interface FileRepositoryInterface extends BaseRepositoryInterface * @return \Psr\Http\Message\ResponseInterface */ public function createDirectory(string $name, string $path): ResponseInterface; + + /** + * Renames or moves a file on the remote machine. + * + * @param string $from + * @param string $to + * @return \Psr\Http\Message\ResponseInterface + */ + public function renameFile(string $from, string $to): ResponseInterface; } diff --git a/app/Http/Controllers/Api/Client/Servers/FileController.php b/app/Http/Controllers/Api/Client/Servers/FileController.php index a65f1155b..08fbd8885 100644 --- a/app/Http/Controllers/Api/Client/Servers/FileController.php +++ b/app/Http/Controllers/Api/Client/Servers/FileController.php @@ -11,6 +11,7 @@ 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\RenameFileRequest; use Pterodactyl\Http\Requests\Api\Client\Servers\Files\CreateFolderRequest; use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DownloadFileRequest; @@ -67,7 +68,22 @@ class FileController extends ClientApiController ->setServer($request->getModel(Server::class)) ->createDirectory($request->input('name'), $request->input('directory', '/')); - return Response::create('s'); + return Response::create('', Response::HTTP_NO_CONTENT); + } + + /** + * Renames a file on the remote machine. + * + * @param \Pterodactyl\Http\Requests\Api\Client\Servers\Files\RenameFileRequest $request + * @return \Illuminate\Http\Response + */ + public function renameFile(RenameFileRequest $request): Response + { + $this->fileRepository + ->setServer($request->getModel(Server::class)) + ->renameFile($request->input('rename_from'), $request->input('rename_to')); + + return Response::create('', Response::HTTP_NO_CONTENT); } /** diff --git a/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php b/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php new file mode 100644 index 000000000..a1c399453 --- /dev/null +++ b/app/Http/Requests/Api/Client/Servers/Files/RenameFileRequest.php @@ -0,0 +1,31 @@ + 'string|required', + 'rename_to' => 'string|required', + ]; + } +} diff --git a/app/Repositories/Wings/FileRepository.php b/app/Repositories/Wings/FileRepository.php index be37d392c..b96d1bb50 100644 --- a/app/Repositories/Wings/FileRepository.php +++ b/app/Repositories/Wings/FileRepository.php @@ -59,8 +59,8 @@ class FileRepository extends BaseWingsRepository implements FileRepositoryInterf 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. + // 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) ); @@ -86,4 +86,24 @@ class FileRepository extends BaseWingsRepository implements FileRepositoryInterf ] ); } + + /** + * Renames or moves a file on the remote machine. + * + * @param string $from + * @param string $to + * @return \Psr\Http\Message\ResponseInterface + */ + public function renameFile(string $from, string $to): ResponseInterface + { + return $this->getHttpClient()->put( + sprintf('/api/servers/%s/files/rename', $this->getServer()->uuid), + [ + 'json' => [ + 'rename_from' => $from, + 'rename_to' => $to, + ], + ] + ); + } } diff --git a/resources/assets/scripts/api/server/files/renameElement.ts b/resources/assets/scripts/api/server/files/renameElement.ts deleted file mode 100644 index efd991b17..000000000 --- a/resources/assets/scripts/api/server/files/renameElement.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {withCredentials} from "@/api/http"; -import {ServerApplicationCredentials} from "@/store/types"; -import { join } from 'path'; - -type RenameObject = { - path: string, - fromName: string, - toName: string, -} - -/** - * Renames a file or folder on the server using the node. - */ -export function renameElement(server: string, credentials: ServerApplicationCredentials, data: RenameObject): Promise { - return new Promise((resolve, reject) => { - withCredentials(server, credentials).post('/v1/server/file/rename', { - from: join(data.path, data.fromName), - to: join(data.path, data.toName), - }) - .then(() => resolve()) - .catch(reject); - }); -} diff --git a/resources/assets/scripts/api/server/files/renameFile.ts b/resources/assets/scripts/api/server/files/renameFile.ts new file mode 100644 index 000000000..75c9c3026 --- /dev/null +++ b/resources/assets/scripts/api/server/files/renameFile.ts @@ -0,0 +1,12 @@ +import http from "@/api/http"; + +export function renameFile(server: string, renameFrom: string, renameTo: string): Promise { + return new Promise((resolve, reject) => { + http.put(`/api/client/servers/${server}/files/rename`, { + rename_from: renameFrom, + rename_to: renameTo, + }) + .then(() => resolve()) + .catch(reject); + }); +} diff --git a/resources/assets/scripts/components/server/components/filemanager/modals/MoveFileModal.vue b/resources/assets/scripts/components/server/components/filemanager/modals/MoveFileModal.vue index e64f63345..eb0c7c63b 100644 --- a/resources/assets/scripts/components/server/components/filemanager/modals/MoveFileModal.vue +++ b/resources/assets/scripts/components/server/components/filemanager/modals/MoveFileModal.vue @@ -42,7 +42,7 @@ import Modal from "@/components/core/Modal.vue"; import MessageBox from "@/components/MessageBox.vue"; import {DirectoryContentObject} from "@/api/server/types"; - import {moveElement} from '@/api/server/files/copyElement'; + import {renameFile} from '@/api/server/files/renameFile'; import {mapState} from "vuex"; import {ApplicationState} from "@/store/types"; import {join} from 'path'; @@ -106,12 +106,7 @@ this.isLoading = true; // @ts-ignore - moveElement(this.server.uuid, this.credentials, { - // @ts-ignore - currentPath: join(this.fm.currentDirectory, this.file.name), - // @ts-ignore - newPath: join(this.fm.currentDirectory, this.moveTo), - }) + renameFile(this.server.uuid, join(this.fm.currentDirectory, this.file.name), join(this.fm.currentDirectory, this.moveTo)) .then(() => this.$emit('moved')) .catch((error: AxiosError) => { this.error = `There was an error moving the requested ${(this.file.directory) ? 'folder' : 'file'}. Response was: ${error.message}`; diff --git a/resources/assets/scripts/components/server/components/filemanager/modals/RenameModal.vue b/resources/assets/scripts/components/server/components/filemanager/modals/RenameModal.vue index 288974ac3..fa760b4c4 100644 --- a/resources/assets/scripts/components/server/components/filemanager/modals/RenameModal.vue +++ b/resources/assets/scripts/components/server/components/filemanager/modals/RenameModal.vue @@ -47,9 +47,10 @@ import MessageBox from '@/components/MessageBox.vue'; import {DirectoryContentObject} from "@/api/server/types"; import {mapState} from "vuex"; - import {renameElement} from "@/api/server/files/renameElement"; + import {renameFile} from "@/api/server/files/renameFile"; import {AxiosError} from 'axios'; import {ApplicationState} from "@/store/types"; + import {join} from "path"; type DataStructure = { error: null | string, @@ -109,12 +110,7 @@ this.error = null; // @ts-ignore - renameElement(this.server.uuid, this.credentials, { - // @ts-ignore - path: this.fm.currentDirectory, - toName: this.newName, - fromName: this.object.name - }) + renameFile(this.server.uuid, join(this.fm.currentDirectory, this.object.name), join(this.fm.currentDirectory, this.newName)) .then(() => { this.$emit('renamed', this.newName); this.closeModal(); diff --git a/routes/api-client.php b/routes/api-client.php index 25515980b..59e3a6b75 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -43,7 +43,7 @@ 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::put('/rename', 'Servers\FileController@renameFile')->name('api.client.servers.files.rename'); Route::post('/create-folder', 'Servers\FileController@createFolder')->name('api.client.servers.files.create-folder'); Route::post('/download/{file}', 'Servers\FileController@download')