mirror of
https://github.com/filegator/filegator.git
synced 2025-08-12 03:44:21 +02:00
Added chmod perm, modal to change, api with local/ftp/sftp (#399)
Read a fill current permissions for local driver Finished permissions for ftp driver, read and change Read permissions for sftp adapter Created FilegatorFtp for a cleaner permissions integration Implemented recursive chmod options for files/folders Modified tests to cover permissions Lint frontend permissions component
This commit is contained in:
@@ -218,7 +218,7 @@ class LDAP implements Service, AuthInterface
|
||||
// ...but not for admins
|
||||
if ($user['role'] == 'admin'){
|
||||
$user['homedir'] = '/';
|
||||
$user['permissions'] = 'read|write|upload|download|batchdownload|zip';
|
||||
$user['permissions'] = 'read|write|upload|download|batchdownload|zip|chmod';
|
||||
}
|
||||
|
||||
if(is_array($user) && !empty($user)) $users[] = $user;
|
||||
|
@@ -24,7 +24,7 @@ class User implements \JsonSerializable
|
||||
|
||||
protected $available_roles = ['guest', 'user', 'admin'];
|
||||
|
||||
protected $available_permissions = ['read', 'write', 'upload', 'download', 'batchdownload', 'zip'];
|
||||
protected $available_permissions = ['read', 'write', 'upload', 'download', 'batchdownload', 'zip', 'chmod'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
91
backend/Services/Storage/Adapters/FilegatorFtp.php
Normal file
91
backend/Services/Storage/Adapters/FilegatorFtp.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the FileGator package.
|
||||
*
|
||||
* (c) Milos Stojanovic <alcalbg@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE file
|
||||
*/
|
||||
|
||||
namespace Filegator\Services\Storage\Adapters;
|
||||
|
||||
use League\Flysystem\Adapter\Ftp;
|
||||
use League\Flysystem\NotSupportedException;
|
||||
|
||||
class FilegatorFtp extends Ftp
|
||||
{
|
||||
|
||||
/**
|
||||
* Normalize a file entry.
|
||||
*
|
||||
* @param string $item
|
||||
* @param string $base
|
||||
*
|
||||
* @return array normalized file array
|
||||
*
|
||||
* @throws NotSupportedException
|
||||
*/
|
||||
protected function normalizeObject($item, $base)
|
||||
{
|
||||
$systemType = $this->systemType ?: $this->detectSystemType($item);
|
||||
|
||||
if ($systemType === 'unix') {
|
||||
$result = $this->normalizeUnixObject($item, $base);
|
||||
return $this->afterNormalizeUnixObject($result, $item, $base);
|
||||
} elseif ($systemType === 'windows') {
|
||||
$result = $this->normalizeWindowsObject($item, $base);
|
||||
return $this->afterNormalizeWindowsObject($result, $item, $base);
|
||||
}
|
||||
|
||||
throw NotSupportedException::forFtpSystemType($systemType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a Unix file entry, with permissions.
|
||||
*
|
||||
* Given $item contains:
|
||||
* '-rw-r--r-- 1 ftp ftp 409 Aug 19 09:01 file1.txt'
|
||||
*
|
||||
* This function will return:
|
||||
* [
|
||||
* 'type' => 'file',
|
||||
* 'path' => 'file1.txt',
|
||||
* 'visibility' => 'public',
|
||||
* 'size' => 409,
|
||||
* 'timestamp' => 1566205260,
|
||||
* 'permissions' => 644
|
||||
* ]
|
||||
*
|
||||
* @param array $result original normalized file array
|
||||
* @param string $item
|
||||
* @param string $base
|
||||
*
|
||||
* @return array normalized file array
|
||||
*/
|
||||
protected function afterNormalizeUnixObject($result, $item, $base)
|
||||
{
|
||||
$item = preg_replace('#\s+#', ' ', trim($item), 7);
|
||||
list($permissions, /* $number */, /* $owner */, /* $group */, $size, $month, $day, $timeOrYear, $name) = explode(' ', $item, 9);
|
||||
$permissions = $this->normalizePermissions($permissions);
|
||||
|
||||
$result['permissions'] = decoct($permissions);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a Windows/DOS file entry, with permissions.
|
||||
*
|
||||
* @param array $result original normalized file array
|
||||
* @param string $item
|
||||
* @param string $base
|
||||
*
|
||||
* @return array normalized file array
|
||||
*/
|
||||
protected function afterNormalizeWindowsObject($result, $item, $base)
|
||||
{
|
||||
$result['permissions'] = 777;
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@@ -23,7 +23,7 @@ class DirectoryCollection implements \JsonSerializable
|
||||
$this->location = $location;
|
||||
}
|
||||
|
||||
public function addFile(string $type, string $path, string $name, int $size, int $timestamp)
|
||||
public function addFile(string $type, string $path, string $name, int $size, int $timestamp, int $permissions)
|
||||
{
|
||||
if (! in_array($type, ['dir', 'file', 'back'])) {
|
||||
throw new \Exception('Invalid file type.');
|
||||
@@ -35,6 +35,7 @@ class DirectoryCollection implements \JsonSerializable
|
||||
'name' => $name,
|
||||
'size' => $size,
|
||||
'time' => $timestamp,
|
||||
'permissions' => $permissions,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,7 @@ namespace Filegator\Services\Storage;
|
||||
|
||||
use Filegator\Services\Service;
|
||||
use League\Flysystem\Filesystem as Flysystem;
|
||||
use League\Flysystem\Util;
|
||||
|
||||
class Filesystem implements Service
|
||||
{
|
||||
@@ -176,6 +177,72 @@ class Filesystem implements Service
|
||||
|
||||
return $this->storage->putStream($destination, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change file permissions one item, with optional recursion
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $permissions
|
||||
* @param null|'all'|'folders'|'files' $recursive
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function chmod(string $path, int $permissions, string $recursive = null)
|
||||
{
|
||||
$path = $this->applyPathPrefix($path);
|
||||
$path = Util::normalizePath($path);
|
||||
$adapter = $this->storage->getAdapter();
|
||||
|
||||
$mainResult = $this->chmodItem($path, $permissions);
|
||||
if ($recursive !== null) {
|
||||
if (method_exists($adapter, 'setRecurseManually')) {
|
||||
$adapter->setRecurseManually(true); // this is needed for ftp driver
|
||||
}
|
||||
$contents = $this->storage->listContents($path, true);
|
||||
foreach ($contents as $item) {
|
||||
try {
|
||||
if ($item['type'] == 'dir' && ($recursive == 'all' || $recursive == 'folders')) {
|
||||
$this->chmodItem($item['path'], $permissions);
|
||||
}
|
||||
if ($item['type'] == 'file' && ($recursive == 'all' || $recursive == 'files')) {
|
||||
$this->chmodItem($item['path'], $permissions);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mainResult;
|
||||
}
|
||||
/**
|
||||
* Change file permissions for a single item
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $permissions
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function chmodItem(string $path, int $permissions)
|
||||
{
|
||||
$adapter = $this->storage->getAdapter();
|
||||
|
||||
switch (get_class($adapter)) {
|
||||
case 'League\Flysystem\Adapter\Local':
|
||||
$absolutePath = $adapter->applyPathPrefix($path);
|
||||
return chmod($absolutePath, octdec($permissions));
|
||||
break;
|
||||
case 'League\Flysystem\Sftp\SftpAdapter':
|
||||
return $adapter->getConnection()->chmod($path, octdec($permissions));
|
||||
break;
|
||||
case 'Filegator\Services\Storage\Adapters\FilegatorFtp':
|
||||
return ftp_chmod($adapter->getConnection(), octdec($permissions), $path) !== false;
|
||||
break;
|
||||
default:
|
||||
throw new \Exception('Selected adapter does not support unix permissions');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function setPathPrefix(string $path_prefix)
|
||||
{
|
||||
@@ -204,16 +271,39 @@ class Filesystem implements Service
|
||||
$dirname = isset($entry['dirname']) ? $entry['dirname'] : $path;
|
||||
$size = isset($entry['size']) ? $entry['size'] : 0;
|
||||
$timestamp = isset($entry['timestamp']) ? $entry['timestamp'] : 0;
|
||||
$permissions = $this->getPermissions($entry);
|
||||
|
||||
$collection->addFile($entry['type'], $userpath, $name, $size, $timestamp);
|
||||
$collection->addFile($entry['type'], $userpath, $name, $size, $timestamp, $permissions);
|
||||
}
|
||||
|
||||
if (! $recursive && $this->addSeparators($path) !== $this->separator) {
|
||||
$collection->addFile('back', $this->getParent($path), '..', 0, 0);
|
||||
$collection->addFile('back', $this->getParent($path), '..', 0, 0, -1);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
protected function getPermissions(array $entry): int
|
||||
{
|
||||
$adapter = $this->storage->getAdapter();
|
||||
$path = $entry['path'];
|
||||
|
||||
switch (get_class($adapter)) {
|
||||
case 'League\Flysystem\Adapter\Local':
|
||||
$path = $adapter->applyPathPrefix($path); // get the full path
|
||||
$permissions = substr(sprintf('%o', fileperms($path)), -3);
|
||||
return $permissions;
|
||||
break;
|
||||
case 'League\Flysystem\Sftp\SftpAdapter':
|
||||
$stat = $adapter->getConnection()->stat($path);
|
||||
return $stat && isset($stat['permissions']) ? substr(decoct($stat['permissions']), -3) : -1;
|
||||
break;
|
||||
case 'Filegator\Services\Storage\Adapters\FilegatorFtp':
|
||||
return isset($entry['permissions']) ? $entry['permissions'] : -1;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected function upcountCallback($matches)
|
||||
{
|
||||
|
Reference in New Issue
Block a user