Principal.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Bart Visscher <bartv@thisnet.nl>
  6. * @author Jakob Sack <mail@jakobsack.de>
  7. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  8. * @author Lukas Reschke <lukas@statuscode.ch>
  9. * @author Morris Jobke <hey@morrisjobke.de>
  10. * @author Thomas Müller <thomas.mueller@tmit.eu>
  11. * @author Thomas Tanghus <thomas@tanghus.net>
  12. * @author Vincent Petry <pvince81@owncloud.com>
  13. *
  14. * @license AGPL-3.0
  15. *
  16. * This code is free software: you can redistribute it and/or modify
  17. * it under the terms of the GNU Affero General Public License, version 3,
  18. * as published by the Free Software Foundation.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU Affero General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU Affero General Public License, version 3,
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>
  27. *
  28. */
  29. namespace OCA\DAV\Connector\Sabre;
  30. use OCP\IGroup;
  31. use OCP\IGroupManager;
  32. use OCP\IUser;
  33. use OCP\IUserManager;
  34. use Sabre\DAV\Exception;
  35. use \Sabre\DAV\PropPatch;
  36. use Sabre\DAVACL\PrincipalBackend\BackendInterface;
  37. use Sabre\HTTP\URLUtil;
  38. class Principal implements BackendInterface {
  39. /** @var IUserManager */
  40. private $userManager;
  41. /** @var IGroupManager */
  42. private $groupManager;
  43. /** @var string */
  44. private $principalPrefix;
  45. /** @var bool */
  46. private $hasGroups;
  47. /**
  48. * @param IUserManager $userManager
  49. * @param IGroupManager $groupManager
  50. * @param string $principalPrefix
  51. */
  52. public function __construct(IUserManager $userManager,
  53. IGroupManager $groupManager,
  54. $principalPrefix = 'principals/users/') {
  55. $this->userManager = $userManager;
  56. $this->groupManager = $groupManager;
  57. $this->principalPrefix = trim($principalPrefix, '/');
  58. $this->hasGroups = ($principalPrefix === 'principals/users/');
  59. }
  60. /**
  61. * Returns a list of principals based on a prefix.
  62. *
  63. * This prefix will often contain something like 'principals'. You are only
  64. * expected to return principals that are in this base path.
  65. *
  66. * You are expected to return at least a 'uri' for every user, you can
  67. * return any additional properties if you wish so. Common properties are:
  68. * {DAV:}displayname
  69. *
  70. * @param string $prefixPath
  71. * @return string[]
  72. */
  73. public function getPrincipalsByPrefix($prefixPath) {
  74. $principals = [];
  75. if ($prefixPath === $this->principalPrefix) {
  76. foreach($this->userManager->search('') as $user) {
  77. $principals[] = $this->userToPrincipal($user);
  78. }
  79. }
  80. return $principals;
  81. }
  82. /**
  83. * Returns a specific principal, specified by it's path.
  84. * The returned structure should be the exact same as from
  85. * getPrincipalsByPrefix.
  86. *
  87. * @param string $path
  88. * @return array
  89. */
  90. public function getPrincipalByPath($path) {
  91. list($prefix, $name) = URLUtil::splitPath($path);
  92. if ($prefix === $this->principalPrefix) {
  93. $user = $this->userManager->get($name);
  94. if (!is_null($user)) {
  95. return $this->userToPrincipal($user);
  96. }
  97. }
  98. return null;
  99. }
  100. /**
  101. * Returns the list of members for a group-principal
  102. *
  103. * @param string $principal
  104. * @return string[]
  105. * @throws Exception
  106. */
  107. public function getGroupMemberSet($principal) {
  108. // TODO: for now the group principal has only one member, the user itself
  109. $principal = $this->getPrincipalByPath($principal);
  110. if (!$principal) {
  111. throw new Exception('Principal not found');
  112. }
  113. return [$principal['uri']];
  114. }
  115. /**
  116. * Returns the list of groups a principal is a member of
  117. *
  118. * @param string $principal
  119. * @param bool $needGroups
  120. * @return array
  121. * @throws Exception
  122. */
  123. public function getGroupMembership($principal, $needGroups = false) {
  124. list($prefix, $name) = URLUtil::splitPath($principal);
  125. if ($prefix === $this->principalPrefix) {
  126. $user = $this->userManager->get($name);
  127. if (!$user) {
  128. throw new Exception('Principal not found');
  129. }
  130. if ($this->hasGroups || $needGroups) {
  131. $groups = $this->groupManager->getUserGroups($user);
  132. $groups = array_map(function($group) {
  133. /** @var IGroup $group */
  134. return 'principals/groups/' . urlencode($group->getGID());
  135. }, $groups);
  136. return $groups;
  137. }
  138. }
  139. return [];
  140. }
  141. /**
  142. * Updates the list of group members for a group principal.
  143. *
  144. * The principals should be passed as a list of uri's.
  145. *
  146. * @param string $principal
  147. * @param string[] $members
  148. * @throws Exception
  149. */
  150. public function setGroupMemberSet($principal, array $members) {
  151. throw new Exception('Setting members of the group is not supported yet');
  152. }
  153. /**
  154. * @param string $path
  155. * @param PropPatch $propPatch
  156. * @return int
  157. */
  158. function updatePrincipal($path, PropPatch $propPatch) {
  159. return 0;
  160. }
  161. /**
  162. * @param string $prefixPath
  163. * @param array $searchProperties
  164. * @param string $test
  165. * @return array
  166. */
  167. function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
  168. return [];
  169. }
  170. /**
  171. * @param string $uri
  172. * @param string $principalPrefix
  173. * @return string
  174. */
  175. function findByUri($uri, $principalPrefix) {
  176. if (substr($uri, 0, 7) === 'mailto:') {
  177. $email = substr($uri, 7);
  178. $users = $this->userManager->getByEmail($email);
  179. if (count($users) === 1) {
  180. return $this->principalPrefix . '/' . $users[0]->getUID();
  181. }
  182. }
  183. return '';
  184. }
  185. /**
  186. * @param IUser $user
  187. * @return array
  188. */
  189. protected function userToPrincipal($user) {
  190. $userId = $user->getUID();
  191. $displayName = $user->getDisplayName();
  192. $principal = [
  193. 'uri' => $this->principalPrefix . '/' . $userId,
  194. '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
  195. ];
  196. $email = $user->getEMailAddress();
  197. if (!empty($email)) {
  198. $principal['{http://sabredav.org/ns}email-address'] = $email;
  199. return $principal;
  200. }
  201. return $principal;
  202. }
  203. public function getPrincipalPrefix() {
  204. return $this->principalPrefix;
  205. }
  206. }