diff --git a/lib/CalDAV/Backend/PDO.php b/lib/CalDAV/Backend/PDO.php index 91b5da4411..b6d59b1690 100644 --- a/lib/CalDAV/Backend/PDO.php +++ b/lib/CalDAV/Backend/PDO.php @@ -192,9 +192,13 @@ public function getCalendarsForUser($principalUri) $calendar['share-access'] = (int) $row['access']; // 1 = owner, 2 = readonly, 3 = readwrite if ($row['access'] > 1) { - // We need to find more information about the original owner. - //$stmt2 = $this->pdo->prepare('SELECT principaluri FROM ' . $this->calendarInstancesTableName . ' WHERE access = 1 AND id = ?'); - //$stmt2->execute([$row['id']]); + $ownerStmt = $this->pdo->prepare("SELECT principaluri FROM {$this->calendarInstancesTableName} WHERE access = 1 AND calendarid = ?"); + $ownerStmt->execute([$row['calendarid']]); + + $ownerRow = $ownerStmt->fetch(\PDO::FETCH_ASSOC); + if ($ownerRow && is_array($ownerRow) && array_key_exists('principaluri', $ownerRow)) { + $calendar['owner-principal'] = $ownerRow['principaluri']; + } // read-only is for backwards compatibility. Might go away in // the future. diff --git a/lib/CalDAV/Principal/User.php b/lib/CalDAV/Principal/User.php index 88bf4b4f77..3973d56648 100644 --- a/lib/CalDAV/Principal/User.php +++ b/lib/CalDAV/Principal/User.php @@ -131,6 +131,22 @@ public function getACL() 'protected' => true, ]; + /** + * Members of shared calendars needs to be able to read information about the owner. + * + * The Principal has no knowledge about the calendars and therefore it is not + * possible to limit the access to members of a shared calendar + * in DAVACL/Plugin.php getCurrentUserPrivilegeSet. + * + * As workaround all authenticated users are getting the read privilege for other users. + */ + + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => '{DAV:}authenticated', + 'protected' => true, + ]; + return $acl; } } diff --git a/lib/CalDAV/SharedCalendar.php b/lib/CalDAV/SharedCalendar.php index 818392f57c..cd1eefbe92 100644 --- a/lib/CalDAV/SharedCalendar.php +++ b/lib/CalDAV/SharedCalendar.php @@ -216,4 +216,16 @@ public function getChildACL() return $acl; } + + /** + * Returns the 'original owner principal' for this shared resource. + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getOwnerPrincipal() + { + return isset($this->calendarInfo['owner-principal']) ? $this->calendarInfo['owner-principal'] : $this->getOwner(); + } } diff --git a/lib/CalDAV/SharingPlugin.php b/lib/CalDAV/SharingPlugin.php index 56962fc14f..cc0bbf8f62 100644 --- a/lib/CalDAV/SharingPlugin.php +++ b/lib/CalDAV/SharingPlugin.php @@ -86,7 +86,7 @@ public function initialize(DAV\Server $server) $this->server->xml->elementMap['{'.Plugin::NS_CALENDARSERVER.'}share'] = \Sabre\CalDAV\Xml\Request\Share::class; $this->server->xml->elementMap['{'.Plugin::NS_CALENDARSERVER.'}invite-reply'] = \Sabre\CalDAV\Xml\Request\InviteReply::class; - $this->server->on('propFind', [$this, 'propFindEarly']); + $this->server->on('propFind', [$this, 'propFindEarly'], 10); $this->server->on('propFind', [$this, 'propFindLate'], 150); $this->server->on('propPatch', [$this, 'propPatch'], 40); $this->server->on('method:POST', [$this, 'httpPost']); @@ -106,6 +106,14 @@ public function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) $node->getInvites() ); }); + + // Needs to be called before ACL + $propFind->handle('{DAV:}owner', function () use ($node) { + $shareAccess = $node->getShareAccess(); + if ($shareAccess > 1) { + return new \Sabre\DAV\Xml\Property\Href($node->getOwnerPrincipal() . '/'); + } + }); } } diff --git a/lib/DAV/Sharing/ISharedNode.php b/lib/DAV/Sharing/ISharedNode.php index a746ac7535..9d1e261513 100644 --- a/lib/DAV/Sharing/ISharedNode.php +++ b/lib/DAV/Sharing/ISharedNode.php @@ -66,4 +66,13 @@ public function updateInvites(array $sharees); * @return \Sabre\DAV\Xml\Element\Sharee[] */ public function getInvites(); + + /** + * Returns the 'original owner principal' for this shared resource. + * + * This must be a url to a principal, or null if there's no owner + * + * @return string|null + */ + public function getOwnerPrincipal(); }