Total Complexity | 222 |
Total Lines | 1161 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like ShareAPIController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ShareAPIController, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
66 | class ShareAPIController extends OCSController { |
||
67 | |||
68 | /** @var IManager */ |
||
69 | private $shareManager; |
||
70 | /** @var IGroupManager */ |
||
71 | private $groupManager; |
||
72 | /** @var IUserManager */ |
||
73 | private $userManager; |
||
74 | /** @var IRootFolder */ |
||
75 | private $rootFolder; |
||
76 | /** @var IURLGenerator */ |
||
77 | private $urlGenerator; |
||
78 | /** @var string */ |
||
79 | private $currentUser; |
||
80 | /** @var IL10N */ |
||
81 | private $l; |
||
82 | /** @var \OCP\Files\Node */ |
||
83 | private $lockedNode; |
||
84 | /** @var IConfig */ |
||
85 | private $config; |
||
86 | /** @var IAppManager */ |
||
87 | private $appManager; |
||
88 | /** @var IServerContainer */ |
||
89 | private $serverContainer; |
||
90 | |||
91 | /** |
||
92 | * Share20OCS constructor. |
||
93 | * |
||
94 | * @param string $appName |
||
95 | * @param IRequest $request |
||
96 | * @param IManager $shareManager |
||
97 | * @param IGroupManager $groupManager |
||
98 | * @param IUserManager $userManager |
||
99 | * @param IRootFolder $rootFolder |
||
100 | * @param IURLGenerator $urlGenerator |
||
101 | * @param string $userId |
||
102 | * @param IL10N $l10n |
||
103 | * @param IConfig $config |
||
104 | * @param IAppManager $appManager |
||
105 | * @param IServerContainer $serverContainer |
||
106 | */ |
||
107 | public function __construct( |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * Convert an IShare to an array for OCS output |
||
138 | * |
||
139 | * @param \OCP\Share\IShare $share |
||
140 | * @param Node|null $recipientNode |
||
141 | * @return array |
||
142 | * @throws NotFoundException In case the node can't be resolved. |
||
143 | * |
||
144 | * @suppress PhanUndeclaredClassMethod |
||
145 | */ |
||
146 | protected function formatShare(\OCP\Share\IShare $share, Node $recipientNode = null): array { |
||
147 | $sharedBy = $this->userManager->get($share->getSharedBy()); |
||
148 | $shareOwner = $this->userManager->get($share->getShareOwner()); |
||
149 | |||
150 | $result = [ |
||
151 | 'id' => $share->getId(), |
||
152 | 'share_type' => $share->getShareType(), |
||
153 | 'uid_owner' => $share->getSharedBy(), |
||
154 | 'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(), |
||
155 | 'permissions' => $share->getPermissions(), |
||
156 | 'stime' => $share->getShareTime()->getTimestamp(), |
||
157 | 'parent' => null, |
||
158 | 'expiration' => null, |
||
159 | 'token' => null, |
||
160 | 'uid_file_owner' => $share->getShareOwner(), |
||
161 | 'note' => $share->getNote(), |
||
162 | 'label' => $share->getLabel(), |
||
163 | 'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(), |
||
164 | ]; |
||
165 | |||
166 | $userFolder = $this->rootFolder->getUserFolder($this->currentUser); |
||
167 | if ($recipientNode) { |
||
168 | $node = $recipientNode; |
||
169 | } else { |
||
170 | $nodes = $userFolder->getById($share->getNodeId()); |
||
171 | if (empty($nodes)) { |
||
172 | // fallback to guessing the path |
||
173 | $node = $userFolder->get($share->getTarget()); |
||
174 | if ($node === null || $share->getTarget() === '') { |
||
175 | throw new NotFoundException(); |
||
176 | } |
||
177 | } else { |
||
178 | $node = $nodes[0]; |
||
179 | } |
||
180 | } |
||
181 | |||
182 | $result['path'] = $userFolder->getRelativePath($node->getPath()); |
||
183 | if ($node instanceOf \OCP\Files\Folder) { |
||
184 | $result['item_type'] = 'folder'; |
||
185 | } else { |
||
186 | $result['item_type'] = 'file'; |
||
187 | } |
||
188 | $result['mimetype'] = $node->getMimetype(); |
||
189 | $result['storage_id'] = $node->getStorage()->getId(); |
||
190 | $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId(); |
||
191 | $result['item_source'] = $node->getId(); |
||
192 | $result['file_source'] = $node->getId(); |
||
193 | $result['file_parent'] = $node->getParent()->getId(); |
||
194 | $result['file_target'] = $share->getTarget(); |
||
195 | |||
196 | $expiration = $share->getExpirationDate(); |
||
197 | if ($expiration !== null) { |
||
198 | $result['expiration'] = $expiration->format('Y-m-d 00:00:00'); |
||
199 | } |
||
200 | |||
201 | if ($share->getShareType() === Share::SHARE_TYPE_USER) { |
||
202 | $sharedWith = $this->userManager->get($share->getSharedWith()); |
||
203 | $result['share_with'] = $share->getSharedWith(); |
||
204 | $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith(); |
||
205 | } else if ($share->getShareType() === Share::SHARE_TYPE_GROUP) { |
||
206 | $group = $this->groupManager->get($share->getSharedWith()); |
||
207 | $result['share_with'] = $share->getSharedWith(); |
||
208 | $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith(); |
||
209 | } else if ($share->getShareType() === Share::SHARE_TYPE_LINK) { |
||
210 | |||
211 | // "share_with" and "share_with_displayname" for passwords of link |
||
212 | // shares was deprecated in Nextcloud 15, use "password" instead. |
||
213 | $result['share_with'] = $share->getPassword(); |
||
214 | $result['share_with_displayname'] = $share->getPassword(); |
||
215 | |||
216 | $result['password'] = $share->getPassword(); |
||
217 | |||
218 | $result['send_password_by_talk'] = $share->getSendPasswordByTalk(); |
||
219 | |||
220 | $result['token'] = $share->getToken(); |
||
221 | $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]); |
||
222 | |||
223 | } else if ($share->getShareType() === Share::SHARE_TYPE_REMOTE || $share->getShareType() === Share::SHARE_TYPE_REMOTE_GROUP) { |
||
224 | $result['share_with'] = $share->getSharedWith(); |
||
225 | $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD'); |
||
226 | $result['token'] = $share->getToken(); |
||
227 | } else if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) { |
||
228 | $result['share_with'] = $share->getSharedWith(); |
||
229 | $result['password'] = $share->getPassword(); |
||
230 | $result['send_password_by_talk'] = $share->getSendPasswordByTalk(); |
||
231 | $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL'); |
||
232 | $result['token'] = $share->getToken(); |
||
233 | } else if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) { |
||
234 | // getSharedWith() returns either "name (type, owner)" or |
||
235 | // "name (type, owner) [id]", depending on the Circles app version. |
||
236 | $hasCircleId = (substr($share->getSharedWith(), -1) === ']'); |
||
237 | |||
238 | $result['share_with_displayname'] = $share->getSharedWithDisplayName(); |
||
239 | if (empty($result['share_with_displayname'])) { |
||
240 | $displayNameLength = ($hasCircleId? strrpos($share->getSharedWith(), ' '): strlen($share->getSharedWith())); |
||
241 | $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength); |
||
242 | } |
||
243 | |||
244 | $result['share_with_avatar'] = $share->getSharedWithAvatar(); |
||
245 | |||
246 | $shareWithStart = ($hasCircleId? strrpos($share->getSharedWith(), '[') + 1: 0); |
||
247 | $shareWithLength = ($hasCircleId? -1: strpos($share->getSharedWith(), ' ')); |
||
248 | if (is_bool($shareWithLength)) { |
||
|
|||
249 | $shareWithLength = -1; |
||
250 | } |
||
251 | $result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength); |
||
252 | } else if ($share->getShareType() === Share::SHARE_TYPE_ROOM) { |
||
253 | $result['share_with'] = $share->getSharedWith(); |
||
254 | $result['share_with_displayname'] = ''; |
||
255 | |||
256 | try { |
||
257 | $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share)); |
||
258 | } catch (QueryException $e) { |
||
259 | } |
||
260 | } |
||
261 | |||
262 | |||
263 | $result['mail_send'] = $share->getMailSend() ? 1 : 0; |
||
264 | $result['hide_download'] = $share->getHideDownload() ? 1 : 0; |
||
265 | |||
266 | return $result; |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Check if one of the users address books knows the exact property, if |
||
271 | * yes we return the full name. |
||
272 | * |
||
273 | * @param string $query |
||
274 | * @param string $property |
||
275 | * @return string |
||
276 | */ |
||
277 | private function getDisplayNameFromAddressBook(string $query, string $property): string { |
||
278 | // FIXME: If we inject the contacts manager it gets initialized bofore any address books are registered |
||
279 | $result = \OC::$server->getContactsManager()->search($query, [$property]); |
||
280 | foreach ($result as $r) { |
||
281 | foreach($r[$property] as $value) { |
||
282 | if ($value === $query) { |
||
283 | return $r['FN']; |
||
284 | } |
||
285 | } |
||
286 | } |
||
287 | |||
288 | return $query; |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Get a specific share by id |
||
293 | * |
||
294 | * @NoAdminRequired |
||
295 | * |
||
296 | * @param string $id |
||
297 | * @return DataResponse |
||
298 | * @throws OCSNotFoundException |
||
299 | */ |
||
300 | public function getShare(string $id): DataResponse { |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Delete a share |
||
321 | * |
||
322 | * @NoAdminRequired |
||
323 | * |
||
324 | * @param string $id |
||
325 | * @return DataResponse |
||
326 | * @throws OCSNotFoundException |
||
327 | */ |
||
328 | public function deleteShare(string $id): DataResponse { |
||
329 | try { |
||
330 | $share = $this->getShareById($id); |
||
331 | } catch (ShareNotFound $e) { |
||
332 | throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist')); |
||
333 | } |
||
334 | |||
335 | try { |
||
336 | $this->lock($share->getNode()); |
||
337 | } catch (LockedException $e) { |
||
338 | throw new OCSNotFoundException($this->l->t('could not delete share')); |
||
339 | } |
||
340 | |||
341 | if (!$this->canAccessShare($share)) { |
||
342 | throw new OCSNotFoundException($this->l->t('Could not delete share')); |
||
343 | } |
||
344 | |||
345 | if (($share->getShareType() === Share::SHARE_TYPE_GROUP || |
||
346 | $share->getShareType() === Share::SHARE_TYPE_ROOM) && |
||
347 | $share->getShareOwner() !== $this->currentUser && |
||
348 | $share->getSharedBy() !== $this->currentUser) { |
||
349 | $this->shareManager->deleteFromSelf($share, $this->currentUser); |
||
350 | } else { |
||
351 | $this->shareManager->deleteShare($share); |
||
352 | } |
||
353 | |||
354 | return new DataResponse(); |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * @NoAdminRequired |
||
359 | * |
||
360 | * @param string $path |
||
361 | * @param int $permissions |
||
362 | * @param int $shareType |
||
363 | * @param string $shareWith |
||
364 | * @param string $publicUpload |
||
365 | * @param string $password |
||
366 | * @param string $sendPasswordByTalk |
||
367 | * @param string $expireDate |
||
368 | * @param string $label |
||
369 | * |
||
370 | * @return DataResponse |
||
371 | * @throws NotFoundException |
||
372 | * @throws OCSBadRequestException |
||
373 | * @throws OCSException |
||
374 | * @throws OCSForbiddenException |
||
375 | * @throws OCSNotFoundException |
||
376 | * @throws \OCP\Files\InvalidPathException |
||
377 | * @suppress PhanUndeclaredClassMethod |
||
378 | */ |
||
379 | public function createShare( |
||
380 | string $path = null, |
||
381 | int $permissions = null, |
||
382 | int $shareType = -1, |
||
383 | string $shareWith = null, |
||
384 | string $publicUpload = 'false', |
||
385 | string $password = '', |
||
386 | string $sendPasswordByTalk = null, |
||
387 | string $expireDate = '', |
||
388 | string $label = '' |
||
389 | ): DataResponse { |
||
390 | $share = $this->shareManager->newShare(); |
||
391 | |||
392 | if ($permissions === null) { |
||
393 | $permissions = $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL); |
||
394 | } |
||
395 | |||
396 | // Verify path |
||
397 | if ($path === null) { |
||
398 | throw new OCSNotFoundException($this->l->t('Please specify a file or folder path')); |
||
399 | } |
||
400 | |||
401 | $userFolder = $this->rootFolder->getUserFolder($this->currentUser); |
||
402 | try { |
||
403 | $path = $userFolder->get($path); |
||
404 | } catch (NotFoundException $e) { |
||
405 | throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist')); |
||
406 | } |
||
407 | |||
408 | $share->setNode($path); |
||
409 | |||
410 | try { |
||
411 | $this->lock($share->getNode()); |
||
412 | } catch (LockedException $e) { |
||
413 | throw new OCSNotFoundException($this->l->t('Could not create share')); |
||
414 | } |
||
415 | |||
416 | if ($permissions < 0 || $permissions > Constants::PERMISSION_ALL) { |
||
417 | throw new OCSNotFoundException($this->l->t('invalid permissions')); |
||
418 | } |
||
419 | |||
420 | // Shares always require read permissions |
||
421 | $permissions |= Constants::PERMISSION_READ; |
||
422 | |||
423 | if ($path instanceof \OCP\Files\File) { |
||
424 | // Single file shares should never have delete or create permissions |
||
425 | $permissions &= ~Constants::PERMISSION_DELETE; |
||
426 | $permissions &= ~Constants::PERMISSION_CREATE; |
||
427 | } |
||
428 | |||
429 | /* |
||
430 | * Hack for https://github.com/owncloud/core/issues/22587 |
||
431 | * We check the permissions via webdav. But the permissions of the mount point |
||
432 | * do not equal the share permissions. Here we fix that for federated mounts. |
||
433 | */ |
||
434 | if ($path->getStorage()->instanceOfStorage(Storage::class)) { |
||
435 | $permissions &= ~($permissions & ~$path->getPermissions()); |
||
436 | } |
||
437 | |||
438 | if ($shareType === Share::SHARE_TYPE_USER) { |
||
439 | // Valid user is required to share |
||
440 | if ($shareWith === null || !$this->userManager->userExists($shareWith)) { |
||
441 | throw new OCSNotFoundException($this->l->t('Please specify a valid user')); |
||
442 | } |
||
443 | $share->setSharedWith($shareWith); |
||
444 | $share->setPermissions($permissions); |
||
445 | } else if ($shareType === Share::SHARE_TYPE_GROUP) { |
||
446 | if (!$this->shareManager->allowGroupSharing()) { |
||
447 | throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator')); |
||
448 | } |
||
449 | |||
450 | // Valid group is required to share |
||
451 | if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) { |
||
452 | throw new OCSNotFoundException($this->l->t('Please specify a valid group')); |
||
453 | } |
||
454 | $share->setSharedWith($shareWith); |
||
455 | $share->setPermissions($permissions); |
||
456 | } else if ($shareType === Share::SHARE_TYPE_LINK) { |
||
457 | //Can we even share links? |
||
458 | if (!$this->shareManager->shareApiAllowLinks()) { |
||
459 | throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator')); |
||
460 | } |
||
461 | |||
462 | if ($publicUpload === 'true') { |
||
463 | // Check if public upload is allowed |
||
464 | if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { |
||
465 | throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator')); |
||
466 | } |
||
467 | |||
468 | // Public upload can only be set for folders |
||
469 | if ($path instanceof \OCP\Files\File) { |
||
470 | throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders')); |
||
471 | } |
||
472 | |||
473 | $share->setPermissions( |
||
474 | Constants::PERMISSION_READ | |
||
475 | Constants::PERMISSION_CREATE | |
||
476 | Constants::PERMISSION_UPDATE | |
||
477 | Constants::PERMISSION_DELETE |
||
478 | ); |
||
479 | } else { |
||
480 | $share->setPermissions(Constants::PERMISSION_READ); |
||
481 | } |
||
482 | |||
483 | // Set password |
||
484 | if ($password !== '') { |
||
485 | $share->setPassword($password); |
||
486 | } |
||
487 | |||
488 | |||
489 | if (!empty($label)) { |
||
490 | $share->setLabel($label); |
||
491 | } |
||
492 | |||
493 | if ($sendPasswordByTalk === 'true') { |
||
494 | if (!$this->appManager->isEnabledForUser('spreed')) { |
||
495 | throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()])); |
||
496 | } |
||
497 | |||
498 | $share->setSendPasswordByTalk(true); |
||
499 | } |
||
500 | |||
501 | //Expire date |
||
502 | if ($expireDate !== '') { |
||
503 | try { |
||
504 | $expireDate = $this->parseDate($expireDate); |
||
505 | $share->setExpirationDate($expireDate); |
||
506 | } catch (\Exception $e) { |
||
507 | throw new OCSNotFoundException($this->l->t('Invalid date, date format must be YYYY-MM-DD')); |
||
508 | } |
||
509 | } |
||
510 | |||
511 | } else if ($shareType === Share::SHARE_TYPE_REMOTE) { |
||
512 | if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { |
||
513 | throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType])); |
||
514 | } |
||
515 | |||
516 | $share->setSharedWith($shareWith); |
||
517 | $share->setPermissions($permissions); |
||
518 | } else if ($shareType === Share::SHARE_TYPE_REMOTE_GROUP) { |
||
519 | if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) { |
||
520 | throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType])); |
||
521 | } |
||
522 | |||
523 | $share->setSharedWith($shareWith); |
||
524 | $share->setPermissions($permissions); |
||
525 | } else if ($shareType === Share::SHARE_TYPE_EMAIL) { |
||
526 | if ($share->getNodeType() === 'file') { |
||
527 | $share->setPermissions(Constants::PERMISSION_READ); |
||
528 | } else { |
||
529 | $share->setPermissions($permissions); |
||
530 | } |
||
531 | $share->setSharedWith($shareWith); |
||
532 | |||
533 | if ($sendPasswordByTalk === 'true') { |
||
534 | if (!$this->appManager->isEnabledForUser('spreed')) { |
||
535 | throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()])); |
||
536 | } |
||
537 | |||
538 | $share->setSendPasswordByTalk(true); |
||
539 | } |
||
540 | } else if ($shareType === Share::SHARE_TYPE_CIRCLE) { |
||
541 | if (!\OC::$server->getAppManager()->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) { |
||
542 | throw new OCSNotFoundException($this->l->t('You cannot share to a Circle if the app is not enabled')); |
||
543 | } |
||
544 | |||
545 | $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($shareWith); |
||
546 | |||
547 | // Valid circle is required to share |
||
548 | if ($circle === null) { |
||
549 | throw new OCSNotFoundException($this->l->t('Please specify a valid circle')); |
||
550 | } |
||
551 | $share->setSharedWith($shareWith); |
||
552 | $share->setPermissions($permissions); |
||
553 | } else if ($shareType === Share::SHARE_TYPE_ROOM) { |
||
554 | try { |
||
555 | $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate); |
||
556 | } catch (QueryException $e) { |
||
557 | throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()])); |
||
558 | } |
||
559 | } else { |
||
560 | throw new OCSBadRequestException($this->l->t('Unknown share type')); |
||
561 | } |
||
562 | |||
563 | $share->setShareType($shareType); |
||
564 | $share->setSharedBy($this->currentUser); |
||
565 | |||
566 | try { |
||
567 | $share = $this->shareManager->createShare($share); |
||
568 | } catch (GenericShareException $e) { |
||
569 | $code = $e->getCode() === 0 ? 403 : $e->getCode(); |
||
570 | throw new OCSException($e->getHint(), $code); |
||
571 | } catch (\Exception $e) { |
||
572 | throw new OCSForbiddenException($e->getMessage(), $e); |
||
573 | } |
||
574 | |||
575 | $output = $this->formatShare($share); |
||
576 | |||
577 | return new DataResponse($output); |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * @param \OCP\Files\File|\OCP\Files\Folder $node |
||
582 | * @param boolean $includeTags |
||
583 | * @return DataResponse |
||
584 | */ |
||
585 | private function getSharedWithMe($node = null, bool $includeTags): DataResponse { |
||
614 | } |
||
615 | |||
616 | /** |
||
617 | * @param \OCP\Files\Folder $folder |
||
618 | * @return DataResponse |
||
619 | * @throws OCSBadRequestException |
||
620 | */ |
||
621 | private function getSharesInDir(Node $folder): DataResponse { |
||
622 | if (!($folder instanceof \OCP\Files\Folder)) { |
||
623 | throw new OCSBadRequestException($this->l->t('Not a directory')); |
||
624 | } |
||
625 | |||
626 | $nodes = $folder->getDirectoryListing(); |
||
627 | /** @var \OCP\Share\IShare[] $shares */ |
||
628 | $shares = []; |
||
629 | foreach ($nodes as $node) { |
||
630 | |||
631 | $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $node, true, -1, 0)); |
||
632 | $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $node, true, -1, 0)); |
||
633 | $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $node, true, -1, 0)); |
||
634 | if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { |
||
635 | $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $node, true, -1, 0)); |
||
636 | } |
||
637 | if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { |
||
638 | $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $node, true, -1, 0)); |
||
639 | } |
||
640 | $shares = array_merge($shares, $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $node, true, -1, 0)); |
||
641 | } |
||
642 | |||
643 | $formatted = $miniFormatted = []; |
||
644 | $resharingRight = false; |
||
645 | $known = []; |
||
646 | foreach ($shares as $share) { |
||
647 | if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->currentUser) { |
||
648 | continue; |
||
649 | } |
||
650 | |||
651 | try { |
||
652 | $format = $this->formatShare($share); |
||
653 | |||
654 | $known[] = $share->getId(); |
||
655 | $formatted[] = $format; |
||
656 | if ($share->getSharedBy() === $this->currentUser) { |
||
657 | $miniFormatted[] = $format; |
||
658 | } |
||
659 | if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $folder)) { |
||
660 | $resharingRight = true; |
||
661 | } |
||
662 | } catch (\Exception $e) { |
||
663 | //Ignore this share |
||
664 | } |
||
665 | } |
||
666 | |||
667 | if (!$resharingRight) { |
||
668 | $formatted = $miniFormatted; |
||
669 | } |
||
670 | |||
671 | return new DataResponse($formatted); |
||
672 | } |
||
673 | |||
674 | /** |
||
675 | * The getShares function. |
||
676 | * |
||
677 | * @NoAdminRequired |
||
678 | * |
||
679 | * @param string $shared_with_me |
||
680 | * @param string $reshares |
||
681 | * @param string $subfiles |
||
682 | * @param string $path |
||
683 | * |
||
684 | * - Get shares by the current user |
||
685 | * - Get shares by the current user and reshares (?reshares=true) |
||
686 | * - Get shares with the current user (?shared_with_me=true) |
||
687 | * - Get shares for a specific path (?path=...) |
||
688 | * - Get all shares in a folder (?subfiles=true&path=..) |
||
689 | * |
||
690 | * @return DataResponse |
||
691 | * @throws OCSNotFoundException |
||
692 | */ |
||
693 | public function getShares( |
||
694 | string $shared_with_me = 'false', |
||
695 | string $reshares = 'false', |
||
696 | string $subfiles = 'false', |
||
697 | string $path = null, |
||
698 | string $include_tags = 'false' |
||
699 | ): DataResponse { |
||
700 | |||
701 | if ($path !== null) { |
||
702 | $userFolder = $this->rootFolder->getUserFolder($this->currentUser); |
||
703 | try { |
||
704 | $path = $userFolder->get($path); |
||
705 | $this->lock($path); |
||
706 | } catch (\OCP\Files\NotFoundException $e) { |
||
707 | throw new OCSNotFoundException($this->l->t('Wrong path, file/folder doesn\'t exist')); |
||
708 | } catch (LockedException $e) { |
||
709 | throw new OCSNotFoundException($this->l->t('Could not lock path')); |
||
710 | } |
||
711 | } |
||
712 | |||
713 | $include_tags = $include_tags === 'true'; |
||
714 | |||
715 | if ($shared_with_me === 'true') { |
||
716 | $result = $this->getSharedWithMe($path, $include_tags); |
||
717 | return $result; |
||
718 | } |
||
719 | |||
720 | if ($subfiles === 'true') { |
||
721 | $result = $this->getSharesInDir($path); |
||
722 | return $result; |
||
723 | } |
||
724 | |||
725 | if ($reshares === 'true') { |
||
726 | $reshares = true; |
||
727 | } else { |
||
728 | $reshares = false; |
||
729 | } |
||
730 | |||
731 | // Get all shares |
||
732 | $userShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_USER, $path, $reshares, -1, 0); |
||
733 | $groupShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_GROUP, $path, $reshares, -1, 0); |
||
734 | $linkShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_LINK, $path, $reshares, -1, 0); |
||
735 | if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { |
||
736 | $mailShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_EMAIL, $path, $reshares, -1, 0); |
||
737 | } else { |
||
738 | $mailShares = []; |
||
739 | } |
||
740 | if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) { |
||
741 | $circleShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_CIRCLE, $path, $reshares, -1, 0); |
||
742 | } else { |
||
743 | $circleShares = []; |
||
744 | } |
||
745 | $roomShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_ROOM, $path, $reshares, -1, 0); |
||
746 | |||
747 | $shares = array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares); |
||
748 | |||
749 | if ($this->shareManager->outgoingServer2ServerSharesAllowed()) { |
||
750 | $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE, $path, $reshares, -1, 0); |
||
751 | $shares = array_merge($shares, $federatedShares); |
||
752 | } |
||
753 | |||
754 | if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) { |
||
755 | $federatedShares = $this->shareManager->getSharesBy($this->currentUser, Share::SHARE_TYPE_REMOTE_GROUP, $path, $reshares, -1, 0); |
||
756 | $shares = array_merge($shares, $federatedShares); |
||
757 | } |
||
758 | |||
759 | $formatted = $miniFormatted = []; |
||
760 | $resharingRight = false; |
||
761 | foreach ($shares as $share) { |
||
762 | /** @var IShare $share */ |
||
763 | try { |
||
764 | $format = $this->formatShare($share, $path); |
||
765 | $formatted[] = $format; |
||
766 | if ($share->getSharedBy() === $this->currentUser) { |
||
767 | $miniFormatted[] = $format; |
||
768 | } |
||
769 | |||
770 | if (!$resharingRight && $this->shareProviderResharingRights($this->currentUser, $share, $path)) { |
||
771 | $resharingRight = true; |
||
772 | } |
||
773 | } catch (\Exception $e) { |
||
774 | //Ignore share |
||
775 | } |
||
776 | } |
||
777 | |||
778 | if (!$resharingRight) { |
||
779 | $formatted = $miniFormatted; |
||
780 | } |
||
781 | |||
782 | if ($include_tags) { |
||
783 | $formatted = Helper::populateTags($formatted, 'file_source', \OC::$server->getTagManager()); |
||
784 | } |
||
785 | |||
786 | return new DataResponse($formatted); |
||
787 | } |
||
788 | |||
789 | /** |
||
790 | * @NoAdminRequired |
||
791 | * |
||
792 | * @param string $id |
||
793 | * @param int $permissions |
||
794 | * @param string $password |
||
795 | * @param string $sendPasswordByTalk |
||
796 | * @param string $publicUpload |
||
797 | * @param string $expireDate |
||
798 | * @param string $note |
||
799 | * @param string $label |
||
800 | * @param string $hideDownload |
||
801 | * @return DataResponse |
||
802 | * @throws LockedException |
||
803 | * @throws NotFoundException |
||
804 | * @throws OCSBadRequestException |
||
805 | * @throws OCSForbiddenException |
||
806 | * @throws OCSNotFoundException |
||
807 | */ |
||
808 | public function updateShare( |
||
809 | string $id, |
||
810 | int $permissions = null, |
||
811 | string $password = null, |
||
812 | string $sendPasswordByTalk = null, |
||
813 | string $publicUpload = null, |
||
814 | string $expireDate = null, |
||
815 | string $note = null, |
||
816 | string $label = null, |
||
817 | string $hideDownload = null |
||
818 | ): DataResponse { |
||
819 | try { |
||
820 | $share = $this->getShareById($id); |
||
821 | } catch (ShareNotFound $e) { |
||
822 | throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist')); |
||
823 | } |
||
824 | |||
825 | $this->lock($share->getNode()); |
||
826 | |||
827 | if (!$this->canAccessShare($share, false)) { |
||
828 | throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist')); |
||
829 | } |
||
830 | |||
831 | if ($share->getShareOwner() !== $this->currentUser && $share->getSharedBy() !== $this->currentUser) { |
||
832 | throw new OCSForbiddenException('You are not allowed to edit incoming shares'); |
||
833 | } |
||
834 | |||
835 | if ($permissions === null && |
||
836 | $password === null && |
||
837 | $sendPasswordByTalk === null && |
||
838 | $publicUpload === null && |
||
839 | $expireDate === null && |
||
840 | $note === null && |
||
841 | $label === null && |
||
842 | $hideDownload === null |
||
843 | ) { |
||
844 | throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given')); |
||
845 | } |
||
846 | |||
847 | if($note !== null) { |
||
848 | $share->setNote($note); |
||
849 | } |
||
850 | |||
851 | /* |
||
852 | * expirationdate, password and publicUpload only make sense for link shares |
||
853 | */ |
||
854 | if ($share->getShareType() === Share::SHARE_TYPE_LINK) { |
||
855 | |||
856 | // Update hide download state |
||
857 | if ($hideDownload === 'true') { |
||
858 | $share->setHideDownload(true); |
||
859 | } else if ($hideDownload === 'false') { |
||
860 | $share->setHideDownload(false); |
||
861 | } |
||
862 | |||
863 | $newPermissions = null; |
||
864 | if ($publicUpload === 'true') { |
||
865 | $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE; |
||
866 | } else if ($publicUpload === 'false') { |
||
867 | $newPermissions = Constants::PERMISSION_READ; |
||
868 | } |
||
869 | |||
870 | if ($permissions !== null) { |
||
871 | $newPermissions = (int)$permissions; |
||
872 | $newPermissions = $newPermissions & ~Constants::PERMISSION_SHARE; |
||
873 | } |
||
874 | |||
875 | if ($newPermissions !== null && |
||
876 | !in_array($newPermissions, [ |
||
877 | Constants::PERMISSION_READ, |
||
878 | Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE, // legacy |
||
879 | Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE, // correct |
||
880 | Constants::PERMISSION_CREATE, // hidden file list |
||
881 | Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE, // allow to edit single files |
||
882 | ], true) |
||
883 | ) { |
||
884 | throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links')); |
||
885 | } |
||
886 | |||
887 | if ( |
||
888 | // legacy |
||
889 | $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE) || |
||
890 | // correct |
||
891 | $newPermissions === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE) |
||
892 | ) { |
||
893 | if (!$this->shareManager->shareApiLinkAllowPublicUpload()) { |
||
894 | throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator')); |
||
895 | } |
||
896 | |||
897 | if (!($share->getNode() instanceof \OCP\Files\Folder)) { |
||
898 | throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders')); |
||
899 | } |
||
900 | |||
901 | // normalize to correct public upload permissions |
||
902 | $newPermissions = Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE; |
||
903 | } |
||
904 | |||
905 | if ($newPermissions !== null) { |
||
906 | $share->setPermissions($newPermissions); |
||
907 | $permissions = $newPermissions; |
||
908 | } |
||
909 | |||
910 | if ($expireDate === '') { |
||
911 | $share->setExpirationDate(null); |
||
912 | } else if ($expireDate !== null) { |
||
913 | try { |
||
914 | $expireDate = $this->parseDate($expireDate); |
||
915 | } catch (\Exception $e) { |
||
916 | throw new OCSBadRequestException($e->getMessage(), $e); |
||
917 | } |
||
918 | $share->setExpirationDate($expireDate); |
||
919 | } |
||
920 | |||
921 | if ($password === '') { |
||
922 | $share->setPassword(null); |
||
923 | } else if ($password !== null) { |
||
924 | $share->setPassword($password); |
||
925 | } |
||
926 | |||
927 | if ($label !== null) { |
||
928 | $share->setLabel($label); |
||
929 | } |
||
930 | |||
931 | if ($sendPasswordByTalk === 'true') { |
||
932 | if (!$this->appManager->isEnabledForUser('spreed')) { |
||
933 | throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled')); |
||
934 | } |
||
935 | |||
936 | $share->setSendPasswordByTalk(true); |
||
937 | } else if ($sendPasswordByTalk !== null) { |
||
938 | $share->setSendPasswordByTalk(false); |
||
939 | } |
||
940 | } else { |
||
941 | if ($permissions !== null) { |
||
942 | $permissions = (int)$permissions; |
||
943 | $share->setPermissions($permissions); |
||
944 | } |
||
945 | |||
946 | if ($share->getShareType() === Share::SHARE_TYPE_EMAIL) { |
||
947 | if ($password === '') { |
||
948 | $share->setPassword(null); |
||
949 | } else if ($password !== null) { |
||
950 | $share->setPassword($password); |
||
951 | } |
||
952 | |||
953 | if ($sendPasswordByTalk === 'true') { |
||
954 | if (!$this->appManager->isEnabledForUser('spreed')) { |
||
955 | throw new OCSForbiddenException($this->l->t('Sharing sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled')); |
||
956 | } |
||
957 | |||
958 | $share->setSendPasswordByTalk(true); |
||
959 | } else { |
||
960 | $share->setSendPasswordByTalk(false); |
||
961 | } |
||
962 | } |
||
963 | |||
964 | if ($expireDate === '') { |
||
965 | $share->setExpirationDate(null); |
||
966 | } else if ($expireDate !== null) { |
||
967 | try { |
||
968 | $expireDate = $this->parseDate($expireDate); |
||
969 | } catch (\Exception $e) { |
||
970 | throw new OCSBadRequestException($e->getMessage(), $e); |
||
971 | } |
||
972 | $share->setExpirationDate($expireDate); |
||
973 | } |
||
974 | |||
975 | } |
||
976 | |||
977 | if ($permissions !== null && $share->getShareOwner() !== $this->currentUser) { |
||
978 | /* Check if this is an incoming share */ |
||
979 | $incomingShares = $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_USER, $share->getNode(), -1, 0); |
||
980 | $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_GROUP, $share->getNode(), -1, 0)); |
||
981 | $incomingShares = array_merge($incomingShares, $this->shareManager->getSharedWith($this->currentUser, Share::SHARE_TYPE_ROOM, $share->getNode(), -1, 0)); |
||
982 | |||
983 | /** @var \OCP\Share\IShare[] $incomingShares */ |
||
984 | if (!empty($incomingShares)) { |
||
985 | $maxPermissions = 0; |
||
986 | foreach ($incomingShares as $incomingShare) { |
||
987 | $maxPermissions |= $incomingShare->getPermissions(); |
||
988 | } |
||
989 | |||
990 | if ($share->getPermissions() & ~$maxPermissions) { |
||
991 | throw new OCSNotFoundException($this->l->t('Cannot increase permissions')); |
||
992 | } |
||
993 | } |
||
994 | } |
||
995 | |||
996 | |||
997 | try { |
||
998 | $share = $this->shareManager->updateShare($share); |
||
999 | } catch (\Exception $e) { |
||
1000 | throw new OCSBadRequestException($e->getMessage(), $e); |
||
1001 | } |
||
1002 | |||
1003 | return new DataResponse($this->formatShare($share)); |
||
1004 | } |
||
1005 | |||
1006 | /** |
||
1007 | * @suppress PhanUndeclaredClassMethod |
||
1008 | */ |
||
1009 | protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool { |
||
1010 | // A file with permissions 0 can't be accessed by us. So Don't show it |
||
1011 | if ($share->getPermissions() === 0) { |
||
1012 | return false; |
||
1013 | } |
||
1014 | |||
1015 | // Owner of the file and the sharer of the file can always get share |
||
1016 | if ($share->getShareOwner() === $this->currentUser || |
||
1017 | $share->getSharedBy() === $this->currentUser |
||
1018 | ) { |
||
1019 | return true; |
||
1020 | } |
||
1021 | |||
1022 | // If the share is shared with you (or a group you are a member of) |
||
1023 | if ($share->getShareType() === Share::SHARE_TYPE_USER && |
||
1024 | $share->getSharedWith() === $this->currentUser |
||
1025 | ) { |
||
1026 | return true; |
||
1027 | } |
||
1028 | |||
1029 | if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) { |
||
1030 | $sharedWith = $this->groupManager->get($share->getSharedWith()); |
||
1031 | $user = $this->userManager->get($this->currentUser); |
||
1032 | if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) { |
||
1033 | return true; |
||
1034 | } |
||
1035 | } |
||
1036 | |||
1037 | if ($share->getShareType() === Share::SHARE_TYPE_CIRCLE) { |
||
1038 | // TODO: have a sanity check like above? |
||
1039 | return true; |
||
1040 | } |
||
1041 | |||
1042 | if ($share->getShareType() === Share::SHARE_TYPE_ROOM) { |
||
1043 | try { |
||
1044 | return $this->getRoomShareHelper()->canAccessShare($share, $this->currentUser); |
||
1045 | } catch (QueryException $e) { |
||
1046 | return false; |
||
1047 | } |
||
1048 | } |
||
1049 | |||
1050 | return false; |
||
1051 | } |
||
1052 | |||
1053 | /** |
||
1054 | * Make sure that the passed date is valid ISO 8601 |
||
1055 | * So YYYY-MM-DD |
||
1056 | * If not throw an exception |
||
1057 | * |
||
1058 | * @param string $expireDate |
||
1059 | * |
||
1060 | * @throws \Exception |
||
1061 | * @return \DateTime |
||
1062 | */ |
||
1063 | private function parseDate(string $expireDate): \DateTime { |
||
1064 | try { |
||
1065 | $date = new \DateTime($expireDate); |
||
1066 | } catch (\Exception $e) { |
||
1067 | throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); |
||
1068 | } |
||
1069 | |||
1070 | if ($date === false) { |
||
1071 | throw new \Exception('Invalid date. Format must be YYYY-MM-DD'); |
||
1072 | } |
||
1073 | |||
1074 | $date->setTime(0, 0, 0); |
||
1075 | |||
1076 | return $date; |
||
1077 | } |
||
1078 | |||
1079 | /** |
||
1080 | * Since we have multiple providers but the OCS Share API v1 does |
||
1081 | * not support this we need to check all backends. |
||
1082 | * |
||
1083 | * @param string $id |
||
1084 | * @return \OCP\Share\IShare |
||
1085 | * @throws ShareNotFound |
||
1086 | */ |
||
1087 | private function getShareById(string $id): IShare { |
||
1088 | $share = null; |
||
1089 | |||
1090 | // First check if it is an internal share. |
||
1091 | try { |
||
1092 | $share = $this->shareManager->getShareById('ocinternal:' . $id, $this->currentUser); |
||
1093 | return $share; |
||
1094 | } catch (ShareNotFound $e) { |
||
1095 | // Do nothing, just try the other share type |
||
1096 | } |
||
1097 | |||
1098 | |||
1099 | try { |
||
1100 | if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_CIRCLE)) { |
||
1101 | $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->currentUser); |
||
1102 | return $share; |
||
1103 | } |
||
1104 | } catch (ShareNotFound $e) { |
||
1105 | // Do nothing, just try the other share type |
||
1106 | } |
||
1107 | |||
1108 | try { |
||
1109 | if ($this->shareManager->shareProviderExists(Share::SHARE_TYPE_EMAIL)) { |
||
1110 | $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->currentUser); |
||
1111 | return $share; |
||
1112 | } |
||
1113 | } catch (ShareNotFound $e) { |
||
1114 | // Do nothing, just try the other share type |
||
1115 | } |
||
1116 | |||
1117 | try { |
||
1118 | $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->currentUser); |
||
1119 | return $share; |
||
1120 | } catch (ShareNotFound $e) { |
||
1121 | // Do nothing, just try the other share type |
||
1122 | } |
||
1123 | |||
1124 | if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) { |
||
1125 | throw new ShareNotFound(); |
||
1126 | } |
||
1127 | $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->currentUser); |
||
1128 | |||
1129 | return $share; |
||
1130 | } |
||
1131 | |||
1132 | /** |
||
1133 | * Lock a Node |
||
1134 | * |
||
1135 | * @param \OCP\Files\Node $node |
||
1136 | * @throws LockedException |
||
1137 | */ |
||
1138 | private function lock(\OCP\Files\Node $node) { |
||
1139 | $node->lock(ILockingProvider::LOCK_SHARED); |
||
1140 | $this->lockedNode = $node; |
||
1141 | } |
||
1142 | |||
1143 | /** |
||
1144 | * Cleanup the remaining locks |
||
1145 | * @throws @LockedException |
||
1146 | */ |
||
1147 | public function cleanup() { |
||
1150 | } |
||
1151 | } |
||
1152 | |||
1153 | /** |
||
1154 | * Returns the helper of ShareAPIController for room shares. |
||
1155 | * |
||
1156 | * If the Talk application is not enabled or the helper is not available |
||
1157 | * a QueryException is thrown instead. |
||
1158 | * |
||
1159 | * @return \OCA\Spreed\Share\Helper\ShareAPIController |
||
1160 | * @throws QueryException |
||
1161 | */ |
||
1162 | private function getRoomShareHelper() { |
||
1163 | if (!$this->appManager->isEnabledForUser('spreed')) { |
||
1164 | throw new QueryException(); |
||
1165 | } |
||
1166 | |||
1167 | return $this->serverContainer->query('\OCA\Spreed\Share\Helper\ShareAPIController'); |
||
1168 | } |
||
1169 | |||
1170 | |||
1171 | /** |
||
1172 | * Returns if we can find resharing rights in an IShare object for a specific user. |
||
1173 | * |
||
1174 | * @suppress PhanUndeclaredClassMethod |
||
1175 | * |
||
1176 | * @param string $userId |
||
1177 | * @param IShare $share |
||
1178 | * @param Node $node |
||
1179 | * @return bool |
||
1180 | * @throws NotFoundException |
||
1181 | * @throws \OCP\Files\InvalidPathException |
||
1182 | */ |
||
1183 | private function shareProviderResharingRights(string $userId, IShare $share, $node): bool { |
||
1227 | } |
||
1228 | |||
1229 | } |
||
1230 |