Update support for moving/renaming files and folders

This commit is contained in:
Dane Everitt 2019-05-04 16:04:59 -07:00
parent eed4be49ab
commit 811026895b
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
9 changed files with 97 additions and 41 deletions

View file

@ -56,4 +56,13 @@ interface FileRepositoryInterface extends BaseRepositoryInterface
* @return \Psr\Http\Message\ResponseInterface * @return \Psr\Http\Message\ResponseInterface
*/ */
public function createDirectory(string $name, string $path): 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;
} }

View file

@ -11,6 +11,7 @@ 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\Contracts\Repository\Daemon\FileRepositoryInterface;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\ListFilesRequest; 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\CreateFolderRequest;
use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DownloadFileRequest; use Pterodactyl\Http\Requests\Api\Client\Servers\Files\DownloadFileRequest;
@ -67,7 +68,22 @@ class FileController extends ClientApiController
->setServer($request->getModel(Server::class)) ->setServer($request->getModel(Server::class))
->createDirectory($request->input('name'), $request->input('directory', '/')); ->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);
} }
/** /**

View file

@ -0,0 +1,31 @@
<?php
namespace Pterodactyl\Http\Requests\Api\Client\Servers\Files;
use Pterodactyl\Contracts\Http\ClientPermissionsRequest;
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
class RenameFileRequest extends ClientApiRequest implements ClientPermissionsRequest
{
/**
* The permission the user is required to have in order to perform this
* request action.
*
* @return string
*/
public function permission(): string
{
return 'move-files';
}
/**
* @return array
*/
public function rules(): array
{
return [
'rename_from' => 'string|required',
'rename_to' => 'string|required',
];
}
}

View file

@ -59,8 +59,8 @@ class FileRepository extends BaseWingsRepository implements FileRepositoryInterf
public function getDirectory(string $path): array public function getDirectory(string $path): array
{ {
$response = $this->getHttpClient()->get( $response = $this->getHttpClient()->get(
// Reason for the path check is because it is unnecessary on the Daemon but we need // Reason for the path check is because it is unnecessary on the Daemon but we need
// to respect the interface. // to respect the interface.
sprintf('/api/servers/%s/files/list/%s', $this->getServer()->uuid, $path === '/' ? '' : $path) 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,
],
]
);
}
} }

View file

@ -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<void> {
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);
});
}

View file

@ -0,0 +1,12 @@
import http from "@/api/http";
export function renameFile(server: string, renameFrom: string, renameTo: string): Promise<void> {
return new Promise((resolve, reject) => {
http.put(`/api/client/servers/${server}/files/rename`, {
rename_from: renameFrom,
rename_to: renameTo,
})
.then(() => resolve())
.catch(reject);
});
}

View file

@ -42,7 +42,7 @@
import Modal from "@/components/core/Modal.vue"; import Modal from "@/components/core/Modal.vue";
import MessageBox from "@/components/MessageBox.vue"; import MessageBox from "@/components/MessageBox.vue";
import {DirectoryContentObject} from "@/api/server/types"; 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 {mapState} from "vuex";
import {ApplicationState} from "@/store/types"; import {ApplicationState} from "@/store/types";
import {join} from 'path'; import {join} from 'path';
@ -106,12 +106,7 @@
this.isLoading = true; this.isLoading = true;
// @ts-ignore // @ts-ignore
moveElement(this.server.uuid, this.credentials, { renameFile(this.server.uuid, join(this.fm.currentDirectory, this.file.name), join(this.fm.currentDirectory, this.moveTo))
// @ts-ignore
currentPath: join(this.fm.currentDirectory, this.file.name),
// @ts-ignore
newPath: join(this.fm.currentDirectory, this.moveTo),
})
.then(() => this.$emit('moved')) .then(() => this.$emit('moved'))
.catch((error: AxiosError) => { .catch((error: AxiosError) => {
this.error = `There was an error moving the requested ${(this.file.directory) ? 'folder' : 'file'}. Response was: ${error.message}`; this.error = `There was an error moving the requested ${(this.file.directory) ? 'folder' : 'file'}. Response was: ${error.message}`;

View file

@ -47,9 +47,10 @@
import MessageBox from '@/components/MessageBox.vue'; import MessageBox from '@/components/MessageBox.vue';
import {DirectoryContentObject} from "@/api/server/types"; import {DirectoryContentObject} from "@/api/server/types";
import {mapState} from "vuex"; import {mapState} from "vuex";
import {renameElement} from "@/api/server/files/renameElement"; import {renameFile} from "@/api/server/files/renameFile";
import {AxiosError} from 'axios'; import {AxiosError} from 'axios';
import {ApplicationState} from "@/store/types"; import {ApplicationState} from "@/store/types";
import {join} from "path";
type DataStructure = { type DataStructure = {
error: null | string, error: null | string,
@ -109,12 +110,7 @@
this.error = null; this.error = null;
// @ts-ignore // @ts-ignore
renameElement(this.server.uuid, this.credentials, { renameFile(this.server.uuid, join(this.fm.currentDirectory, this.object.name), join(this.fm.currentDirectory, this.newName))
// @ts-ignore
path: this.fm.currentDirectory,
toName: this.newName,
fromName: this.object.name
})
.then(() => { .then(() => {
this.$emit('renamed', this.newName); this.$emit('renamed', this.newName);
this.closeModal(); this.closeModal();

View file

@ -43,7 +43,7 @@ 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::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('/create-folder', 'Servers\FileController@createFolder')->name('api.client.servers.files.create-folder');
Route::post('/download/{file}', 'Servers\FileController@download') Route::post('/download/{file}', 'Servers\FileController@download')