PrincipalProxyTrait.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <?php
  2. /**
  3. * @copyright 2019, Georg Ehrke <oc.list@georgehrke.com>
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Georg Ehrke <oc.list@georgehrke.com>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OCA\DAV\Traits;
  25. use OCA\DAV\CalDAV\Proxy\Proxy;
  26. use OCA\DAV\CalDAV\Proxy\ProxyMapper;
  27. use Sabre\DAV\Exception;
  28. /**
  29. * Trait PrincipalTrait
  30. *
  31. * @package OCA\DAV\Traits
  32. */
  33. trait PrincipalProxyTrait {
  34. /**
  35. * Returns the list of members for a group-principal
  36. *
  37. * @param string $principal
  38. * @return string[]
  39. * @throws Exception
  40. */
  41. public function getGroupMemberSet($principal) {
  42. $members = [];
  43. if ($this->isProxyPrincipal($principal)) {
  44. $realPrincipal = $this->getPrincipalUriFromProxyPrincipal($principal);
  45. $principalArray = $this->getPrincipalByPath($realPrincipal);
  46. if (!$principalArray) {
  47. throw new Exception('Principal not found');
  48. }
  49. $proxies = $this->proxyMapper->getProxiesOf($principalArray['uri']);
  50. foreach ($proxies as $proxy) {
  51. if ($this->isReadProxyPrincipal($principal) && $proxy->getPermissions() === ProxyMapper::PERMISSION_READ) {
  52. $members[] = $proxy->getProxyId();
  53. }
  54. if ($this->isWriteProxyPrincipal($principal) && $proxy->getPermissions() === (ProxyMapper::PERMISSION_READ | ProxyMapper::PERMISSION_WRITE)) {
  55. $members[] = $proxy->getProxyId();
  56. }
  57. }
  58. }
  59. return $members;
  60. }
  61. /**
  62. * Returns the list of groups a principal is a member of
  63. *
  64. * @param string $principal
  65. * @param bool $needGroups
  66. * @return array
  67. * @throws Exception
  68. */
  69. public function getGroupMembership($principal, $needGroups = false) {
  70. [$prefix, $name] = \Sabre\Uri\split($principal);
  71. if ($prefix !== $this->principalPrefix) {
  72. return [];
  73. }
  74. $principalArray = $this->getPrincipalByPath($principal);
  75. if (!$principalArray) {
  76. throw new Exception('Principal not found');
  77. }
  78. $groups = [];
  79. $proxies = $this->proxyMapper->getProxiesFor($principal);
  80. foreach ($proxies as $proxy) {
  81. if ($proxy->getPermissions() === ProxyMapper::PERMISSION_READ) {
  82. $groups[] = $proxy->getOwnerId() . '/calendar-proxy-read';
  83. }
  84. if ($proxy->getPermissions() === (ProxyMapper::PERMISSION_READ | ProxyMapper::PERMISSION_WRITE)) {
  85. $groups[] = $proxy->getOwnerId() . '/calendar-proxy-write';
  86. }
  87. }
  88. return $groups;
  89. }
  90. /**
  91. * Updates the list of group members for a group principal.
  92. *
  93. * The principals should be passed as a list of uri's.
  94. *
  95. * @param string $principal
  96. * @param string[] $members
  97. * @throws Exception
  98. */
  99. public function setGroupMemberSet($principal, array $members) {
  100. [$principalUri, $target] = \Sabre\Uri\split($principal);
  101. if ($target !== 'calendar-proxy-write' && $target !== 'calendar-proxy-read') {
  102. throw new Exception('Setting members of the group is not supported yet');
  103. }
  104. $masterPrincipalArray = $this->getPrincipalByPath($principalUri);
  105. if (!$masterPrincipalArray) {
  106. throw new Exception('Principal not found');
  107. }
  108. $permission = ProxyMapper::PERMISSION_READ;
  109. if ($target === 'calendar-proxy-write') {
  110. $permission |= ProxyMapper::PERMISSION_WRITE;
  111. }
  112. [$prefix, $owner] = \Sabre\Uri\split($principalUri);
  113. $proxies = $this->proxyMapper->getProxiesOf($principalUri);
  114. foreach ($members as $member) {
  115. [$prefix, $name] = \Sabre\Uri\split($member);
  116. if ($prefix !== $this->principalPrefix) {
  117. throw new Exception('Invalid member group prefix: ' . $prefix);
  118. }
  119. $principalArray = $this->getPrincipalByPath($member);
  120. if (!$principalArray) {
  121. throw new Exception('Principal not found');
  122. }
  123. $found = false;
  124. foreach ($proxies as $proxy) {
  125. if ($proxy->getProxyId() === $member) {
  126. $found = true;
  127. $proxy->setPermissions($proxy->getPermissions() | $permission);
  128. $this->proxyMapper->update($proxy);
  129. $proxies = array_filter($proxies, function (Proxy $p) use ($proxy) {
  130. return $p->getId() !== $proxy->getId();
  131. });
  132. break;
  133. }
  134. }
  135. if ($found === false) {
  136. $proxy = new Proxy();
  137. $proxy->setOwnerId($principalUri);
  138. $proxy->setProxyId($member);
  139. $proxy->setPermissions($permission);
  140. $this->proxyMapper->insert($proxy);
  141. }
  142. }
  143. // Delete all remaining proxies
  144. foreach ($proxies as $proxy) {
  145. // Write and Read Proxies have individual requests,
  146. // so only delete proxies of this permission
  147. if ($proxy->getPermissions() === $permission) {
  148. $this->proxyMapper->delete($proxy);
  149. }
  150. }
  151. }
  152. /**
  153. * @param string $principalUri
  154. * @return bool
  155. */
  156. private function isProxyPrincipal(string $principalUri):bool {
  157. [$realPrincipalUri, $proxy] = \Sabre\Uri\split($principalUri);
  158. [$prefix, $userId] = \Sabre\Uri\split($realPrincipalUri);
  159. if (!isset($prefix) || !isset($userId)) {
  160. return false;
  161. }
  162. if ($prefix !== $this->principalPrefix) {
  163. return false;
  164. }
  165. return $proxy === 'calendar-proxy-read'
  166. || $proxy === 'calendar-proxy-write';
  167. }
  168. /**
  169. * @param string $principalUri
  170. * @return bool
  171. */
  172. private function isReadProxyPrincipal(string $principalUri):bool {
  173. [, $proxy] = \Sabre\Uri\split($principalUri);
  174. return $proxy === 'calendar-proxy-read';
  175. }
  176. /**
  177. * @param string $principalUri
  178. * @return bool
  179. */
  180. private function isWriteProxyPrincipal(string $principalUri):bool {
  181. [, $proxy] = \Sabre\Uri\split($principalUri);
  182. return $proxy === 'calendar-proxy-write';
  183. }
  184. /**
  185. * @param string $principalUri
  186. * @return string
  187. */
  188. private function getPrincipalUriFromProxyPrincipal(string $principalUri):string {
  189. [$realPrincipalUri, ] = \Sabre\Uri\split($principalUri);
  190. return $realPrincipalUri;
  191. }
  192. }