namespace OCA\DAV\DAV\Sharing;
use OCA\DAV\Connector\Sabre\Principal;
+use OCP\Cache\CappedMemoryCache;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IUserManager;
public const ACCESS_READ_WRITE = 2;
public const ACCESS_READ = 3;
+ private CappedMemoryCache $shareCache;
+
public function __construct(IDBConnection $db, IUserManager $userManager, IGroupManager $groupManager, Principal $principalBackend, string $resourceType) {
$this->db = $db;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->principalBackend = $principalBackend;
$this->resourceType = $resourceType;
+ $this->shareCache = new CappedMemoryCache();
}
/**
* @param list<string> $remove
*/
public function updateShares(IShareable $shareable, array $add, array $remove): void {
+ $this->shareCache->clear();
foreach ($add as $element) {
$principal = $this->principalBackend->findByUri($element['href'], '');
if ($principal !== '') {
* @param array{href: string, commonName: string, readOnly: bool} $element
*/
private function shareWith(IShareable $shareable, array $element): void {
+ $this->shareCache->clear();
$user = $element['href'];
$parts = explode(':', $user, 2);
if ($parts[0] !== 'principal') {
}
public function deleteAllShares(int $resourceId): void {
+ $this->shareCache->clear();
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
}
public function deleteAllSharesByUser(string $principaluri): void {
+ $this->shareCache->clear();
$query = $this->db->getQueryBuilder();
$query->delete('dav_shares')
->where($query->expr()->eq('principaluri', $query->createNamedParameter($principaluri)))
}
private function unshare(IShareable $shareable, string $element): void {
+ $this->shareCache->clear();
$parts = explode(':', $element, 2);
if ($parts[0] !== 'principal') {
return;
* @return list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}>
*/
public function getShares(int $resourceId): array {
+ $cached = $this->shareCache->get($resourceId);
+ if ($cached) {
+ return $cached;
+ }
$query = $this->db->getQueryBuilder();
$result = $query->select(['principaluri', 'access'])
->from('dav_shares')
];
}
+ $this->shareCache->set($resourceId, $shares);
return $shares;
}
+ public function preloadShares(array $resourceIds) {
+ $resourceIds = array_filter($resourceIds, function(int $resourceId) {
+ return !isset($this->shareCache[$resourceId]);
+ });
+ if (count($resourceIds) === 0) {
+ return;
+ }
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select(['resourceid', 'principaluri', 'access'])
+ ->from('dav_shares')
+ ->where($query->expr()->in('resourceid', $query->createNamedParameter($resourceIds, IQueryBuilder::PARAM_INT_ARRAY)))
+ ->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
+ ->groupBy(['principaluri', 'access', 'resourceid'])
+ ->executeQuery();
+
+ $sharesByResource = array_fill_keys($resourceIds, []);
+ while ($row = $result->fetch()) {
+ $resourceId = (int)$row['resourceid'];
+ $p = $this->principalBackend->getPrincipalByPath($row['principaluri']);
+ $sharesByResource[$resourceId][] = [
+ 'href' => "principal:{$row['principaluri']}",
+ 'commonName' => isset($p['{DAV:}displayname']) ? (string)$p['{DAV:}displayname'] : '',
+ 'status' => 1,
+ 'readOnly' => (int) $row['access'] === self::ACCESS_READ,
+ '{http://owncloud.org/ns}principal' => (string)$row['principaluri'],
+ '{http://owncloud.org/ns}group-share' => isset($p['uri']) ? str_starts_with($p['uri'], 'principals/groups') : false
+ ];
+ }
+
+ foreach ($resourceIds as $resourceId) {
+ $this->shareCache->set($resourceId, $sharesByResource[$resourceId]);
+ }
+ }
+
/**
* For shared resources the sharee is set in the ACL of the resource
*
*/
namespace OCA\DAV\DAV\Sharing;
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\Connector\Sabre\Auth;
use OCA\DAV\DAV\Sharing\Xml\Invite;
use OCA\DAV\DAV\Sharing\Xml\ShareRequest;
* @return void
*/
public function propFind(PropFind $propFind, INode $node) {
+ if ($node instanceof CalendarHome && $propFind->getDepth() === 1) {
+ $backend = $node->getCalDAVBackend();
+ if ($backend instanceof CalDavBackend) {
+ $calendars = $node->getChildren();
+ $calendars = array_filter($calendars, function (INode $node) {
+ return $node instanceof IShareable;
+ });
+ /** @var int[] $resourceIds */
+ $resourceIds = array_map(function (IShareable $node) {
+ return $node->getResourceId();
+ }, $calendars);
+ $backend->preloadShares($resourceIds);
+ }
+ }
if ($node instanceof IShareable) {
$propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use ($node) {
return new Invite(