Completed
Push — master ( 8e25df...fd681f )
by Joas
13:41
created

Backend::shareWith()   C

Complexity

Conditions 12
Paths 7

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 25
nc 7
nop 2
dl 0
loc 41
rs 5.1612
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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