Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@
'OCP\\Share\\Exceptions\\ShareTokenException' => $baseDir . '/lib/public/Share/Exceptions/ShareTokenException.php',
'OCP\\Share\\IAttributes' => $baseDir . '/lib/public/Share/IAttributes.php',
'OCP\\Share\\IManager' => $baseDir . '/lib/public/Share/IManager.php',
'OCP\\Share\\IPartialShareProvider' => $baseDir . '/lib/public/Share/IPartialShareProvider.php',
'OCP\\Share\\IProviderFactory' => $baseDir . '/lib/public/Share/IProviderFactory.php',
'OCP\\Share\\IPublicShareTemplateFactory' => $baseDir . '/lib/public/Share/IPublicShareTemplateFactory.php',
'OCP\\Share\\IPublicShareTemplateProvider' => $baseDir . '/lib/public/Share/IPublicShareTemplateProvider.php',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Share\\Exceptions\\ShareTokenException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareTokenException.php',
'OCP\\Share\\IAttributes' => __DIR__ . '/../../..' . '/lib/public/Share/IAttributes.php',
'OCP\\Share\\IManager' => __DIR__ . '/../../..' . '/lib/public/Share/IManager.php',
'OCP\\Share\\IPartialShareProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IPartialShareProvider.php',
'OCP\\Share\\IProviderFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IProviderFactory.php',
'OCP\\Share\\IPublicShareTemplateFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IPublicShareTemplateFactory.php',
'OCP\\Share\\IPublicShareTemplateProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IPublicShareTemplateProvider.php',
Expand Down
110 changes: 109 additions & 1 deletion lib/private/Share20/DefaultShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IAttributes;
use OCP\Share\IManager;
use OCP\Share\IPartialShareProvider;
use OCP\Share\IShare;
use OCP\Share\IShareProviderGetUsers;
use OCP\Share\IShareProviderSupportsAccept;
Expand All @@ -49,7 +50,8 @@ class DefaultShareProvider implements
IShareProviderWithNotification,
IShareProviderSupportsAccept,
IShareProviderSupportsAllSharesInFolder,
IShareProviderGetUsers {
IShareProviderGetUsers,
IPartialShareProvider {
public function __construct(
private IDBConnection $dbConn,
private IUserManager $userManager,
Expand Down Expand Up @@ -953,6 +955,112 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
return $shares;
}

/**
* @inheritDoc
*/
public function getSharedWithByPath(
string $userId,
int $shareType,
string $path,
bool $forChildren,
int $limit,
int $offset,
): iterable {
$shares = [];

if ($shareType === IShare::TYPE_USER) {
//Get shares directly with this user
$qb = $this->dbConn->getQueryBuilder();
$qb->select('s.*',
'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
)
->selectAlias('st.id', 'storage_string_id')
->from('share', 's')
->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));

// Order by id
$qb->orderBy('s.id');

// Set limit and offset
if ($limit !== -1) {
$qb->setMaxResults($limit);
}
$qb->setFirstResult($offset);

$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));

if ($forChildren) {
$qb->andWhere($qb->expr()->like('file_target', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($path) . '_%')));
} else {
$qb->andWhere($qb->expr()->eq('file_target', $qb->createNamedParameter($path)));
}

$cursor = $qb->executeQuery();

while ($data = $cursor->fetch()) {
if ($data['fileid'] && $data['path'] === null) {
$data['path'] = (string)$data['path'];
$data['name'] = (string)$data['name'];
$data['checksum'] = (string)$data['checksum'];
}
if ($this->isAccessibleResult($data)) {
$shares[] = $this->createShare($data);
}
}
$cursor->closeCursor();
} elseif ($shareType === IShare::TYPE_GROUP) {
// get the parent share info (s) along with the child one (s2)
$qb = $this->dbConn->getQueryBuilder();
$qb->select('s.*', 's2.permissions AS s2_permissions', 's2.accepted AS s2_accepted', 's2.file_target AS s2_file_target', 's2.parent AS s2_parent',
'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
)
->selectAlias('st.id', 'storage_string_id')
->from('share', 's2')
->leftJoin('s2', 'filecache', 'f', $qb->expr()->eq('s2.file_source', 'f.fileid'))
->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
->leftJoin('s2', 'share', 's', $qb->expr()->eq('s2.parent', 's.id'))
->where($qb->expr()->eq('s2.share_with', $qb->createNamedParameter($userId)))
->andWhere($qb->expr()->eq('s2.share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
->andWhere($qb->expr()->in('s2.item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
->orderBy('s2.id')
->setFirstResult($offset);
if ($limit !== -1) {
$qb->setMaxResults($limit);
}

if ($forChildren) {
$qb->andWhere($qb->expr()->like('s2.file_target', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($path) . '_%')));
} else {
$qb->andWhere($qb->expr()->eq('s2.file_target', $qb->createNamedParameter($path)));
}

$cursor = $qb->executeQuery();
while ($data = $cursor->fetch()) {
if ($this->isAccessibleResult($data)) {
$share = $this->createShare($data);
// patch the parent data with the user-specific changes
$share->setPermissions((int)$data['s2_permissions']);
$share->setStatus((int)$data['s2_accepted']);
$share->setTarget($data['s2_file_target']);
$share->setParent($data['s2_parent']);
$shares[] = $share;
}
}
$cursor->closeCursor();
} else {
throw new BackendError('Invalid backend');
}

return $shares;
}

/**
* Get a share by token
*
Expand Down
39 changes: 39 additions & 0 deletions lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
namespace OC\Share20;

use ArrayIterator;
use OC\Core\AppInfo\ConfigLexicon;
use OC\Files\Mount\MoveableMount;
use OC\KnownUser\KnownUserService;
Expand Down Expand Up @@ -49,6 +50,7 @@
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\Exceptions\ShareTokenException;
use OCP\Share\IManager;
use OCP\Share\IPartialShareProvider;
use OCP\Share\IProviderFactory;
use OCP\Share\IShare;
use OCP\Share\IShareProvider;
Expand Down Expand Up @@ -1283,6 +1285,43 @@ public function getSharedWith(string $userId, int $shareType, ?Node $node = null
return $shares;
}

/**
* @inheritDoc
*/
public function getSharedWithByPath(string $userId, int $shareType, string $path, bool $forChildren, int $limit = 50, int $offset = 0): iterable {
try {
$provider = $this->factory->getProviderForType($shareType);
} catch (ProviderException $e) {
return [];
}

if (!$provider instanceof IPartialShareProvider) {
throw new \RuntimeException(\get_class($provider) . ' must implement IPartialShareProvider');
}

$shares = $provider->getSharedWithByPath($userId,
$shareType,
$path,
$forChildren,
$limit,
$offset
);

if (\is_array($shares)) {
$shares = new ArrayIterator($shares);
}

return new \CallbackFilterIterator($shares, function (IShare $share) {
// remove all shares which are already expired
try {
$this->checkShare($share);
return true;
} catch (ShareNotFound $e) {
return false;
}
});
}

#[Override]
public function getDeletedSharedWith(string $userId, int $shareType, ?Node $node = null, int $limit = 50, int $offset = 0): array {
$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
Expand Down
12 changes: 12 additions & 0 deletions lib/public/Share/IManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ public function getSharesBy(string $userId, int $shareType, ?Node $path = null,
*/
public function getSharedWith(string $userId, int $shareType, ?Node $node = null, int $limit = 50, int $offset = 0): array;

/**
* Get shares shared with a $user filtering by $path.
*
* @param IShare::TYPE_* $shareType
* @param bool $forChildren if true, results should only include children of $path
* @param int $limit The maximum number of shares returned, -1 for all
*
* @return iterable<IShare>
* @since 33.0.0
*/
public function getSharedWithByPath(string $userId, int $shareType, string $path, bool $forChildren, int $limit = 50, int $offset = 0): iterable;

/**
* Get deleted shares shared with $user.
* Filter by $node if provided
Expand Down
31 changes: 31 additions & 0 deletions lib/public/Share/IPartialShareProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCP\Share;

/**
* Interface IPartialShareProvider
*
* @since 33.0.0
*/
interface IPartialShareProvider extends IShareProvider {
/**
* Get shares received by the given user and filtered by path.
*
* If $forChildren is true, results should only include children of $path
*
* @return iterable<IShare>
* @since 33.0.0
*/
public function getSharedWithByPath(
string $userId,
int $shareType,
string $path,
bool $forChildren,
int $limit,
int $offset,
): iterable;
}
Loading