Completed
Push — master ( 188b96...0947dd )
by Morris
43s queued 10s
created

Backend::deleteAllShares()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 7
Ratio 100 %

Importance

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