Passed
Push — master ( 465e91...f452e2 )
by Roeland
12:18 queued 10s
created
apps/dav/lib/Connector/Sabre/Principal.php 2 patches
Indentation   +431 added lines, -431 removed lines patch added patch discarded remove patch
@@ -52,435 +52,435 @@
 block discarded – undo
52 52
 
53 53
 class Principal implements BackendInterface {
54 54
 
55
-	/** @var IUserManager */
56
-	private $userManager;
57
-
58
-	/** @var IGroupManager */
59
-	private $groupManager;
60
-
61
-	/** @var IShareManager */
62
-	private $shareManager;
63
-
64
-	/** @var IUserSession */
65
-	private $userSession;
66
-
67
-	/** @var IAppManager */
68
-	private $appManager;
69
-
70
-	/** @var string */
71
-	private $principalPrefix;
72
-
73
-	/** @var bool */
74
-	private $hasGroups;
75
-
76
-	/** @var bool */
77
-	private $hasCircles;
78
-
79
-	/** @var ProxyMapper */
80
-	private $proxyMapper;
81
-
82
-	/**
83
-	 * Principal constructor.
84
-	 *
85
-	 * @param IUserManager $userManager
86
-	 * @param IGroupManager $groupManager
87
-	 * @param IShareManager $shareManager
88
-	 * @param IUserSession $userSession
89
-	 * @param IAppManager $appManager
90
-	 * @param ProxyMapper $proxyMapper
91
-	 * @param string $principalPrefix
92
-	 */
93
-	public function __construct(IUserManager $userManager,
94
-								IGroupManager $groupManager,
95
-								IShareManager $shareManager,
96
-								IUserSession $userSession,
97
-								IAppManager $appManager,
98
-								ProxyMapper $proxyMapper,
99
-								string $principalPrefix = 'principals/users/') {
100
-		$this->userManager = $userManager;
101
-		$this->groupManager = $groupManager;
102
-		$this->shareManager = $shareManager;
103
-		$this->userSession = $userSession;
104
-		$this->appManager = $appManager;
105
-		$this->principalPrefix = trim($principalPrefix, '/');
106
-		$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
107
-		$this->proxyMapper = $proxyMapper;
108
-	}
109
-
110
-	use PrincipalProxyTrait {
111
-		getGroupMembership as protected traitGetGroupMembership;
112
-	}
113
-
114
-	/**
115
-	 * Returns a list of principals based on a prefix.
116
-	 *
117
-	 * This prefix will often contain something like 'principals'. You are only
118
-	 * expected to return principals that are in this base path.
119
-	 *
120
-	 * You are expected to return at least a 'uri' for every user, you can
121
-	 * return any additional properties if you wish so. Common properties are:
122
-	 *   {DAV:}displayname
123
-	 *
124
-	 * @param string $prefixPath
125
-	 * @return string[]
126
-	 */
127
-	public function getPrincipalsByPrefix($prefixPath) {
128
-		$principals = [];
129
-
130
-		if ($prefixPath === $this->principalPrefix) {
131
-			foreach($this->userManager->search('') as $user) {
132
-				$principals[] = $this->userToPrincipal($user);
133
-			}
134
-		}
135
-
136
-		return $principals;
137
-	}
138
-
139
-	/**
140
-	 * Returns a specific principal, specified by it's path.
141
-	 * The returned structure should be the exact same as from
142
-	 * getPrincipalsByPrefix.
143
-	 *
144
-	 * @param string $path
145
-	 * @return array
146
-	 */
147
-	public function getPrincipalByPath($path) {
148
-		list($prefix, $name) = \Sabre\Uri\split($path);
149
-
150
-		if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') {
151
-			list($prefix2, $name2) = \Sabre\Uri\split($prefix);
152
-
153
-			if ($prefix2 === $this->principalPrefix) {
154
-				$user = $this->userManager->get($name2);
155
-
156
-				if ($user !== null) {
157
-					return [
158
-						'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
159
-					];
160
-				}
161
-				return null;
162
-			}
163
-		}
164
-
165
-		if ($prefix === $this->principalPrefix) {
166
-			$user = $this->userManager->get($name);
167
-
168
-			if ($user !== null) {
169
-				return $this->userToPrincipal($user);
170
-			}
171
-		} else if ($prefix === 'principals/circles') {
172
-			try {
173
-				return $this->circleToPrincipal($name);
174
-			} catch (QueryException $e) {
175
-				return null;
176
-			}
177
-		}
178
-		return null;
179
-	}
180
-
181
-	/**
182
-	 * Returns the list of groups a principal is a member of
183
-	 *
184
-	 * @param string $principal
185
-	 * @param bool $needGroups
186
-	 * @return array
187
-	 * @throws Exception
188
-	 */
189
-	public function getGroupMembership($principal, $needGroups = false) {
190
-		list($prefix, $name) = \Sabre\Uri\split($principal);
191
-
192
-		if ($prefix !== $this->principalPrefix) {
193
-			return [];
194
-		}
195
-
196
-		$user = $this->userManager->get($name);
197
-		if (!$user) {
198
-			throw new Exception('Principal not found');
199
-		}
200
-
201
-		$groups = [];
202
-
203
-		if ($this->hasGroups || $needGroups) {
204
-			$userGroups = $this->groupManager->getUserGroups($user);
205
-			foreach($userGroups as $userGroup) {
206
-				$groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
207
-			}
208
-		}
209
-
210
-		$groups = array_unique(array_merge(
211
-			$groups,
212
-			$this->traitGetGroupMembership($principal, $needGroups)
213
-		));
214
-
215
-		return $groups;
216
-	}
217
-
218
-	/**
219
-	 * @param string $path
220
-	 * @param PropPatch $propPatch
221
-	 * @return int
222
-	 */
223
-	function updatePrincipal($path, PropPatch $propPatch) {
224
-		return 0;
225
-	}
226
-
227
-	/**
228
-	 * Search user principals
229
-	 *
230
-	 * @param array $searchProperties
231
-	 * @param string $test
232
-	 * @return array
233
-	 */
234
-	protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
235
-		$results = [];
236
-
237
-		// If sharing is disabled, return the empty array
238
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
239
-		if (!$shareAPIEnabled) {
240
-			return [];
241
-		}
242
-
243
-		// If sharing is restricted to group members only,
244
-		// return only members that have groups in common
245
-		$restrictGroups = false;
246
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
247
-			$user = $this->userSession->getUser();
248
-			if (!$user) {
249
-				return [];
250
-			}
251
-
252
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
253
-		}
254
-
255
-		foreach ($searchProperties as $prop => $value) {
256
-			switch ($prop) {
257
-				case '{http://sabredav.org/ns}email-address':
258
-					$users = $this->userManager->getByEmail($value);
259
-
260
-					$results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
261
-						// is sharing restricted to groups only?
262
-						if ($restrictGroups !== false) {
263
-							$userGroups = $this->groupManager->getUserGroupIds($user);
264
-							if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
265
-								return $carry;
266
-							}
267
-						}
268
-
269
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
270
-						return $carry;
271
-					}, []);
272
-					break;
273
-
274
-				case '{DAV:}displayname':
275
-					$users = $this->userManager->searchDisplayName($value);
276
-
277
-					$results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
278
-						// is sharing restricted to groups only?
279
-						if ($restrictGroups !== false) {
280
-							$userGroups = $this->groupManager->getUserGroupIds($user);
281
-							if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
282
-								return $carry;
283
-							}
284
-						}
285
-
286
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
287
-						return $carry;
288
-					}, []);
289
-					break;
290
-
291
-				case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
292
-					// If you add support for more search properties that qualify as a user-address,
293
-					// please also add them to the array below
294
-					$results[] = $this->searchUserPrincipals([
295
-						// In theory this should also search for principal:principals/users/...
296
-						// but that's used internally only anyway and i don't know of any client querying that
297
-						'{http://sabredav.org/ns}email-address' => $value,
298
-					], 'anyof');
299
-					break;
300
-
301
-				default:
302
-					$results[] = [];
303
-					break;
304
-			}
305
-		}
306
-
307
-		// results is an array of arrays, so this is not the first search result
308
-		// but the results of the first searchProperty
309
-		if (count($results) === 1) {
310
-			return $results[0];
311
-		}
312
-
313
-		switch ($test) {
314
-			case 'anyof':
315
-				return array_values(array_unique(array_merge(...$results)));
316
-
317
-			case 'allof':
318
-			default:
319
-				return array_values(array_intersect(...$results));
320
-		}
321
-	}
322
-
323
-	/**
324
-	 * @param string $prefixPath
325
-	 * @param array $searchProperties
326
-	 * @param string $test
327
-	 * @return array
328
-	 */
329
-	function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
330
-		if (count($searchProperties) === 0) {
331
-			return [];
332
-		}
333
-
334
-		switch ($prefixPath) {
335
-			case 'principals/users':
336
-				return $this->searchUserPrincipals($searchProperties, $test);
337
-
338
-			default:
339
-				return [];
340
-		}
341
-	}
342
-
343
-	/**
344
-	 * @param string $uri
345
-	 * @param string $principalPrefix
346
-	 * @return string
347
-	 */
348
-	function findByUri($uri, $principalPrefix) {
349
-		// If sharing is disabled, return the empty array
350
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
351
-		if (!$shareAPIEnabled) {
352
-			return null;
353
-		}
354
-
355
-		// If sharing is restricted to group members only,
356
-		// return only members that have groups in common
357
-		$restrictGroups = false;
358
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
359
-			$user = $this->userSession->getUser();
360
-			if (!$user) {
361
-				return null;
362
-			}
363
-
364
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
365
-		}
366
-
367
-		if (strpos($uri, 'mailto:') === 0) {
368
-			if ($principalPrefix === 'principals/users') {
369
-				$users = $this->userManager->getByEmail(substr($uri, 7));
370
-				if (count($users) !== 1) {
371
-					return null;
372
-				}
373
-				$user = $users[0];
374
-
375
-				if ($restrictGroups !== false) {
376
-					$userGroups = $this->groupManager->getUserGroupIds($user);
377
-					if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
378
-						return null;
379
-					}
380
-				}
381
-
382
-				return $this->principalPrefix . '/' . $user->getUID();
383
-			}
384
-		}
385
-		if (substr($uri, 0, 10) === 'principal:') {
386
-			$principal = substr($uri, 10);
387
-			$principal = $this->getPrincipalByPath($principal);
388
-			if ($principal !== null) {
389
-				return $principal['uri'];
390
-			}
391
-		}
392
-
393
-		return null;
394
-	}
395
-
396
-	/**
397
-	 * @param IUser $user
398
-	 * @return array
399
-	 */
400
-	protected function userToPrincipal($user) {
401
-		$userId = $user->getUID();
402
-		$displayName = $user->getDisplayName();
403
-		$principal = [
404
-				'uri' => $this->principalPrefix . '/' . $userId,
405
-				'{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
406
-				'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
407
-		];
408
-
409
-		$email = $user->getEMailAddress();
410
-		if (!empty($email)) {
411
-			$principal['{http://sabredav.org/ns}email-address'] = $email;
412
-		}
413
-
414
-		return $principal;
415
-	}
416
-
417
-	public function getPrincipalPrefix() {
418
-		return $this->principalPrefix;
419
-	}
420
-
421
-	/**
422
-	 * @param string $circleUniqueId
423
-	 * @return array|null
424
-	 * @throws \OCP\AppFramework\QueryException
425
-	 * @suppress PhanUndeclaredClassMethod
426
-	 * @suppress PhanUndeclaredClassCatch
427
-	 */
428
-	protected function circleToPrincipal($circleUniqueId) {
429
-		if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
430
-			return null;
431
-		}
432
-
433
-		try {
434
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
435
-		} catch(QueryException $ex) {
436
-			return null;
437
-		} catch(CircleDoesNotExistException $ex) {
438
-			return null;
439
-		}
440
-
441
-		if (!$circle) {
442
-			return null;
443
-		}
444
-
445
-		$principal = [
446
-			'uri' => 'principals/circles/' . $circleUniqueId,
447
-			'{DAV:}displayname' => $circle->getName(),
448
-		];
449
-
450
-		return $principal;
451
-	}
452
-
453
-	/**
454
-	 * Returns the list of circles a principal is a member of
455
-	 *
456
-	 * @param string $principal
457
-	 * @return array
458
-	 * @throws Exception
459
-	 * @throws \OCP\AppFramework\QueryException
460
-	 * @suppress PhanUndeclaredClassMethod
461
-	 */
462
-	public function getCircleMembership($principal):array {
463
-		if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
464
-			return [];
465
-		}
466
-
467
-		list($prefix, $name) = \Sabre\Uri\split($principal);
468
-		if ($this->hasCircles && $prefix === $this->principalPrefix) {
469
-			$user = $this->userManager->get($name);
470
-			if (!$user) {
471
-				throw new Exception('Principal not found');
472
-			}
473
-
474
-			$circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
475
-
476
-			$circles = array_map(function($circle) {
477
-				/** @var \OCA\Circles\Model\Circle $circle */
478
-				return 'principals/circles/' . urlencode($circle->getUniqueId());
479
-			}, $circles);
480
-
481
-			return $circles;
482
-		}
483
-
484
-		return [];
485
-	}
55
+    /** @var IUserManager */
56
+    private $userManager;
57
+
58
+    /** @var IGroupManager */
59
+    private $groupManager;
60
+
61
+    /** @var IShareManager */
62
+    private $shareManager;
63
+
64
+    /** @var IUserSession */
65
+    private $userSession;
66
+
67
+    /** @var IAppManager */
68
+    private $appManager;
69
+
70
+    /** @var string */
71
+    private $principalPrefix;
72
+
73
+    /** @var bool */
74
+    private $hasGroups;
75
+
76
+    /** @var bool */
77
+    private $hasCircles;
78
+
79
+    /** @var ProxyMapper */
80
+    private $proxyMapper;
81
+
82
+    /**
83
+     * Principal constructor.
84
+     *
85
+     * @param IUserManager $userManager
86
+     * @param IGroupManager $groupManager
87
+     * @param IShareManager $shareManager
88
+     * @param IUserSession $userSession
89
+     * @param IAppManager $appManager
90
+     * @param ProxyMapper $proxyMapper
91
+     * @param string $principalPrefix
92
+     */
93
+    public function __construct(IUserManager $userManager,
94
+                                IGroupManager $groupManager,
95
+                                IShareManager $shareManager,
96
+                                IUserSession $userSession,
97
+                                IAppManager $appManager,
98
+                                ProxyMapper $proxyMapper,
99
+                                string $principalPrefix = 'principals/users/') {
100
+        $this->userManager = $userManager;
101
+        $this->groupManager = $groupManager;
102
+        $this->shareManager = $shareManager;
103
+        $this->userSession = $userSession;
104
+        $this->appManager = $appManager;
105
+        $this->principalPrefix = trim($principalPrefix, '/');
106
+        $this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
107
+        $this->proxyMapper = $proxyMapper;
108
+    }
109
+
110
+    use PrincipalProxyTrait {
111
+        getGroupMembership as protected traitGetGroupMembership;
112
+    }
113
+
114
+    /**
115
+     * Returns a list of principals based on a prefix.
116
+     *
117
+     * This prefix will often contain something like 'principals'. You are only
118
+     * expected to return principals that are in this base path.
119
+     *
120
+     * You are expected to return at least a 'uri' for every user, you can
121
+     * return any additional properties if you wish so. Common properties are:
122
+     *   {DAV:}displayname
123
+     *
124
+     * @param string $prefixPath
125
+     * @return string[]
126
+     */
127
+    public function getPrincipalsByPrefix($prefixPath) {
128
+        $principals = [];
129
+
130
+        if ($prefixPath === $this->principalPrefix) {
131
+            foreach($this->userManager->search('') as $user) {
132
+                $principals[] = $this->userToPrincipal($user);
133
+            }
134
+        }
135
+
136
+        return $principals;
137
+    }
138
+
139
+    /**
140
+     * Returns a specific principal, specified by it's path.
141
+     * The returned structure should be the exact same as from
142
+     * getPrincipalsByPrefix.
143
+     *
144
+     * @param string $path
145
+     * @return array
146
+     */
147
+    public function getPrincipalByPath($path) {
148
+        list($prefix, $name) = \Sabre\Uri\split($path);
149
+
150
+        if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') {
151
+            list($prefix2, $name2) = \Sabre\Uri\split($prefix);
152
+
153
+            if ($prefix2 === $this->principalPrefix) {
154
+                $user = $this->userManager->get($name2);
155
+
156
+                if ($user !== null) {
157
+                    return [
158
+                        'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
159
+                    ];
160
+                }
161
+                return null;
162
+            }
163
+        }
164
+
165
+        if ($prefix === $this->principalPrefix) {
166
+            $user = $this->userManager->get($name);
167
+
168
+            if ($user !== null) {
169
+                return $this->userToPrincipal($user);
170
+            }
171
+        } else if ($prefix === 'principals/circles') {
172
+            try {
173
+                return $this->circleToPrincipal($name);
174
+            } catch (QueryException $e) {
175
+                return null;
176
+            }
177
+        }
178
+        return null;
179
+    }
180
+
181
+    /**
182
+     * Returns the list of groups a principal is a member of
183
+     *
184
+     * @param string $principal
185
+     * @param bool $needGroups
186
+     * @return array
187
+     * @throws Exception
188
+     */
189
+    public function getGroupMembership($principal, $needGroups = false) {
190
+        list($prefix, $name) = \Sabre\Uri\split($principal);
191
+
192
+        if ($prefix !== $this->principalPrefix) {
193
+            return [];
194
+        }
195
+
196
+        $user = $this->userManager->get($name);
197
+        if (!$user) {
198
+            throw new Exception('Principal not found');
199
+        }
200
+
201
+        $groups = [];
202
+
203
+        if ($this->hasGroups || $needGroups) {
204
+            $userGroups = $this->groupManager->getUserGroups($user);
205
+            foreach($userGroups as $userGroup) {
206
+                $groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
207
+            }
208
+        }
209
+
210
+        $groups = array_unique(array_merge(
211
+            $groups,
212
+            $this->traitGetGroupMembership($principal, $needGroups)
213
+        ));
214
+
215
+        return $groups;
216
+    }
217
+
218
+    /**
219
+     * @param string $path
220
+     * @param PropPatch $propPatch
221
+     * @return int
222
+     */
223
+    function updatePrincipal($path, PropPatch $propPatch) {
224
+        return 0;
225
+    }
226
+
227
+    /**
228
+     * Search user principals
229
+     *
230
+     * @param array $searchProperties
231
+     * @param string $test
232
+     * @return array
233
+     */
234
+    protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
235
+        $results = [];
236
+
237
+        // If sharing is disabled, return the empty array
238
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
239
+        if (!$shareAPIEnabled) {
240
+            return [];
241
+        }
242
+
243
+        // If sharing is restricted to group members only,
244
+        // return only members that have groups in common
245
+        $restrictGroups = false;
246
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
247
+            $user = $this->userSession->getUser();
248
+            if (!$user) {
249
+                return [];
250
+            }
251
+
252
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
253
+        }
254
+
255
+        foreach ($searchProperties as $prop => $value) {
256
+            switch ($prop) {
257
+                case '{http://sabredav.org/ns}email-address':
258
+                    $users = $this->userManager->getByEmail($value);
259
+
260
+                    $results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
261
+                        // is sharing restricted to groups only?
262
+                        if ($restrictGroups !== false) {
263
+                            $userGroups = $this->groupManager->getUserGroupIds($user);
264
+                            if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
265
+                                return $carry;
266
+                            }
267
+                        }
268
+
269
+                        $carry[] = $this->principalPrefix . '/' . $user->getUID();
270
+                        return $carry;
271
+                    }, []);
272
+                    break;
273
+
274
+                case '{DAV:}displayname':
275
+                    $users = $this->userManager->searchDisplayName($value);
276
+
277
+                    $results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
278
+                        // is sharing restricted to groups only?
279
+                        if ($restrictGroups !== false) {
280
+                            $userGroups = $this->groupManager->getUserGroupIds($user);
281
+                            if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
282
+                                return $carry;
283
+                            }
284
+                        }
285
+
286
+                        $carry[] = $this->principalPrefix . '/' . $user->getUID();
287
+                        return $carry;
288
+                    }, []);
289
+                    break;
290
+
291
+                case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
292
+                    // If you add support for more search properties that qualify as a user-address,
293
+                    // please also add them to the array below
294
+                    $results[] = $this->searchUserPrincipals([
295
+                        // In theory this should also search for principal:principals/users/...
296
+                        // but that's used internally only anyway and i don't know of any client querying that
297
+                        '{http://sabredav.org/ns}email-address' => $value,
298
+                    ], 'anyof');
299
+                    break;
300
+
301
+                default:
302
+                    $results[] = [];
303
+                    break;
304
+            }
305
+        }
306
+
307
+        // results is an array of arrays, so this is not the first search result
308
+        // but the results of the first searchProperty
309
+        if (count($results) === 1) {
310
+            return $results[0];
311
+        }
312
+
313
+        switch ($test) {
314
+            case 'anyof':
315
+                return array_values(array_unique(array_merge(...$results)));
316
+
317
+            case 'allof':
318
+            default:
319
+                return array_values(array_intersect(...$results));
320
+        }
321
+    }
322
+
323
+    /**
324
+     * @param string $prefixPath
325
+     * @param array $searchProperties
326
+     * @param string $test
327
+     * @return array
328
+     */
329
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
330
+        if (count($searchProperties) === 0) {
331
+            return [];
332
+        }
333
+
334
+        switch ($prefixPath) {
335
+            case 'principals/users':
336
+                return $this->searchUserPrincipals($searchProperties, $test);
337
+
338
+            default:
339
+                return [];
340
+        }
341
+    }
342
+
343
+    /**
344
+     * @param string $uri
345
+     * @param string $principalPrefix
346
+     * @return string
347
+     */
348
+    function findByUri($uri, $principalPrefix) {
349
+        // If sharing is disabled, return the empty array
350
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
351
+        if (!$shareAPIEnabled) {
352
+            return null;
353
+        }
354
+
355
+        // If sharing is restricted to group members only,
356
+        // return only members that have groups in common
357
+        $restrictGroups = false;
358
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
359
+            $user = $this->userSession->getUser();
360
+            if (!$user) {
361
+                return null;
362
+            }
363
+
364
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
365
+        }
366
+
367
+        if (strpos($uri, 'mailto:') === 0) {
368
+            if ($principalPrefix === 'principals/users') {
369
+                $users = $this->userManager->getByEmail(substr($uri, 7));
370
+                if (count($users) !== 1) {
371
+                    return null;
372
+                }
373
+                $user = $users[0];
374
+
375
+                if ($restrictGroups !== false) {
376
+                    $userGroups = $this->groupManager->getUserGroupIds($user);
377
+                    if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
378
+                        return null;
379
+                    }
380
+                }
381
+
382
+                return $this->principalPrefix . '/' . $user->getUID();
383
+            }
384
+        }
385
+        if (substr($uri, 0, 10) === 'principal:') {
386
+            $principal = substr($uri, 10);
387
+            $principal = $this->getPrincipalByPath($principal);
388
+            if ($principal !== null) {
389
+                return $principal['uri'];
390
+            }
391
+        }
392
+
393
+        return null;
394
+    }
395
+
396
+    /**
397
+     * @param IUser $user
398
+     * @return array
399
+     */
400
+    protected function userToPrincipal($user) {
401
+        $userId = $user->getUID();
402
+        $displayName = $user->getDisplayName();
403
+        $principal = [
404
+                'uri' => $this->principalPrefix . '/' . $userId,
405
+                '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
406
+                '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
407
+        ];
408
+
409
+        $email = $user->getEMailAddress();
410
+        if (!empty($email)) {
411
+            $principal['{http://sabredav.org/ns}email-address'] = $email;
412
+        }
413
+
414
+        return $principal;
415
+    }
416
+
417
+    public function getPrincipalPrefix() {
418
+        return $this->principalPrefix;
419
+    }
420
+
421
+    /**
422
+     * @param string $circleUniqueId
423
+     * @return array|null
424
+     * @throws \OCP\AppFramework\QueryException
425
+     * @suppress PhanUndeclaredClassMethod
426
+     * @suppress PhanUndeclaredClassCatch
427
+     */
428
+    protected function circleToPrincipal($circleUniqueId) {
429
+        if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
430
+            return null;
431
+        }
432
+
433
+        try {
434
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
435
+        } catch(QueryException $ex) {
436
+            return null;
437
+        } catch(CircleDoesNotExistException $ex) {
438
+            return null;
439
+        }
440
+
441
+        if (!$circle) {
442
+            return null;
443
+        }
444
+
445
+        $principal = [
446
+            'uri' => 'principals/circles/' . $circleUniqueId,
447
+            '{DAV:}displayname' => $circle->getName(),
448
+        ];
449
+
450
+        return $principal;
451
+    }
452
+
453
+    /**
454
+     * Returns the list of circles a principal is a member of
455
+     *
456
+     * @param string $principal
457
+     * @return array
458
+     * @throws Exception
459
+     * @throws \OCP\AppFramework\QueryException
460
+     * @suppress PhanUndeclaredClassMethod
461
+     */
462
+    public function getCircleMembership($principal):array {
463
+        if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
464
+            return [];
465
+        }
466
+
467
+        list($prefix, $name) = \Sabre\Uri\split($principal);
468
+        if ($this->hasCircles && $prefix === $this->principalPrefix) {
469
+            $user = $this->userManager->get($name);
470
+            if (!$user) {
471
+                throw new Exception('Principal not found');
472
+            }
473
+
474
+            $circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
475
+
476
+            $circles = array_map(function($circle) {
477
+                /** @var \OCA\Circles\Model\Circle $circle */
478
+                return 'principals/circles/' . urlencode($circle->getUniqueId());
479
+            }, $circles);
480
+
481
+            return $circles;
482
+        }
483
+
484
+        return [];
485
+    }
486 486
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
 		$principals = [];
129 129
 
130 130
 		if ($prefixPath === $this->principalPrefix) {
131
-			foreach($this->userManager->search('') as $user) {
131
+			foreach ($this->userManager->search('') as $user) {
132 132
 				$principals[] = $this->userToPrincipal($user);
133 133
 			}
134 134
 		}
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
 
156 156
 				if ($user !== null) {
157 157
 					return [
158
-						'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
158
+						'uri' => 'principals/users/'.$user->getUID().'/'.$name,
159 159
 					];
160 160
 				}
161 161
 				return null;
@@ -202,8 +202,8 @@  discard block
 block discarded – undo
202 202
 
203 203
 		if ($this->hasGroups || $needGroups) {
204 204
 			$userGroups = $this->groupManager->getUserGroups($user);
205
-			foreach($userGroups as $userGroup) {
206
-				$groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
205
+			foreach ($userGroups as $userGroup) {
206
+				$groups[] = 'principals/groups/'.urlencode($userGroup->getGID());
207 207
 			}
208 208
 		}
209 209
 
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
 							}
267 267
 						}
268 268
 
269
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
269
+						$carry[] = $this->principalPrefix.'/'.$user->getUID();
270 270
 						return $carry;
271 271
 					}, []);
272 272
 					break;
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 							}
284 284
 						}
285 285
 
286
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
286
+						$carry[] = $this->principalPrefix.'/'.$user->getUID();
287 287
 						return $carry;
288 288
 					}, []);
289 289
 					break;
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
 					}
380 380
 				}
381 381
 
382
-				return $this->principalPrefix . '/' . $user->getUID();
382
+				return $this->principalPrefix.'/'.$user->getUID();
383 383
 			}
384 384
 		}
385 385
 		if (substr($uri, 0, 10) === 'principal:') {
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
 		$userId = $user->getUID();
402 402
 		$displayName = $user->getDisplayName();
403 403
 		$principal = [
404
-				'uri' => $this->principalPrefix . '/' . $userId,
404
+				'uri' => $this->principalPrefix.'/'.$userId,
405 405
 				'{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
406 406
 				'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
407 407
 		];
@@ -432,9 +432,9 @@  discard block
 block discarded – undo
432 432
 
433 433
 		try {
434 434
 			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
435
-		} catch(QueryException $ex) {
435
+		} catch (QueryException $ex) {
436 436
 			return null;
437
-		} catch(CircleDoesNotExistException $ex) {
437
+		} catch (CircleDoesNotExistException $ex) {
438 438
 			return null;
439 439
 		}
440 440
 
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
 		}
444 444
 
445 445
 		$principal = [
446
-			'uri' => 'principals/circles/' . $circleUniqueId,
446
+			'uri' => 'principals/circles/'.$circleUniqueId,
447 447
 			'{DAV:}displayname' => $circle->getName(),
448 448
 		];
449 449
 
@@ -475,7 +475,7 @@  discard block
 block discarded – undo
475 475
 
476 476
 			$circles = array_map(function($circle) {
477 477
 				/** @var \OCA\Circles\Model\Circle $circle */
478
-				return 'principals/circles/' . urlencode($circle->getUniqueId());
478
+				return 'principals/circles/'.urlencode($circle->getUniqueId());
479 479
 			}, $circles);
480 480
 
481 481
 			return $circles;
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/Calendar.php 2 patches
Indentation   +352 added lines, -352 removed lines patch added patch discarded remove patch
@@ -44,356 +44,356 @@
 block discarded – undo
44 44
  */
45 45
 class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
46 46
 
47
-	/** @var IConfig */
48
-	private $config;
49
-
50
-	/**
51
-	 * Calendar constructor.
52
-	 *
53
-	 * @param BackendInterface $caldavBackend
54
-	 * @param $calendarInfo
55
-	 * @param IL10N $l10n
56
-	 * @param IConfig $config
57
-	 */
58
-	public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n, IConfig $config) {
59
-		parent::__construct($caldavBackend, $calendarInfo);
60
-
61
-		if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
62
-			$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Contact birthdays');
63
-		}
64
-		if ($this->getName() === CalDavBackend::PERSONAL_CALENDAR_URI &&
65
-			$this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
66
-			$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Personal');
67
-		}
68
-
69
-		$this->config = $config;
70
-	}
71
-
72
-	/**
73
-	 * Updates the list of shares.
74
-	 *
75
-	 * The first array is a list of people that are to be added to the
76
-	 * resource.
77
-	 *
78
-	 * Every element in the add array has the following properties:
79
-	 *   * href - A url. Usually a mailto: address
80
-	 *   * commonName - Usually a first and last name, or false
81
-	 *   * summary - A description of the share, can also be false
82
-	 *   * readOnly - A boolean value
83
-	 *
84
-	 * Every element in the remove array is just the address string.
85
-	 *
86
-	 * @param array $add
87
-	 * @param array $remove
88
-	 * @return void
89
-	 * @throws Forbidden
90
-	 */
91
-	public function updateShares(array $add, array $remove) {
92
-		if ($this->isShared()) {
93
-			throw new Forbidden();
94
-		}
95
-		$this->caldavBackend->updateShares($this, $add, $remove);
96
-	}
97
-
98
-	/**
99
-	 * Returns the list of people whom this resource is shared with.
100
-	 *
101
-	 * Every element in this array should have the following properties:
102
-	 *   * href - Often a mailto: address
103
-	 *   * commonName - Optional, for example a first + last name
104
-	 *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
105
-	 *   * readOnly - boolean
106
-	 *   * summary - Optional, a description for the share
107
-	 *
108
-	 * @return array
109
-	 */
110
-	public function getShares() {
111
-		if ($this->isShared()) {
112
-			return [];
113
-		}
114
-		return $this->caldavBackend->getShares($this->getResourceId());
115
-	}
116
-
117
-	/**
118
-	 * @return int
119
-	 */
120
-	public function getResourceId() {
121
-		return $this->calendarInfo['id'];
122
-	}
123
-
124
-	/**
125
-	 * @return string
126
-	 */
127
-	public function getPrincipalURI() {
128
-		return $this->calendarInfo['principaluri'];
129
-	}
130
-
131
-	/**
132
-	 * @return array
133
-	 */
134
-	public function getACL() {
135
-		$acl =  [
136
-			[
137
-				'privilege' => '{DAV:}read',
138
-				'principal' => $this->getOwner(),
139
-				'protected' => true,
140
-			],
141
-			[
142
-				'privilege' => '{DAV:}read',
143
-				'principal' => $this->getOwner() . '/calendar-proxy-write',
144
-				'protected' => true,
145
-			],
146
-			[
147
-				'privilege' => '{DAV:}read',
148
-				'principal' => $this->getOwner() . '/calendar-proxy-read',
149
-				'protected' => true,
150
-			],
151
-		];
152
-
153
-		if ($this->getName() !== BirthdayService::BIRTHDAY_CALENDAR_URI) {
154
-			$acl[] = [
155
-				'privilege' => '{DAV:}write',
156
-				'principal' => $this->getOwner(),
157
-				'protected' => true,
158
-			];
159
-			$acl[] = [
160
-				'privilege' => '{DAV:}write',
161
-				'principal' => $this->getOwner() . '/calendar-proxy-write',
162
-				'protected' => true,
163
-			];
164
-		} else {
165
-			$acl[] = [
166
-				'privilege' => '{DAV:}write-properties',
167
-				'principal' => $this->getOwner(),
168
-				'protected' => true,
169
-			];
170
-			$acl[] = [
171
-				'privilege' => '{DAV:}write-properties',
172
-				'principal' => $this->getOwner() . '/calendar-proxy-write',
173
-				'protected' => true,
174
-			];
175
-		}
176
-
177
-		$acl[] = [
178
-			'privilege' => '{DAV:}write-properties',
179
-			'principal' => $this->getOwner() . '/calendar-proxy-read',
180
-			'protected' => true,
181
-		];
182
-
183
-		if (!$this->isShared()) {
184
-			return $acl;
185
-		}
186
-
187
-		if ($this->getOwner() !== parent::getOwner()) {
188
-			$acl[] =  [
189
-					'privilege' => '{DAV:}read',
190
-					'principal' => parent::getOwner(),
191
-					'protected' => true,
192
-				];
193
-			if ($this->canWrite()) {
194
-				$acl[] = [
195
-					'privilege' => '{DAV:}write',
196
-					'principal' => parent::getOwner(),
197
-					'protected' => true,
198
-				];
199
-			} else {
200
-				$acl[] = [
201
-					'privilege' => '{DAV:}write-properties',
202
-					'principal' => parent::getOwner(),
203
-					'protected' => true,
204
-				];
205
-			}
206
-		}
207
-		if ($this->isPublic()) {
208
-			$acl[] = [
209
-				'privilege' => '{DAV:}read',
210
-				'principal' => 'principals/system/public',
211
-				'protected' => true,
212
-			];
213
-		}
214
-
215
-		$acl = $this->caldavBackend->applyShareAcl($this->getResourceId(), $acl);
216
-		$allowedPrincipals = [
217
-			$this->getOwner(),
218
-			$this->getOwner(). '/calendar-proxy-read',
219
-			$this->getOwner(). '/calendar-proxy-write',
220
-			parent::getOwner(),
221
-			'principals/system/public'
222
-		];
223
-		return array_filter($acl, function($rule) use ($allowedPrincipals) {
224
-			return \in_array($rule['principal'], $allowedPrincipals, true);
225
-		});
226
-	}
227
-
228
-	public function getChildACL() {
229
-		return $this->getACL();
230
-	}
231
-
232
-	public function getOwner() {
233
-		if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
234
-			return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'];
235
-		}
236
-		return parent::getOwner();
237
-	}
238
-
239
-	public function delete() {
240
-		if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) &&
241
-			$this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri']) {
242
-			$principal = 'principal:' . parent::getOwner();
243
-			$shares = $this->caldavBackend->getShares($this->getResourceId());
244
-			$shares = array_filter($shares, function($share) use ($principal){
245
-				return $share['href'] === $principal;
246
-			});
247
-			if (empty($shares)) {
248
-				throw new Forbidden();
249
-			}
250
-
251
-			$this->caldavBackend->updateShares($this, [], [
252
-				$principal
253
-			]);
254
-			return;
255
-		}
256
-
257
-		// Remember when a user deleted their birthday calendar
258
-		// in order to not regenerate it on the next contacts change
259
-		if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
260
-			$principalURI = $this->getPrincipalURI();
261
-			$userId = substr($principalURI, 17);
262
-
263
-			$this->config->setUserValue($userId, 'dav', 'generateBirthdayCalendar', 'no');
264
-		}
265
-
266
-		parent::delete();
267
-	}
268
-
269
-	public function propPatch(PropPatch $propPatch) {
270
-		// parent::propPatch will only update calendars table
271
-		// if calendar is shared, changes have to be made to the properties table
272
-		if (!$this->isShared()) {
273
-			parent::propPatch($propPatch);
274
-		}
275
-	}
276
-
277
-	public function getChild($name) {
278
-
279
-		$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
280
-
281
-		if (!$obj) {
282
-			throw new NotFound('Calendar object not found');
283
-		}
284
-
285
-		if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
286
-			throw new NotFound('Calendar object not found');
287
-		}
288
-
289
-		$obj['acl'] = $this->getChildACL();
290
-
291
-		return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
292
-
293
-	}
294
-
295
-	public function getChildren() {
296
-
297
-		$objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
298
-		$children = [];
299
-		foreach ($objs as $obj) {
300
-			if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
301
-				continue;
302
-			}
303
-			$obj['acl'] = $this->getChildACL();
304
-			$children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
305
-		}
306
-		return $children;
307
-
308
-	}
309
-
310
-	public function getMultipleChildren(array $paths) {
311
-
312
-		$objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
313
-		$children = [];
314
-		foreach ($objs as $obj) {
315
-			if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
316
-				continue;
317
-			}
318
-			$obj['acl'] = $this->getChildACL();
319
-			$children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
320
-		}
321
-		return $children;
322
-
323
-	}
324
-
325
-	public function childExists($name) {
326
-		$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
327
-		if (!$obj) {
328
-			return false;
329
-		}
330
-		if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
331
-			return false;
332
-		}
333
-
334
-		return true;
335
-	}
336
-
337
-	public function calendarQuery(array $filters) {
338
-
339
-		$uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
340
-		if ($this->isShared()) {
341
-			return array_filter($uris, function ($uri) {
342
-				return $this->childExists($uri);
343
-			});
344
-		}
345
-
346
-		return $uris;
347
-	}
348
-
349
-	/**
350
-	 * @param boolean $value
351
-	 * @return string|null
352
-	 */
353
-	public function setPublishStatus($value) {
354
-		$publicUri = $this->caldavBackend->setPublishStatus($value, $this);
355
-		$this->calendarInfo['publicuri'] = $publicUri;
356
-		return $publicUri;
357
-	}
358
-
359
-	/**
360
-	 * @return mixed $value
361
-	 */
362
-	public function getPublishStatus() {
363
-		return $this->caldavBackend->getPublishStatus($this);
364
-	}
365
-
366
-	private function canWrite() {
367
-		if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
368
-			return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
369
-		}
370
-		return true;
371
-	}
372
-
373
-	private function isPublic() {
374
-		return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
375
-	}
376
-
377
-	protected function isShared() {
378
-		if (!isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
379
-			return false;
380
-		}
381
-
382
-		return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri'];
383
-	}
384
-
385
-	public function isSubscription() {
386
-		return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
387
-	}
388
-
389
-	/**
390
-	 * @inheritDoc
391
-	 */
392
-	public function getChanges($syncToken, $syncLevel, $limit = null) {
393
-		if (!$syncToken && $limit) {
394
-			throw new UnsupportedLimitOnInitialSyncException();
395
-		}
396
-
397
-		return parent::getChanges($syncToken, $syncLevel, $limit);
398
-	}
47
+    /** @var IConfig */
48
+    private $config;
49
+
50
+    /**
51
+     * Calendar constructor.
52
+     *
53
+     * @param BackendInterface $caldavBackend
54
+     * @param $calendarInfo
55
+     * @param IL10N $l10n
56
+     * @param IConfig $config
57
+     */
58
+    public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n, IConfig $config) {
59
+        parent::__construct($caldavBackend, $calendarInfo);
60
+
61
+        if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
62
+            $this->calendarInfo['{DAV:}displayname'] = $l10n->t('Contact birthdays');
63
+        }
64
+        if ($this->getName() === CalDavBackend::PERSONAL_CALENDAR_URI &&
65
+            $this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
66
+            $this->calendarInfo['{DAV:}displayname'] = $l10n->t('Personal');
67
+        }
68
+
69
+        $this->config = $config;
70
+    }
71
+
72
+    /**
73
+     * Updates the list of shares.
74
+     *
75
+     * The first array is a list of people that are to be added to the
76
+     * resource.
77
+     *
78
+     * Every element in the add array has the following properties:
79
+     *   * href - A url. Usually a mailto: address
80
+     *   * commonName - Usually a first and last name, or false
81
+     *   * summary - A description of the share, can also be false
82
+     *   * readOnly - A boolean value
83
+     *
84
+     * Every element in the remove array is just the address string.
85
+     *
86
+     * @param array $add
87
+     * @param array $remove
88
+     * @return void
89
+     * @throws Forbidden
90
+     */
91
+    public function updateShares(array $add, array $remove) {
92
+        if ($this->isShared()) {
93
+            throw new Forbidden();
94
+        }
95
+        $this->caldavBackend->updateShares($this, $add, $remove);
96
+    }
97
+
98
+    /**
99
+     * Returns the list of people whom this resource is shared with.
100
+     *
101
+     * Every element in this array should have the following properties:
102
+     *   * href - Often a mailto: address
103
+     *   * commonName - Optional, for example a first + last name
104
+     *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
105
+     *   * readOnly - boolean
106
+     *   * summary - Optional, a description for the share
107
+     *
108
+     * @return array
109
+     */
110
+    public function getShares() {
111
+        if ($this->isShared()) {
112
+            return [];
113
+        }
114
+        return $this->caldavBackend->getShares($this->getResourceId());
115
+    }
116
+
117
+    /**
118
+     * @return int
119
+     */
120
+    public function getResourceId() {
121
+        return $this->calendarInfo['id'];
122
+    }
123
+
124
+    /**
125
+     * @return string
126
+     */
127
+    public function getPrincipalURI() {
128
+        return $this->calendarInfo['principaluri'];
129
+    }
130
+
131
+    /**
132
+     * @return array
133
+     */
134
+    public function getACL() {
135
+        $acl =  [
136
+            [
137
+                'privilege' => '{DAV:}read',
138
+                'principal' => $this->getOwner(),
139
+                'protected' => true,
140
+            ],
141
+            [
142
+                'privilege' => '{DAV:}read',
143
+                'principal' => $this->getOwner() . '/calendar-proxy-write',
144
+                'protected' => true,
145
+            ],
146
+            [
147
+                'privilege' => '{DAV:}read',
148
+                'principal' => $this->getOwner() . '/calendar-proxy-read',
149
+                'protected' => true,
150
+            ],
151
+        ];
152
+
153
+        if ($this->getName() !== BirthdayService::BIRTHDAY_CALENDAR_URI) {
154
+            $acl[] = [
155
+                'privilege' => '{DAV:}write',
156
+                'principal' => $this->getOwner(),
157
+                'protected' => true,
158
+            ];
159
+            $acl[] = [
160
+                'privilege' => '{DAV:}write',
161
+                'principal' => $this->getOwner() . '/calendar-proxy-write',
162
+                'protected' => true,
163
+            ];
164
+        } else {
165
+            $acl[] = [
166
+                'privilege' => '{DAV:}write-properties',
167
+                'principal' => $this->getOwner(),
168
+                'protected' => true,
169
+            ];
170
+            $acl[] = [
171
+                'privilege' => '{DAV:}write-properties',
172
+                'principal' => $this->getOwner() . '/calendar-proxy-write',
173
+                'protected' => true,
174
+            ];
175
+        }
176
+
177
+        $acl[] = [
178
+            'privilege' => '{DAV:}write-properties',
179
+            'principal' => $this->getOwner() . '/calendar-proxy-read',
180
+            'protected' => true,
181
+        ];
182
+
183
+        if (!$this->isShared()) {
184
+            return $acl;
185
+        }
186
+
187
+        if ($this->getOwner() !== parent::getOwner()) {
188
+            $acl[] =  [
189
+                    'privilege' => '{DAV:}read',
190
+                    'principal' => parent::getOwner(),
191
+                    'protected' => true,
192
+                ];
193
+            if ($this->canWrite()) {
194
+                $acl[] = [
195
+                    'privilege' => '{DAV:}write',
196
+                    'principal' => parent::getOwner(),
197
+                    'protected' => true,
198
+                ];
199
+            } else {
200
+                $acl[] = [
201
+                    'privilege' => '{DAV:}write-properties',
202
+                    'principal' => parent::getOwner(),
203
+                    'protected' => true,
204
+                ];
205
+            }
206
+        }
207
+        if ($this->isPublic()) {
208
+            $acl[] = [
209
+                'privilege' => '{DAV:}read',
210
+                'principal' => 'principals/system/public',
211
+                'protected' => true,
212
+            ];
213
+        }
214
+
215
+        $acl = $this->caldavBackend->applyShareAcl($this->getResourceId(), $acl);
216
+        $allowedPrincipals = [
217
+            $this->getOwner(),
218
+            $this->getOwner(). '/calendar-proxy-read',
219
+            $this->getOwner(). '/calendar-proxy-write',
220
+            parent::getOwner(),
221
+            'principals/system/public'
222
+        ];
223
+        return array_filter($acl, function($rule) use ($allowedPrincipals) {
224
+            return \in_array($rule['principal'], $allowedPrincipals, true);
225
+        });
226
+    }
227
+
228
+    public function getChildACL() {
229
+        return $this->getACL();
230
+    }
231
+
232
+    public function getOwner() {
233
+        if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
234
+            return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'];
235
+        }
236
+        return parent::getOwner();
237
+    }
238
+
239
+    public function delete() {
240
+        if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) &&
241
+            $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri']) {
242
+            $principal = 'principal:' . parent::getOwner();
243
+            $shares = $this->caldavBackend->getShares($this->getResourceId());
244
+            $shares = array_filter($shares, function($share) use ($principal){
245
+                return $share['href'] === $principal;
246
+            });
247
+            if (empty($shares)) {
248
+                throw new Forbidden();
249
+            }
250
+
251
+            $this->caldavBackend->updateShares($this, [], [
252
+                $principal
253
+            ]);
254
+            return;
255
+        }
256
+
257
+        // Remember when a user deleted their birthday calendar
258
+        // in order to not regenerate it on the next contacts change
259
+        if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
260
+            $principalURI = $this->getPrincipalURI();
261
+            $userId = substr($principalURI, 17);
262
+
263
+            $this->config->setUserValue($userId, 'dav', 'generateBirthdayCalendar', 'no');
264
+        }
265
+
266
+        parent::delete();
267
+    }
268
+
269
+    public function propPatch(PropPatch $propPatch) {
270
+        // parent::propPatch will only update calendars table
271
+        // if calendar is shared, changes have to be made to the properties table
272
+        if (!$this->isShared()) {
273
+            parent::propPatch($propPatch);
274
+        }
275
+    }
276
+
277
+    public function getChild($name) {
278
+
279
+        $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
280
+
281
+        if (!$obj) {
282
+            throw new NotFound('Calendar object not found');
283
+        }
284
+
285
+        if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
286
+            throw new NotFound('Calendar object not found');
287
+        }
288
+
289
+        $obj['acl'] = $this->getChildACL();
290
+
291
+        return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
292
+
293
+    }
294
+
295
+    public function getChildren() {
296
+
297
+        $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
298
+        $children = [];
299
+        foreach ($objs as $obj) {
300
+            if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
301
+                continue;
302
+            }
303
+            $obj['acl'] = $this->getChildACL();
304
+            $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
305
+        }
306
+        return $children;
307
+
308
+    }
309
+
310
+    public function getMultipleChildren(array $paths) {
311
+
312
+        $objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
313
+        $children = [];
314
+        foreach ($objs as $obj) {
315
+            if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
316
+                continue;
317
+            }
318
+            $obj['acl'] = $this->getChildACL();
319
+            $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
320
+        }
321
+        return $children;
322
+
323
+    }
324
+
325
+    public function childExists($name) {
326
+        $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
327
+        if (!$obj) {
328
+            return false;
329
+        }
330
+        if ($obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE && $this->isShared()) {
331
+            return false;
332
+        }
333
+
334
+        return true;
335
+    }
336
+
337
+    public function calendarQuery(array $filters) {
338
+
339
+        $uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
340
+        if ($this->isShared()) {
341
+            return array_filter($uris, function ($uri) {
342
+                return $this->childExists($uri);
343
+            });
344
+        }
345
+
346
+        return $uris;
347
+    }
348
+
349
+    /**
350
+     * @param boolean $value
351
+     * @return string|null
352
+     */
353
+    public function setPublishStatus($value) {
354
+        $publicUri = $this->caldavBackend->setPublishStatus($value, $this);
355
+        $this->calendarInfo['publicuri'] = $publicUri;
356
+        return $publicUri;
357
+    }
358
+
359
+    /**
360
+     * @return mixed $value
361
+     */
362
+    public function getPublishStatus() {
363
+        return $this->caldavBackend->getPublishStatus($this);
364
+    }
365
+
366
+    private function canWrite() {
367
+        if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
368
+            return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
369
+        }
370
+        return true;
371
+    }
372
+
373
+    private function isPublic() {
374
+        return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
375
+    }
376
+
377
+    protected function isShared() {
378
+        if (!isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
379
+            return false;
380
+        }
381
+
382
+        return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri'];
383
+    }
384
+
385
+    public function isSubscription() {
386
+        return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
387
+    }
388
+
389
+    /**
390
+     * @inheritDoc
391
+     */
392
+    public function getChanges($syncToken, $syncLevel, $limit = null) {
393
+        if (!$syncToken && $limit) {
394
+            throw new UnsupportedLimitOnInitialSyncException();
395
+        }
396
+
397
+        return parent::getChanges($syncToken, $syncLevel, $limit);
398
+    }
399 399
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
 	 * @return array
133 133
 	 */
134 134
 	public function getACL() {
135
-		$acl =  [
135
+		$acl = [
136 136
 			[
137 137
 				'privilege' => '{DAV:}read',
138 138
 				'principal' => $this->getOwner(),
@@ -140,12 +140,12 @@  discard block
 block discarded – undo
140 140
 			],
141 141
 			[
142 142
 				'privilege' => '{DAV:}read',
143
-				'principal' => $this->getOwner() . '/calendar-proxy-write',
143
+				'principal' => $this->getOwner().'/calendar-proxy-write',
144 144
 				'protected' => true,
145 145
 			],
146 146
 			[
147 147
 				'privilege' => '{DAV:}read',
148
-				'principal' => $this->getOwner() . '/calendar-proxy-read',
148
+				'principal' => $this->getOwner().'/calendar-proxy-read',
149 149
 				'protected' => true,
150 150
 			],
151 151
 		];
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 			];
159 159
 			$acl[] = [
160 160
 				'privilege' => '{DAV:}write',
161
-				'principal' => $this->getOwner() . '/calendar-proxy-write',
161
+				'principal' => $this->getOwner().'/calendar-proxy-write',
162 162
 				'protected' => true,
163 163
 			];
164 164
 		} else {
@@ -169,14 +169,14 @@  discard block
 block discarded – undo
169 169
 			];
170 170
 			$acl[] = [
171 171
 				'privilege' => '{DAV:}write-properties',
172
-				'principal' => $this->getOwner() . '/calendar-proxy-write',
172
+				'principal' => $this->getOwner().'/calendar-proxy-write',
173 173
 				'protected' => true,
174 174
 			];
175 175
 		}
176 176
 
177 177
 		$acl[] = [
178 178
 			'privilege' => '{DAV:}write-properties',
179
-			'principal' => $this->getOwner() . '/calendar-proxy-read',
179
+			'principal' => $this->getOwner().'/calendar-proxy-read',
180 180
 			'protected' => true,
181 181
 		];
182 182
 
@@ -185,7 +185,7 @@  discard block
 block discarded – undo
185 185
 		}
186 186
 
187 187
 		if ($this->getOwner() !== parent::getOwner()) {
188
-			$acl[] =  [
188
+			$acl[] = [
189 189
 					'privilege' => '{DAV:}read',
190 190
 					'principal' => parent::getOwner(),
191 191
 					'protected' => true,
@@ -215,8 +215,8 @@  discard block
 block discarded – undo
215 215
 		$acl = $this->caldavBackend->applyShareAcl($this->getResourceId(), $acl);
216 216
 		$allowedPrincipals = [
217 217
 			$this->getOwner(),
218
-			$this->getOwner(). '/calendar-proxy-read',
219
-			$this->getOwner(). '/calendar-proxy-write',
218
+			$this->getOwner().'/calendar-proxy-read',
219
+			$this->getOwner().'/calendar-proxy-write',
220 220
 			parent::getOwner(),
221 221
 			'principals/system/public'
222 222
 		];
@@ -239,7 +239,7 @@  discard block
 block discarded – undo
239 239
 	public function delete() {
240 240
 		if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) &&
241 241
 			$this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri']) {
242
-			$principal = 'principal:' . parent::getOwner();
242
+			$principal = 'principal:'.parent::getOwner();
243 243
 			$shares = $this->caldavBackend->getShares($this->getResourceId());
244 244
 			$shares = array_filter($shares, function($share) use ($principal){
245 245
 				return $share['href'] === $principal;
@@ -338,7 +338,7 @@  discard block
 block discarded – undo
338 338
 
339 339
 		$uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
340 340
 		if ($this->isShared()) {
341
-			return array_filter($uris, function ($uri) {
341
+			return array_filter($uris, function($uri) {
342 342
 				return $this->childExists($uri);
343 343
 			});
344 344
 		}
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/Proxy/Proxy.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -36,16 +36,16 @@
 block discarded – undo
36 36
  */
37 37
 class Proxy extends Entity {
38 38
 
39
-	/** @var string */
40
-	protected $ownerId;
41
-	/** @var string */
42
-	protected $proxyId;
43
-	/** @var int */
44
-	protected $permissions;
39
+    /** @var string */
40
+    protected $ownerId;
41
+    /** @var string */
42
+    protected $proxyId;
43
+    /** @var int */
44
+    protected $permissions;
45 45
 
46
-	public function __construct() {
47
-		$this->addType('ownerId', 'string');
48
-		$this->addType('proxyId', 'string');
49
-		$this->addType('permissions', 'int');
50
-	}
46
+    public function __construct() {
47
+        $this->addType('ownerId', 'string');
48
+        $this->addType('proxyId', 'string');
49
+        $this->addType('permissions', 'int');
50
+    }
51 51
 }
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/Proxy/ProxyMapper.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -34,45 +34,45 @@
 block discarded – undo
34 34
  */
35 35
 class ProxyMapper extends QBMapper {
36 36
 
37
-	const PERMISSION_READ  = 1;
38
-	const PERMISSION_WRITE = 2;
37
+    const PERMISSION_READ  = 1;
38
+    const PERMISSION_WRITE = 2;
39 39
 
40
-	/**
41
-	 * ProxyMapper constructor.
42
-	 *
43
-	 * @param IDBConnection $db
44
-	 */
45
-	public function __construct(IDBConnection $db) {
46
-		parent::__construct($db, 'dav_cal_proxy', Proxy::class);
47
-	}
40
+    /**
41
+     * ProxyMapper constructor.
42
+     *
43
+     * @param IDBConnection $db
44
+     */
45
+    public function __construct(IDBConnection $db) {
46
+        parent::__construct($db, 'dav_cal_proxy', Proxy::class);
47
+    }
48 48
 
49
-	/**
50
-	 * @param string $proxyId The principal uri that can act as a proxy for the resulting calendars
51
-	 *
52
-	 * @return Proxy[]
53
-	 */
54
-	public function getProxiesFor(string $proxyId): array {
55
-		$qb = $this->db->getQueryBuilder();
49
+    /**
50
+     * @param string $proxyId The principal uri that can act as a proxy for the resulting calendars
51
+     *
52
+     * @return Proxy[]
53
+     */
54
+    public function getProxiesFor(string $proxyId): array {
55
+        $qb = $this->db->getQueryBuilder();
56 56
 
57
-		$qb->select('*')
58
-			->from($this->getTableName())
59
-			->where($qb->expr()->eq('proxy_id', $qb->createNamedParameter($proxyId)));
57
+        $qb->select('*')
58
+            ->from($this->getTableName())
59
+            ->where($qb->expr()->eq('proxy_id', $qb->createNamedParameter($proxyId)));
60 60
 
61
-		return $this->findEntities($qb);
62
-	}
61
+        return $this->findEntities($qb);
62
+    }
63 63
 
64
-	/**
65
-	 * @param string $ownerId The principal uri that has the resulting proxies for their calendars
66
-	 *
67
-	 * @return Proxy[]
68
-	 */
69
-	public function getProxiesOf(string $ownerId): array {
70
-		$qb = $this->db->getQueryBuilder();
64
+    /**
65
+     * @param string $ownerId The principal uri that has the resulting proxies for their calendars
66
+     *
67
+     * @return Proxy[]
68
+     */
69
+    public function getProxiesOf(string $ownerId): array {
70
+        $qb = $this->db->getQueryBuilder();
71 71
 
72
-		$qb->select('*')
73
-			->from($this->getTableName())
74
-			->where($qb->expr()->eq('owner_id', $qb->createNamedParameter($ownerId)));
72
+        $qb->select('*')
73
+            ->from($this->getTableName())
74
+            ->where($qb->expr()->eq('owner_id', $qb->createNamedParameter($ownerId)));
75 75
 
76
-		return $this->findEntities($qb);
77
-	}
76
+        return $this->findEntities($qb);
77
+    }
78 78
 }
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -35,21 +35,21 @@
 block discarded – undo
35 35
  */
36 36
 class ResourcePrincipalBackend extends AbstractPrincipalBackend {
37 37
 
38
-	/**
39
-	 * ResourcePrincipalBackend constructor.
40
-	 *
41
-	 * @param IDBConnection $dbConnection
42
-	 * @param IUserSession $userSession
43
-	 * @param IGroupManager $groupManager
44
-	 * @param ILogger $logger
45
-	 * @param ProxyMapper $proxyMapper
46
-	 */
47
-	public function __construct(IDBConnection $dbConnection,
48
-								IUserSession $userSession,
49
-								IGroupManager $groupManager,
50
-								ILogger $logger,
51
-								ProxyMapper $proxyMapper) {
52
-		parent::__construct($dbConnection, $userSession, $groupManager, $logger,
53
-			$proxyMapper, 'principals/calendar-resources', 'resource', 'RESOURCE');
54
-	}
38
+    /**
39
+     * ResourcePrincipalBackend constructor.
40
+     *
41
+     * @param IDBConnection $dbConnection
42
+     * @param IUserSession $userSession
43
+     * @param IGroupManager $groupManager
44
+     * @param ILogger $logger
45
+     * @param ProxyMapper $proxyMapper
46
+     */
47
+    public function __construct(IDBConnection $dbConnection,
48
+                                IUserSession $userSession,
49
+                                IGroupManager $groupManager,
50
+                                ILogger $logger,
51
+                                ProxyMapper $proxyMapper) {
52
+        parent::__construct($dbConnection, $userSession, $groupManager, $logger,
53
+            $proxyMapper, 'principals/calendar-resources', 'resource', 'RESOURCE');
54
+    }
55 55
 }
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php 2 patches
Indentation   +435 added lines, -435 removed lines patch added patch discarded remove patch
@@ -34,439 +34,439 @@
 block discarded – undo
34 34
 
35 35
 abstract class AbstractPrincipalBackend implements BackendInterface {
36 36
 
37
-	/** @var IDBConnection */
38
-	private $db;
39
-
40
-	/** @var IUserSession */
41
-	private $userSession;
42
-
43
-	/** @var IGroupManager */
44
-	private $groupManager;
45
-
46
-	/** @var ILogger */
47
-	private $logger;
48
-
49
-	/** @var ProxyMapper */
50
-	private $proxyMapper;
51
-
52
-	/** @var string */
53
-	private $principalPrefix;
54
-
55
-	/** @var string */
56
-	private $dbTableName;
57
-
58
-	/** @var string */
59
-	private $dbMetaDataTableName;
60
-
61
-	/** @var string */
62
-	private $dbForeignKeyName;
63
-
64
-	/** @var string */
65
-	private $cuType;
66
-
67
-	/**
68
-	 * @param IDBConnection $dbConnection
69
-	 * @param IUserSession $userSession
70
-	 * @param IGroupManager $groupManager
71
-	 * @param ILogger $logger
72
-	 * @param string $principalPrefix
73
-	 * @param string $dbPrefix
74
-	 * @param string $cuType
75
-	 */
76
-	public function __construct(IDBConnection $dbConnection,
77
-								IUserSession $userSession,
78
-								IGroupManager $groupManager,
79
-								ILogger $logger,
80
-								ProxyMapper $proxyMapper,
81
-								string $principalPrefix,
82
-								string $dbPrefix,
83
-								string $cuType) {
84
-		$this->db = $dbConnection;
85
-		$this->userSession = $userSession;
86
-		$this->groupManager = $groupManager;
87
-		$this->logger = $logger;
88
-		$this->proxyMapper = $proxyMapper;
89
-		$this->principalPrefix = $principalPrefix;
90
-		$this->dbTableName = 'calendar_' . $dbPrefix . 's';
91
-		$this->dbMetaDataTableName = $this->dbTableName . '_md';
92
-		$this->dbForeignKeyName = $dbPrefix . '_id';
93
-		$this->cuType = $cuType;
94
-	}
95
-
96
-	use PrincipalProxyTrait;
97
-
98
-	/**
99
-	 * Returns a list of principals based on a prefix.
100
-	 *
101
-	 * This prefix will often contain something like 'principals'. You are only
102
-	 * expected to return principals that are in this base path.
103
-	 *
104
-	 * You are expected to return at least a 'uri' for every user, you can
105
-	 * return any additional properties if you wish so. Common properties are:
106
-	 *   {DAV:}displayname
107
-	 *
108
-	 * @param string $prefixPath
109
-	 * @return string[]
110
-	 */
111
-	public function getPrincipalsByPrefix($prefixPath) {
112
-		$principals = [];
113
-
114
-		if ($prefixPath === $this->principalPrefix) {
115
-			$query = $this->db->getQueryBuilder();
116
-			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
117
-				->from($this->dbTableName);
118
-			$stmt = $query->execute();
119
-
120
-			$metaDataQuery = $this->db->getQueryBuilder();
121
-			$metaDataQuery->select([$this->dbForeignKeyName, 'key', 'value'])
122
-				->from($this->dbMetaDataTableName);
123
-			$metaDataStmt = $metaDataQuery->execute();
124
-			$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
125
-
126
-			$metaDataById = [];
127
-			foreach($metaDataRows as $metaDataRow) {
128
-				if (!isset($metaDataById[$metaDataRow[$this->dbForeignKeyName]])) {
129
-					$metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
130
-				}
131
-
132
-				$metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']] =
133
-					$metaDataRow['value'];
134
-			}
135
-
136
-			while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
137
-				$id = $row['id'];
138
-
139
-				if (isset($metaDataById[$id])) {
140
-					$principals[] = $this->rowToPrincipal($row, $metaDataById[$id]);
141
-				} else {
142
-					$principals[] = $this->rowToPrincipal($row);
143
-				}
144
-
145
-			}
146
-
147
-			$stmt->closeCursor();
148
-		}
149
-
150
-		return $principals;
151
-	}
152
-
153
-	/**
154
-	 * Returns a specific principal, specified by it's path.
155
-	 * The returned structure should be the exact same as from
156
-	 * getPrincipalsByPrefix.
157
-	 *
158
-	 * @param string $path
159
-	 * @return array
160
-	 */
161
-	public function getPrincipalByPath($path) {
162
-		if (strpos($path, $this->principalPrefix) !== 0) {
163
-			return null;
164
-		}
165
-		list(, $name) = \Sabre\Uri\split($path);
166
-
167
-		list($backendId, $resourceId) = explode('-',  $name, 2);
168
-
169
-		$query = $this->db->getQueryBuilder();
170
-		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
171
-			->from($this->dbTableName)
172
-			->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
173
-			->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
174
-		$stmt = $query->execute();
175
-		$row = $stmt->fetch(\PDO::FETCH_ASSOC);
176
-
177
-		if(!$row) {
178
-			return null;
179
-		}
180
-
181
-		$metaDataQuery = $this->db->getQueryBuilder();
182
-		$metaDataQuery->select(['key', 'value'])
183
-			->from($this->dbMetaDataTableName)
184
-			->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
185
-		$metaDataStmt = $metaDataQuery->execute();
186
-		$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
187
-		$metadata = [];
188
-
189
-		foreach($metaDataRows as $metaDataRow) {
190
-			$metadata[$metaDataRow['key']] = $metaDataRow['value'];
191
-		}
192
-
193
-		return $this->rowToPrincipal($row, $metadata);
194
-	}
195
-
196
-	/**
197
-	 * @param int $id
198
-	 * @return array|null
199
-	 */
200
-	public function getPrincipalById($id):?array {
201
-		$query = $this->db->getQueryBuilder();
202
-		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
203
-			->from($this->dbTableName)
204
-			->where($query->expr()->eq('id', $query->createNamedParameter($id)));
205
-		$stmt = $query->execute();
206
-		$row = $stmt->fetch(\PDO::FETCH_ASSOC);
207
-
208
-		if(!$row) {
209
-			return null;
210
-		}
211
-
212
-		$metaDataQuery = $this->db->getQueryBuilder();
213
-		$metaDataQuery->select(['key', 'value'])
214
-			->from($this->dbMetaDataTableName)
215
-			->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
216
-		$metaDataStmt = $metaDataQuery->execute();
217
-		$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
218
-		$metadata = [];
219
-
220
-		foreach($metaDataRows as $metaDataRow) {
221
-			$metadata[$metaDataRow['key']] = $metaDataRow['value'];
222
-		}
223
-
224
-		return $this->rowToPrincipal($row, $metadata);
225
-	}
226
-
227
-	/**
228
-	 * @param string $path
229
-	 * @param PropPatch $propPatch
230
-	 * @return int
231
-	 */
232
-	function updatePrincipal($path, PropPatch $propPatch) {
233
-		return 0;
234
-	}
235
-
236
-	/**
237
-	 * @param string $prefixPath
238
-	 * @param array $searchProperties
239
-	 * @param string $test
240
-	 * @return array
241
-	 */
242
-	function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
243
-		$results = [];
244
-		if (\count($searchProperties) === 0) {
245
-			return [];
246
-		}
247
-		if ($prefixPath !== $this->principalPrefix) {
248
-			return [];
249
-		}
250
-
251
-		$user = $this->userSession->getUser();
252
-		if (!$user) {
253
-			return [];
254
-		}
255
-		$usersGroups = $this->groupManager->getUserGroupIds($user);
256
-
257
-		foreach ($searchProperties as $prop => $value) {
258
-			switch ($prop) {
259
-				case '{http://sabredav.org/ns}email-address':
260
-					$query = $this->db->getQueryBuilder();
261
-					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
262
-						->from($this->dbTableName)
263
-						->where($query->expr()->iLike('email', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
264
-
265
-					$stmt = $query->execute();
266
-					$principals = [];
267
-					while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
268
-						if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
269
-							continue;
270
-						}
271
-						$principals[] = $this->rowToPrincipal($row)['uri'];
272
-					}
273
-					$results[] = $principals;
274
-
275
-					$stmt->closeCursor();
276
-					break;
277
-
278
-				case '{DAV:}displayname':
279
-					$query = $this->db->getQueryBuilder();
280
-					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
281
-						->from($this->dbTableName)
282
-						->where($query->expr()->iLike('displayname', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
283
-
284
-					$stmt = $query->execute();
285
-					$principals = [];
286
-					while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
287
-						if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
288
-							continue;
289
-						}
290
-						$principals[] = $this->rowToPrincipal($row)['uri'];
291
-					}
292
-					$results[] = $principals;
293
-
294
-					$stmt->closeCursor();
295
-					break;
296
-
297
-				case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
298
-					// If you add support for more search properties that qualify as a user-address,
299
-					// please also add them to the array below
300
-					$results[] = $this->searchPrincipals($this->principalPrefix, [
301
-						'{http://sabredav.org/ns}email-address' => $value,
302
-					], 'anyof');
303
-					break;
304
-
305
-				default:
306
-					$rowsByMetadata = $this->searchPrincipalsByMetadataKey($prop, $value);
307
-					$filteredRows = array_filter($rowsByMetadata, function($row) use ($usersGroups) {
308
-						return $this->isAllowedToAccessResource($row, $usersGroups);
309
-					});
310
-
311
-					$results[] = array_map(function($row) {
312
-						return $row['uri'];
313
-					}, $filteredRows);
314
-
315
-					break;
316
-			}
317
-		}
318
-
319
-		// results is an array of arrays, so this is not the first search result
320
-		// but the results of the first searchProperty
321
-		if (count($results) === 1) {
322
-			return $results[0];
323
-		}
324
-
325
-		switch ($test) {
326
-			case 'anyof':
327
-				return array_values(array_unique(array_merge(...$results)));
328
-
329
-			case 'allof':
330
-			default:
331
-				return array_values(array_intersect(...$results));
332
-		}
333
-	}
334
-
335
-	/**
336
-	 * Searches principals based on their metadata keys.
337
-	 * This allows to search for all principals with a specific key.
338
-	 * e.g.:
339
-	 * '{http://nextcloud.com/ns}room-building-address' => 'ABC Street 123, ...'
340
-	 *
341
-	 * @param $key
342
-	 * @param $value
343
-	 * @return array
344
-	 */
345
-	private function searchPrincipalsByMetadataKey($key, $value):array {
346
-		$query = $this->db->getQueryBuilder();
347
-		$query->select([$this->dbForeignKeyName])
348
-			->from($this->dbMetaDataTableName)
349
-			->where($query->expr()->eq('key', $query->createNamedParameter($key)))
350
-			->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
351
-		$stmt = $query->execute();
352
-
353
-		$rows = [];
354
-		while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
355
-			$id = $row[$this->dbForeignKeyName];
356
-
357
-			$principalRow = $this->getPrincipalById($id);
358
-			if (!$principalRow) {
359
-				continue;
360
-			}
361
-
362
-			$rows[] = $principalRow;
363
-		}
364
-
365
-		return $rows;
366
-	}
367
-
368
-	/**
369
-	 * @param string $uri
370
-	 * @param string $principalPrefix
371
-	 * @return null|string
372
-	 */
373
-	function findByUri($uri, $principalPrefix) {
374
-		$user = $this->userSession->getUser();
375
-		if (!$user) {
376
-			return null;
377
-		}
378
-		$usersGroups = $this->groupManager->getUserGroupIds($user);
379
-
380
-		if (strpos($uri, 'mailto:') === 0) {
381
-			$email = substr($uri, 7);
382
-			$query = $this->db->getQueryBuilder();
383
-			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
384
-				->from($this->dbTableName)
385
-				->where($query->expr()->eq('email', $query->createNamedParameter($email)));
386
-
387
-			$stmt = $query->execute();
388
-			$row = $stmt->fetch(\PDO::FETCH_ASSOC);
389
-
390
-			if(!$row) {
391
-				return null;
392
-			}
393
-			if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
394
-				return null;
395
-			}
396
-
397
-			return $this->rowToPrincipal($row)['uri'];
398
-		}
399
-
400
-		if (strpos($uri, 'principal:') === 0) {
401
-			$path = substr($uri, 10);
402
-			if (strpos($path, $this->principalPrefix) !== 0) {
403
-				return null;
404
-			}
405
-
406
-			list(, $name) = \Sabre\Uri\split($path);
407
-			list($backendId, $resourceId) = explode('-',  $name, 2);
408
-
409
-			$query = $this->db->getQueryBuilder();
410
-			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
411
-				->from($this->dbTableName)
412
-				->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
413
-				->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
414
-			$stmt = $query->execute();
415
-			$row = $stmt->fetch(\PDO::FETCH_ASSOC);
416
-
417
-			if(!$row) {
418
-				return null;
419
-			}
420
-			if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
421
-				return null;
422
-			}
423
-
424
-			return $this->rowToPrincipal($row)['uri'];
425
-		}
426
-
427
-		return null;
428
-	}
429
-
430
-	/**
431
-	 * convert database row to principal
432
-	 *
433
-	 * @param String[] $row
434
-	 * @param String[] $metadata
435
-	 * @return Array
436
-	 */
437
-	private function rowToPrincipal(array $row, array $metadata=[]):array {
438
-		return array_merge([
439
-			'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
440
-			'{DAV:}displayname' => $row['displayname'],
441
-			'{http://sabredav.org/ns}email-address' => $row['email'],
442
-			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
443
-		], $metadata);
444
-	}
445
-
446
-	/**
447
-	 * @param $row
448
-	 * @param $userGroups
449
-	 * @return bool
450
-	 */
451
-	private function isAllowedToAccessResource(array $row, array $userGroups):bool {
452
-		if (!isset($row['group_restrictions']) ||
453
-			$row['group_restrictions'] === null ||
454
-			$row['group_restrictions'] === '') {
455
-			return true;
456
-		}
457
-
458
-		// group restrictions contains something, but not parsable, deny access and log warning
459
-		$json = json_decode($row['group_restrictions']);
460
-		if (!\is_array($json)) {
461
-			$this->logger->info('group_restrictions field could not be parsed for ' . $this->dbTableName . '::' . $row['id'] . ', denying access to resource');
462
-			return false;
463
-		}
464
-
465
-		// empty array => no group restrictions
466
-		if (empty($json)) {
467
-			return true;
468
-		}
469
-
470
-		return !empty(array_intersect($json, $userGroups));
471
-	}
37
+    /** @var IDBConnection */
38
+    private $db;
39
+
40
+    /** @var IUserSession */
41
+    private $userSession;
42
+
43
+    /** @var IGroupManager */
44
+    private $groupManager;
45
+
46
+    /** @var ILogger */
47
+    private $logger;
48
+
49
+    /** @var ProxyMapper */
50
+    private $proxyMapper;
51
+
52
+    /** @var string */
53
+    private $principalPrefix;
54
+
55
+    /** @var string */
56
+    private $dbTableName;
57
+
58
+    /** @var string */
59
+    private $dbMetaDataTableName;
60
+
61
+    /** @var string */
62
+    private $dbForeignKeyName;
63
+
64
+    /** @var string */
65
+    private $cuType;
66
+
67
+    /**
68
+     * @param IDBConnection $dbConnection
69
+     * @param IUserSession $userSession
70
+     * @param IGroupManager $groupManager
71
+     * @param ILogger $logger
72
+     * @param string $principalPrefix
73
+     * @param string $dbPrefix
74
+     * @param string $cuType
75
+     */
76
+    public function __construct(IDBConnection $dbConnection,
77
+                                IUserSession $userSession,
78
+                                IGroupManager $groupManager,
79
+                                ILogger $logger,
80
+                                ProxyMapper $proxyMapper,
81
+                                string $principalPrefix,
82
+                                string $dbPrefix,
83
+                                string $cuType) {
84
+        $this->db = $dbConnection;
85
+        $this->userSession = $userSession;
86
+        $this->groupManager = $groupManager;
87
+        $this->logger = $logger;
88
+        $this->proxyMapper = $proxyMapper;
89
+        $this->principalPrefix = $principalPrefix;
90
+        $this->dbTableName = 'calendar_' . $dbPrefix . 's';
91
+        $this->dbMetaDataTableName = $this->dbTableName . '_md';
92
+        $this->dbForeignKeyName = $dbPrefix . '_id';
93
+        $this->cuType = $cuType;
94
+    }
95
+
96
+    use PrincipalProxyTrait;
97
+
98
+    /**
99
+     * Returns a list of principals based on a prefix.
100
+     *
101
+     * This prefix will often contain something like 'principals'. You are only
102
+     * expected to return principals that are in this base path.
103
+     *
104
+     * You are expected to return at least a 'uri' for every user, you can
105
+     * return any additional properties if you wish so. Common properties are:
106
+     *   {DAV:}displayname
107
+     *
108
+     * @param string $prefixPath
109
+     * @return string[]
110
+     */
111
+    public function getPrincipalsByPrefix($prefixPath) {
112
+        $principals = [];
113
+
114
+        if ($prefixPath === $this->principalPrefix) {
115
+            $query = $this->db->getQueryBuilder();
116
+            $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
117
+                ->from($this->dbTableName);
118
+            $stmt = $query->execute();
119
+
120
+            $metaDataQuery = $this->db->getQueryBuilder();
121
+            $metaDataQuery->select([$this->dbForeignKeyName, 'key', 'value'])
122
+                ->from($this->dbMetaDataTableName);
123
+            $metaDataStmt = $metaDataQuery->execute();
124
+            $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
125
+
126
+            $metaDataById = [];
127
+            foreach($metaDataRows as $metaDataRow) {
128
+                if (!isset($metaDataById[$metaDataRow[$this->dbForeignKeyName]])) {
129
+                    $metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
130
+                }
131
+
132
+                $metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']] =
133
+                    $metaDataRow['value'];
134
+            }
135
+
136
+            while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
137
+                $id = $row['id'];
138
+
139
+                if (isset($metaDataById[$id])) {
140
+                    $principals[] = $this->rowToPrincipal($row, $metaDataById[$id]);
141
+                } else {
142
+                    $principals[] = $this->rowToPrincipal($row);
143
+                }
144
+
145
+            }
146
+
147
+            $stmt->closeCursor();
148
+        }
149
+
150
+        return $principals;
151
+    }
152
+
153
+    /**
154
+     * Returns a specific principal, specified by it's path.
155
+     * The returned structure should be the exact same as from
156
+     * getPrincipalsByPrefix.
157
+     *
158
+     * @param string $path
159
+     * @return array
160
+     */
161
+    public function getPrincipalByPath($path) {
162
+        if (strpos($path, $this->principalPrefix) !== 0) {
163
+            return null;
164
+        }
165
+        list(, $name) = \Sabre\Uri\split($path);
166
+
167
+        list($backendId, $resourceId) = explode('-',  $name, 2);
168
+
169
+        $query = $this->db->getQueryBuilder();
170
+        $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
171
+            ->from($this->dbTableName)
172
+            ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
173
+            ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
174
+        $stmt = $query->execute();
175
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
176
+
177
+        if(!$row) {
178
+            return null;
179
+        }
180
+
181
+        $metaDataQuery = $this->db->getQueryBuilder();
182
+        $metaDataQuery->select(['key', 'value'])
183
+            ->from($this->dbMetaDataTableName)
184
+            ->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
185
+        $metaDataStmt = $metaDataQuery->execute();
186
+        $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
187
+        $metadata = [];
188
+
189
+        foreach($metaDataRows as $metaDataRow) {
190
+            $metadata[$metaDataRow['key']] = $metaDataRow['value'];
191
+        }
192
+
193
+        return $this->rowToPrincipal($row, $metadata);
194
+    }
195
+
196
+    /**
197
+     * @param int $id
198
+     * @return array|null
199
+     */
200
+    public function getPrincipalById($id):?array {
201
+        $query = $this->db->getQueryBuilder();
202
+        $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
203
+            ->from($this->dbTableName)
204
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id)));
205
+        $stmt = $query->execute();
206
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
207
+
208
+        if(!$row) {
209
+            return null;
210
+        }
211
+
212
+        $metaDataQuery = $this->db->getQueryBuilder();
213
+        $metaDataQuery->select(['key', 'value'])
214
+            ->from($this->dbMetaDataTableName)
215
+            ->where($metaDataQuery->expr()->eq($this->dbForeignKeyName, $metaDataQuery->createNamedParameter($row['id'])));
216
+        $metaDataStmt = $metaDataQuery->execute();
217
+        $metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
218
+        $metadata = [];
219
+
220
+        foreach($metaDataRows as $metaDataRow) {
221
+            $metadata[$metaDataRow['key']] = $metaDataRow['value'];
222
+        }
223
+
224
+        return $this->rowToPrincipal($row, $metadata);
225
+    }
226
+
227
+    /**
228
+     * @param string $path
229
+     * @param PropPatch $propPatch
230
+     * @return int
231
+     */
232
+    function updatePrincipal($path, PropPatch $propPatch) {
233
+        return 0;
234
+    }
235
+
236
+    /**
237
+     * @param string $prefixPath
238
+     * @param array $searchProperties
239
+     * @param string $test
240
+     * @return array
241
+     */
242
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
243
+        $results = [];
244
+        if (\count($searchProperties) === 0) {
245
+            return [];
246
+        }
247
+        if ($prefixPath !== $this->principalPrefix) {
248
+            return [];
249
+        }
250
+
251
+        $user = $this->userSession->getUser();
252
+        if (!$user) {
253
+            return [];
254
+        }
255
+        $usersGroups = $this->groupManager->getUserGroupIds($user);
256
+
257
+        foreach ($searchProperties as $prop => $value) {
258
+            switch ($prop) {
259
+                case '{http://sabredav.org/ns}email-address':
260
+                    $query = $this->db->getQueryBuilder();
261
+                    $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
262
+                        ->from($this->dbTableName)
263
+                        ->where($query->expr()->iLike('email', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
264
+
265
+                    $stmt = $query->execute();
266
+                    $principals = [];
267
+                    while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
268
+                        if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
269
+                            continue;
270
+                        }
271
+                        $principals[] = $this->rowToPrincipal($row)['uri'];
272
+                    }
273
+                    $results[] = $principals;
274
+
275
+                    $stmt->closeCursor();
276
+                    break;
277
+
278
+                case '{DAV:}displayname':
279
+                    $query = $this->db->getQueryBuilder();
280
+                    $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
281
+                        ->from($this->dbTableName)
282
+                        ->where($query->expr()->iLike('displayname', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
283
+
284
+                    $stmt = $query->execute();
285
+                    $principals = [];
286
+                    while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
287
+                        if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
288
+                            continue;
289
+                        }
290
+                        $principals[] = $this->rowToPrincipal($row)['uri'];
291
+                    }
292
+                    $results[] = $principals;
293
+
294
+                    $stmt->closeCursor();
295
+                    break;
296
+
297
+                case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
298
+                    // If you add support for more search properties that qualify as a user-address,
299
+                    // please also add them to the array below
300
+                    $results[] = $this->searchPrincipals($this->principalPrefix, [
301
+                        '{http://sabredav.org/ns}email-address' => $value,
302
+                    ], 'anyof');
303
+                    break;
304
+
305
+                default:
306
+                    $rowsByMetadata = $this->searchPrincipalsByMetadataKey($prop, $value);
307
+                    $filteredRows = array_filter($rowsByMetadata, function($row) use ($usersGroups) {
308
+                        return $this->isAllowedToAccessResource($row, $usersGroups);
309
+                    });
310
+
311
+                    $results[] = array_map(function($row) {
312
+                        return $row['uri'];
313
+                    }, $filteredRows);
314
+
315
+                    break;
316
+            }
317
+        }
318
+
319
+        // results is an array of arrays, so this is not the first search result
320
+        // but the results of the first searchProperty
321
+        if (count($results) === 1) {
322
+            return $results[0];
323
+        }
324
+
325
+        switch ($test) {
326
+            case 'anyof':
327
+                return array_values(array_unique(array_merge(...$results)));
328
+
329
+            case 'allof':
330
+            default:
331
+                return array_values(array_intersect(...$results));
332
+        }
333
+    }
334
+
335
+    /**
336
+     * Searches principals based on their metadata keys.
337
+     * This allows to search for all principals with a specific key.
338
+     * e.g.:
339
+     * '{http://nextcloud.com/ns}room-building-address' => 'ABC Street 123, ...'
340
+     *
341
+     * @param $key
342
+     * @param $value
343
+     * @return array
344
+     */
345
+    private function searchPrincipalsByMetadataKey($key, $value):array {
346
+        $query = $this->db->getQueryBuilder();
347
+        $query->select([$this->dbForeignKeyName])
348
+            ->from($this->dbMetaDataTableName)
349
+            ->where($query->expr()->eq('key', $query->createNamedParameter($key)))
350
+            ->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
351
+        $stmt = $query->execute();
352
+
353
+        $rows = [];
354
+        while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
355
+            $id = $row[$this->dbForeignKeyName];
356
+
357
+            $principalRow = $this->getPrincipalById($id);
358
+            if (!$principalRow) {
359
+                continue;
360
+            }
361
+
362
+            $rows[] = $principalRow;
363
+        }
364
+
365
+        return $rows;
366
+    }
367
+
368
+    /**
369
+     * @param string $uri
370
+     * @param string $principalPrefix
371
+     * @return null|string
372
+     */
373
+    function findByUri($uri, $principalPrefix) {
374
+        $user = $this->userSession->getUser();
375
+        if (!$user) {
376
+            return null;
377
+        }
378
+        $usersGroups = $this->groupManager->getUserGroupIds($user);
379
+
380
+        if (strpos($uri, 'mailto:') === 0) {
381
+            $email = substr($uri, 7);
382
+            $query = $this->db->getQueryBuilder();
383
+            $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
384
+                ->from($this->dbTableName)
385
+                ->where($query->expr()->eq('email', $query->createNamedParameter($email)));
386
+
387
+            $stmt = $query->execute();
388
+            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
389
+
390
+            if(!$row) {
391
+                return null;
392
+            }
393
+            if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
394
+                return null;
395
+            }
396
+
397
+            return $this->rowToPrincipal($row)['uri'];
398
+        }
399
+
400
+        if (strpos($uri, 'principal:') === 0) {
401
+            $path = substr($uri, 10);
402
+            if (strpos($path, $this->principalPrefix) !== 0) {
403
+                return null;
404
+            }
405
+
406
+            list(, $name) = \Sabre\Uri\split($path);
407
+            list($backendId, $resourceId) = explode('-',  $name, 2);
408
+
409
+            $query = $this->db->getQueryBuilder();
410
+            $query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
411
+                ->from($this->dbTableName)
412
+                ->where($query->expr()->eq('backend_id', $query->createNamedParameter($backendId)))
413
+                ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resourceId)));
414
+            $stmt = $query->execute();
415
+            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
416
+
417
+            if(!$row) {
418
+                return null;
419
+            }
420
+            if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
421
+                return null;
422
+            }
423
+
424
+            return $this->rowToPrincipal($row)['uri'];
425
+        }
426
+
427
+        return null;
428
+    }
429
+
430
+    /**
431
+     * convert database row to principal
432
+     *
433
+     * @param String[] $row
434
+     * @param String[] $metadata
435
+     * @return Array
436
+     */
437
+    private function rowToPrincipal(array $row, array $metadata=[]):array {
438
+        return array_merge([
439
+            'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
440
+            '{DAV:}displayname' => $row['displayname'],
441
+            '{http://sabredav.org/ns}email-address' => $row['email'],
442
+            '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
443
+        ], $metadata);
444
+    }
445
+
446
+    /**
447
+     * @param $row
448
+     * @param $userGroups
449
+     * @return bool
450
+     */
451
+    private function isAllowedToAccessResource(array $row, array $userGroups):bool {
452
+        if (!isset($row['group_restrictions']) ||
453
+            $row['group_restrictions'] === null ||
454
+            $row['group_restrictions'] === '') {
455
+            return true;
456
+        }
457
+
458
+        // group restrictions contains something, but not parsable, deny access and log warning
459
+        $json = json_decode($row['group_restrictions']);
460
+        if (!\is_array($json)) {
461
+            $this->logger->info('group_restrictions field could not be parsed for ' . $this->dbTableName . '::' . $row['id'] . ', denying access to resource');
462
+            return false;
463
+        }
464
+
465
+        // empty array => no group restrictions
466
+        if (empty($json)) {
467
+            return true;
468
+        }
469
+
470
+        return !empty(array_intersect($json, $userGroups));
471
+    }
472 472
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -87,9 +87,9 @@  discard block
 block discarded – undo
87 87
 		$this->logger = $logger;
88 88
 		$this->proxyMapper = $proxyMapper;
89 89
 		$this->principalPrefix = $principalPrefix;
90
-		$this->dbTableName = 'calendar_' . $dbPrefix . 's';
91
-		$this->dbMetaDataTableName = $this->dbTableName . '_md';
92
-		$this->dbForeignKeyName = $dbPrefix . '_id';
90
+		$this->dbTableName = 'calendar_'.$dbPrefix.'s';
91
+		$this->dbMetaDataTableName = $this->dbTableName.'_md';
92
+		$this->dbForeignKeyName = $dbPrefix.'_id';
93 93
 		$this->cuType = $cuType;
94 94
 	}
95 95
 
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
 			$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
125 125
 
126 126
 			$metaDataById = [];
127
-			foreach($metaDataRows as $metaDataRow) {
127
+			foreach ($metaDataRows as $metaDataRow) {
128 128
 				if (!isset($metaDataById[$metaDataRow[$this->dbForeignKeyName]])) {
129 129
 					$metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
130 130
 				}
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
 					$metaDataRow['value'];
134 134
 			}
135 135
 
136
-			while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
136
+			while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
137 137
 				$id = $row['id'];
138 138
 
139 139
 				if (isset($metaDataById[$id])) {
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
 		}
165 165
 		list(, $name) = \Sabre\Uri\split($path);
166 166
 
167
-		list($backendId, $resourceId) = explode('-',  $name, 2);
167
+		list($backendId, $resourceId) = explode('-', $name, 2);
168 168
 
169 169
 		$query = $this->db->getQueryBuilder();
170 170
 		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
@@ -174,7 +174,7 @@  discard block
 block discarded – undo
174 174
 		$stmt = $query->execute();
175 175
 		$row = $stmt->fetch(\PDO::FETCH_ASSOC);
176 176
 
177
-		if(!$row) {
177
+		if (!$row) {
178 178
 			return null;
179 179
 		}
180 180
 
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
 		$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
187 187
 		$metadata = [];
188 188
 
189
-		foreach($metaDataRows as $metaDataRow) {
189
+		foreach ($metaDataRows as $metaDataRow) {
190 190
 			$metadata[$metaDataRow['key']] = $metaDataRow['value'];
191 191
 		}
192 192
 
@@ -197,7 +197,7 @@  discard block
 block discarded – undo
197 197
 	 * @param int $id
198 198
 	 * @return array|null
199 199
 	 */
200
-	public function getPrincipalById($id):?array {
200
+	public function getPrincipalById($id): ?array {
201 201
 		$query = $this->db->getQueryBuilder();
202 202
 		$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname'])
203 203
 			->from($this->dbTableName)
@@ -205,7 +205,7 @@  discard block
 block discarded – undo
205 205
 		$stmt = $query->execute();
206 206
 		$row = $stmt->fetch(\PDO::FETCH_ASSOC);
207 207
 
208
-		if(!$row) {
208
+		if (!$row) {
209 209
 			return null;
210 210
 		}
211 211
 
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
 		$metaDataRows = $metaDataStmt->fetchAll(\PDO::FETCH_ASSOC);
218 218
 		$metadata = [];
219 219
 
220
-		foreach($metaDataRows as $metaDataRow) {
220
+		foreach ($metaDataRows as $metaDataRow) {
221 221
 			$metadata[$metaDataRow['key']] = $metaDataRow['value'];
222 222
 		}
223 223
 
@@ -260,11 +260,11 @@  discard block
 block discarded – undo
260 260
 					$query = $this->db->getQueryBuilder();
261 261
 					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
262 262
 						->from($this->dbTableName)
263
-						->where($query->expr()->iLike('email', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
263
+						->where($query->expr()->iLike('email', $query->createNamedParameter('%'.$this->db->escapeLikeParameter($value).'%')));
264 264
 
265 265
 					$stmt = $query->execute();
266 266
 					$principals = [];
267
-					while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
267
+					while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
268 268
 						if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
269 269
 							continue;
270 270
 						}
@@ -279,11 +279,11 @@  discard block
 block discarded – undo
279 279
 					$query = $this->db->getQueryBuilder();
280 280
 					$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
281 281
 						->from($this->dbTableName)
282
-						->where($query->expr()->iLike('displayname', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
282
+						->where($query->expr()->iLike('displayname', $query->createNamedParameter('%'.$this->db->escapeLikeParameter($value).'%')));
283 283
 
284 284
 					$stmt = $query->execute();
285 285
 					$principals = [];
286
-					while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
286
+					while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
287 287
 						if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
288 288
 							continue;
289 289
 						}
@@ -347,11 +347,11 @@  discard block
 block discarded – undo
347 347
 		$query->select([$this->dbForeignKeyName])
348 348
 			->from($this->dbMetaDataTableName)
349 349
 			->where($query->expr()->eq('key', $query->createNamedParameter($key)))
350
-			->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%' . $this->db->escapeLikeParameter($value) . '%')));
350
+			->andWhere($query->expr()->iLike('value', $query->createNamedParameter('%'.$this->db->escapeLikeParameter($value).'%')));
351 351
 		$stmt = $query->execute();
352 352
 
353 353
 		$rows = [];
354
-		while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
354
+		while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
355 355
 			$id = $row[$this->dbForeignKeyName];
356 356
 
357 357
 			$principalRow = $this->getPrincipalById($id);
@@ -387,7 +387,7 @@  discard block
 block discarded – undo
387 387
 			$stmt = $query->execute();
388 388
 			$row = $stmt->fetch(\PDO::FETCH_ASSOC);
389 389
 
390
-			if(!$row) {
390
+			if (!$row) {
391 391
 				return null;
392 392
 			}
393 393
 			if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
@@ -404,7 +404,7 @@  discard block
 block discarded – undo
404 404
 			}
405 405
 
406 406
 			list(, $name) = \Sabre\Uri\split($path);
407
-			list($backendId, $resourceId) = explode('-',  $name, 2);
407
+			list($backendId, $resourceId) = explode('-', $name, 2);
408 408
 
409 409
 			$query = $this->db->getQueryBuilder();
410 410
 			$query->select(['id', 'backend_id', 'resource_id', 'email', 'displayname', 'group_restrictions'])
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
 			$stmt = $query->execute();
415 415
 			$row = $stmt->fetch(\PDO::FETCH_ASSOC);
416 416
 
417
-			if(!$row) {
417
+			if (!$row) {
418 418
 				return null;
419 419
 			}
420 420
 			if (!$this->isAllowedToAccessResource($row, $usersGroups)) {
@@ -434,9 +434,9 @@  discard block
 block discarded – undo
434 434
 	 * @param String[] $metadata
435 435
 	 * @return Array
436 436
 	 */
437
-	private function rowToPrincipal(array $row, array $metadata=[]):array {
437
+	private function rowToPrincipal(array $row, array $metadata = []):array {
438 438
 		return array_merge([
439
-			'uri' => $this->principalPrefix . '/' . $row['backend_id'] . '-' . $row['resource_id'],
439
+			'uri' => $this->principalPrefix.'/'.$row['backend_id'].'-'.$row['resource_id'],
440 440
 			'{DAV:}displayname' => $row['displayname'],
441 441
 			'{http://sabredav.org/ns}email-address' => $row['email'],
442 442
 			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->cuType,
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
 		// group restrictions contains something, but not parsable, deny access and log warning
459 459
 		$json = json_decode($row['group_restrictions']);
460 460
 		if (!\is_array($json)) {
461
-			$this->logger->info('group_restrictions field could not be parsed for ' . $this->dbTableName . '::' . $row['id'] . ', denying access to resource');
461
+			$this->logger->info('group_restrictions field could not be parsed for '.$this->dbTableName.'::'.$row['id'].', denying access to resource');
462 462
 			return false;
463 463
 		}
464 464
 
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -35,21 +35,21 @@
 block discarded – undo
35 35
  */
36 36
 class RoomPrincipalBackend extends AbstractPrincipalBackend {
37 37
 
38
-	/**
39
-	 * RoomPrincipalBackend constructor.
40
-	 *
41
-	 * @param IDBConnection $dbConnection
42
-	 * @param IUserSession $userSession
43
-	 * @param IGroupManager $groupManager
44
-	 * @param ILogger $logger
45
-	 * @param ProxyMapper $proxyMapper
46
-	 */
47
-	public function __construct(IDBConnection $dbConnection,
48
-								IUserSession $userSession,
49
-								IGroupManager $groupManager,
50
-								ILogger $logger,
51
-								ProxyMapper $proxyMapper) {
52
-		parent::__construct($dbConnection, $userSession, $groupManager, $logger,
53
-			$proxyMapper, 'principals/calendar-rooms', 'room', 'ROOM');
54
-	}
38
+    /**
39
+     * RoomPrincipalBackend constructor.
40
+     *
41
+     * @param IDBConnection $dbConnection
42
+     * @param IUserSession $userSession
43
+     * @param IGroupManager $groupManager
44
+     * @param ILogger $logger
45
+     * @param ProxyMapper $proxyMapper
46
+     */
47
+    public function __construct(IDBConnection $dbConnection,
48
+                                IUserSession $userSession,
49
+                                IGroupManager $groupManager,
50
+                                ILogger $logger,
51
+                                ProxyMapper $proxyMapper) {
52
+        parent::__construct($dbConnection, $userSession, $groupManager, $logger,
53
+            $proxyMapper, 'principals/calendar-rooms', 'room', 'ROOM');
54
+    }
55 55
 }
Please login to merge, or discard this patch.
apps/dav/lib/Server.php 1 patch
Indentation   +256 added lines, -256 removed lines patch added patch discarded remove patch
@@ -70,260 +70,260 @@
 block discarded – undo
70 70
 
71 71
 class Server {
72 72
 
73
-	/** @var IRequest */
74
-	private $request;
75
-
76
-	/** @var  string */
77
-	private $baseUri;
78
-
79
-	/** @var Connector\Sabre\Server  */
80
-	public $server;
81
-
82
-	public function __construct(IRequest $request, $baseUri) {
83
-		$this->request = $request;
84
-		$this->baseUri = $baseUri;
85
-		$logger = \OC::$server->getLogger();
86
-		$dispatcher = \OC::$server->getEventDispatcher();
87
-
88
-		$root = new RootCollection();
89
-		$this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root));
90
-
91
-		// Add maintenance plugin
92
-		$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin(\OC::$server->getConfig()));
93
-
94
-		// Backends
95
-		$authBackend = new Auth(
96
-			\OC::$server->getSession(),
97
-			\OC::$server->getUserSession(),
98
-			\OC::$server->getRequest(),
99
-			\OC::$server->getTwoFactorAuthManager(),
100
-			\OC::$server->getBruteForceThrottler()
101
-		);
102
-
103
-		// Set URL explicitly due to reverse-proxy situations
104
-		$this->server->httpRequest->setUrl($this->request->getRequestUri());
105
-		$this->server->setBaseUri($this->baseUri);
106
-
107
-		$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
108
-		$this->server->addPlugin(new AnonymousOptionsPlugin());
109
-		$authPlugin = new Plugin();
110
-		$authPlugin->addBackend(new PublicAuth());
111
-		$this->server->addPlugin($authPlugin);
112
-
113
-		// allow setup of additional auth backends
114
-		$event = new SabrePluginEvent($this->server);
115
-		$dispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);
116
-
117
-		$bearerAuthBackend = new BearerAuth(
118
-			\OC::$server->getUserSession(),
119
-			\OC::$server->getSession(),
120
-			\OC::$server->getRequest()
121
-		);
122
-		$authPlugin->addBackend($bearerAuthBackend);
123
-		// because we are throwing exceptions this plugin has to be the last one
124
-		$authPlugin->addBackend($authBackend);
125
-
126
-		// debugging
127
-		if(\OC::$server->getConfig()->getSystemValue('debug', false)) {
128
-			$this->server->addPlugin(new \Sabre\DAV\Browser\Plugin());
129
-		} else {
130
-			$this->server->addPlugin(new DummyGetResponsePlugin());
131
-		}
132
-
133
-		$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $logger));
134
-		$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin());
135
-		$this->server->addPlugin(new \Sabre\DAV\Sync\Plugin());
136
-
137
-		// acl
138
-		$acl = new DavAclPlugin();
139
-		$acl->principalCollectionSet = [
140
-			'principals/users',
141
-			'principals/groups',
142
-			'principals/calendar-resources',
143
-			'principals/calendar-rooms',
144
-		];
145
-		$acl->defaultUsernamePath = 'principals/users';
146
-		$this->server->addPlugin($acl);
147
-
148
-		// calendar plugins
149
-		if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'system-calendars', 'principals'])) {
150
-			$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
151
-			$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
152
-			$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());
153
-			if (\OC::$server->getConfig()->getAppValue('dav', 'sendInvitations', 'yes') === 'yes') {
154
-				$this->server->addPlugin(\OC::$server->query(\OCA\DAV\CalDAV\Schedule\IMipPlugin::class));
155
-			}
156
-
157
-			$this->server->addPlugin(new CalDAV\WebcalCaching\Plugin($request));
158
-			$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
159
-
160
-			$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
161
-			$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
162
-			$this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin(
163
-				\OC::$server->getConfig(),
164
-				\OC::$server->getURLGenerator()
165
-			));
166
-		}
167
-
168
-		// addressbook plugins
169
-		if ($this->requestIsForSubtree(['addressbooks', 'principals'])) {
170
-			$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
171
-			$this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
172
-			$this->server->addPlugin(new VCFExportPlugin());
173
-			$this->server->addPlugin(new MultiGetExportPlugin());
174
-			$this->server->addPlugin(new HasPhotoPlugin());
175
-			$this->server->addPlugin(new ImageExportPlugin(new PhotoCache(
176
-				\OC::$server->getAppDataDir('dav-photocache'),
177
-				\OC::$server->getLogger())
178
-			));
179
-		}
180
-
181
-		// system tags plugins
182
-		$this->server->addPlugin(new SystemTagPlugin(
183
-			\OC::$server->getSystemTagManager(),
184
-			\OC::$server->getGroupManager(),
185
-			\OC::$server->getUserSession()
186
-		));
187
-
188
-		// comments plugin
189
-		$this->server->addPlugin(new CommentsPlugin(
190
-			\OC::$server->getCommentsManager(),
191
-			\OC::$server->getUserSession()
192
-		));
193
-
194
-		$this->server->addPlugin(new CopyEtagHeaderPlugin());
195
-		$this->server->addPlugin(new ChunkingPlugin());
196
-
197
-		// allow setup of additional plugins
198
-		$dispatcher->dispatch('OCA\DAV\Connector\Sabre::addPlugin', $event);
199
-
200
-		// Some WebDAV clients do require Class 2 WebDAV support (locking), since
201
-		// we do not provide locking we emulate it using a fake locking plugin.
202
-		if($request->isUserAgent([
203
-			'/WebDAVFS/',
204
-			'/OneNote/',
205
-			'/^Microsoft-WebDAV/',// Microsoft-WebDAV-MiniRedir/6.1.7601
206
-		])) {
207
-			$this->server->addPlugin(new FakeLockerPlugin());
208
-		}
209
-
210
-		if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
211
-			$this->server->addPlugin(new BrowserErrorPagePlugin());
212
-		}
213
-
214
-		$lazySearchBackend = new LazySearchBackend();
215
-		$this->server->addPlugin(new SearchPlugin($lazySearchBackend));
216
-
217
-		// wait with registering these until auth is handled and the filesystem is setup
218
-		$this->server->on('beforeMethod', function () use ($root, $lazySearchBackend) {
219
-			// custom properties plugin must be the last one
220
-			$userSession = \OC::$server->getUserSession();
221
-			$user = $userSession->getUser();
222
-			if ($user !== null) {
223
-				$view = \OC\Files\Filesystem::getView();
224
-				$this->server->addPlugin(
225
-					new FilesPlugin(
226
-						$this->server->tree,
227
-						\OC::$server->getConfig(),
228
-						$this->request,
229
-						\OC::$server->getPreviewManager(),
230
-						false,
231
-						!\OC::$server->getConfig()->getSystemValue('debug', false)
232
-					)
233
-				);
234
-
235
-				$this->server->addPlugin(
236
-					new \Sabre\DAV\PropertyStorage\Plugin(
237
-						new CustomPropertiesBackend(
238
-							$this->server->tree,
239
-							\OC::$server->getDatabaseConnection(),
240
-							\OC::$server->getUserSession()->getUser()
241
-						)
242
-					)
243
-				);
244
-				if ($view !== null) {
245
-					$this->server->addPlugin(
246
-						new QuotaPlugin($view, false));
247
-				}
248
-				$this->server->addPlugin(
249
-					new TagsPlugin(
250
-						$this->server->tree, \OC::$server->getTagManager()
251
-					)
252
-				);
253
-				// TODO: switch to LazyUserFolder
254
-				$userFolder = \OC::$server->getUserFolder();
255
-				$this->server->addPlugin(new SharesPlugin(
256
-					$this->server->tree,
257
-					$userSession,
258
-					$userFolder,
259
-					\OC::$server->getShareManager()
260
-				));
261
-				$this->server->addPlugin(new CommentPropertiesPlugin(
262
-					\OC::$server->getCommentsManager(),
263
-					$userSession
264
-				));
265
-				$this->server->addPlugin(new \OCA\DAV\CalDAV\Search\SearchPlugin());
266
-				if ($view !== null) {
267
-					$this->server->addPlugin(new FilesReportPlugin(
268
-						$this->server->tree,
269
-						$view,
270
-						\OC::$server->getSystemTagManager(),
271
-						\OC::$server->getSystemTagObjectMapper(),
272
-						\OC::$server->getTagManager(),
273
-						$userSession,
274
-						\OC::$server->getGroupManager(),
275
-						$userFolder,
276
-						\OC::$server->getAppManager()
277
-					));
278
-					$lazySearchBackend->setBackend(new \OCA\DAV\Files\FileSearchBackend(
279
-						$this->server->tree,
280
-						$user,
281
-						\OC::$server->getRootFolder(),
282
-						\OC::$server->getShareManager(),
283
-						$view
284
-					));
285
-				}
286
-				$this->server->addPlugin(new \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin(
287
-					\OC::$server->getConfig(),
288
-					\OC::$server->query(BirthdayService::class)
289
-				));
290
-				$this->server->addPlugin(new AppleProvisioningPlugin(
291
-					\OC::$server->getUserSession(),
292
-					\OC::$server->getURLGenerator(),
293
-					\OC::$server->getThemingDefaults(),
294
-					\OC::$server->getRequest(),
295
-					\OC::$server->getL10N('dav'),
296
-					function() {
297
-						return UUIDUtil::getUUID();
298
-					}
299
-				));
300
-			}
301
-
302
-			// register plugins from apps
303
-			$pluginManager = new PluginManager(
304
-				\OC::$server,
305
-				\OC::$server->getAppManager()
306
-			);
307
-			foreach ($pluginManager->getAppPlugins() as $appPlugin) {
308
-				$this->server->addPlugin($appPlugin);
309
-			}
310
-			foreach ($pluginManager->getAppCollections() as $appCollection) {
311
-				$root->addChild($appCollection);
312
-			}
313
-		});
314
-	}
315
-
316
-	public function exec() {
317
-		$this->server->exec();
318
-	}
319
-
320
-	private function requestIsForSubtree(array $subTrees): bool {
321
-		foreach ($subTrees as $subTree) {
322
-			$subTree = trim($subTree, ' /');
323
-			if (strpos($this->server->getRequestUri(), $subTree.'/') === 0) {
324
-				return true;
325
-			}
326
-		}
327
-		return false;
328
-	}
73
+    /** @var IRequest */
74
+    private $request;
75
+
76
+    /** @var  string */
77
+    private $baseUri;
78
+
79
+    /** @var Connector\Sabre\Server  */
80
+    public $server;
81
+
82
+    public function __construct(IRequest $request, $baseUri) {
83
+        $this->request = $request;
84
+        $this->baseUri = $baseUri;
85
+        $logger = \OC::$server->getLogger();
86
+        $dispatcher = \OC::$server->getEventDispatcher();
87
+
88
+        $root = new RootCollection();
89
+        $this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root));
90
+
91
+        // Add maintenance plugin
92
+        $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin(\OC::$server->getConfig()));
93
+
94
+        // Backends
95
+        $authBackend = new Auth(
96
+            \OC::$server->getSession(),
97
+            \OC::$server->getUserSession(),
98
+            \OC::$server->getRequest(),
99
+            \OC::$server->getTwoFactorAuthManager(),
100
+            \OC::$server->getBruteForceThrottler()
101
+        );
102
+
103
+        // Set URL explicitly due to reverse-proxy situations
104
+        $this->server->httpRequest->setUrl($this->request->getRequestUri());
105
+        $this->server->setBaseUri($this->baseUri);
106
+
107
+        $this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
108
+        $this->server->addPlugin(new AnonymousOptionsPlugin());
109
+        $authPlugin = new Plugin();
110
+        $authPlugin->addBackend(new PublicAuth());
111
+        $this->server->addPlugin($authPlugin);
112
+
113
+        // allow setup of additional auth backends
114
+        $event = new SabrePluginEvent($this->server);
115
+        $dispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);
116
+
117
+        $bearerAuthBackend = new BearerAuth(
118
+            \OC::$server->getUserSession(),
119
+            \OC::$server->getSession(),
120
+            \OC::$server->getRequest()
121
+        );
122
+        $authPlugin->addBackend($bearerAuthBackend);
123
+        // because we are throwing exceptions this plugin has to be the last one
124
+        $authPlugin->addBackend($authBackend);
125
+
126
+        // debugging
127
+        if(\OC::$server->getConfig()->getSystemValue('debug', false)) {
128
+            $this->server->addPlugin(new \Sabre\DAV\Browser\Plugin());
129
+        } else {
130
+            $this->server->addPlugin(new DummyGetResponsePlugin());
131
+        }
132
+
133
+        $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $logger));
134
+        $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin());
135
+        $this->server->addPlugin(new \Sabre\DAV\Sync\Plugin());
136
+
137
+        // acl
138
+        $acl = new DavAclPlugin();
139
+        $acl->principalCollectionSet = [
140
+            'principals/users',
141
+            'principals/groups',
142
+            'principals/calendar-resources',
143
+            'principals/calendar-rooms',
144
+        ];
145
+        $acl->defaultUsernamePath = 'principals/users';
146
+        $this->server->addPlugin($acl);
147
+
148
+        // calendar plugins
149
+        if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'system-calendars', 'principals'])) {
150
+            $this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
151
+            $this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
152
+            $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin());
153
+            if (\OC::$server->getConfig()->getAppValue('dav', 'sendInvitations', 'yes') === 'yes') {
154
+                $this->server->addPlugin(\OC::$server->query(\OCA\DAV\CalDAV\Schedule\IMipPlugin::class));
155
+            }
156
+
157
+            $this->server->addPlugin(new CalDAV\WebcalCaching\Plugin($request));
158
+            $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
159
+
160
+            $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
161
+            $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
162
+            $this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin(
163
+                \OC::$server->getConfig(),
164
+                \OC::$server->getURLGenerator()
165
+            ));
166
+        }
167
+
168
+        // addressbook plugins
169
+        if ($this->requestIsForSubtree(['addressbooks', 'principals'])) {
170
+            $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
171
+            $this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
172
+            $this->server->addPlugin(new VCFExportPlugin());
173
+            $this->server->addPlugin(new MultiGetExportPlugin());
174
+            $this->server->addPlugin(new HasPhotoPlugin());
175
+            $this->server->addPlugin(new ImageExportPlugin(new PhotoCache(
176
+                \OC::$server->getAppDataDir('dav-photocache'),
177
+                \OC::$server->getLogger())
178
+            ));
179
+        }
180
+
181
+        // system tags plugins
182
+        $this->server->addPlugin(new SystemTagPlugin(
183
+            \OC::$server->getSystemTagManager(),
184
+            \OC::$server->getGroupManager(),
185
+            \OC::$server->getUserSession()
186
+        ));
187
+
188
+        // comments plugin
189
+        $this->server->addPlugin(new CommentsPlugin(
190
+            \OC::$server->getCommentsManager(),
191
+            \OC::$server->getUserSession()
192
+        ));
193
+
194
+        $this->server->addPlugin(new CopyEtagHeaderPlugin());
195
+        $this->server->addPlugin(new ChunkingPlugin());
196
+
197
+        // allow setup of additional plugins
198
+        $dispatcher->dispatch('OCA\DAV\Connector\Sabre::addPlugin', $event);
199
+
200
+        // Some WebDAV clients do require Class 2 WebDAV support (locking), since
201
+        // we do not provide locking we emulate it using a fake locking plugin.
202
+        if($request->isUserAgent([
203
+            '/WebDAVFS/',
204
+            '/OneNote/',
205
+            '/^Microsoft-WebDAV/',// Microsoft-WebDAV-MiniRedir/6.1.7601
206
+        ])) {
207
+            $this->server->addPlugin(new FakeLockerPlugin());
208
+        }
209
+
210
+        if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
211
+            $this->server->addPlugin(new BrowserErrorPagePlugin());
212
+        }
213
+
214
+        $lazySearchBackend = new LazySearchBackend();
215
+        $this->server->addPlugin(new SearchPlugin($lazySearchBackend));
216
+
217
+        // wait with registering these until auth is handled and the filesystem is setup
218
+        $this->server->on('beforeMethod', function () use ($root, $lazySearchBackend) {
219
+            // custom properties plugin must be the last one
220
+            $userSession = \OC::$server->getUserSession();
221
+            $user = $userSession->getUser();
222
+            if ($user !== null) {
223
+                $view = \OC\Files\Filesystem::getView();
224
+                $this->server->addPlugin(
225
+                    new FilesPlugin(
226
+                        $this->server->tree,
227
+                        \OC::$server->getConfig(),
228
+                        $this->request,
229
+                        \OC::$server->getPreviewManager(),
230
+                        false,
231
+                        !\OC::$server->getConfig()->getSystemValue('debug', false)
232
+                    )
233
+                );
234
+
235
+                $this->server->addPlugin(
236
+                    new \Sabre\DAV\PropertyStorage\Plugin(
237
+                        new CustomPropertiesBackend(
238
+                            $this->server->tree,
239
+                            \OC::$server->getDatabaseConnection(),
240
+                            \OC::$server->getUserSession()->getUser()
241
+                        )
242
+                    )
243
+                );
244
+                if ($view !== null) {
245
+                    $this->server->addPlugin(
246
+                        new QuotaPlugin($view, false));
247
+                }
248
+                $this->server->addPlugin(
249
+                    new TagsPlugin(
250
+                        $this->server->tree, \OC::$server->getTagManager()
251
+                    )
252
+                );
253
+                // TODO: switch to LazyUserFolder
254
+                $userFolder = \OC::$server->getUserFolder();
255
+                $this->server->addPlugin(new SharesPlugin(
256
+                    $this->server->tree,
257
+                    $userSession,
258
+                    $userFolder,
259
+                    \OC::$server->getShareManager()
260
+                ));
261
+                $this->server->addPlugin(new CommentPropertiesPlugin(
262
+                    \OC::$server->getCommentsManager(),
263
+                    $userSession
264
+                ));
265
+                $this->server->addPlugin(new \OCA\DAV\CalDAV\Search\SearchPlugin());
266
+                if ($view !== null) {
267
+                    $this->server->addPlugin(new FilesReportPlugin(
268
+                        $this->server->tree,
269
+                        $view,
270
+                        \OC::$server->getSystemTagManager(),
271
+                        \OC::$server->getSystemTagObjectMapper(),
272
+                        \OC::$server->getTagManager(),
273
+                        $userSession,
274
+                        \OC::$server->getGroupManager(),
275
+                        $userFolder,
276
+                        \OC::$server->getAppManager()
277
+                    ));
278
+                    $lazySearchBackend->setBackend(new \OCA\DAV\Files\FileSearchBackend(
279
+                        $this->server->tree,
280
+                        $user,
281
+                        \OC::$server->getRootFolder(),
282
+                        \OC::$server->getShareManager(),
283
+                        $view
284
+                    ));
285
+                }
286
+                $this->server->addPlugin(new \OCA\DAV\CalDAV\BirthdayCalendar\EnablePlugin(
287
+                    \OC::$server->getConfig(),
288
+                    \OC::$server->query(BirthdayService::class)
289
+                ));
290
+                $this->server->addPlugin(new AppleProvisioningPlugin(
291
+                    \OC::$server->getUserSession(),
292
+                    \OC::$server->getURLGenerator(),
293
+                    \OC::$server->getThemingDefaults(),
294
+                    \OC::$server->getRequest(),
295
+                    \OC::$server->getL10N('dav'),
296
+                    function() {
297
+                        return UUIDUtil::getUUID();
298
+                    }
299
+                ));
300
+            }
301
+
302
+            // register plugins from apps
303
+            $pluginManager = new PluginManager(
304
+                \OC::$server,
305
+                \OC::$server->getAppManager()
306
+            );
307
+            foreach ($pluginManager->getAppPlugins() as $appPlugin) {
308
+                $this->server->addPlugin($appPlugin);
309
+            }
310
+            foreach ($pluginManager->getAppCollections() as $appCollection) {
311
+                $root->addChild($appCollection);
312
+            }
313
+        });
314
+    }
315
+
316
+    public function exec() {
317
+        $this->server->exec();
318
+    }
319
+
320
+    private function requestIsForSubtree(array $subTrees): bool {
321
+        foreach ($subTrees as $subTree) {
322
+            $subTree = trim($subTree, ' /');
323
+            if (strpos($this->server->getRequestUri(), $subTree.'/') === 0) {
324
+                return true;
325
+            }
326
+        }
327
+        return false;
328
+    }
329 329
 }
Please login to merge, or discard this patch.
apps/dav/lib/Command/CreateCalendar.php 1 patch
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -36,58 +36,58 @@
 block discarded – undo
36 36
 
37 37
 class CreateCalendar extends Command {
38 38
 
39
-	/** @var IUserManager */
40
-	protected $userManager;
39
+    /** @var IUserManager */
40
+    protected $userManager;
41 41
 
42
-	/** @var IGroupManager $groupManager */
43
-	private $groupManager;
42
+    /** @var IGroupManager $groupManager */
43
+    private $groupManager;
44 44
 
45
-	/** @var \OCP\IDBConnection */
46
-	protected $dbConnection;
45
+    /** @var \OCP\IDBConnection */
46
+    protected $dbConnection;
47 47
 
48
-	/**
49
-	 * @param IUserManager $userManager
50
-	 * @param IGroupManager $groupManager
51
-	 * @param IDBConnection $dbConnection
52
-	 */
53
-	function __construct(IUserManager $userManager, IGroupManager $groupManager, IDBConnection $dbConnection) {
54
-		parent::__construct();
55
-		$this->userManager = $userManager;
56
-		$this->groupManager = $groupManager;
57
-		$this->dbConnection = $dbConnection;
58
-	}
48
+    /**
49
+     * @param IUserManager $userManager
50
+     * @param IGroupManager $groupManager
51
+     * @param IDBConnection $dbConnection
52
+     */
53
+    function __construct(IUserManager $userManager, IGroupManager $groupManager, IDBConnection $dbConnection) {
54
+        parent::__construct();
55
+        $this->userManager = $userManager;
56
+        $this->groupManager = $groupManager;
57
+        $this->dbConnection = $dbConnection;
58
+    }
59 59
 
60
-	protected function configure() {
61
-		$this
62
-			->setName('dav:create-calendar')
63
-			->setDescription('Create a dav calendar')
64
-			->addArgument('user',
65
-				InputArgument::REQUIRED,
66
-				'User for whom the calendar will be created')
67
-			->addArgument('name',
68
-				InputArgument::REQUIRED,
69
-				'Name of the calendar');
70
-	}
60
+    protected function configure() {
61
+        $this
62
+            ->setName('dav:create-calendar')
63
+            ->setDescription('Create a dav calendar')
64
+            ->addArgument('user',
65
+                InputArgument::REQUIRED,
66
+                'User for whom the calendar will be created')
67
+            ->addArgument('name',
68
+                InputArgument::REQUIRED,
69
+                'Name of the calendar');
70
+    }
71 71
 
72
-	protected function execute(InputInterface $input, OutputInterface $output) {
73
-		$user = $input->getArgument('user');
74
-		if (!$this->userManager->userExists($user)) {
75
-			throw new \InvalidArgumentException("User <$user> in unknown.");
76
-		}
77
-		$principalBackend = new Principal(
78
-			$this->userManager,
79
-			$this->groupManager,
80
-			\OC::$server->getShareManager(),
81
-			\OC::$server->getUserSession(),
82
-			\OC::$server->getAppManager(),
83
-			\OC::$server->query(ProxyMapper::class)
84
-		);
85
-		$random = \OC::$server->getSecureRandom();
86
-		$logger = \OC::$server->getLogger();
87
-		$dispatcher = \OC::$server->getEventDispatcher();
72
+    protected function execute(InputInterface $input, OutputInterface $output) {
73
+        $user = $input->getArgument('user');
74
+        if (!$this->userManager->userExists($user)) {
75
+            throw new \InvalidArgumentException("User <$user> in unknown.");
76
+        }
77
+        $principalBackend = new Principal(
78
+            $this->userManager,
79
+            $this->groupManager,
80
+            \OC::$server->getShareManager(),
81
+            \OC::$server->getUserSession(),
82
+            \OC::$server->getAppManager(),
83
+            \OC::$server->query(ProxyMapper::class)
84
+        );
85
+        $random = \OC::$server->getSecureRandom();
86
+        $logger = \OC::$server->getLogger();
87
+        $dispatcher = \OC::$server->getEventDispatcher();
88 88
 
89
-		$name = $input->getArgument('name');
90
-		$caldav = new CalDavBackend($this->dbConnection, $principalBackend, $this->userManager, $this->groupManager, $random, $logger, $dispatcher);
91
-		$caldav->createCalendar("principals/users/$user", $name, []);
92
-	}
89
+        $name = $input->getArgument('name');
90
+        $caldav = new CalDavBackend($this->dbConnection, $principalBackend, $this->userManager, $this->groupManager, $random, $logger, $dispatcher);
91
+        $caldav->createCalendar("principals/users/$user", $name, []);
92
+    }
93 93
 }
Please login to merge, or discard this patch.