diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 9487f16fc7..971fde9c6f 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -39,13 +39,13 @@ return array( 'OCA\\DAV\\CalDAV\\CalendarManager' => $baseDir . '/../lib/CalDAV/CalendarManager.php', 'OCA\\DAV\\CalDAV\\CalendarObject' => $baseDir . '/../lib/CalDAV/CalendarObject.php', 'OCA\\DAV\\CalDAV\\CalendarRoot' => $baseDir . '/../lib/CalDAV/CalendarRoot.php', - 'OCA\\DAV\\CalDAV\\Delegation\\Proxy' => $baseDir . '/../lib/CalDAV/Proxy/Proxy.php', 'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => $baseDir . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php', 'OCA\\DAV\\CalDAV\\Outbox' => $baseDir . '/../lib/CalDAV/Outbox.php', 'OCA\\DAV\\CalDAV\\Plugin' => $baseDir . '/../lib/CalDAV/Plugin.php', 'OCA\\DAV\\CalDAV\\Principal\\Collection' => $baseDir . '/../lib/CalDAV/Principal/Collection.php', 'OCA\\DAV\\CalDAV\\Principal\\User' => $baseDir . '/../lib/CalDAV/Principal/User.php', - 'OCA\\DAV\\CalDAV\\ProxyMapper' => $baseDir . '/../lib/CalDAV/Proxy/ProxyMapper.php', + 'OCA\\DAV\\CalDAV\\Proxy\\Proxy' => $baseDir . '/../lib/CalDAV/Proxy/Proxy.php', + 'OCA\\DAV\\CalDAV\\Proxy\\ProxyMapper' => $baseDir . '/../lib/CalDAV/Proxy/ProxyMapper.php', 'OCA\\DAV\\CalDAV\\PublicCalendar' => $baseDir . '/../lib/CalDAV/PublicCalendar.php', 'OCA\\DAV\\CalDAV\\PublicCalendarObject' => $baseDir . '/../lib/CalDAV/PublicCalendarObject.php', 'OCA\\DAV\\CalDAV\\PublicCalendarRoot' => $baseDir . '/../lib/CalDAV/PublicCalendarRoot.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index bbf04103fe..625d50b3c3 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -54,13 +54,13 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CalDAV\\CalendarManager' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarManager.php', 'OCA\\DAV\\CalDAV\\CalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarObject.php', 'OCA\\DAV\\CalDAV\\CalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarRoot.php', - 'OCA\\DAV\\CalDAV\\Delegation\\Proxy' => __DIR__ . '/..' . '/../lib/CalDAV/Proxy/Proxy.php', 'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => __DIR__ . '/..' . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php', 'OCA\\DAV\\CalDAV\\Outbox' => __DIR__ . '/..' . '/../lib/CalDAV/Outbox.php', 'OCA\\DAV\\CalDAV\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Plugin.php', 'OCA\\DAV\\CalDAV\\Principal\\Collection' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/Collection.php', 'OCA\\DAV\\CalDAV\\Principal\\User' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/User.php', - 'OCA\\DAV\\CalDAV\\ProxyMapper' => __DIR__ . '/..' . '/../lib/CalDAV/Proxy/ProxyMapper.php', + 'OCA\\DAV\\CalDAV\\Proxy\\Proxy' => __DIR__ . '/..' . '/../lib/CalDAV/Proxy/Proxy.php', + 'OCA\\DAV\\CalDAV\\Proxy\\ProxyMapper' => __DIR__ . '/..' . '/../lib/CalDAV/Proxy/ProxyMapper.php', 'OCA\\DAV\\CalDAV\\PublicCalendar' => __DIR__ . '/..' . '/../lib/CalDAV/PublicCalendar.php', 'OCA\\DAV\\CalDAV\\PublicCalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/PublicCalendarObject.php', 'OCA\\DAV\\CalDAV\\PublicCalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/PublicCalendarRoot.php', diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php index f26913d7ce..ae5cb226b0 100644 --- a/apps/dav/lib/CalDAV/Calendar.php +++ b/apps/dav/lib/CalDAV/Calendar.php @@ -26,6 +26,7 @@ */ namespace OCA\DAV\CalDAV; +use OCA\DAV\CalDAV\Proxy\ProxyMapper; use OCA\DAV\DAV\Sharing\IShareable; use OCA\DAV\Exception\UnsupportedLimitOnInitialSyncException; use OCP\IConfig; @@ -46,6 +47,9 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { /** @var IConfig */ private $config; + /** @var ProxyMapper */ + private $proxyMapper; + public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n, IConfig $config) { parent::__construct($caldavBackend, $calendarInfo); @@ -58,6 +62,9 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { } $this->config = $config; + + // TODO: proper DI + $this->proxyMapper = \OC::$server->query(ProxyMapper::class); } /** @@ -141,7 +148,7 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { } if (!$this->isShared()) { - return $acl; + return $this->addProxies($acl); } if ($this->getOwner() !== parent::getOwner()) { @@ -174,9 +181,37 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { $acl = $this->caldavBackend->applyShareAcl($this->getResourceId(), $acl); $allowedPrincipals = [$this->getOwner(), parent::getOwner(), 'principals/system/public']; - return array_filter($acl, function($rule) use ($allowedPrincipals) { + $acl = array_filter($acl, function($rule) use ($allowedPrincipals) { return \in_array($rule['principal'], $allowedPrincipals, true); }); + + $acl = $this->addProxies($acl); + + return $acl; + } + + public function addProxies(array $acl): array { + list($prefix, $name) = \Sabre\Uri\split($this->getOwner()); + $proxies = $this->proxyMapper->getProxiesOf($name); + + foreach ($proxies as $proxy) { + if ($proxy->getPermissions() & ProxyMapper::PERMISSION_READ) { + $acl[] = [ + 'privilege' => '{DAV:}read', + 'principal' => 'principals/users/' . $proxy->getProxyId(), + 'protected' => true, + ]; + } + if ($proxy->getPermissions() & ProxyMapper::PERMISSION_WRITE) { + $acl[] = [ + 'privilege' => '{DAV:}write', + 'principal' => 'principals/users/' . $proxy->getProxyId(), + 'protected' => true, + ]; + } + } + + return $acl; } public function getChildACL() { diff --git a/apps/dav/lib/CalDAV/Proxy/Proxy.php b/apps/dav/lib/CalDAV/Proxy/Proxy.php index 1df97dee19..cb01470ae8 100644 --- a/apps/dav/lib/CalDAV/Proxy/Proxy.php +++ b/apps/dav/lib/CalDAV/Proxy/Proxy.php @@ -22,11 +22,18 @@ declare(strict_types=1); * */ -namespace OCA\DAV\CalDAV\Delegation; +namespace OCA\DAV\CalDAV\Proxy; -use OCA\DAV\CalDAV\ProxyMapper; use OCP\AppFramework\Db\Entity; +/** + * @method string getOwnerId() + * @method void setOwnerId(string $ownerId) + * @method string getProxyId() + * @method void setProxyId(string $proxyId) + * @method int getPermissions() + * @method void setPermissions(int $permissions) + */ class Proxy extends Entity { /** @var string */ @@ -34,7 +41,7 @@ class Proxy extends Entity { /** @var string */ protected $proxyId; /** @var int */ - private $permissions; + protected $permissions; public function __construct() { $this->addType('ownerId', 'string'); diff --git a/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php b/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php index d3657b306a..6a569394c4 100644 --- a/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php +++ b/apps/dav/lib/CalDAV/Proxy/ProxyMapper.php @@ -22,9 +22,8 @@ declare(strict_types=1); * */ -namespace OCA\DAV\CalDAV; +namespace OCA\DAV\CalDAV\Proxy; -use OCA\DAV\CalDAV\Delegation\Proxy; use OCP\AppFramework\Db\QBMapper; use OCP\IDBConnection; @@ -39,6 +38,8 @@ class ProxyMapper extends QBMapper { /** * @param string $proxyId The userId that can act as a proxy for the resulting calendars + * + * @return Proxy[] */ public function getProxiesFor(string $proxyId): array { $qb = $this->db->getQueryBuilder(); @@ -52,6 +53,8 @@ class ProxyMapper extends QBMapper { /** * @param string $ownerId The userId that has the resulting proxies for their calendars + * + * @return Proxy[] */ public function getProxiesOf(string $ownerId): array { $qb = $this->db->getQueryBuilder(); diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php index 902c70bdaf..9a0cd3b521 100644 --- a/apps/dav/lib/Connector/Sabre/Principal.php +++ b/apps/dav/lib/Connector/Sabre/Principal.php @@ -35,9 +35,9 @@ namespace OCA\DAV\Connector\Sabre; use OCA\Circles\Exceptions\CircleDoesNotExistException; +use OCA\DAV\CalDAV\Proxy\ProxyMapper; use OCP\App\IAppManager; use OCP\AppFramework\QueryException; -use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; use OCP\IUser; @@ -62,9 +62,6 @@ class Principal implements BackendInterface { /** @var IUserSession */ private $userSession; - /** @var IConfig */ - private $config; - /** @var IAppManager */ private $appManager; @@ -76,30 +73,24 @@ class Principal implements BackendInterface { /** @var bool */ private $hasCircles; + /** @var ProxyMapper */ + private $proxyMapper; - /** - * @param IUserManager $userManager - * @param IGroupManager $groupManager - * @param IShareManager $shareManager - * @param IUserSession $userSession - * @param IConfig $config - * @param string $principalPrefix - */ public function __construct(IUserManager $userManager, IGroupManager $groupManager, IShareManager $shareManager, IUserSession $userSession, - IConfig $config, IAppManager $appManager, + ProxyMapper $proxyMapper, string $principalPrefix = 'principals/users/') { $this->userManager = $userManager; $this->groupManager = $groupManager; $this->shareManager = $shareManager; $this->userSession = $userSession; - $this->config = $config; $this->appManager = $appManager; $this->principalPrefix = trim($principalPrefix, '/'); $this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/'); + $this->proxyMapper = $proxyMapper; } /** @@ -138,6 +129,21 @@ class Principal implements BackendInterface { public function getPrincipalByPath($path) { list($prefix, $name) = \Sabre\Uri\split($path); + if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') { + list($prefix2, $name2) = \Sabre\Uri\split($prefix); + + if ($prefix2 === $this->principalPrefix) { + $user = $this->userManager->get($name2); + + if ($user !== null) { + return [ + 'uri' => 'principals/users/' . $user->getUID() . '/' . $name, + ]; + } + return null; + } + } + if ($prefix === $this->principalPrefix) { $user = $this->userManager->get($name); @@ -195,6 +201,17 @@ class Principal implements BackendInterface { 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'; + } + + if ($proxy->getPermissions() & ProxyMapper::PERMISSION_WRITE) { + $groups[] = 'principals/users/' . $proxy->getOwnerId() . '/calendar-proxy-write'; + } + } + return $groups; } } @@ -211,6 +228,7 @@ class Principal implements BackendInterface { * @throws Exception */ public function setGroupMemberSet($principal, array $members) { + $a = 'b'; throw new Exception('Setting members of the group is not supported yet'); } diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php index 38c8b2f6b4..12b870932b 100644 --- a/apps/dav/lib/RootCollection.php +++ b/apps/dav/lib/RootCollection.php @@ -26,6 +26,7 @@ namespace OCA\DAV; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\CalendarRoot; +use OCA\DAV\CalDAV\Proxy\ProxyMapper; use OCA\DAV\CalDAV\PublicCalendarRoot; use OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend; use OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend; @@ -58,8 +59,8 @@ class RootCollection extends SimpleCollection { $groupManager, $shareManager, \OC::$server->getUserSession(), - $config, - \OC::$server->getAppManager() + \OC::$server->getAppManager(), + \OC::$server->query(ProxyMapper::class) ); $groupPrincipalBackend = new GroupPrincipalBackend($groupManager, $userSession, $shareManager, $l10n); $calendarResourcePrincipalBackend = new ResourcePrincipalBackend($db, $userSession, $groupManager, $logger); diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 7eb68ce587..cd67b3995a 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -137,7 +137,8 @@ class Server { // acl $acl = new DavAclPlugin(); $acl->principalCollectionSet = [ - 'principals/users', 'principals/groups', + 'principals/users', + 'principals/groups', 'principals/calendar-resources', 'principals/calendar-rooms', ]; diff --git a/apps/files_trashbin/lib/AppInfo/Application.php b/apps/files_trashbin/lib/AppInfo/Application.php index 761298673a..4baa82a6b4 100644 --- a/apps/files_trashbin/lib/AppInfo/Application.php +++ b/apps/files_trashbin/lib/AppInfo/Application.php @@ -23,6 +23,7 @@ namespace OCA\Files_Trashbin\AppInfo; +use OCA\DAV\CalDAV\Proxy\ProxyMapper; use OCA\DAV\Connector\Sabre\Principal; use OCA\Files_Trashbin\Trash\ITrashManager; use OCA\Files_Trashbin\Trash\TrashManager; @@ -61,8 +62,8 @@ class Application extends App { \OC::$server->getGroupManager(), \OC::$server->getShareManager(), \OC::$server->getUserSession(), - \OC::$server->getConfig(), - \OC::$server->getAppManager() + \OC::$server->getAppManager(), + \OC::$server->query(ProxyMapper::class) ); }); diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php index 6a8e50dba9..919a9b42d7 100644 --- a/apps/files_versions/lib/AppInfo/Application.php +++ b/apps/files_versions/lib/AppInfo/Application.php @@ -23,6 +23,7 @@ namespace OCA\Files_Versions\AppInfo; +use OCA\DAV\CalDAV\Proxy\ProxyMapper; use OCA\DAV\Connector\Sabre\Principal; use OCA\Files_Versions\Versions\IVersionManager; use OCA\Files_Versions\Versions\VersionManager; @@ -51,8 +52,8 @@ class Application extends App { $server->getGroupManager(), $server->getShareManager(), $server->getUserSession(), - $server->getConfig(), - $server->getAppManager() + $server->getAppManager(), + $server->query(ProxyMapper::class) ); });