1
0

PrincipalProxyTrait.php 6.2 KB

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