Skip to content

Commit a449af6

Browse files
committed
feat: introduce API for partial share providers
Adds support for retrieval of shares by path Signed-off-by: Salvatore Martire <[email protected]>
1 parent ed6d0e5 commit a449af6

File tree

6 files changed

+193
-1
lines changed

6 files changed

+193
-1
lines changed

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@
817817
'OCP\\Share\\Exceptions\\ShareTokenException' => $baseDir . '/lib/public/Share/Exceptions/ShareTokenException.php',
818818
'OCP\\Share\\IAttributes' => $baseDir . '/lib/public/Share/IAttributes.php',
819819
'OCP\\Share\\IManager' => $baseDir . '/lib/public/Share/IManager.php',
820+
'OCP\\Share\\IPartialShareProvider' => $baseDir . '/lib/public/Share/IPartialShareProvider.php',
820821
'OCP\\Share\\IProviderFactory' => $baseDir . '/lib/public/Share/IProviderFactory.php',
821822
'OCP\\Share\\IPublicShareTemplateFactory' => $baseDir . '/lib/public/Share/IPublicShareTemplateFactory.php',
822823
'OCP\\Share\\IPublicShareTemplateProvider' => $baseDir . '/lib/public/Share/IPublicShareTemplateProvider.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
858858
'OCP\\Share\\Exceptions\\ShareTokenException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareTokenException.php',
859859
'OCP\\Share\\IAttributes' => __DIR__ . '/../../..' . '/lib/public/Share/IAttributes.php',
860860
'OCP\\Share\\IManager' => __DIR__ . '/../../..' . '/lib/public/Share/IManager.php',
861+
'OCP\\Share\\IPartialShareProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IPartialShareProvider.php',
861862
'OCP\\Share\\IProviderFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IProviderFactory.php',
862863
'OCP\\Share\\IPublicShareTemplateFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IPublicShareTemplateFactory.php',
863864
'OCP\\Share\\IPublicShareTemplateProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IPublicShareTemplateProvider.php',

lib/private/Share20/DefaultShareProvider.php

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use OCP\Share\Exceptions\ShareNotFound;
3333
use OCP\Share\IAttributes;
3434
use OCP\Share\IManager;
35+
use OCP\Share\IPartialShareProvider;
3536
use OCP\Share\IShare;
3637
use OCP\Share\IShareProviderGetUsers;
3738
use OCP\Share\IShareProviderSupportsAccept;
@@ -49,7 +50,8 @@ class DefaultShareProvider implements
4950
IShareProviderWithNotification,
5051
IShareProviderSupportsAccept,
5152
IShareProviderSupportsAllSharesInFolder,
52-
IShareProviderGetUsers {
53+
IShareProviderGetUsers,
54+
IPartialShareProvider {
5355
public function __construct(
5456
private IDBConnection $dbConn,
5557
private IUserManager $userManager,
@@ -953,6 +955,112 @@ public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
953955
return $shares;
954956
}
955957

958+
/**
959+
* @inheritDoc
960+
*/
961+
public function getSharedWithByPath(
962+
string $userId,
963+
int $shareType,
964+
string $path,
965+
bool $forChildren,
966+
int $limit,
967+
int $offset,
968+
): iterable {
969+
$shares = [];
970+
971+
if ($shareType === IShare::TYPE_USER) {
972+
//Get shares directly with this user
973+
$qb = $this->dbConn->getQueryBuilder();
974+
$qb->select('s.*',
975+
'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
976+
'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
977+
'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
978+
)
979+
->selectAlias('st.id', 'storage_string_id')
980+
->from('share', 's')
981+
->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
982+
->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
983+
984+
// Order by id
985+
$qb->orderBy('s.id');
986+
987+
// Set limit and offset
988+
if ($limit !== -1) {
989+
$qb->setMaxResults($limit);
990+
}
991+
$qb->setFirstResult($offset);
992+
993+
$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
994+
->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
995+
->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
996+
997+
if ($forChildren) {
998+
$qb->andWhere($qb->expr()->like('file_target', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($path) . '_%')));
999+
} else {
1000+
$qb->andWhere($qb->expr()->eq('file_target', $qb->createNamedParameter($path)));
1001+
}
1002+
1003+
$cursor = $qb->executeQuery();
1004+
1005+
while ($data = $cursor->fetch()) {
1006+
if ($data['fileid'] && $data['path'] === null) {
1007+
$data['path'] = (string)$data['path'];
1008+
$data['name'] = (string)$data['name'];
1009+
$data['checksum'] = (string)$data['checksum'];
1010+
}
1011+
if ($this->isAccessibleResult($data)) {
1012+
$shares[] = $this->createShare($data);
1013+
}
1014+
}
1015+
$cursor->closeCursor();
1016+
} elseif ($shareType === IShare::TYPE_GROUP) {
1017+
// get the parent share info (s) along with the child one (s2)
1018+
$qb = $this->dbConn->getQueryBuilder();
1019+
$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',
1020+
'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
1021+
'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
1022+
'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
1023+
)
1024+
->selectAlias('st.id', 'storage_string_id')
1025+
->from('share', 's2')
1026+
->leftJoin('s2', 'filecache', 'f', $qb->expr()->eq('s2.file_source', 'f.fileid'))
1027+
->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
1028+
->leftJoin('s2', 'share', 's', $qb->expr()->eq('s2.parent', 's.id'))
1029+
->where($qb->expr()->eq('s2.share_with', $qb->createNamedParameter($userId)))
1030+
->andWhere($qb->expr()->eq('s2.share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1031+
->andWhere($qb->expr()->in('s2.item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
1032+
->orderBy('s2.id')
1033+
->setFirstResult($offset);
1034+
if ($limit !== -1) {
1035+
$qb->setMaxResults($limit);
1036+
}
1037+
1038+
if ($forChildren) {
1039+
$qb->andWhere($qb->expr()->like('s2.file_target', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($path) . '_%')));
1040+
} else {
1041+
$qb->andWhere($qb->expr()->eq('s2.file_target', $qb->createNamedParameter($path)));
1042+
}
1043+
1044+
$cursor = $qb->executeQuery();
1045+
while ($data = $cursor->fetch()) {
1046+
if ($this->isAccessibleResult($data)) {
1047+
$share = $this->createShare($data);
1048+
// patch the parent data with the user-specific changes
1049+
$share->setPermissions((int)$data['s2_permissions']);
1050+
$share->setStatus((int)$data['s2_accepted']);
1051+
$share->setTarget($data['s2_file_target']);
1052+
$share->setParent($data['s2_parent']);
1053+
$shares[] = $share;
1054+
}
1055+
}
1056+
$cursor->closeCursor();
1057+
} else {
1058+
throw new BackendError('Invalid backend');
1059+
}
1060+
1061+
return $shares;
1062+
}
1063+
9561064
/**
9571065
* Get a share by token
9581066
*

lib/private/Share20/Manager.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
namespace OC\Share20;
99

10+
use ArrayIterator;
1011
use OC\Core\AppInfo\ConfigLexicon;
1112
use OC\Files\Mount\MoveableMount;
1213
use OC\KnownUser\KnownUserService;
@@ -49,6 +50,7 @@
4950
use OCP\Share\Exceptions\ShareNotFound;
5051
use OCP\Share\Exceptions\ShareTokenException;
5152
use OCP\Share\IManager;
53+
use OCP\Share\IPartialShareProvider;
5254
use OCP\Share\IProviderFactory;
5355
use OCP\Share\IShare;
5456
use OCP\Share\IShareProvider;
@@ -1283,6 +1285,43 @@ public function getSharedWith(string $userId, int $shareType, ?Node $node = null
12831285
return $shares;
12841286
}
12851287

1288+
/**
1289+
* @inheritDoc
1290+
*/
1291+
public function getSharedWithByPath(string $userId, int $shareType, string $path, bool $forChildren, int $limit = 50, int $offset = 0): iterable {
1292+
try {
1293+
$provider = $this->factory->getProviderForType($shareType);
1294+
} catch (ProviderException $e) {
1295+
return [];
1296+
}
1297+
1298+
if (!$provider instanceof IPartialShareProvider) {
1299+
throw new \RuntimeException(\get_class($provider) . ' must implement IPartialShareProvider');
1300+
}
1301+
1302+
$shares = $provider->getSharedWithByPath($userId,
1303+
$shareType,
1304+
$path,
1305+
$forChildren,
1306+
$limit,
1307+
$offset
1308+
);
1309+
1310+
if (\is_array($shares)) {
1311+
$shares = new ArrayIterator($shares);
1312+
}
1313+
1314+
return new \CallbackFilterIterator($shares, function (IShare $share) {
1315+
// remove all shares which are already expired
1316+
try {
1317+
$this->checkShare($share);
1318+
return true;
1319+
} catch (ShareNotFound $e) {
1320+
return false;
1321+
}
1322+
});
1323+
}
1324+
12861325
#[Override]
12871326
public function getDeletedSharedWith(string $userId, int $shareType, ?Node $node = null, int $limit = 50, int $offset = 0): array {
12881327
$shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);

lib/public/Share/IManager.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,18 @@ public function getSharesBy(string $userId, int $shareType, ?Node $path = null,
134134
*/
135135
public function getSharedWith(string $userId, int $shareType, ?Node $node = null, int $limit = 50, int $offset = 0): array;
136136

137+
/**
138+
* Get shares shared with a $user filtering by $path.
139+
*
140+
* @param IShare::TYPE_* $shareType
141+
* @param bool $forChildren if true, results should only include children of $path
142+
* @param int $limit The maximum number of shares returned, -1 for all
143+
*
144+
* @return iterable<IShare>
145+
* @since 33.0.0
146+
*/
147+
public function getSharedWithByPath(string $userId, int $shareType, string $path, bool $forChildren, int $limit = 50, int $offset = 0): iterable;
148+
137149
/**
138150
* Get deleted shares shared with $user.
139151
* Filter by $node if provided
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/**
4+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
namespace OCP\Share;
8+
9+
/**
10+
* Interface IPartialShareProvider
11+
*
12+
* @since 33.0.0
13+
*/
14+
interface IPartialShareProvider extends IShareProvider {
15+
/**
16+
* Get shares received by the given user and filtered by path.
17+
*
18+
* If $forChildren is true, results should only include children of $path
19+
*
20+
* @return iterable<IShare>
21+
* @since 33.0.0
22+
*/
23+
public function getSharedWithByPath(
24+
string $userId,
25+
int $shareType,
26+
string $path,
27+
bool $forChildren,
28+
int $limit,
29+
int $offset,
30+
): iterable;
31+
}

0 commit comments

Comments
 (0)