Backend.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. * @author Lukas Reschke <lukas@statuscode.ch>
  7. * @author Thomas Müller <thomas.mueller@tmit.eu>
  8. *
  9. * @license AGPL-3.0
  10. *
  11. * This code is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU Affero General Public License, version 3,
  13. * as published by the Free Software Foundation.
  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, version 3,
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>
  22. *
  23. */
  24. namespace OCA\DAV\DAV\Sharing;
  25. use OCA\DAV\Connector\Sabre\Principal;
  26. use OCP\IDBConnection;
  27. class Backend {
  28. /** @var IDBConnection */
  29. private $db;
  30. /** @var Principal */
  31. private $principalBackend;
  32. /** @var string */
  33. private $resourceType;
  34. const ACCESS_OWNER = 1;
  35. const ACCESS_READ_WRITE = 2;
  36. const ACCESS_READ = 3;
  37. /**
  38. * @param IDBConnection $db
  39. * @param Principal $principalBackend
  40. * @param string $resourceType
  41. */
  42. public function __construct(IDBConnection $db, Principal $principalBackend, $resourceType) {
  43. $this->db = $db;
  44. $this->principalBackend = $principalBackend;
  45. $this->resourceType = $resourceType;
  46. }
  47. /**
  48. * @param IShareable $shareable
  49. * @param string[] $add
  50. * @param string[] $remove
  51. */
  52. public function updateShares($shareable, $add, $remove) {
  53. foreach($add as $element) {
  54. $this->shareWith($shareable, $element);
  55. }
  56. foreach($remove as $element) {
  57. $this->unshare($shareable, $element);
  58. }
  59. }
  60. /**
  61. * @param IShareable $shareable
  62. * @param string $element
  63. */
  64. private function shareWith($shareable, $element) {
  65. $user = $element['href'];
  66. $parts = explode(':', $user, 2);
  67. if ($parts[0] !== 'principal') {
  68. return;
  69. }
  70. // don't share with owner
  71. if ($shareable->getOwner() === $parts[1]) {
  72. return;
  73. }
  74. // remove the share if it already exists
  75. $this->unshare($shareable, $element['href']);
  76. $access = self::ACCESS_READ;
  77. if (isset($element['readOnly'])) {
  78. $access = $element['readOnly'] ? self::ACCESS_READ : self::ACCESS_READ_WRITE;
  79. }
  80. $query = $this->db->getQueryBuilder();
  81. $query->insert('dav_shares')
  82. ->values([
  83. 'principaluri' => $query->createNamedParameter($parts[1]),
  84. 'type' => $query->createNamedParameter($this->resourceType),
  85. 'access' => $query->createNamedParameter($access),
  86. 'resourceid' => $query->createNamedParameter($shareable->getResourceId())
  87. ]);
  88. $query->execute();
  89. }
  90. /**
  91. * @param $resourceId
  92. */
  93. public function deleteAllShares($resourceId) {
  94. $query = $this->db->getQueryBuilder();
  95. $query->delete('dav_shares')
  96. ->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
  97. ->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
  98. ->execute();
  99. }
  100. public function deleteAllSharesByUser($principaluri) {
  101. $query = $this->db->getQueryBuilder();
  102. $query->delete('dav_shares')
  103. ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principaluri)))
  104. ->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
  105. ->execute();
  106. }
  107. /**
  108. * @param IShareable $shareable
  109. * @param string $element
  110. */
  111. private function unshare($shareable, $element) {
  112. $parts = explode(':', $element, 2);
  113. if ($parts[0] !== 'principal') {
  114. return;
  115. }
  116. // don't share with owner
  117. if ($shareable->getOwner() === $parts[1]) {
  118. return;
  119. }
  120. $query = $this->db->getQueryBuilder();
  121. $query->delete('dav_shares')
  122. ->where($query->expr()->eq('resourceid', $query->createNamedParameter($shareable->getResourceId())))
  123. ->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
  124. ->andWhere($query->expr()->eq('principaluri', $query->createNamedParameter($parts[1])))
  125. ;
  126. $query->execute();
  127. }
  128. /**
  129. * Returns the list of people whom this resource is shared with.
  130. *
  131. * Every element in this array should have the following properties:
  132. * * href - Often a mailto: address
  133. * * commonName - Optional, for example a first + last name
  134. * * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
  135. * * readOnly - boolean
  136. * * summary - Optional, a description for the share
  137. *
  138. * @param int $resourceId
  139. * @return array
  140. */
  141. public function getShares($resourceId) {
  142. $query = $this->db->getQueryBuilder();
  143. $result = $query->select(['principaluri', 'access'])
  144. ->from('dav_shares')
  145. ->where($query->expr()->eq('resourceid', $query->createNamedParameter($resourceId)))
  146. ->andWhere($query->expr()->eq('type', $query->createNamedParameter($this->resourceType)))
  147. ->execute();
  148. $shares = [];
  149. while($row = $result->fetch()) {
  150. $p = $this->principalBackend->getPrincipalByPath($row['principaluri']);
  151. $shares[]= [
  152. 'href' => "principal:${row['principaluri']}",
  153. 'commonName' => isset($p['{DAV:}displayname']) ? $p['{DAV:}displayname'] : '',
  154. 'status' => 1,
  155. 'readOnly' => ($row['access'] == self::ACCESS_READ),
  156. '{http://owncloud.org/ns}principal' => $row['principaluri'],
  157. '{http://owncloud.org/ns}group-share' => is_null($p)
  158. ];
  159. }
  160. return $shares;
  161. }
  162. /**
  163. * For shared resources the sharee is set in the ACL of the resource
  164. *
  165. * @param int $resourceId
  166. * @param array $acl
  167. * @return array
  168. */
  169. public function applyShareAcl($resourceId, $acl) {
  170. $shares = $this->getShares($resourceId);
  171. foreach ($shares as $share) {
  172. $acl[] = [
  173. 'privilege' => '{DAV:}read',
  174. 'principal' => $share['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
  175. 'protected' => true,
  176. ];
  177. if (!$share['readOnly']) {
  178. $acl[] = [
  179. 'privilege' => '{DAV:}write',
  180. 'principal' => $share['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
  181. 'protected' => true,
  182. ];
  183. } else if ($this->resourceType === 'calendar') {
  184. // Allow changing the properties of read only calendars,
  185. // so users can change the visibility.
  186. $acl[] = [
  187. 'privilege' => '{DAV:}write-properties',
  188. 'principal' => $share['{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}principal'],
  189. 'protected' => true,
  190. ];
  191. }
  192. }
  193. return $acl;
  194. }
  195. }