This has been implicitely deprecated for a while with Share20 containing the new implementation. The only use was to determine whether remote sharing was enabled or not, which we can do much more easily. Signed-off-by: Carl Schwan <carlschwan@kde.org>pull/58593/head
parent
6f1fc07868
commit
af94028bdb
@ -1,228 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
namespace OCA\Files_Sharing\ShareBackend; |
||||
|
||||
use OC\Files\Filesystem; |
||||
use OC\Files\View; |
||||
use OCA\FederatedFileSharing\FederatedShareProvider; |
||||
use OCA\Files_Sharing\Helper; |
||||
use OCP\Files\NotFoundException; |
||||
use OCP\IDBConnection; |
||||
use OCP\Server; |
||||
use OCP\Share\IShare; |
||||
use OCP\Share_Backend_File_Dependent; |
||||
use Psr\Log\LoggerInterface; |
||||
|
||||
class File implements Share_Backend_File_Dependent { |
||||
public const FORMAT_SHARED_STORAGE = 0; |
||||
public const FORMAT_GET_FOLDER_CONTENTS = 1; |
||||
public const FORMAT_FILE_APP_ROOT = 2; |
||||
public const FORMAT_OPENDIR = 3; |
||||
public const FORMAT_GET_ALL = 4; |
||||
public const FORMAT_PERMISSIONS = 5; |
||||
public const FORMAT_TARGET_NAMES = 6; |
||||
|
||||
private $path; |
||||
|
||||
public function __construct( |
||||
private ?FederatedShareProvider $federatedShareProvider = null, |
||||
) { |
||||
if ($federatedShareProvider) { |
||||
$this->federatedShareProvider = $federatedShareProvider; |
||||
} else { |
||||
$this->federatedShareProvider = Server::get(FederatedShareProvider::class); |
||||
} |
||||
} |
||||
|
||||
public function isValidSource($itemSource, $uidOwner) { |
||||
try { |
||||
$path = Filesystem::getPath($itemSource); |
||||
// FIXME: attributes should not be set here, |
||||
// keeping this pattern for now to avoid unexpected |
||||
// regressions |
||||
$this->path = Filesystem::normalizePath(basename($path)); |
||||
return true; |
||||
} catch (NotFoundException $e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public function getFilePath($itemSource, $uidOwner) { |
||||
if (isset($this->path)) { |
||||
$path = $this->path; |
||||
$this->path = null; |
||||
return $path; |
||||
} else { |
||||
try { |
||||
$path = Filesystem::getPath($itemSource); |
||||
return $path; |
||||
} catch (NotFoundException $e) { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* create unique target |
||||
* |
||||
* @param string $itemSource |
||||
* @param string $shareWith |
||||
* @return string |
||||
*/ |
||||
public function generateTarget($itemSource, $shareWith) { |
||||
$shareFolder = Helper::getShareFolder(); |
||||
$target = Filesystem::normalizePath($shareFolder . '/' . basename($itemSource)); |
||||
|
||||
Filesystem::initMountPoints($shareWith); |
||||
$view = new View('/' . $shareWith . '/files'); |
||||
|
||||
if (!$view->is_dir($shareFolder)) { |
||||
$dir = ''; |
||||
$subdirs = explode('/', $shareFolder); |
||||
foreach ($subdirs as $subdir) { |
||||
$dir = $dir . '/' . $subdir; |
||||
if (!$view->is_dir($dir)) { |
||||
$view->mkdir($dir); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return Helper::generateUniqueTarget($target, $view); |
||||
} |
||||
|
||||
public function formatItems($items, $format, $parameters = null) { |
||||
if ($format === self::FORMAT_SHARED_STORAGE) { |
||||
// Only 1 item should come through for this format call |
||||
$item = array_shift($items); |
||||
return [ |
||||
'parent' => $item['parent'], |
||||
'path' => $item['path'], |
||||
'storage' => $item['storage'], |
||||
'permissions' => $item['permissions'], |
||||
'uid_owner' => $item['uid_owner'], |
||||
]; |
||||
} elseif ($format === self::FORMAT_GET_FOLDER_CONTENTS) { |
||||
$files = []; |
||||
foreach ($items as $item) { |
||||
$file = []; |
||||
$file['fileid'] = $item['file_source']; |
||||
$file['storage'] = $item['storage']; |
||||
$file['path'] = $item['file_target']; |
||||
$file['parent'] = $item['file_parent']; |
||||
$file['name'] = basename($item['file_target']); |
||||
$file['mimetype'] = $item['mimetype']; |
||||
$file['mimepart'] = $item['mimepart']; |
||||
$file['mtime'] = $item['mtime']; |
||||
$file['encrypted'] = $item['encrypted']; |
||||
$file['etag'] = $item['etag']; |
||||
$file['uid_owner'] = $item['uid_owner']; |
||||
$file['displayname_owner'] = $item['displayname_owner']; |
||||
|
||||
$storage = Filesystem::getStorage('/'); |
||||
$cache = $storage->getCache(); |
||||
$file['size'] = $item['size']; |
||||
$files[] = $file; |
||||
} |
||||
return $files; |
||||
} elseif ($format === self::FORMAT_OPENDIR) { |
||||
$files = []; |
||||
foreach ($items as $item) { |
||||
$files[] = basename($item['file_target']); |
||||
} |
||||
return $files; |
||||
} elseif ($format === self::FORMAT_GET_ALL) { |
||||
$ids = []; |
||||
foreach ($items as $item) { |
||||
$ids[] = $item['file_source']; |
||||
} |
||||
return $ids; |
||||
} elseif ($format === self::FORMAT_PERMISSIONS) { |
||||
$filePermissions = []; |
||||
foreach ($items as $item) { |
||||
$filePermissions[$item['file_source']] = $item['permissions']; |
||||
} |
||||
return $filePermissions; |
||||
} elseif ($format === self::FORMAT_TARGET_NAMES) { |
||||
$targets = []; |
||||
foreach ($items as $item) { |
||||
$targets[] = $item['file_target']; |
||||
} |
||||
return $targets; |
||||
} |
||||
return []; |
||||
} |
||||
|
||||
/** |
||||
* check if server2server share is enabled |
||||
* |
||||
* @param int $shareType |
||||
* @return boolean |
||||
*/ |
||||
public function isShareTypeAllowed($shareType) { |
||||
if ($shareType === IShare::TYPE_REMOTE) { |
||||
return $this->federatedShareProvider->isOutgoingServer2serverShareEnabled(); |
||||
} |
||||
|
||||
if ($shareType === IShare::TYPE_REMOTE_GROUP) { |
||||
return $this->federatedShareProvider->isOutgoingServer2serverGroupShareEnabled(); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* resolve reshares to return the correct source item |
||||
* @param array $source |
||||
* @return array source item |
||||
*/ |
||||
protected static function resolveReshares($source) { |
||||
if (isset($source['parent'])) { |
||||
$parent = $source['parent']; |
||||
while (isset($parent)) { |
||||
$qb = Server::get(IDBConnection::class)->getQueryBuilder(); |
||||
$qb->select('parent', 'uid_owner') |
||||
->from('share') |
||||
->where( |
||||
$qb->expr()->eq('id', $qb->createNamedParameter($parent)) |
||||
); |
||||
$result = $qb->executeQuery(); |
||||
$item = $result->fetchAssociative(); |
||||
$result->closeCursor(); |
||||
if (isset($item['parent'])) { |
||||
$parent = $item['parent']; |
||||
} else { |
||||
$fileOwner = $item['uid_owner']; |
||||
break; |
||||
} |
||||
} |
||||
} else { |
||||
$fileOwner = $source['uid_owner']; |
||||
} |
||||
if (isset($fileOwner)) { |
||||
$source['fileOwner'] = $fileOwner; |
||||
} else { |
||||
Server::get(LoggerInterface::class)->error('No owner found for reshare', ['app' => 'files_sharing']); |
||||
} |
||||
|
||||
return $source; |
||||
} |
||||
|
||||
/** |
||||
* @param string $target |
||||
* @param array $share |
||||
* @return array|false source item |
||||
*/ |
||||
public static function getSource($target, $share) { |
||||
if ($share['item_type'] === 'folder' && $target !== '') { |
||||
// note: in case of ext storage mount points the path might be empty |
||||
// which would cause a leading slash to appear |
||||
$share['path'] = ltrim($share['path'] . '/' . $target, '/'); |
||||
} |
||||
return self::resolveReshares($share); |
||||
} |
||||
} |
||||
@ -1,61 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
namespace OCA\Files_Sharing\ShareBackend; |
||||
|
||||
use OCP\IDBConnection; |
||||
use OCP\Server; |
||||
use OCP\Share_Backend_Collection; |
||||
|
||||
class Folder extends File implements Share_Backend_Collection { |
||||
public function getChildren($itemSource): array { |
||||
$children = []; |
||||
$parents = [$itemSource]; |
||||
|
||||
$qb = Server::get(IDBConnection::class)->getQueryBuilder(); |
||||
$qb->select('id') |
||||
->from('mimetypes') |
||||
->where( |
||||
$qb->expr()->eq('mimetype', $qb->createNamedParameter('httpd/unix-directory')) |
||||
); |
||||
$result = $qb->executeQuery(); |
||||
|
||||
if (($row = $result->fetchAssociative()) !== false) { |
||||
$mimetype = (int)$row['id']; |
||||
} else { |
||||
$mimetype = -1; |
||||
} |
||||
$result->closeCursor(); |
||||
|
||||
while (!empty($parents)) { |
||||
$qb = Server::get(IDBConnection::class)->getQueryBuilder(); |
||||
|
||||
$parents = array_map(function ($parent) use ($qb) { |
||||
return $qb->createNamedParameter($parent); |
||||
}, $parents); |
||||
|
||||
$qb->select('`fileid', 'name', '`mimetype') |
||||
->from('filecache') |
||||
->where( |
||||
$qb->expr()->in('parent', $parents) |
||||
); |
||||
|
||||
$result = $qb->executeQuery(); |
||||
|
||||
$parents = []; |
||||
foreach ($result->iterateAssociative() as $file) { |
||||
$children[] = ['source' => $file['fileid'], 'file_path' => $file['name']]; |
||||
// If a child folder is found look inside it |
||||
if ((int)$file['mimetype'] === $mimetype) { |
||||
$parents[] = $file['fileid']; |
||||
} |
||||
} |
||||
$result->closeCursor(); |
||||
} |
||||
return $children; |
||||
} |
||||
} |
||||
@ -1,36 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
namespace OCA\Files_Sharing\Tests; |
||||
|
||||
use OC\Files\Filesystem; |
||||
use OCA\Files_Sharing\Helper; |
||||
use OCP\IConfig; |
||||
use OCP\Server; |
||||
|
||||
/** |
||||
* Class HelperTest |
||||
*/ |
||||
#[\PHPUnit\Framework\Attributes\Group(name: 'DB')] |
||||
class HelperTest extends TestCase { |
||||
|
||||
/** |
||||
* test set and get share folder |
||||
*/ |
||||
public function testSetGetShareFolder(): void { |
||||
$this->assertSame('/', Helper::getShareFolder()); |
||||
|
||||
Helper::setShareFolder('/Shared/Folder'); |
||||
|
||||
$sharedFolder = Helper::getShareFolder(); |
||||
$this->assertSame('/Shared/Folder', Helper::getShareFolder()); |
||||
$this->assertTrue(Filesystem::is_dir($sharedFolder)); |
||||
|
||||
// cleanup |
||||
Server::get(IConfig::class)->deleteSystemValue('share_folder'); |
||||
} |
||||
} |
||||
@ -1,184 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
namespace OC\Share; |
||||
|
||||
use OCA\Files_Sharing\ShareBackend\File; |
||||
use OCP\IConfig; |
||||
use OCP\Server; |
||||
use OCP\Share_Backend; |
||||
use OCP\Util; |
||||
use Psr\Log\LoggerInterface; |
||||
|
||||
/** |
||||
* This class provides the ability for apps to share their content between users. |
||||
* Apps must create a backend class that implements OCP\Share_Backend and register it with this class. |
||||
* |
||||
* It provides the following hooks: |
||||
* - post_shared |
||||
*/ |
||||
class Share extends Constants { |
||||
/** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask |
||||
* Construct permissions for share() and setPermissions with Or (|) e.g. |
||||
* Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE |
||||
* |
||||
* Check if permission is granted with And (&) e.g. Check if delete is |
||||
* granted: if ($permissions & PERMISSION_DELETE) |
||||
* |
||||
* Remove permissions with And (&) and Not (~) e.g. Remove the update |
||||
* permission: $permissions &= ~PERMISSION_UPDATE |
||||
* |
||||
* Apps are required to handle permissions on their own, this class only |
||||
* stores and manages the permissions of shares |
||||
* |
||||
* @see lib/public/Constants.php |
||||
*/ |
||||
|
||||
/** |
||||
* Register a sharing backend class that implements OCP\Share_Backend for an item type |
||||
* |
||||
* @param string $itemType Item type |
||||
* @param string $class Backend class |
||||
* @param string $collectionOf (optional) Depends on item type |
||||
* @param array $supportedFileExtensions (optional) List of supported file extensions if this item type depends on files |
||||
* @return boolean true if backend is registered or false if error |
||||
*/ |
||||
public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) { |
||||
if (Server::get(IConfig::class)->getAppValue('core', 'shareapi_enabled', 'yes') == 'yes') { |
||||
if (!isset(self::$backendTypes[$itemType])) { |
||||
self::$backendTypes[$itemType] = [ |
||||
'class' => $class, |
||||
'collectionOf' => $collectionOf, |
||||
'supportedFileExtensions' => $supportedFileExtensions |
||||
]; |
||||
return true; |
||||
} |
||||
Server::get(LoggerInterface::class)->warning( |
||||
'Sharing backend ' . $class . ' not registered, ' . self::$backendTypes[$itemType]['class'] |
||||
. ' is already registered for ' . $itemType, |
||||
['app' => 'files_sharing']); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Get the backend class for the specified item type |
||||
* |
||||
* @param string $itemType |
||||
* @return Share_Backend |
||||
* @throws \Exception |
||||
*/ |
||||
public static function getBackend($itemType) { |
||||
$l = Util::getL10N('lib'); |
||||
$logger = Server::get(LoggerInterface::class); |
||||
if (isset(self::$backends[$itemType])) { |
||||
return self::$backends[$itemType]; |
||||
} elseif (isset(self::$backendTypes[$itemType]['class'])) { |
||||
$class = self::$backendTypes[$itemType]['class']; |
||||
if (class_exists($class)) { |
||||
self::$backends[$itemType] = new $class; |
||||
if (!(self::$backends[$itemType] instanceof Share_Backend)) { |
||||
$message = 'Sharing backend %s must implement the interface OCP\Share_Backend'; |
||||
$message_t = $l->t('Sharing backend %s must implement the interface OCP\Share_Backend', [$class]); |
||||
$logger->error(sprintf($message, $class), ['app' => 'OCP\Share']); |
||||
throw new \Exception($message_t); |
||||
} |
||||
return self::$backends[$itemType]; |
||||
} else { |
||||
$message = 'Sharing backend %s not found'; |
||||
$message_t = $l->t('Sharing backend %s not found', [$class]); |
||||
$logger->error(sprintf($message, $class), ['app' => 'OCP\Share']); |
||||
throw new \Exception($message_t); |
||||
} |
||||
} |
||||
$message = 'Sharing backend for %s not found'; |
||||
$message_t = $l->t('Sharing backend for %s not found', [$itemType]); |
||||
$logger->error(sprintf($message, $itemType), ['app' => 'OCP\Share']); |
||||
throw new \Exception($message_t); |
||||
} |
||||
|
||||
/** |
||||
* Check if resharing is allowed |
||||
* |
||||
* @return boolean true if allowed or false |
||||
* |
||||
* Resharing is allowed by default if not configured |
||||
*/ |
||||
public static function isResharingAllowed() { |
||||
if (!isset(self::$isResharingAllowed)) { |
||||
if (Server::get(IConfig::class)->getAppValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') { |
||||
self::$isResharingAllowed = true; |
||||
} else { |
||||
self::$isResharingAllowed = false; |
||||
} |
||||
} |
||||
return self::$isResharingAllowed; |
||||
} |
||||
|
||||
/** |
||||
* group items with link to the same source |
||||
* |
||||
* @param array $items |
||||
* @param string $itemType |
||||
* @return array of grouped items |
||||
*/ |
||||
protected static function groupItems($items, $itemType) { |
||||
$fileSharing = $itemType === 'file' || $itemType === 'folder'; |
||||
|
||||
$result = []; |
||||
|
||||
foreach ($items as $item) { |
||||
$grouped = false; |
||||
foreach ($result as $key => $r) { |
||||
// for file/folder shares we need to compare file_source, otherwise we compare item_source |
||||
// only group shares if they already point to the same target, otherwise the file where shared |
||||
// before grouping of shares was added. In this case we don't group them to avoid confusions |
||||
if (($fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) |
||||
|| (!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) { |
||||
// add the first item to the list of grouped shares |
||||
if (!isset($result[$key]['grouped'])) { |
||||
$result[$key]['grouped'][] = $result[$key]; |
||||
} |
||||
$result[$key]['permissions'] = (int)$item['permissions'] | (int)$r['permissions']; |
||||
$result[$key]['grouped'][] = $item; |
||||
$grouped = true; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (!$grouped) { |
||||
$result[] = $item; |
||||
} |
||||
} |
||||
|
||||
return $result; |
||||
} |
||||
|
||||
/** |
||||
* remove protocol from URL |
||||
* |
||||
* @param string $url |
||||
* @return string |
||||
*/ |
||||
public static function removeProtocolFromUrl($url) { |
||||
if (str_starts_with($url, 'https://')) { |
||||
return substr($url, strlen('https://')); |
||||
} elseif (str_starts_with($url, 'http://')) { |
||||
return substr($url, strlen('http://')); |
||||
} |
||||
|
||||
return $url; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @return int |
||||
*/ |
||||
public static function getExpireInterval() { |
||||
return (int)Server::get(IConfig::class)->getAppValue('core', 'shareapi_expire_after_n_days', '7'); |
||||
} |
||||
} |
||||
@ -1,78 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
// use OCP namespace for all classes that are considered public. |
||||
// This means that they should be used by apps instead of the internal Nextcloud classes |
||||
|
||||
namespace OCP; |
||||
|
||||
/** |
||||
* Interface that apps must implement to share content. |
||||
* @since 5.0.0 |
||||
*/ |
||||
interface Share_Backend { |
||||
/** |
||||
* Check if this $itemSource exist for the user |
||||
* @param string $itemSource |
||||
* @param string $uidOwner Owner of the item |
||||
* @return boolean|null Source |
||||
* |
||||
* Return false if the item does not exist for the user |
||||
* @since 5.0.0 |
||||
*/ |
||||
public function isValidSource($itemSource, $uidOwner); |
||||
|
||||
/** |
||||
* Get a unique name of the item for the specified user |
||||
* @param string $itemSource |
||||
* @param string|false $shareWith User the item is being shared with |
||||
* @return string Target name |
||||
* |
||||
* This function needs to verify that the user does not already have an item with this name. |
||||
* If it does generate a new name e.g. name_# |
||||
* @since 5.0.0 |
||||
* @deprecated 31.0.0 |
||||
*/ |
||||
public function generateTarget($itemSource, $shareWith); |
||||
|
||||
/** |
||||
* Converts the shared item sources back into the item in the specified format |
||||
* @param array $items Shared items |
||||
* @param int $format |
||||
* @return array |
||||
* |
||||
* The items array is a 3-dimensional array with the item_source as the |
||||
* first key and the share id as the second key to an array with the share |
||||
* info. |
||||
* |
||||
* The key/value pairs included in the share info depend on the function originally called: |
||||
* If called by getItem(s)Shared: id, item_type, item, item_source, |
||||
* share_type, share_with, permissions, stime, file_source |
||||
* |
||||
* If called by getItem(s)SharedWith: id, item_type, item, item_source, |
||||
* item_target, share_type, share_with, permissions, stime, file_source, |
||||
* file_target |
||||
* |
||||
* This function allows the backend to control the output of shared items with custom formats. |
||||
* It is only called through calls to the public getItem(s)Shared(With) functions. |
||||
* @since 5.0.0 |
||||
*/ |
||||
public function formatItems($items, $format, $parameters = null); |
||||
|
||||
/** |
||||
* Check if a given share type is allowed by the back-end |
||||
* |
||||
* @param int $shareType share type |
||||
* @return boolean |
||||
* |
||||
* The back-end can enable/disable specific share types. Just return true if |
||||
* the back-end doesn't provide any specific settings for it and want to allow |
||||
* all share types defined by the share API |
||||
* @since 8.0.0 |
||||
*/ |
||||
public function isShareTypeAllowed($shareType); |
||||
} |
||||
@ -1,26 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
// use OCP namespace for all classes that are considered public. |
||||
// This means that they should be used by apps instead of the internal Nextcloud classes |
||||
|
||||
namespace OCP; |
||||
|
||||
/** |
||||
* Interface for collections of items implemented by another share backend. |
||||
* Extends the Share_Backend interface. |
||||
* @since 5.0.0 |
||||
*/ |
||||
interface Share_Backend_Collection extends Share_Backend { |
||||
/** |
||||
* Get the sources of the children of the item |
||||
* @param string $itemSource |
||||
* @return array Returns an array of children each inside an array with the keys: source, target, and file_path if applicable |
||||
* @since 5.0.0 |
||||
*/ |
||||
public function getChildren($itemSource); |
||||
} |
||||
@ -1,27 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-only |
||||
*/ |
||||
// use OCP namespace for all classes that are considered public. |
||||
// This means that they should be used by apps instead of the internal Nextcloud classes |
||||
|
||||
namespace OCP; |
||||
|
||||
/** |
||||
* Interface for share backends that share content that is dependent on files. |
||||
* Extends the Share_Backend interface. |
||||
* @since 5.0.0 |
||||
*/ |
||||
interface Share_Backend_File_Dependent extends Share_Backend { |
||||
/** |
||||
* Get the file path of the item |
||||
* @param string $itemSource |
||||
* @param string $uidOwner User that is the owner of shared item |
||||
* @return string|false |
||||
* @since 5.0.0 |
||||
*/ |
||||
public function getFilePath($itemSource, $uidOwner); |
||||
} |
||||
@ -1,86 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
|
||||
namespace Test\Share; |
||||
|
||||
use OC\Share20\Manager; |
||||
use OCP\Server; |
||||
use OCP\Share\IShare; |
||||
use OCP\Share_Backend; |
||||
|
||||
class Backend implements Share_Backend { |
||||
public const FORMAT_SOURCE = 0; |
||||
public const FORMAT_TARGET = 1; |
||||
public const FORMAT_PERMISSIONS = 2; |
||||
|
||||
private $testItem1 = 'test.txt'; |
||||
private $testItem2 = 'share.txt'; |
||||
private $testId = 1; |
||||
|
||||
public function isValidSource($itemSource, $uidOwner) { |
||||
if ($itemSource == $this->testItem1 || $itemSource == $this->testItem2 || $itemSource == 1) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public function generateTarget($itemSource, $shareWith, $exclude = null) { |
||||
// Always make target be test.txt to cause conflicts |
||||
|
||||
if (substr($itemSource, 0, strlen('test')) !== 'test') { |
||||
$target = 'test.txt'; |
||||
} else { |
||||
$target = $itemSource; |
||||
} |
||||
|
||||
|
||||
$shareManager = Server::get(Manager::class); |
||||
$shares = array_merge( |
||||
$shareManager->getSharedWith($shareWith, IShare::TYPE_USER), |
||||
$shareManager->getSharedWith($shareWith, IShare::TYPE_GROUP), |
||||
); |
||||
|
||||
$knownTargets = []; |
||||
foreach ($shares as $share) { |
||||
$knownTargets[] = $share['item_target']; |
||||
} |
||||
|
||||
|
||||
if (in_array($target, $knownTargets)) { |
||||
$pos = strrpos($target, '.'); |
||||
$name = substr($target, 0, $pos); |
||||
$ext = substr($target, $pos); |
||||
$append = ''; |
||||
$i = 1; |
||||
while (in_array($name . $append . $ext, $knownTargets)) { |
||||
$append = $i; |
||||
$i++; |
||||
} |
||||
$target = $name . $append . $ext; |
||||
} |
||||
|
||||
return $target; |
||||
} |
||||
|
||||
public function formatItems($items, $format, $parameters = null) { |
||||
$testItems = []; |
||||
foreach ($items as $item) { |
||||
if ($format === self::FORMAT_SOURCE) { |
||||
$testItems[] = $item['item_source']; |
||||
} elseif ($format === self::FORMAT_TARGET) { |
||||
$testItems[] = $item['item_target']; |
||||
} elseif ($format === self::FORMAT_PERMISSIONS) { |
||||
$testItems[] = $item['permissions']; |
||||
} |
||||
} |
||||
return $testItems; |
||||
} |
||||
|
||||
public function isShareTypeAllowed($shareType) { |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,235 +0,0 @@ |
||||
<?php |
||||
|
||||
/** |
||||
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors |
||||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc. |
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
||||
*/ |
||||
|
||||
namespace Test\Share; |
||||
|
||||
use OC\Share\Share; |
||||
use OC\SystemConfig; |
||||
use OCP\Constants; |
||||
use OCP\IConfig; |
||||
use OCP\IDBConnection; |
||||
use OCP\IGroup; |
||||
use OCP\IGroupManager; |
||||
use OCP\IUser; |
||||
use OCP\IUserManager; |
||||
use OCP\Server; |
||||
|
||||
/** |
||||
* Class Test_Share |
||||
*/ |
||||
#[\PHPUnit\Framework\Attributes\Group('DB')] |
||||
class ShareTest extends \Test\TestCase { |
||||
protected $itemType; |
||||
|
||||
protected IUser $user1; |
||||
protected IUser $user2; |
||||
protected IUser $user3; |
||||
protected IUser $user4; |
||||
protected IUser $user5; |
||||
protected IUser $user6; |
||||
protected IUser $groupAndUser_user; |
||||
|
||||
protected IGroup $group1; |
||||
protected IGroup $group2; |
||||
protected IGroup $groupAndUser_group; |
||||
|
||||
protected string $resharing; |
||||
protected string $dateInFuture; |
||||
protected string $dateInPast; |
||||
|
||||
protected IGroupManager $groupManager; |
||||
protected IUserManager $userManager; |
||||
private IDBConnection $connection; |
||||
|
||||
protected function setUp(): void { |
||||
parent::setUp(); |
||||
|
||||
$this->groupManager = Server::get(IGroupManager::class); |
||||
$this->userManager = Server::get(IUserManager::class); |
||||
|
||||
$this->userManager->clearBackends(); |
||||
$this->userManager->registerBackend(new \Test\Util\User\Dummy()); |
||||
|
||||
$this->user1 = $this->userManager->createUser($this->getUniqueID('user1_'), 'pass'); |
||||
$this->user2 = $this->userManager->createUser($this->getUniqueID('user2_'), 'pass'); |
||||
$this->user3 = $this->userManager->createUser($this->getUniqueID('user3_'), 'pass'); |
||||
$this->user4 = $this->userManager->createUser($this->getUniqueID('user4_'), 'pass'); |
||||
$this->user5 = $this->userManager->createUser($this->getUniqueID('user5_'), 'pass'); |
||||
$this->user6 = $this->userManager->createUser($this->getUniqueID('user6_'), 'pass'); |
||||
$groupAndUserId = $this->getUniqueID('groupAndUser_'); |
||||
$this->groupAndUser_user = $this->userManager->createUser($groupAndUserId, 'pass'); |
||||
\OC_User::setUserId($this->user1->getUID()); |
||||
|
||||
$this->groupManager->clearBackends(); |
||||
$this->groupManager->addBackend(new \Test\Util\Group\Dummy()); |
||||
$this->group1 = $this->groupManager->createGroup($this->getUniqueID('group1_')); |
||||
$this->group2 = $this->groupManager->createGroup($this->getUniqueID('group2_')); |
||||
$this->groupAndUser_group = $this->groupManager->createGroup($groupAndUserId); |
||||
$this->connection = Server::get(IDBConnection::class); |
||||
|
||||
$this->group1->addUser($this->user1); |
||||
$this->group1->addUser($this->user2); |
||||
$this->group1->addUser($this->user3); |
||||
$this->group2->addUser($this->user2); |
||||
$this->group2->addUser($this->user4); |
||||
$this->groupAndUser_group->addUser($this->user2); |
||||
$this->groupAndUser_group->addUser($this->user3); |
||||
|
||||
Share::registerBackend('test', 'Test\Share\Backend'); |
||||
\OC_Hook::clear('OCP\\Share'); |
||||
\OC::registerShareHooks(Server::get(SystemConfig::class)); |
||||
$this->resharing = Server::get(IConfig::class)->getAppValue('core', 'shareapi_allow_resharing', 'yes'); |
||||
Server::get(IConfig::class)->setAppValue('core', 'shareapi_allow_resharing', 'yes'); |
||||
|
||||
// 20 Minutes in the past, 20 minutes in the future. |
||||
$now = time(); |
||||
$dateFormat = 'Y-m-d H:i:s'; |
||||
$this->dateInPast = date($dateFormat, $now - 20 * 60); |
||||
$this->dateInFuture = date($dateFormat, $now + 20 * 60); |
||||
} |
||||
|
||||
protected function tearDown(): void { |
||||
$query = $this->connection->getQueryBuilder(); |
||||
$query->delete('share')->andWhere($query->expr()->eq('item_type', $query->createNamedParameter('test'))); |
||||
$query->executeStatement(); |
||||
Server::get(IConfig::class)->setAppValue('core', 'shareapi_allow_resharing', $this->resharing); |
||||
|
||||
$this->user1->delete(); |
||||
$this->user2->delete(); |
||||
$this->user3->delete(); |
||||
$this->user4->delete(); |
||||
$this->user5->delete(); |
||||
$this->user6->delete(); |
||||
$this->groupAndUser_user->delete(); |
||||
|
||||
$this->group1->delete(); |
||||
$this->group2->delete(); |
||||
$this->groupAndUser_group->delete(); |
||||
|
||||
$this->logout(); |
||||
parent::tearDown(); |
||||
} |
||||
|
||||
public function verifyResult($result, $expected) { |
||||
foreach ($result as $r) { |
||||
if (in_array($r['item_target'], $expected)) { |
||||
$key = array_search($r['item_target'], $expected); |
||||
unset($expected[$key]); |
||||
} |
||||
} |
||||
$this->assertEmpty($expected, 'did not found all expected values'); |
||||
} |
||||
|
||||
/** |
||||
* @param string $url |
||||
* @param string $expectedResult |
||||
*/ |
||||
#[\PHPUnit\Framework\Attributes\DataProvider('urls')] |
||||
public function testRemoveProtocolFromUrl($url, $expectedResult): void { |
||||
$share = new Share(); |
||||
$result = self::invokePrivate($share, 'removeProtocolFromUrl', [$url]); |
||||
$this->assertSame($expectedResult, $result); |
||||
} |
||||
|
||||
public static function urls(): array { |
||||
return [ |
||||
['http://owncloud.org', 'owncloud.org'], |
||||
['https://owncloud.org', 'owncloud.org'], |
||||
['owncloud.org', 'owncloud.org'], |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* @param array $ungrouped |
||||
* @param array $grouped |
||||
*/ |
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataProviderTestGroupItems')] |
||||
public function testGroupItems($ungrouped, $grouped): void { |
||||
$result = DummyShareClass::groupItemsTest($ungrouped); |
||||
|
||||
$this->compareArrays($grouped, $result); |
||||
} |
||||
|
||||
public function compareArrays($result, $expectedResult) { |
||||
foreach ($expectedResult as $key => $value) { |
||||
if (is_array($value)) { |
||||
$this->compareArrays($result[$key], $value); |
||||
} else { |
||||
$this->assertSame($value, $result[$key]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static function dataProviderTestGroupItems(): array { |
||||
return [ |
||||
// one array with one share |
||||
[ |
||||
[ // input |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_ALL, 'item_target' => 't1']], |
||||
[ // expected result |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_ALL, 'item_target' => 't1']]], |
||||
// two shares both point to the same source |
||||
[ |
||||
[ // input |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ, 'item_target' => 't1'], |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_UPDATE, 'item_target' => 't1'], |
||||
], |
||||
[ // expected result |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, 'item_target' => 't1', |
||||
'grouped' => [ |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ, 'item_target' => 't1'], |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_UPDATE, 'item_target' => 't1'], |
||||
] |
||||
], |
||||
] |
||||
], |
||||
// two shares both point to the same source but with different targets |
||||
[ |
||||
[ // input |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ, 'item_target' => 't1'], |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_UPDATE, 'item_target' => 't2'], |
||||
], |
||||
[ // expected result |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ, 'item_target' => 't1'], |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_UPDATE, 'item_target' => 't2'], |
||||
] |
||||
], |
||||
// three shares two point to the same source |
||||
[ |
||||
[ // input |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ, 'item_target' => 't1'], |
||||
['item_source' => 2, 'permissions' => Constants::PERMISSION_CREATE, 'item_target' => 't2'], |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_UPDATE, 'item_target' => 't1'], |
||||
], |
||||
[ // expected result |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, 'item_target' => 't1', |
||||
'grouped' => [ |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_READ, 'item_target' => 't1'], |
||||
['item_source' => 1, 'permissions' => Constants::PERMISSION_UPDATE, 'item_target' => 't1'], |
||||
] |
||||
], |
||||
['item_source' => 2, 'permissions' => Constants::PERMISSION_CREATE, 'item_target' => 't2'], |
||||
] |
||||
], |
||||
]; |
||||
} |
||||
} |
||||
|
||||
class DummyShareClass extends Share { |
||||
public static function groupItemsTest($items) { |
||||
return parent::groupItems($items, 'test'); |
||||
} |
||||
} |
||||
|
||||
class DummyHookListener { |
||||
public static $shareType = null; |
||||
|
||||
public static function listen($params) { |
||||
self::$shareType = $params['shareType']; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue