From a2fc511e7eb92c2c67d6c68517833451253aec5f Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 6 Oct 2016 20:29:21 -0400 Subject: [PATCH] Add permissions for filemanager stuff to subusers --- app/Policies/ServerPolicy.php | 64 ++ app/Repositories/ServerRepository.php | 14 +- app/Repositories/SubuserRepository.php | 4 + .../server/js/filemanager/actions.blade.php | 665 +++++++++--------- .../js/filemanager/contextmenu.blade.php | 112 +-- resources/views/server/users/new.blade.php | 26 +- resources/views/server/users/view.blade.php | 23 + 7 files changed, 522 insertions(+), 386 deletions(-) diff --git a/app/Policies/ServerPolicy.php b/app/Policies/ServerPolicy.php index 302ace0f4..2615149f0 100644 --- a/app/Policies/ServerPolicy.php +++ b/app/Policies/ServerPolicy.php @@ -209,6 +209,70 @@ class ServerPolicy return $user->permissions()->server($server)->permission('save-files')->exists(); } + /** + * Check if user has permission to move and rename files and folders on a server. + * + * @param Pterodactyl\Models\User $user + * @param Pterodactyl\Models\Server $server + * @return boolean + */ + public function moveFiles(User $user, Server $server) + { + if ($this->isOwner($user, $server)) { + return true; + } + + return $user->permissions()->server($server)->permission('move-files')->exists(); + } + + /** + * Check if user has permission to copy folders and files on a server. + * + * @param Pterodactyl\Models\User $user + * @param Pterodactyl\Models\Server $server + * @return boolean + */ + public function copyFiles(User $user, Server $server) + { + if ($this->isOwner($user, $server)) { + return true; + } + + return $user->permissions()->server($server)->permission('copy-files')->exists(); + } + + /** + * Check if user has permission to compress files and folders on a server. + * + * @param Pterodactyl\Models\User $user + * @param Pterodactyl\Models\Server $server + * @return boolean + */ + public function compressFiles(User $user, Server $server) + { + if ($this->isOwner($user, $server)) { + return true; + } + + return $user->permissions()->server($server)->permission('compress-files')->exists(); + } + + /** + * Check if user has permission to decompress files on a server. + * + * @param Pterodactyl\Models\User $user + * @param Pterodactyl\Models\Server $server + * @return boolean + */ + public function decompressFiles(User $user, Server $server) + { + if ($this->isOwner($user, $server)) { + return true; + } + + return $user->permissions()->server($server)->permission('decompress-files')->exists(); + } + /** * Check if user has permission to add files to a server. * diff --git a/app/Repositories/ServerRepository.php b/app/Repositories/ServerRepository.php index 549941b75..394c057a2 100644 --- a/app/Repositories/ServerRepository.php +++ b/app/Repositories/ServerRepository.php @@ -41,19 +41,7 @@ class ServerRepository { protected $daemonPermissions = [ - 's:get', - 's:power:start', - 's:power:stop', - 's:power:restart', - 's:power:kill', - 's:console', - 's:command', - 's:files:get', - 's:files:read', - 's:files:post', - 's:files:delete', - 's:files:upload', - 's:set-password' + 's:*' ]; public function __construct() diff --git a/app/Repositories/SubuserRepository.php b/app/Repositories/SubuserRepository.php index 38910e00a..1e812a14a 100644 --- a/app/Repositories/SubuserRepository.php +++ b/app/Repositories/SubuserRepository.php @@ -71,6 +71,10 @@ class SubuserRepository 'download-files' => null, 'upload-files' => 's:files:upload', 'delete-files' => 's:files:delete', + 'move-files' => 's:files:move', + 'copy-files' => 's:files:copy', + 'compress-files' => 's:files:compress', + 'decompress-files' => 's:files:decompress', // Subusers 'list-subusers' => null, diff --git a/resources/views/server/js/filemanager/actions.blade.php b/resources/views/server/js/filemanager/actions.blade.php index a2e74c565..04620f2b6 100644 --- a/resources/views/server/js/filemanager/actions.blade.php +++ b/resources/views/server/js/filemanager/actions.blade.php @@ -29,357 +29,370 @@ class ActionsClass { this.element = undefined; } - folder() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const currentName = decodeURIComponent(nameBlock.attr('data-name')); - const currentPath = decodeURIComponent(nameBlock.data('path')); - - let inputValue = `${currentPath}${currentName}/`; - if ($(this.element).data('type') === 'file') { - inputValue = currentPath; - } - swal({ - type: 'input', - title: 'Create Folder', - text: 'Please enter the path and folder name below.', - showCancelButton: true, - showConfirmButton: true, - closeOnConfirm: false, - showLoaderOnConfirm: true, - inputValue: inputValue - }, (val) => { - $.ajax({ - type: 'POST', - headers: { - 'X-Access-Token': '{{ $server->daemonSecret }}', - 'X-Access-Server': '{{ $server->uuid }}' - }, - contentType: 'application/json; charset=utf-8', - url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/folder', - timeout: 10000, - data: JSON.stringify({ - path: val, - }), - }).done(data => { - swal.close(); - Files.list(); - }).fail(jqXHR => { - console.error(jqXHR); - var error = 'An error occured while trying to process this request.'; - if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { - error = jqXHR.responseJSON.error; - } - swal({ - type: 'error', - title: '', - text: error, - }); - }); - }); - } - - move() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const currentName = decodeURIComponent(nameBlock.attr('data-name')); - const currentPath = decodeURIComponent(nameBlock.data('path')); - - swal({ - type: 'input', - title: 'Move File', - text: 'Please enter the new path for the file below.', - showCancelButton: true, - showConfirmButton: true, - closeOnConfirm: false, - showLoaderOnConfirm: true, - inputValue: `${currentPath}${currentName}`, - }, (val) => { - $.ajax({ - type: 'POST', - headers: { - 'X-Access-Token': '{{ $server->daemonSecret }}', - 'X-Access-Server': '{{ $server->uuid }}' - }, - contentType: 'application/json; charset=utf-8', - url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/move', - timeout: 10000, - data: JSON.stringify({ - from: `${currentPath}${currentName}`, - to: `${val}`, - }), - }).done(data => { - nameBlock.parent().addClass('warning').delay(200).fadeOut(); - swal.close(); - }).fail(jqXHR => { - console.error(jqXHR); - var error = 'An error occured while trying to process this request.'; - if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { - error = jqXHR.responseJSON.error; - } - swal({ - type: 'error', - title: '', - text: error, - }); - }); - }); - - } - - copy() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const currentName = decodeURIComponent(nameBlock.attr('data-name')); - const currentPath = decodeURIComponent(nameBlock.data('path')); - - swal({ - type: 'input', - title: 'Copy File', - text: 'Please enter the new path for the copied file below.', - showCancelButton: true, - showConfirmButton: true, - closeOnConfirm: false, - showLoaderOnConfirm: true, - inputValue: `${currentPath}${currentName}`, - }, (val) => { - $.ajax({ - type: 'POST', - headers: { - 'X-Access-Token': '{{ $server->daemonSecret }}', - 'X-Access-Server': '{{ $server->uuid }}' - }, - contentType: 'application/json; charset=utf-8', - url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/copy', - timeout: 10000, - data: JSON.stringify({ - from: `${currentPath}${currentName}`, - to: `${val}`, - }), - }).done(data => { - swal({ - type: 'success', - title: '', - text: 'File successfully copied.' - }); - Files.list(); - }).fail(jqXHR => { - console.error(jqXHR); - var error = 'An error occured while trying to process this request.'; - if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { - error = jqXHR.responseJSON.error; - } - swal({ - type: 'error', - title: '', - text: error, - }); - }); - }); - - } - - download() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const fileName = decodeURIComponent(nameBlock.attr('data-name')); - const filePath = decodeURIComponent(nameBlock.data('path')); - - window.location = `/server/{{ $server->uuidShort }}/files/download/${filePath}${fileName}`; - } - - rename() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const currentLink = nameBlock.find('a'); - const currentName = decodeURIComponent(nameBlock.attr('data-name')); - const attachEditor = ` - - - `; - - nameBlock.html(attachEditor); - const inputField = nameBlock.find('input'); - const inputLoader = nameBlock.find('.input-loader'); - - inputField.focus(); - inputField.on('blur keydown', e => { - // Save Field - if ( - (e.type === 'keydown' && e.which === 27) - || e.type === 'blur' - || (e.type === 'keydown' && e.which === 13 && currentName === inputField.val()) - ) { - if (!_.isEmpty(currentLink)) { - nameBlock.html(currentLink); - } else { - nameBlock.html(currentName); - } - inputField.remove(); - ContextMenu.unbind().run(); - return; - } - - if (e.type === 'keydown' && e.which !== 13) return; - - inputLoader.show(); + @can('create-files', $server) + folder() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const currentName = decodeURIComponent(nameBlock.attr('data-name')); const currentPath = decodeURIComponent(nameBlock.data('path')); + let inputValue = `${currentPath}${currentName}/`; + if ($(this.element).data('type') === 'file') { + inputValue = currentPath; + } + swal({ + type: 'input', + title: 'Create Folder', + text: 'Please enter the path and folder name below.', + showCancelButton: true, + showConfirmButton: true, + closeOnConfirm: false, + showLoaderOnConfirm: true, + inputValue: inputValue + }, (val) => { + $.ajax({ + type: 'POST', + headers: { + 'X-Access-Token': '{{ $server->daemonSecret }}', + 'X-Access-Server': '{{ $server->uuid }}' + }, + contentType: 'application/json; charset=utf-8', + url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/folder', + timeout: 10000, + data: JSON.stringify({ + path: val, + }), + }).done(data => { + swal.close(); + Files.list(); + }).fail(jqXHR => { + console.error(jqXHR); + var error = 'An error occured while trying to process this request.'; + if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { + error = jqXHR.responseJSON.error; + } + swal({ + type: 'error', + title: '', + text: error, + }); + }); + }); + } + @endcan + + @can('move-files', $server) + move() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const currentName = decodeURIComponent(nameBlock.attr('data-name')); + const currentPath = decodeURIComponent(nameBlock.data('path')); + + swal({ + type: 'input', + title: 'Move File', + text: 'Please enter the new path for the file below.', + showCancelButton: true, + showConfirmButton: true, + closeOnConfirm: false, + showLoaderOnConfirm: true, + inputValue: `${currentPath}${currentName}`, + }, (val) => { + $.ajax({ + type: 'POST', + headers: { + 'X-Access-Token': '{{ $server->daemonSecret }}', + 'X-Access-Server': '{{ $server->uuid }}' + }, + contentType: 'application/json; charset=utf-8', + url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/move', + timeout: 10000, + data: JSON.stringify({ + from: `${currentPath}${currentName}`, + to: `${val}`, + }), + }).done(data => { + nameBlock.parent().addClass('warning').delay(200).fadeOut(); + swal.close(); + }).fail(jqXHR => { + console.error(jqXHR); + var error = 'An error occured while trying to process this request.'; + if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { + error = jqXHR.responseJSON.error; + } + swal({ + type: 'error', + title: '', + text: error, + }); + }); + }); + + } + + rename() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const currentLink = nameBlock.find('a'); + const currentName = decodeURIComponent(nameBlock.attr('data-name')); + const attachEditor = ` + + + `; + + nameBlock.html(attachEditor); + const inputField = nameBlock.find('input'); + const inputLoader = nameBlock.find('.input-loader'); + + inputField.focus(); + inputField.on('blur keydown', e => { + // Save Field + if ( + (e.type === 'keydown' && e.which === 27) + || e.type === 'blur' + || (e.type === 'keydown' && e.which === 13 && currentName === inputField.val()) + ) { + if (!_.isEmpty(currentLink)) { + nameBlock.html(currentLink); + } else { + nameBlock.html(currentName); + } + inputField.remove(); + ContextMenu.unbind().run(); + return; + } + + if (e.type === 'keydown' && e.which !== 13) return; + + inputLoader.show(); + const currentPath = decodeURIComponent(nameBlock.data('path')); + + $.ajax({ + type: 'POST', + headers: { + 'X-Access-Token': '{{ $server->daemonSecret }}', + 'X-Access-Server': '{{ $server->uuid }}' + }, + contentType: 'application/json; charset=utf-8', + url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/rename', + timeout: 10000, + data: JSON.stringify({ + from: `${currentPath}${currentName}`, + to: `${currentPath}${inputField.val()}`, + }), + }).done(data => { + nameBlock.attr('data-name', inputField.val()); + if (!_.isEmpty(currentLink)) { + let newLink = currentLink.attr('href'); + if (nameBlock.parent().data('type') !== 'folder') { + newLink = newLink.substr(0, newLink.lastIndexOf('/')) + '/' + inputField.val(); + } + currentLink.attr('href', newLink); + nameBlock.html( + currentLink.html(inputField.val()) + ); + } else { + nameBlock.html(inputField.val()); + } + inputField.remove(); + }).fail(jqXHR => { + console.error(jqXHR); + var error = 'An error occured while trying to process this request.'; + if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { + error = jqXHR.responseJSON.error; + } + nameBlock.addClass('has-error').delay(2000).queue(() => { + nameBlock.removeClass('has-error').dequeue(); + }); + inputField.popover({ + animation: true, + placement: 'top', + content: error, + title: 'Save Error' + }).popover('show'); + }).always(() => { + inputLoader.remove(); + ContextMenu.unbind().run(); + }); + }); + } + @endcan + + @can('copy-files', $server) + copy() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const currentName = decodeURIComponent(nameBlock.attr('data-name')); + const currentPath = decodeURIComponent(nameBlock.data('path')); + + swal({ + type: 'input', + title: 'Copy File', + text: 'Please enter the new path for the copied file below.', + showCancelButton: true, + showConfirmButton: true, + closeOnConfirm: false, + showLoaderOnConfirm: true, + inputValue: `${currentPath}${currentName}`, + }, (val) => { + $.ajax({ + type: 'POST', + headers: { + 'X-Access-Token': '{{ $server->daemonSecret }}', + 'X-Access-Server': '{{ $server->uuid }}' + }, + contentType: 'application/json; charset=utf-8', + url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/copy', + timeout: 10000, + data: JSON.stringify({ + from: `${currentPath}${currentName}`, + to: `${val}`, + }), + }).done(data => { + swal({ + type: 'success', + title: '', + text: 'File successfully copied.' + }); + Files.list(); + }).fail(jqXHR => { + console.error(jqXHR); + var error = 'An error occured while trying to process this request.'; + if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { + error = jqXHR.responseJSON.error; + } + swal({ + type: 'error', + title: '', + text: error, + }); + }); + }); + } + @endcan + + @can('download-files', $server) + download() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const fileName = decodeURIComponent(nameBlock.attr('data-name')); + const filePath = decodeURIComponent(nameBlock.data('path')); + + window.location = `/server/{{ $server->uuidShort }}/files/download/${filePath}${fileName}`; + } + @endcan + + @can('delete-files', $server) + delete() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const delPath = decodeURIComponent(nameBlock.data('path')); + const delName = decodeURIComponent(nameBlock.data('name')); + + swal({ + type: 'warning', + title: '', + text: 'Are you sure you want to delete ' + delName + '? There is no reversing this action.', + html: true, + showCancelButton: true, + showConfirmButton: true, + closeOnConfirm: false, + showLoaderOnConfirm: true + }, () => { + $.ajax({ + type: 'DELETE', + url: `{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/f/${delPath}${delName}`, + headers: { + 'X-Access-Token': '{{ $server->daemonSecret }}', + 'X-Access-Server': '{{ $server->uuid }}' + } + }).done(data => { + nameBlock.parent().addClass('warning').delay(200).fadeOut(); + swal({ + type: 'success', + title: 'File Deleted' + }); + }).fail(jqXHR => { + console.error(jqXHR); + swal({ + type: 'error', + title: 'Whoops!', + html: true, + text: 'An error occured while attempting to delete this file. Please try again.', + }); + }); + }); + } + @endcan + + @can('decompress-files', $server) + decompress() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const compPath = decodeURIComponent(nameBlock.data('path')); + const compName = decodeURIComponent(nameBlock.data('name')); + $.ajax({ type: 'POST', + url: `{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/decompress`, headers: { 'X-Access-Token': '{{ $server->daemonSecret }}', 'X-Access-Server': '{{ $server->uuid }}' }, contentType: 'application/json; charset=utf-8', - url: '{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/rename', - timeout: 10000, data: JSON.stringify({ - from: `${currentPath}${currentName}`, - to: `${currentPath}${inputField.val()}`, - }), + files: `${compPath}${compName}` + }) }).done(data => { - nameBlock.attr('data-name', inputField.val()); - if (!_.isEmpty(currentLink)) { - let newLink = currentLink.attr('href'); - if (nameBlock.parent().data('type') !== 'folder') { - newLink = newLink.substr(0, newLink.lastIndexOf('/')) + '/' + inputField.val(); - } - currentLink.attr('href', newLink); - nameBlock.html( - currentLink.html(inputField.val()) - ); - } else { - nameBlock.html(inputField.val()); - } - inputField.remove(); + Files.list(compPath); }).fail(jqXHR => { console.error(jqXHR); var error = 'An error occured while trying to process this request.'; if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { error = jqXHR.responseJSON.error; } - nameBlock.addClass('has-error').delay(2000).queue(() => { - nameBlock.removeClass('has-error').dequeue(); - }); - inputField.popover({ - animation: true, - placement: 'top', - content: error, - title: 'Save Error' - }).popover('show'); - }).always(() => { - inputLoader.remove(); - ContextMenu.unbind().run(); - }); - }); - } - - delete() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const delPath = decodeURIComponent(nameBlock.data('path')); - const delName = decodeURIComponent(nameBlock.data('name')); - - swal({ - type: 'warning', - title: '', - text: 'Are you sure you want to delete ' + delName + '? There is no reversing this action.', - html: true, - showCancelButton: true, - showConfirmButton: true, - closeOnConfirm: false, - showLoaderOnConfirm: true - }, () => { - $.ajax({ - type: 'DELETE', - url: `{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/f/${delPath}${delName}`, - headers: { - 'X-Access-Token': '{{ $server->daemonSecret }}', - 'X-Access-Server': '{{ $server->uuid }}' - } - }).done(data => { - nameBlock.parent().addClass('warning').delay(200).fadeOut(); - swal({ - type: 'success', - title: 'File Deleted' - }); - }).fail(jqXHR => { - console.error(jqXHR); swal({ type: 'error', title: 'Whoops!', html: true, - text: 'An error occured while attempting to delete this file. Please try again.', + text: error }); }); - }); - } + } + @endcan - decompress() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const compPath = decodeURIComponent(nameBlock.data('path')); - const compName = decodeURIComponent(nameBlock.data('name')); + @can('compress-files', $server) + compress() { + const nameBlock = $(this.element).find('td[data-identifier="name"]'); + const compPath = decodeURIComponent(nameBlock.data('path')); + const compName = decodeURIComponent(nameBlock.data('name')); - $.ajax({ - type: 'POST', - url: `{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/decompress`, - headers: { - 'X-Access-Token': '{{ $server->daemonSecret }}', - 'X-Access-Server': '{{ $server->uuid }}' - }, - contentType: 'application/json; charset=utf-8', - data: JSON.stringify({ - files: `${compPath}${compName}` - }) - }).done(data => { - Files.list(compPath); - }).fail(jqXHR => { - console.error(jqXHR); - var error = 'An error occured while trying to process this request.'; - if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { - error = jqXHR.responseJSON.error; - } - swal({ - type: 'error', - title: 'Whoops!', - html: true, - text: error - }); - }); - } - - compress() { - const nameBlock = $(this.element).find('td[data-identifier="name"]'); - const compPath = decodeURIComponent(nameBlock.data('path')); - const compName = decodeURIComponent(nameBlock.data('name')); - - $.ajax({ - type: 'POST', - url: `{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/compress`, - headers: { - 'X-Access-Token': '{{ $server->daemonSecret }}', - 'X-Access-Server': '{{ $server->uuid }}' - }, - contentType: 'application/json; charset=utf-8', - data: JSON.stringify({ - files: `${compPath}${compName}`, - to: compPath.toString() - }) - }).done(data => { - Files.list(compPath, err => { - if (err) return; - const fileListing = $('#file_listing').find(`[data-name="${data.saved_as}"]`).parent(); - fileListing.addClass('success pulsate').delay(3000).queue(() => { - fileListing.removeClass('success pulsate').dequeue(); + $.ajax({ + type: 'POST', + url: `{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/compress`, + headers: { + 'X-Access-Token': '{{ $server->daemonSecret }}', + 'X-Access-Server': '{{ $server->uuid }}' + }, + contentType: 'application/json; charset=utf-8', + data: JSON.stringify({ + files: `${compPath}${compName}`, + to: compPath.toString() + }) + }).done(data => { + Files.list(compPath, err => { + if (err) return; + const fileListing = $('#file_listing').find(`[data-name="${data.saved_as}"]`).parent(); + fileListing.addClass('success pulsate').delay(3000).queue(() => { + fileListing.removeClass('success pulsate').dequeue(); + }); + }); + }).fail(jqXHR => { + console.error(jqXHR); + var error = 'An error occured while trying to process this request.'; + if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { + error = jqXHR.responseJSON.error; + } + swal({ + type: 'error', + title: 'Whoops!', + html: true, + text: error }); }); - }).fail(jqXHR => { - console.error(jqXHR); - var error = 'An error occured while trying to process this request.'; - if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') { - error = jqXHR.responseJSON.error; - } - swal({ - type: 'error', - title: 'Whoops!', - html: true, - text: error - }); - }); - } + } + @endcan } diff --git a/resources/views/server/js/filemanager/contextmenu.blade.php b/resources/views/server/js/filemanager/contextmenu.blade.php index c68a0046b..a4111415c 100644 --- a/resources/views/server/js/filemanager/contextmenu.blade.php +++ b/resources/views/server/js/filemanager/contextmenu.blade.php @@ -41,17 +41,17 @@ class ContextMenuClass { newFilePath = `${currentPath}${currentName}`; } return ''; } @@ -74,54 +74,74 @@ class ContextMenuClass { this.activeLine = parent; this.activeLine.addClass('active'); - if (parent.data('type') === 'file') { - $(menu).find('li[data-action="download"]').removeClass('hidden'); - } + @can('download-files', $server) + if (parent.data('type') === 'file') { + $(menu).find('li[data-action="download"]').removeClass('hidden'); + } + @endcan - if (parent.data('type') === 'folder') { - $(menu).find('li[data-action="compress"]').removeClass('hidden'); - } + @can('compress-files', $server) + if (parent.data('type') === 'folder') { + $(menu).find('li[data-action="compress"]').removeClass('hidden'); + } + @endcan - if (_.without(['application/zip', 'application/gzip', 'application/x-gzip'], parent.data('mime')).length < 3) { - $(menu).find('li[data-action="decompress"]').removeClass('hidden'); - } + @can('decompress-files', $server) + if (_.without(['application/zip', 'application/gzip', 'application/x-gzip'], parent.data('mime')).length < 3) { + $(menu).find('li[data-action="decompress"]').removeClass('hidden'); + } + @endcan // Handle Events const Actions = new ActionsClass(parent, menu); - $(menu).find('li[data-action="move"]').unbind().on('click', e => { - e.preventDefault(); - Actions.move(); - }); + @can('move-files', $server) + $(menu).find('li[data-action="move"]').unbind().on('click', e => { + e.preventDefault(); + Actions.move(); + }); + @endcan - $(menu).find('li[data-action="copy"]').unbind().on('click', e => { - e.preventDefault(); - Actions.copy(); - }); + @can('copy-files', $server) + $(menu).find('li[data-action="copy"]').unbind().on('click', e => { + e.preventDefault(); + Actions.copy(); + }); + @endcan - $(menu).find('li[data-action="rename"]').unbind().on('click', e => { - e.preventDefault(); - Actions.rename(); - }); + @can('move-files', $server) + $(menu).find('li[data-action="rename"]').unbind().on('click', e => { + e.preventDefault(); + Actions.rename(); + }); + @endcan - $(menu).find('li[data-action="compress"]').unbind().on('click', e => { - e.preventDefault(); - Actions.compress(); - }); + @can('compress-files', $server) + $(menu).find('li[data-action="compress"]').unbind().on('click', e => { + e.preventDefault(); + Actions.compress(); + }); + @endcan - $(menu).find('li[data-action="decompress"]').unbind().on('click', e => { - e.preventDefault(); - Actions.decompress(); - }); + @can('decompress-files', $server) + $(menu).find('li[data-action="decompress"]').unbind().on('click', e => { + e.preventDefault(); + Actions.decompress(); + }); + @endcan - $(menu).find('li[data-action="folder"]').unbind().on('click', e => { - e.preventDefault(); - Actions.folder(); - }); + @can('create-files', $server) + $(menu).find('li[data-action="folder"]').unbind().on('click', e => { + e.preventDefault(); + Actions.folder(); + }); + @endcan - $(menu).find('li[data-action="download"]').unbind().on('click', e => { - e.preventDefault(); - Actions.download(); - }); + @can('download-files', $server) + $(menu).find('li[data-action="download"]').unbind().on('click', e => { + e.preventDefault(); + Actions.download(); + }); + @endcan $(menu).find('li[data-action="delete"]').unbind().on('click', e => { e.preventDefault(); diff --git a/resources/views/server/users/new.blade.php b/resources/views/server/users/new.blade.php index 44f35671f..c954bcd4b 100644 --- a/resources/views/server/users/new.blade.php +++ b/resources/views/server/users/new.blade.php @@ -96,7 +96,31 @@
+
+
+
+
+
+
+
+
diff --git a/resources/views/server/users/view.blade.php b/resources/views/server/users/view.blade.php index f9851934f..6ac4dc9a8 100644 --- a/resources/views/server/users/view.blade.php +++ b/resources/views/server/users/view.blade.php @@ -83,6 +83,29 @@

Allows user to save modified file contents.

+

Allows user to move and rename files and folders on the filesystem.

+ + +

+
+
+
+
+