Skip to content
Open
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
2 changes: 2 additions & 0 deletions apps/files_sharing/tests/CapabilitiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IDateTimeZone;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IURLGenerator;
use OCP\IUserManager;
Expand Down Expand Up @@ -100,6 +101,7 @@ private function getResults(array $map, array $typedMap = [], bool $federationEn
$this->createMock(ShareDisableChecker::class),
$this->createMock(IDateTimeZone::class),
$appConfig,
$this->createMock(IDBConnection::class),
);

$cap = new Capabilities($config, $appConfig, $shareManager, $appManager);
Expand Down
2 changes: 2 additions & 0 deletions apps/settings/tests/Settings/Admin/SharingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Share\IManager;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;

#[Group(name: 'DB')]
class SharingTest extends TestCase {
private Sharing $admin;

Expand Down
2 changes: 1 addition & 1 deletion lib/private/Share20/DefaultShareProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ public function getShareByToken($token) {
* @return \OCP\Share\IShare
* @throws InvalidShare
*/
private function createShare($data) {
private function createShare($data): IShare {
$share = new Share($this->rootFolder, $this->userManager);
$share->setId((int)$data['id'])
->setShareType((int)$data['share_type'])
Expand Down
92 changes: 68 additions & 24 deletions lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use OCA\Files_Sharing\AppInfo\Application;
use OCA\Files_Sharing\SharedStorage;
use OCA\ShareByMail\ShareByMailProvider;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
Expand All @@ -27,6 +28,7 @@
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IDateTimeZone;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
Expand Down Expand Up @@ -86,6 +88,7 @@ public function __construct(
private ShareDisableChecker $shareDisableChecker,
private IDateTimeZone $dateTimeZone,
private IAppConfig $appConfig,
private IDBConnection $connection,
) {
$this->l = $this->l10nFactory->get('lib');
// The constructor of LegacyHooks registers the listeners of share events
Expand Down Expand Up @@ -1068,35 +1071,76 @@ protected function promoteReshares(IShare $share): void {
IShare::TYPE_EMAIL,
];

foreach ($userIds as $userId) {
foreach ($shareTypes as $shareType) {
// Figure out which users has some shares with which providers
$qb = $this->connection->getQueryBuilder();
$qb->select('uid_initiator', 'share_type', 'uid_owner', 'file_source')
->from('share')
->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($shareTypes, IQueryBuilder::PARAM_INT_ARRAY)))
->andWhere(
$qb->expr()->orX(
$qb->expr()->in('uid_initiator', $qb->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY)),
// Special case for old shares created via the web UI
$qb->expr()->andX(
$qb->expr()->in('uid_owner', $qb->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY)),
$qb->expr()->isNull('uid_initiator')
)
)
);

if (!$node instanceof Folder) {
$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId(), IQueryBuilder::PARAM_INT)));
}

$qb->orderBy('id');

$cursor = $qb->executeQuery();
/** @var array<string, list<array{IShare::TYPE_*, Node}>> $rawShare */
$rawShares = [];
while ($data = $cursor->fetch()) {
if (!isset($rawShares[$data['uid_initiator']])) {
$rawShares[$data['uid_initiator']] = [];
}
if (!in_array($data['share_type'], $rawShares[$data['uid_initiator']], true)) {
if ($node instanceof Folder) {
if ($data['file_source'] === null || $data['uid_owner'] === null) {
/* Ignore share of non-existing node */
continue;
}

// for federated shares the owner can be a remote user, in this
// case we use the initiator
if ($this->userManager->userExists($data['uid_owner'])) {
$userFolder = $this->rootFolder->getUserFolder($data['uid_owner']);
} else {
$userFolder = $this->rootFolder->getUserFolder($data['uid_initiator']);
}
$sharedNode = $userFolder->getFirstNodeById((int)$data['file_source']);
if (!$sharedNode) {
continue;
}
if ($node->getRelativePath($sharedNode->getPath()) !== null) {
$rawShares[$data['uid_initiator']][] = [(int)$data['share_type'], $sharedNode];
}
} elseif ($node instanceof File) {
$rawShares[$data['uid_initiator']][] = [(int)$data['share_type'], $node];
}
}
}
$cursor->closeCursor();

foreach ($rawShares as $userId => $shareInfos) {
foreach ($shareInfos as $shareInfo) {
[$shareType, $sharedNode] = $shareInfo;
try {
$provider = $this->factory->getProviderForType($shareType);
} catch (ProviderException $e) {
} catch (ProviderException) {
continue;
}

if ($node instanceof Folder) {
/* We need to get all shares by this user to get subshares */
$shares = $provider->getSharesBy($userId, $shareType, null, false, -1, 0);

foreach ($shares as $share) {
try {
$path = $share->getNode()->getPath();
} catch (NotFoundException) {
/* Ignore share of non-existing node */
continue;
}
if ($node->getRelativePath($path) !== null) {
/* If relative path is not null it means the shared node is the same or in a subfolder */
$reshareRecords[] = $share;
}
}
} else {
$shares = $provider->getSharesBy($userId, $shareType, $node, false, -1, 0);
foreach ($shares as $child) {
$reshareRecords[] = $child;
}
$shares = $provider->getSharesBy($userId, $shareType, $sharedNode, false, -1, 0);
foreach ($shares as $child) {
$reshareRecords[] = $child;
}
}
}
Expand Down
14 changes: 5 additions & 9 deletions tests/lib/Share20/LegacyHooksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

use OC\EventDispatcher\EventDispatcher;
use OC\Share20\LegacyHooks;
use OC\Share20\Manager;
use OCP\Constants;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Cache\ICacheEntry;
Expand All @@ -24,6 +23,7 @@
use OCP\Share\IManager as IShareManager;
use OCP\Share\IShare;
use OCP\Util;
use PHPUnit\Framework\Attributes\Group;
use Psr\Log\LoggerInterface;
use Test\TestCase;

Expand All @@ -40,15 +40,11 @@ public function pre() {
}
}

#[Group(name: 'DB')]
class LegacyHooksTest extends TestCase {
/** @var LegacyHooks */
private $hooks;

/** @var IEventDispatcher */
private $eventDispatcher;

/** @var Manager */
private $manager;
private LegacyHooks $hooks;
private IEventDispatcher $eventDispatcher;
private IShareManager $manager;

protected function setUp(): void {
parent::setUp();
Expand Down
Loading
Loading