From 168507b1298a395c253b60ccc100086b24812a9b Mon Sep 17 00:00:00 2001 From: Georg Ehrke Date: Wed, 14 Aug 2019 13:38:11 +0200 Subject: [PATCH] !fixup use principaluri instead of userid, allowing to add delegates for rooms and things Signed-off-by: Georg Ehrke --- apps/dav/lib/CalDAV/Proxy/ProxyMapper.php | 14 +- apps/dav/lib/Connector/Sabre/Principal.php | 149 ++++++++++++++++----- 2 files changed, 126 insertions(+), 37 deletions(-) diff --git a/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php b/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php index 6a569394c4b53..8d8adb811b620 100644 --- a/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php +++ b/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php @@ -27,17 +27,27 @@ use OCP\AppFramework\Db\QBMapper; use OCP\IDBConnection; +/** + * Class ProxyMapper + * + * @package OCA\DAV\CalDAV\Proxy + */ class ProxyMapper extends QBMapper { const PERMISSION_READ = 1; const PERMISSION_WRITE = 2; + /** + * ProxyMapper constructor. + * + * @param IDBConnection $db + */ public function __construct(IDBConnection $db) { parent::__construct($db, 'dav_cal_proxy', Proxy::class); } /** - * @param string $proxyId The userId that can act as a proxy for the resulting calendars + * @param string $proxyId The principal uri that can act as a proxy for the resulting calendars * * @return Proxy[] */ @@ -52,7 +62,7 @@ public function getProxiesFor(string $proxyId): array { } /** - * @param string $ownerId The userId that has the resulting proxies for their calendars + * @param string $ownerId The principal uri that has the resulting proxies for their calendars * * @return Proxy[] */ diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php index cc8e9c7accb36..69fa3affabb63 100644 --- a/apps/dav/lib/Connector/Sabre/Principal.php +++ b/apps/dav/lib/Connector/Sabre/Principal.php @@ -74,9 +74,21 @@ class Principal implements BackendInterface { /** @var bool */ private $hasCircles; + /** @var ProxyMapper */ private $proxyMapper; + /** + * Principal constructor. + * + * @param IUserManager $userManager + * @param IGroupManager $groupManager + * @param IShareManager $shareManager + * @param IUserSession $userSession + * @param IAppManager $appManager + * @param ProxyMapper $proxyMapper + * @param string $principalPrefix + */ public function __construct(IUserManager $userManager, IGroupManager $groupManager, IShareManager $shareManager, @@ -169,13 +181,28 @@ public function getPrincipalByPath($path) { * @throws Exception */ public function getGroupMemberSet($principal) { - // TODO: for now the group principal has only one member, the user itself - $principal = $this->getPrincipalByPath($principal); - if (!$principal) { - throw new Exception('Principal not found'); + $members = []; + + if ($this->isProxyPrincipal($principal)) { + $realPrincipal = $this->getPrincipalUriFromProxyPrincipal($principal); + $principalArray = $this->getPrincipalByPath($realPrincipal); + if (!$principalArray) { + throw new Exception('Principal not found'); + } + + $proxies = $this->proxyMapper->getProxiesOf($principalArray['uri']); + foreach ($proxies as $proxy) { + if ($this->isReadProxyPrincipal($principal) && $proxy->getPermissions() === ProxyMapper::PERMISSION_READ) { + $members[] = $proxy->getProxyId(); + } + + if ($this->isWriteProxyPrincipal($principal) && $proxy->getPermissions() === (ProxyMapper::PERMISSION_READ | ProxyMapper::PERMISSION_WRITE)) { + $members[] = $proxy->getProxyId(); + } + } } - return [$principal['uri']]; + return $members; } /** @@ -189,34 +216,36 @@ public function getGroupMemberSet($principal) { public function getGroupMembership($principal, $needGroups = false) { list($prefix, $name) = \Sabre\Uri\split($principal); - if ($prefix === $this->principalPrefix) { - $user = $this->userManager->get($name); - if (!$user) { - throw new Exception('Principal not found'); - } + if ($prefix !== $this->principalPrefix) { + return []; + } - if ($this->hasGroups || $needGroups) { - $groups = $this->groupManager->getUserGroups($user); - $groups = array_map(function($group) { - /** @var IGroup $group */ - return 'principals/groups/' . urlencode($group->getGID()); - }, $groups); - - $proxies = $this->proxyMapper->getProxiesFor($user->getUID()); - foreach ($proxies as $proxy) { - if ($proxy->getPermissions() & ProxyMapper::PERMISSION_READ) { - $groups[] = 'principals/users/' . $proxy->getOwnerId() . '/calendar-proxy-read'; - } + $user = $this->userManager->get($name); + if (!$user) { + throw new Exception('Principal not found'); + } - if ($proxy->getPermissions() & ProxyMapper::PERMISSION_WRITE) { - $groups[] = 'principals/users/' . $proxy->getOwnerId() . '/calendar-proxy-write'; - } - } + $groups = []; - return $groups; + if ($this->hasGroups || $needGroups) { + $userGroups = $this->groupManager->getUserGroups($user); + foreach($userGroups as $userGroup) { + $groups[] = 'principals/groups/' . urlencode($userGroup->getGID()); } } - return []; + + $proxies = $this->proxyMapper->getProxiesFor($principal); + foreach ($proxies as $proxy) { + if ($proxy->getPermissions() === ProxyMapper::PERMISSION_READ) { + $groups[] = $proxy->getOwnerId() . '/calendar-proxy-read'; + } + + if ($proxy->getPermissions() === (ProxyMapper::PERMISSION_READ | ProxyMapper::PERMISSION_WRITE)) { + $groups[] = $proxy->getOwnerId() . '/calendar-proxy-write'; + } + } + + return $groups; } /** @@ -229,7 +258,7 @@ public function getGroupMembership($principal, $needGroups = false) { * @throws Exception */ public function setGroupMemberSet($principal, array $members) { - list($prefix, $target) = \Sabre\Uri\split($principal); + list($principalUri, $target) = \Sabre\Uri\split($principal); if ($target !== 'calendar-proxy-write' && $target !== 'calendar-proxy-read') { throw new Exception('Setting members of the group is not supported yet'); @@ -240,8 +269,8 @@ public function setGroupMemberSet($principal, array $members) { $permission |= ProxyMapper::PERMISSION_WRITE; } - list($prefix, $owner) = \Sabre\Uri\split($prefix); - $proxies = $this->proxyMapper->getProxiesOf($owner); + list($prefix, $owner) = \Sabre\Uri\split($principalUri); + $proxies = $this->proxyMapper->getProxiesOf($principalUri); foreach ($members as $member) { list($prefix, $name) = \Sabre\Uri\split($member); @@ -257,7 +286,7 @@ public function setGroupMemberSet($principal, array $members) { $found = false; foreach ($proxies as $proxy) { - if ($proxy->getProxyId() === $user->getUID()) { + if ($proxy->getProxyId() === $member) { $found = true; $proxy->setPermissions($proxy->getPermissions() | $permission); $this->proxyMapper->update($proxy); @@ -271,8 +300,8 @@ public function setGroupMemberSet($principal, array $members) { if ($found === false) { $proxy = new Proxy(); - $proxy->setOwnerId($owner); - $proxy->setProxyId($user->getUID()); + $proxy->setOwnerId($principalUri); + $proxy->setProxyId($member); $proxy->setPermissions($permission); $this->proxyMapper->insert($proxy); } @@ -280,7 +309,11 @@ public function setGroupMemberSet($principal, array $members) { // Delete all remaining proxies foreach ($proxies as $proxy) { - $this->proxyMapper->delete($proxy); + // Write and Read Proxies have individual requests, + // so only delete proxies of this permission + if ($proxy->getPermissions() === $permission) { + $this->proxyMapper->delete($proxy); + } } } @@ -553,4 +586,50 @@ public function getCircleMembership($principal):array { return []; } + /** + * @param string $principalUri + * @return bool + */ + private function isProxyPrincipal(string $principalUri):bool { + list($realPrincipalUri, $proxy) = \Sabre\Uri\split($principalUri); + list($prefix, $userId) = \Sabre\Uri\split($realPrincipalUri); + + if (!isset($prefix) || !isset($userId)) { + return false; + } + if ($prefix !== $this->principalPrefix) { + return false; + } + + return $proxy === 'calendar-proxy-read' + || $proxy === 'calendar-proxy-write'; + + } + + /** + * @param string $principalUri + * @return bool + */ + private function isReadProxyPrincipal(string $principalUri):bool { + list(, $proxy) = \Sabre\Uri\split($principalUri); + return $proxy === 'calendar-proxy-read'; + } + + /** + * @param string $principalUri + * @return bool + */ + private function isWriteProxyPrincipal(string $principalUri):bool { + list(, $proxy) = \Sabre\Uri\split($principalUri); + return $proxy === 'calendar-proxy-write'; + } + + /** + * @param string $principalUri + * @return string + */ + private function getPrincipalUriFromProxyPrincipal(string $principalUri):string { + list($realPrincipalUri, ) = \Sabre\Uri\split($principalUri); + return $realPrincipalUri; + } }