Completed
Push — master ( 2cbfdc...ebc5ae )
by
unknown
28:26 queued 14s
created
apps/files_sharing/lib/Controller/ShareAPIController.php 1 patch
Indentation   +2185 added lines, -2185 removed lines patch added patch discarded remove patch
@@ -75,2192 +75,2192 @@
 block discarded – undo
75 75
  */
76 76
 class ShareAPIController extends OCSController {
77 77
 
78
-	private ?Node $lockedNode = null;
79
-
80
-	/**
81
-	 * Share20OCS constructor.
82
-	 */
83
-	public function __construct(
84
-		string $appName,
85
-		IRequest $request,
86
-		private IManager $shareManager,
87
-		private IGroupManager $groupManager,
88
-		private IUserManager $userManager,
89
-		private IRootFolder $rootFolder,
90
-		private IURLGenerator $urlGenerator,
91
-		private IL10N $l,
92
-		private IConfig $config,
93
-		private IAppConfig $appConfig,
94
-		private IAppManager $appManager,
95
-		private ContainerInterface $serverContainer,
96
-		private IUserStatusManager $userStatusManager,
97
-		private IPreview $previewManager,
98
-		private IDateTimeZone $dateTimeZone,
99
-		private LoggerInterface $logger,
100
-		private IProviderFactory $factory,
101
-		private IMailer $mailer,
102
-		private ITagManager $tagManager,
103
-		private ?string $userId = null,
104
-	) {
105
-		parent::__construct($appName, $request);
106
-	}
107
-
108
-	/**
109
-	 * Convert an IShare to an array for OCS output
110
-	 *
111
-	 * @param IShare $share
112
-	 * @param Node|null $recipientNode
113
-	 * @return Files_SharingShare
114
-	 * @throws NotFoundException In case the node can't be resolved.
115
-	 *
116
-	 * @suppress PhanUndeclaredClassMethod
117
-	 */
118
-	protected function formatShare(IShare $share, ?Node $recipientNode = null): array {
119
-		$sharedBy = $this->userManager->get($share->getSharedBy());
120
-		$shareOwner = $this->userManager->get($share->getShareOwner());
121
-
122
-		$isOwnShare = false;
123
-		if ($shareOwner !== null) {
124
-			$isOwnShare = $shareOwner->getUID() === $this->userId;
125
-		}
126
-
127
-		$result = [
128
-			'id' => $share->getId(),
129
-			'share_type' => $share->getShareType(),
130
-			'uid_owner' => $share->getSharedBy(),
131
-			'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
132
-			// recipient permissions
133
-			'permissions' => $share->getPermissions(),
134
-			// current user permissions on this share
135
-			'can_edit' => $this->canEditShare($share),
136
-			'can_delete' => $this->canDeleteShare($share),
137
-			'stime' => $share->getShareTime()->getTimestamp(),
138
-			'parent' => null,
139
-			'expiration' => null,
140
-			'token' => null,
141
-			'uid_file_owner' => $share->getShareOwner(),
142
-			'note' => $share->getNote(),
143
-			'label' => $share->getLabel(),
144
-			'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
145
-		];
146
-
147
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
148
-		if ($recipientNode) {
149
-			$node = $recipientNode;
150
-		} else {
151
-			$node = $userFolder->getFirstNodeById($share->getNodeId());
152
-			if (!$node) {
153
-				// fallback to guessing the path
154
-				$node = $userFolder->get($share->getTarget());
155
-				if ($node === null || $share->getTarget() === '') {
156
-					throw new NotFoundException();
157
-				}
158
-			}
159
-		}
160
-
161
-		$result['path'] = $userFolder->getRelativePath($node->getPath());
162
-		if ($node instanceof Folder) {
163
-			$result['item_type'] = 'folder';
164
-		} else {
165
-			$result['item_type'] = 'file';
166
-		}
167
-
168
-		// Get the original node permission if the share owner is the current user
169
-		if ($isOwnShare) {
170
-			$result['item_permissions'] = $node->getPermissions();
171
-		}
172
-
173
-		// If we're on the recipient side, the node permissions
174
-		// are bound to the share permissions. So we need to
175
-		// adjust the permissions to the share permissions if necessary.
176
-		if (!$isOwnShare) {
177
-			$result['item_permissions'] = $share->getPermissions();
178
-
179
-			// For some reason, single files share are forbidden to have the delete permission
180
-			// since we have custom methods to check those, let's adjust straight away.
181
-			// DAV permissions does not have that issue though.
182
-			if ($this->canDeleteShare($share) || $this->canDeleteShareFromSelf($share)) {
183
-				$result['item_permissions'] |= Constants::PERMISSION_DELETE;
184
-			}
185
-			if ($this->canEditShare($share)) {
186
-				$result['item_permissions'] |= Constants::PERMISSION_UPDATE;
187
-			}
188
-		}
189
-
190
-		// See MOUNT_ROOT_PROPERTYNAME dav property
191
-		$result['is-mount-root'] = $node->getInternalPath() === '';
192
-		$result['mount-type'] = $node->getMountPoint()->getMountType();
193
-
194
-		$result['mimetype'] = $node->getMimetype();
195
-		$result['has_preview'] = $this->previewManager->isAvailable($node);
196
-		$result['storage_id'] = $node->getStorage()->getId();
197
-		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
198
-		$result['item_source'] = $node->getId();
199
-		$result['file_source'] = $node->getId();
200
-		$result['file_parent'] = $node->getParent()->getId();
201
-		$result['file_target'] = $share->getTarget();
202
-		$result['item_size'] = $node->getSize();
203
-		$result['item_mtime'] = $node->getMTime();
204
-
205
-		$expiration = $share->getExpirationDate();
206
-		if ($expiration !== null) {
207
-			$expiration->setTimezone($this->dateTimeZone->getTimeZone());
208
-			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
209
-		}
210
-
211
-		if ($share->getShareType() === IShare::TYPE_USER) {
212
-			$sharedWith = $this->userManager->get($share->getSharedWith());
213
-			$result['share_with'] = $share->getSharedWith();
214
-			$result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
215
-			$result['share_with_displayname_unique'] = $sharedWith !== null ? (
216
-				!empty($sharedWith->getSystemEMailAddress()) ? $sharedWith->getSystemEMailAddress() : $sharedWith->getUID()
217
-			) : $share->getSharedWith();
218
-
219
-			$userStatuses = $this->userStatusManager->getUserStatuses([$share->getSharedWith()]);
220
-			$userStatus = array_shift($userStatuses);
221
-			if ($userStatus) {
222
-				$result['status'] = [
223
-					'status' => $userStatus->getStatus(),
224
-					'message' => $userStatus->getMessage(),
225
-					'icon' => $userStatus->getIcon(),
226
-					'clearAt' => $userStatus->getClearAt()
227
-						? (int)$userStatus->getClearAt()->format('U')
228
-						: null,
229
-				];
230
-			}
231
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
232
-			$group = $this->groupManager->get($share->getSharedWith());
233
-			$result['share_with'] = $share->getSharedWith();
234
-			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
235
-		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
236
-
237
-			// "share_with" and "share_with_displayname" for passwords of link
238
-			// shares was deprecated in Nextcloud 15, use "password" instead.
239
-			$result['share_with'] = $share->getPassword();
240
-			$result['share_with_displayname'] = '(' . $this->l->t('Shared link') . ')';
241
-
242
-			$result['password'] = $share->getPassword();
243
-
244
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
245
-
246
-			$result['token'] = $share->getToken();
247
-			$result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
248
-		} elseif ($share->getShareType() === IShare::TYPE_REMOTE) {
249
-			$result['share_with'] = $share->getSharedWith();
250
-			$result['share_with_displayname'] = $this->getCachedFederatedDisplayName($share->getSharedWith());
251
-			$result['token'] = $share->getToken();
252
-		} elseif ($share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
253
-			$result['share_with'] = $share->getSharedWith();
254
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
255
-			$result['token'] = $share->getToken();
256
-		} elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
257
-			$result['share_with'] = $share->getSharedWith();
258
-			$result['password'] = $share->getPassword();
259
-			$result['password_expiration_time'] = $share->getPasswordExpirationTime() !== null ? $share->getPasswordExpirationTime()->format(\DateTime::ATOM) : null;
260
-			$result['send_password_by_talk'] = $share->getSendPasswordByTalk();
261
-			$result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
262
-			$result['token'] = $share->getToken();
263
-		} elseif ($share->getShareType() === IShare::TYPE_CIRCLE) {
264
-			// getSharedWith() returns either "name (type, owner)" or
265
-			// "name (type, owner) [id]", depending on the Teams app version.
266
-			$hasCircleId = (substr($share->getSharedWith(), -1) === ']');
267
-
268
-			$result['share_with_displayname'] = $share->getSharedWithDisplayName();
269
-			if (empty($result['share_with_displayname'])) {
270
-				$displayNameLength = ($hasCircleId ? strrpos($share->getSharedWith(), ' ') : strlen($share->getSharedWith()));
271
-				$result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
272
-			}
273
-
274
-			$result['share_with_avatar'] = $share->getSharedWithAvatar();
275
-
276
-			$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
277
-			$shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
278
-			if ($shareWithLength === false) {
279
-				$result['share_with'] = substr($share->getSharedWith(), $shareWithStart);
280
-			} else {
281
-				$result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
282
-			}
283
-		} elseif ($share->getShareType() === IShare::TYPE_ROOM) {
284
-			$result['share_with'] = $share->getSharedWith();
285
-			$result['share_with_displayname'] = '';
286
-
287
-			try {
288
-				/** @var array{share_with_displayname: string, share_with_link: string, share_with?: string, token?: string} $roomShare */
289
-				$roomShare = $this->getRoomShareHelper()->formatShare($share);
290
-				$result = array_merge($result, $roomShare);
291
-			} catch (ContainerExceptionInterface $e) {
292
-			}
293
-		} elseif ($share->getShareType() === IShare::TYPE_DECK) {
294
-			$result['share_with'] = $share->getSharedWith();
295
-			$result['share_with_displayname'] = '';
296
-
297
-			try {
298
-				/** @var array{share_with: string, share_with_displayname: string, share_with_link: string} $deckShare */
299
-				$deckShare = $this->getDeckShareHelper()->formatShare($share);
300
-				$result = array_merge($result, $deckShare);
301
-			} catch (ContainerExceptionInterface $e) {
302
-			}
303
-		} elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
304
-			$result['share_with'] = $share->getSharedWith();
305
-			$result['share_with_displayname'] = '';
306
-
307
-			try {
308
-				/** @var array{share_with: string, share_with_displayname: string, token: string} $scienceMeshShare */
309
-				$scienceMeshShare = $this->getSciencemeshShareHelper()->formatShare($share);
310
-				$result = array_merge($result, $scienceMeshShare);
311
-			} catch (ContainerExceptionInterface $e) {
312
-			}
313
-		}
314
-
315
-
316
-		$result['mail_send'] = $share->getMailSend() ? 1 : 0;
317
-		$result['hide_download'] = $share->getHideDownload() ? 1 : 0;
318
-
319
-		$result['attributes'] = null;
320
-		if ($attributes = $share->getAttributes()) {
321
-			$result['attributes'] = (string)\json_encode($attributes->toArray());
322
-		}
323
-
324
-		return $result;
325
-	}
326
-
327
-	/**
328
-	 * Check if one of the users address books knows the exact property, if
329
-	 * not we return the full name.
330
-	 *
331
-	 * @param string $query
332
-	 * @param string $property
333
-	 * @return string
334
-	 */
335
-	private function getDisplayNameFromAddressBook(string $query, string $property): string {
336
-		// FIXME: If we inject the contacts manager it gets initialized before any address books are registered
337
-		try {
338
-			$result = Server::get(\OCP\Contacts\IManager::class)->search($query, [$property], [
339
-				'limit' => 1,
340
-				'enumeration' => false,
341
-				'strict_search' => true,
342
-			]);
343
-		} catch (Exception $e) {
344
-			$this->logger->error(
345
-				$e->getMessage(),
346
-				['exception' => $e]
347
-			);
348
-			return $query;
349
-		}
350
-
351
-		foreach ($result as $r) {
352
-			foreach ($r[$property] as $value) {
353
-				if ($value === $query && $r['FN']) {
354
-					return $r['FN'];
355
-				}
356
-			}
357
-		}
358
-
359
-		return $query;
360
-	}
361
-
362
-
363
-	/**
364
-	 * @param list<Files_SharingShare> $shares
365
-	 * @param array<string, string>|null $updatedDisplayName
366
-	 *
367
-	 * @return list<Files_SharingShare>
368
-	 */
369
-	private function fixMissingDisplayName(array $shares, ?array $updatedDisplayName = null): array {
370
-		$userIds = $updated = [];
371
-		foreach ($shares as $share) {
372
-			// share is federated and share have no display name yet
373
-			if ($share['share_type'] === IShare::TYPE_REMOTE
374
-				&& ($share['share_with'] ?? '') !== ''
375
-				&& ($share['share_with_displayname'] ?? '') === '') {
376
-				$userIds[] = $userId = $share['share_with'];
377
-
378
-				if ($updatedDisplayName !== null && array_key_exists($userId, $updatedDisplayName)) {
379
-					$share['share_with_displayname'] = $updatedDisplayName[$userId];
380
-				}
381
-			}
382
-
383
-			// prepping userIds with displayName to be updated
384
-			$updated[] = $share;
385
-		}
386
-
387
-		// if $updatedDisplayName is not null, it means we should have already fixed displayNames of the shares
388
-		if ($updatedDisplayName !== null) {
389
-			return $updated;
390
-		}
391
-
392
-		// get displayName for the generated list of userId with no displayName
393
-		$displayNames = $this->retrieveFederatedDisplayName($userIds);
394
-
395
-		// if no displayName are updated, we exit
396
-		if (empty($displayNames)) {
397
-			return $updated;
398
-		}
399
-
400
-		// let's fix missing display name and returns all shares
401
-		return $this->fixMissingDisplayName($shares, $displayNames);
402
-	}
403
-
404
-
405
-	/**
406
-	 * get displayName of a list of userIds from the lookup-server; through the globalsiteselector app.
407
-	 * returns an array with userIds as keys and displayName as values.
408
-	 *
409
-	 * @param array $userIds
410
-	 * @param bool $cacheOnly - do not reach LUS, get data from cache.
411
-	 *
412
-	 * @return array
413
-	 * @throws ContainerExceptionInterface
414
-	 */
415
-	private function retrieveFederatedDisplayName(array $userIds, bool $cacheOnly = false): array {
416
-		// check if gss is enabled and available
417
-		if (count($userIds) === 0
418
-			|| !$this->appManager->isEnabledForAnyone('globalsiteselector')
419
-			|| !class_exists('\OCA\GlobalSiteSelector\Service\SlaveService')) {
420
-			return [];
421
-		}
422
-
423
-		try {
424
-			$slaveService = Server::get(SlaveService::class);
425
-		} catch (\Throwable $e) {
426
-			$this->logger->error(
427
-				$e->getMessage(),
428
-				['exception' => $e]
429
-			);
430
-			return [];
431
-		}
432
-
433
-		return $slaveService->getUsersDisplayName($userIds, $cacheOnly);
434
-	}
435
-
436
-
437
-	/**
438
-	 * retrieve displayName from cache if available (should be used on federated shares)
439
-	 * if not available in cache/lus, try for get from address-book, else returns empty string.
440
-	 *
441
-	 * @param string $userId
442
-	 * @param bool $cacheOnly if true will not reach the lus but will only get data from cache
443
-	 *
444
-	 * @return string
445
-	 */
446
-	private function getCachedFederatedDisplayName(string $userId, bool $cacheOnly = true): string {
447
-		$details = $this->retrieveFederatedDisplayName([$userId], $cacheOnly);
448
-		if (array_key_exists($userId, $details)) {
449
-			return $details[$userId];
450
-		}
451
-
452
-		$displayName = $this->getDisplayNameFromAddressBook($userId, 'CLOUD');
453
-		return ($displayName === $userId) ? '' : $displayName;
454
-	}
455
-
456
-
457
-
458
-	/**
459
-	 * Get a specific share by id
460
-	 *
461
-	 * @param string $id ID of the share
462
-	 * @param bool $include_tags Include tags in the share
463
-	 * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
464
-	 * @throws OCSNotFoundException Share not found
465
-	 *
466
-	 * 200: Share returned
467
-	 */
468
-	#[NoAdminRequired]
469
-	public function getShare(string $id, bool $include_tags = false): DataResponse {
470
-		try {
471
-			$share = $this->getShareById($id);
472
-		} catch (ShareNotFound $e) {
473
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
474
-		}
475
-
476
-		try {
477
-			if ($this->canAccessShare($share)) {
478
-				$share = $this->formatShare($share);
479
-
480
-				if ($include_tags) {
481
-					$share = $this->populateTags([$share]);
482
-				} else {
483
-					$share = [$share];
484
-				}
485
-
486
-				return new DataResponse($share);
487
-			}
488
-		} catch (NotFoundException $e) {
489
-			// Fall through
490
-		}
491
-
492
-		throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
493
-	}
494
-
495
-	/**
496
-	 * Delete a share
497
-	 *
498
-	 * @param string $id ID of the share
499
-	 * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
500
-	 * @throws OCSNotFoundException Share not found
501
-	 * @throws OCSForbiddenException Missing permissions to delete the share
502
-	 *
503
-	 * 200: Share deleted successfully
504
-	 */
505
-	#[NoAdminRequired]
506
-	public function deleteShare(string $id): DataResponse {
507
-		try {
508
-			$share = $this->getShareById($id);
509
-		} catch (ShareNotFound $e) {
510
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
511
-		}
512
-
513
-		try {
514
-			$this->lock($share->getNode());
515
-		} catch (LockedException $e) {
516
-			throw new OCSNotFoundException($this->l->t('Could not delete share'));
517
-		}
518
-
519
-		if (!$this->canAccessShare($share)) {
520
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
521
-		}
522
-
523
-		// if it's a group share or a room share
524
-		// we don't delete the share, but only the
525
-		// mount point. Allowing it to be restored
526
-		// from the deleted shares
527
-		if ($this->canDeleteShareFromSelf($share)) {
528
-			$this->shareManager->deleteFromSelf($share, $this->userId);
529
-		} else {
530
-			if (!$this->canDeleteShare($share)) {
531
-				throw new OCSForbiddenException($this->l->t('Could not delete share'));
532
-			}
533
-
534
-			$this->shareManager->deleteShare($share);
535
-		}
536
-
537
-		return new DataResponse();
538
-	}
539
-
540
-	/**
541
-	 * Create a share
542
-	 *
543
-	 * @param string|null $path Path of the share
544
-	 * @param int|null $permissions Permissions for the share
545
-	 * @param int $shareType Type of the share
546
-	 * @param ?string $shareWith The entity this should be shared with
547
-	 * @param 'true'|'false'|null $publicUpload If public uploading is allowed (deprecated)
548
-	 * @param string $password Password for the share
549
-	 * @param string|null $sendPasswordByTalk Send the password for the share over Talk
550
-	 * @param ?string $expireDate The expiry date of the share in the user's timezone at 00:00.
551
-	 *                            If $expireDate is not supplied or set to `null`, the system default will be used.
552
-	 * @param string $note Note for the share
553
-	 * @param string $label Label for the share (only used in link and email)
554
-	 * @param string|null $attributes Additional attributes for the share
555
-	 * @param 'false'|'true'|null $sendMail Send a mail to the recipient
556
-	 *
557
-	 * @return DataResponse<Http::STATUS_OK, Files_SharingShare, array{}>
558
-	 * @throws OCSBadRequestException Unknown share type
559
-	 * @throws OCSException
560
-	 * @throws OCSForbiddenException Creating the share is not allowed
561
-	 * @throws OCSNotFoundException Creating the share failed
562
-	 * @suppress PhanUndeclaredClassMethod
563
-	 *
564
-	 * 200: Share created
565
-	 */
566
-	#[NoAdminRequired]
567
-	#[UserRateLimit(limit: 20, period: 600)]
568
-	public function createShare(
569
-		?string $path = null,
570
-		?int $permissions = null,
571
-		int $shareType = -1,
572
-		?string $shareWith = null,
573
-		?string $publicUpload = null,
574
-		string $password = '',
575
-		?string $sendPasswordByTalk = null,
576
-		?string $expireDate = null,
577
-		string $note = '',
578
-		string $label = '',
579
-		?string $attributes = null,
580
-		?string $sendMail = null,
581
-	): DataResponse {
582
-		assert($this->userId !== null);
583
-
584
-		$share = $this->shareManager->newShare();
585
-		$hasPublicUpload = $this->getLegacyPublicUpload($publicUpload);
586
-
587
-		// Verify path
588
-		if ($path === null) {
589
-			throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
590
-		}
591
-
592
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
593
-		try {
594
-			/** @var \OC\Files\Node\Node $node */
595
-			$node = $userFolder->get($path);
596
-		} catch (NotFoundException $e) {
597
-			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder does not exist'));
598
-		}
599
-
600
-		// a user can have access to a file through different paths, with differing permissions
601
-		// combine all permissions to determine if the user can share this file
602
-		$nodes = $userFolder->getById($node->getId());
603
-		foreach ($nodes as $nodeById) {
604
-			/** @var FileInfo $fileInfo */
605
-			$fileInfo = $node->getFileInfo();
606
-			$fileInfo['permissions'] |= $nodeById->getPermissions();
607
-		}
608
-
609
-		$share->setNode($node);
610
-
611
-		try {
612
-			$this->lock($share->getNode());
613
-		} catch (LockedException $e) {
614
-			throw new OCSNotFoundException($this->l->t('Could not create share'));
615
-		}
616
-
617
-		// Set permissions
618
-		if ($shareType === IShare::TYPE_LINK || $shareType === IShare::TYPE_EMAIL) {
619
-			$permissions = $this->getLinkSharePermissions($permissions, $hasPublicUpload);
620
-			$this->validateLinkSharePermissions($node, $permissions, $hasPublicUpload);
621
-		} else {
622
-			// Use default permissions only for non-link shares to keep legacy behavior
623
-			if ($permissions === null) {
624
-				$permissions = (int)$this->config->getAppValue('core', 'shareapi_default_permissions', (string)Constants::PERMISSION_ALL);
625
-			}
626
-			// Non-link shares always require read permissions (link shares could be file drop)
627
-			$permissions |= Constants::PERMISSION_READ;
628
-		}
629
-
630
-		// For legacy reasons the API allows to pass PERMISSIONS_ALL even for single file shares (I look at you Talk)
631
-		if ($node instanceof File) {
632
-			// if this is a single file share we remove the DELETE and CREATE permissions
633
-			$permissions = $permissions & ~(Constants::PERMISSION_DELETE | Constants::PERMISSION_CREATE);
634
-		}
635
-
636
-		/**
637
-		 * Hack for https://github.com/owncloud/core/issues/22587
638
-		 * We check the permissions via webdav. But the permissions of the mount point
639
-		 * do not equal the share permissions. Here we fix that for federated mounts.
640
-		 */
641
-		if ($node->getStorage()->instanceOfStorage(Storage::class)) {
642
-			$permissions &= ~($permissions & ~$node->getPermissions());
643
-		}
644
-
645
-		if ($attributes !== null) {
646
-			$share = $this->setShareAttributes($share, $attributes);
647
-		}
648
-
649
-		// Expire date checks
650
-		// Normally, null means no expiration date but we still set the default for backwards compatibility
651
-		// If the client sends an empty string, we set noExpirationDate to true
652
-		if ($expireDate !== null) {
653
-			if ($expireDate !== '') {
654
-				try {
655
-					$expireDateTime = $this->parseDate($expireDate);
656
-					$share->setExpirationDate($expireDateTime);
657
-				} catch (\Exception $e) {
658
-					throw new OCSNotFoundException($e->getMessage(), $e);
659
-				}
660
-			} else {
661
-				// Client sent empty string for expire date.
662
-				// Set noExpirationDate to true so overwrite is prevented.
663
-				$share->setNoExpirationDate(true);
664
-			}
665
-		}
666
-
667
-		$share->setSharedBy($this->userId);
668
-
669
-		// Handle mail send
670
-		if (is_null($sendMail)) {
671
-			$allowSendMail = $this->config->getSystemValueBool('sharing.enable_share_mail', true);
672
-			if ($allowSendMail !== true || $shareType === IShare::TYPE_EMAIL) {
673
-				// Define a default behavior when sendMail is not provided
674
-				// For email shares with a valid recipient, the default is to send the mail
675
-				// For all other share types, the default is to not send the mail
676
-				$allowSendMail = ($shareType === IShare::TYPE_EMAIL && $shareWith !== null && $shareWith !== '');
677
-			}
678
-			$share->setMailSend($allowSendMail);
679
-		} else {
680
-			$share->setMailSend($sendMail === 'true');
681
-		}
682
-
683
-		if ($shareType === IShare::TYPE_USER) {
684
-			// Valid user is required to share
685
-			if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
686
-				throw new OCSNotFoundException($this->l->t('Please specify a valid account to share with'));
687
-			}
688
-			$share->setSharedWith($shareWith);
689
-			$share->setPermissions($permissions);
690
-		} elseif ($shareType === IShare::TYPE_GROUP) {
691
-			if (!$this->shareManager->allowGroupSharing()) {
692
-				throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
693
-			}
694
-
695
-			// Valid group is required to share
696
-			if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
697
-				throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
698
-			}
699
-			$share->setSharedWith($shareWith);
700
-			$share->setPermissions($permissions);
701
-		} elseif ($shareType === IShare::TYPE_LINK
702
-			|| $shareType === IShare::TYPE_EMAIL) {
703
-
704
-			// Can we even share links?
705
-			if (!$this->shareManager->shareApiAllowLinks()) {
706
-				throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
707
-			}
708
-
709
-			$this->validateLinkSharePermissions($node, $permissions, $hasPublicUpload);
710
-			$share->setPermissions($permissions);
711
-
712
-			// Set password
713
-			if ($password !== '') {
714
-				$share->setPassword($password);
715
-			}
716
-
717
-			// Only share by mail have a recipient
718
-			if (is_string($shareWith) && $shareType === IShare::TYPE_EMAIL) {
719
-				// If sending a mail have been requested, validate the mail address
720
-				if ($share->getMailSend() && !$this->mailer->validateMailAddress($shareWith)) {
721
-					throw new OCSNotFoundException($this->l->t('Please specify a valid email address'));
722
-				}
723
-				$share->setSharedWith($shareWith);
724
-			}
725
-
726
-			// If we have a label, use it
727
-			if ($label !== '') {
728
-				if (strlen($label) > 255) {
729
-					throw new OCSBadRequestException('Maximum label length is 255');
730
-				}
731
-				$share->setLabel($label);
732
-			}
733
-
734
-			if ($sendPasswordByTalk === 'true') {
735
-				if (!$this->appManager->isEnabledForUser('spreed')) {
736
-					throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$node->getPath()]));
737
-				}
738
-
739
-				$share->setSendPasswordByTalk(true);
740
-			}
741
-		} elseif ($shareType === IShare::TYPE_REMOTE) {
742
-			if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
743
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
744
-			}
745
-
746
-			if ($shareWith === null) {
747
-				throw new OCSNotFoundException($this->l->t('Please specify a valid federated account ID'));
748
-			}
749
-
750
-			$share->setSharedWith($shareWith);
751
-			$share->setPermissions($permissions);
752
-			$share->setSharedWithDisplayName($this->getCachedFederatedDisplayName($shareWith, false));
753
-		} elseif ($shareType === IShare::TYPE_REMOTE_GROUP) {
754
-			if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
755
-				throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
756
-			}
757
-
758
-			if ($shareWith === null) {
759
-				throw new OCSNotFoundException($this->l->t('Please specify a valid federated group ID'));
760
-			}
761
-
762
-			$share->setSharedWith($shareWith);
763
-			$share->setPermissions($permissions);
764
-		} elseif ($shareType === IShare::TYPE_CIRCLE) {
765
-			if (!Server::get(IAppManager::class)->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
766
-				throw new OCSNotFoundException($this->l->t('You cannot share to a Team if the app is not enabled'));
767
-			}
768
-
769
-			$circle = Circles::detailsCircle($shareWith);
770
-
771
-			// Valid team is required to share
772
-			if ($circle === null) {
773
-				throw new OCSNotFoundException($this->l->t('Please specify a valid team'));
774
-			}
775
-			$share->setSharedWith($shareWith);
776
-			$share->setPermissions($permissions);
777
-		} elseif ($shareType === IShare::TYPE_ROOM) {
778
-			try {
779
-				$this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
780
-			} catch (ContainerExceptionInterface $e) {
781
-				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
782
-			}
783
-		} elseif ($shareType === IShare::TYPE_DECK) {
784
-			try {
785
-				$this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
786
-			} catch (ContainerExceptionInterface $e) {
787
-				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
788
-			}
789
-		} elseif ($shareType === IShare::TYPE_SCIENCEMESH) {
790
-			try {
791
-				$this->getSciencemeshShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
792
-			} catch (ContainerExceptionInterface $e) {
793
-				throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support ScienceMesh shares', [$node->getPath()]));
794
-			}
795
-		} else {
796
-			throw new OCSBadRequestException($this->l->t('Unknown share type'));
797
-		}
798
-
799
-		$share->setShareType($shareType);
800
-		$this->checkInheritedAttributes($share);
801
-
802
-		if ($note !== '') {
803
-			$share->setNote($note);
804
-		}
805
-
806
-		try {
807
-			$share = $this->shareManager->createShare($share);
808
-		} catch (HintException $e) {
809
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
810
-			throw new OCSException($e->getHint(), $code);
811
-		} catch (GenericShareException|\InvalidArgumentException $e) {
812
-			$this->logger->error($e->getMessage(), ['exception' => $e]);
813
-			throw new OCSForbiddenException($e->getMessage(), $e);
814
-		} catch (\Exception $e) {
815
-			$this->logger->error($e->getMessage(), ['exception' => $e]);
816
-			throw new OCSForbiddenException('Failed to create share.', $e);
817
-		}
818
-
819
-		$output = $this->formatShare($share);
820
-
821
-		return new DataResponse($output);
822
-	}
823
-
824
-	/**
825
-	 * @param null|Node $node
826
-	 * @param boolean $includeTags
827
-	 *
828
-	 * @return list<Files_SharingShare>
829
-	 */
830
-	private function getSharedWithMe($node, bool $includeTags): array {
831
-		$userShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_USER, $node, -1, 0);
832
-		$groupShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_GROUP, $node, -1, 0);
833
-		$circleShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_CIRCLE, $node, -1, 0);
834
-		$roomShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_ROOM, $node, -1, 0);
835
-		$deckShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_DECK, $node, -1, 0);
836
-		$sciencemeshShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_SCIENCEMESH, $node, -1, 0);
837
-
838
-		$shares = array_merge($userShares, $groupShares, $circleShares, $roomShares, $deckShares, $sciencemeshShares);
839
-
840
-		$filteredShares = array_filter($shares, function (IShare $share) {
841
-			return $share->getShareOwner() !== $this->userId;
842
-		});
843
-
844
-		$formatted = [];
845
-		foreach ($filteredShares as $share) {
846
-			if ($this->canAccessShare($share)) {
847
-				try {
848
-					$formatted[] = $this->formatShare($share);
849
-				} catch (NotFoundException $e) {
850
-					// Ignore this share
851
-				}
852
-			}
853
-		}
854
-
855
-		if ($includeTags) {
856
-			$formatted = $this->populateTags($formatted);
857
-		}
858
-
859
-		return $formatted;
860
-	}
861
-
862
-	/**
863
-	 * @param Node $folder
864
-	 *
865
-	 * @return list<Files_SharingShare>
866
-	 * @throws OCSBadRequestException
867
-	 * @throws NotFoundException
868
-	 */
869
-	private function getSharesInDir(Node $folder): array {
870
-		if (!($folder instanceof Folder)) {
871
-			throw new OCSBadRequestException($this->l->t('Not a directory'));
872
-		}
873
-
874
-		$nodes = $folder->getDirectoryListing();
875
-
876
-		/** @var IShare[] $shares */
877
-		$shares = array_reduce($nodes, function ($carry, $node) {
878
-			$carry = array_merge($carry, $this->getAllShares($node, true));
879
-			return $carry;
880
-		}, []);
881
-
882
-		// filter out duplicate shares
883
-		$known = [];
884
-
885
-		$formatted = $miniFormatted = [];
886
-		$resharingRight = false;
887
-		$known = [];
888
-		foreach ($shares as $share) {
889
-			if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->userId) {
890
-				continue;
891
-			}
892
-
893
-			try {
894
-				$format = $this->formatShare($share);
895
-
896
-				$known[] = $share->getId();
897
-				$formatted[] = $format;
898
-				if ($share->getSharedBy() === $this->userId) {
899
-					$miniFormatted[] = $format;
900
-				}
901
-				if (!$resharingRight && $this->shareProviderResharingRights($this->userId, $share, $folder)) {
902
-					$resharingRight = true;
903
-				}
904
-			} catch (\Exception $e) {
905
-				//Ignore this share
906
-			}
907
-		}
908
-
909
-		if (!$resharingRight) {
910
-			$formatted = $miniFormatted;
911
-		}
912
-
913
-		return $formatted;
914
-	}
915
-
916
-	/**
917
-	 * Get shares of the current user
918
-	 *
919
-	 * @param string $shared_with_me Only get shares with the current user
920
-	 * @param string $reshares Only get shares by the current user and reshares
921
-	 * @param string $subfiles Only get all shares in a folder
922
-	 * @param string $path Get shares for a specific path
923
-	 * @param string $include_tags Include tags in the share
924
-	 *
925
-	 * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
926
-	 * @throws OCSNotFoundException The folder was not found or is inaccessible
927
-	 *
928
-	 * 200: Shares returned
929
-	 */
930
-	#[NoAdminRequired]
931
-	public function getShares(
932
-		string $shared_with_me = 'false',
933
-		string $reshares = 'false',
934
-		string $subfiles = 'false',
935
-		string $path = '',
936
-		string $include_tags = 'false',
937
-	): DataResponse {
938
-		$node = null;
939
-		if ($path !== '') {
940
-			$userFolder = $this->rootFolder->getUserFolder($this->userId);
941
-			try {
942
-				$node = $userFolder->get($path);
943
-				$this->lock($node);
944
-			} catch (NotFoundException $e) {
945
-				throw new OCSNotFoundException(
946
-					$this->l->t('Wrong path, file/folder does not exist')
947
-				);
948
-			} catch (LockedException $e) {
949
-				throw new OCSNotFoundException($this->l->t('Could not lock node'));
950
-			}
951
-		}
952
-
953
-		$shares = $this->getFormattedShares(
954
-			$this->userId,
955
-			$node,
956
-			($shared_with_me === 'true'),
957
-			($reshares === 'true'),
958
-			($subfiles === 'true'),
959
-			($include_tags === 'true')
960
-		);
961
-
962
-		return new DataResponse($shares);
963
-	}
964
-
965
-	private function getLinkSharePermissions(?int $permissions, ?bool $legacyPublicUpload): int {
966
-		$permissions = $permissions ?? Constants::PERMISSION_READ;
967
-
968
-		// Legacy option handling
969
-		if ($legacyPublicUpload !== null) {
970
-			$permissions = $legacyPublicUpload
971
-				? (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
972
-				: Constants::PERMISSION_READ;
973
-		}
974
-
975
-		if ($this->hasPermission($permissions, Constants::PERMISSION_READ)
976
-			&& $this->shareManager->outgoingServer2ServerSharesAllowed()
977
-			&& $this->appConfig->getValueBool('core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES)) {
978
-			$permissions |= Constants::PERMISSION_SHARE;
979
-		}
980
-
981
-		return $permissions;
982
-	}
983
-
984
-	/**
985
-	 * Helper to check for legacy "publicUpload" handling.
986
-	 * If the value is set to `true` or `false` then true or false are returned.
987
-	 * Otherwise null is returned to indicate that the option was not (or wrong) set.
988
-	 *
989
-	 * @param null|string $legacyPublicUpload The value of `publicUpload`
990
-	 */
991
-	private function getLegacyPublicUpload(?string $legacyPublicUpload): ?bool {
992
-		if ($legacyPublicUpload === 'true') {
993
-			return true;
994
-		} elseif ($legacyPublicUpload === 'false') {
995
-			return false;
996
-		}
997
-		// Not set at all
998
-		return null;
999
-	}
1000
-
1001
-	/**
1002
-	 * For link and email shares validate that only allowed combinations are set.
1003
-	 *
1004
-	 * @throw OCSBadRequestException If permission combination is invalid.
1005
-	 * @throw OCSForbiddenException If public upload was forbidden by the administrator.
1006
-	 */
1007
-	private function validateLinkSharePermissions(Node $node, int $permissions, ?bool $legacyPublicUpload): void {
1008
-		if ($legacyPublicUpload && ($node instanceof File)) {
1009
-			throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
1010
-		}
1011
-
1012
-		// We need at least READ or CREATE (file drop)
1013
-		if (!$this->hasPermission($permissions, Constants::PERMISSION_READ)
1014
-			&& !$this->hasPermission($permissions, Constants::PERMISSION_CREATE)) {
1015
-			throw new OCSBadRequestException($this->l->t('Share must at least have READ or CREATE permissions'));
1016
-		}
1017
-
1018
-		// UPDATE and DELETE require a READ permission
1019
-		if (!$this->hasPermission($permissions, Constants::PERMISSION_READ)
1020
-			&& ($this->hasPermission($permissions, Constants::PERMISSION_UPDATE) || $this->hasPermission($permissions, Constants::PERMISSION_DELETE))) {
1021
-			throw new OCSBadRequestException($this->l->t('Share must have READ permission if UPDATE or DELETE permission is set'));
1022
-		}
1023
-
1024
-		// Check if public uploading was disabled
1025
-		if ($this->hasPermission($permissions, Constants::PERMISSION_CREATE)
1026
-			&& !$this->shareManager->shareApiLinkAllowPublicUpload()) {
1027
-			throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
1028
-		}
1029
-	}
1030
-
1031
-	/**
1032
-	 * @param string $viewer
1033
-	 * @param Node $node
1034
-	 * @param bool $sharedWithMe
1035
-	 * @param bool $reShares
1036
-	 * @param bool $subFiles
1037
-	 * @param bool $includeTags
1038
-	 *
1039
-	 * @return list<Files_SharingShare>
1040
-	 * @throws NotFoundException
1041
-	 * @throws OCSBadRequestException
1042
-	 */
1043
-	private function getFormattedShares(
1044
-		string $viewer,
1045
-		$node = null,
1046
-		bool $sharedWithMe = false,
1047
-		bool $reShares = false,
1048
-		bool $subFiles = false,
1049
-		bool $includeTags = false,
1050
-	): array {
1051
-		if ($sharedWithMe) {
1052
-			return $this->getSharedWithMe($node, $includeTags);
1053
-		}
1054
-
1055
-		if ($subFiles) {
1056
-			return $this->getSharesInDir($node);
1057
-		}
1058
-
1059
-		$shares = $this->getSharesFromNode($viewer, $node, $reShares);
1060
-
1061
-		$known = $formatted = $miniFormatted = [];
1062
-		$resharingRight = false;
1063
-		foreach ($shares as $share) {
1064
-			try {
1065
-				$share->getNode();
1066
-			} catch (NotFoundException $e) {
1067
-				/*
78
+    private ?Node $lockedNode = null;
79
+
80
+    /**
81
+     * Share20OCS constructor.
82
+     */
83
+    public function __construct(
84
+        string $appName,
85
+        IRequest $request,
86
+        private IManager $shareManager,
87
+        private IGroupManager $groupManager,
88
+        private IUserManager $userManager,
89
+        private IRootFolder $rootFolder,
90
+        private IURLGenerator $urlGenerator,
91
+        private IL10N $l,
92
+        private IConfig $config,
93
+        private IAppConfig $appConfig,
94
+        private IAppManager $appManager,
95
+        private ContainerInterface $serverContainer,
96
+        private IUserStatusManager $userStatusManager,
97
+        private IPreview $previewManager,
98
+        private IDateTimeZone $dateTimeZone,
99
+        private LoggerInterface $logger,
100
+        private IProviderFactory $factory,
101
+        private IMailer $mailer,
102
+        private ITagManager $tagManager,
103
+        private ?string $userId = null,
104
+    ) {
105
+        parent::__construct($appName, $request);
106
+    }
107
+
108
+    /**
109
+     * Convert an IShare to an array for OCS output
110
+     *
111
+     * @param IShare $share
112
+     * @param Node|null $recipientNode
113
+     * @return Files_SharingShare
114
+     * @throws NotFoundException In case the node can't be resolved.
115
+     *
116
+     * @suppress PhanUndeclaredClassMethod
117
+     */
118
+    protected function formatShare(IShare $share, ?Node $recipientNode = null): array {
119
+        $sharedBy = $this->userManager->get($share->getSharedBy());
120
+        $shareOwner = $this->userManager->get($share->getShareOwner());
121
+
122
+        $isOwnShare = false;
123
+        if ($shareOwner !== null) {
124
+            $isOwnShare = $shareOwner->getUID() === $this->userId;
125
+        }
126
+
127
+        $result = [
128
+            'id' => $share->getId(),
129
+            'share_type' => $share->getShareType(),
130
+            'uid_owner' => $share->getSharedBy(),
131
+            'displayname_owner' => $sharedBy !== null ? $sharedBy->getDisplayName() : $share->getSharedBy(),
132
+            // recipient permissions
133
+            'permissions' => $share->getPermissions(),
134
+            // current user permissions on this share
135
+            'can_edit' => $this->canEditShare($share),
136
+            'can_delete' => $this->canDeleteShare($share),
137
+            'stime' => $share->getShareTime()->getTimestamp(),
138
+            'parent' => null,
139
+            'expiration' => null,
140
+            'token' => null,
141
+            'uid_file_owner' => $share->getShareOwner(),
142
+            'note' => $share->getNote(),
143
+            'label' => $share->getLabel(),
144
+            'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(),
145
+        ];
146
+
147
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
148
+        if ($recipientNode) {
149
+            $node = $recipientNode;
150
+        } else {
151
+            $node = $userFolder->getFirstNodeById($share->getNodeId());
152
+            if (!$node) {
153
+                // fallback to guessing the path
154
+                $node = $userFolder->get($share->getTarget());
155
+                if ($node === null || $share->getTarget() === '') {
156
+                    throw new NotFoundException();
157
+                }
158
+            }
159
+        }
160
+
161
+        $result['path'] = $userFolder->getRelativePath($node->getPath());
162
+        if ($node instanceof Folder) {
163
+            $result['item_type'] = 'folder';
164
+        } else {
165
+            $result['item_type'] = 'file';
166
+        }
167
+
168
+        // Get the original node permission if the share owner is the current user
169
+        if ($isOwnShare) {
170
+            $result['item_permissions'] = $node->getPermissions();
171
+        }
172
+
173
+        // If we're on the recipient side, the node permissions
174
+        // are bound to the share permissions. So we need to
175
+        // adjust the permissions to the share permissions if necessary.
176
+        if (!$isOwnShare) {
177
+            $result['item_permissions'] = $share->getPermissions();
178
+
179
+            // For some reason, single files share are forbidden to have the delete permission
180
+            // since we have custom methods to check those, let's adjust straight away.
181
+            // DAV permissions does not have that issue though.
182
+            if ($this->canDeleteShare($share) || $this->canDeleteShareFromSelf($share)) {
183
+                $result['item_permissions'] |= Constants::PERMISSION_DELETE;
184
+            }
185
+            if ($this->canEditShare($share)) {
186
+                $result['item_permissions'] |= Constants::PERMISSION_UPDATE;
187
+            }
188
+        }
189
+
190
+        // See MOUNT_ROOT_PROPERTYNAME dav property
191
+        $result['is-mount-root'] = $node->getInternalPath() === '';
192
+        $result['mount-type'] = $node->getMountPoint()->getMountType();
193
+
194
+        $result['mimetype'] = $node->getMimetype();
195
+        $result['has_preview'] = $this->previewManager->isAvailable($node);
196
+        $result['storage_id'] = $node->getStorage()->getId();
197
+        $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
198
+        $result['item_source'] = $node->getId();
199
+        $result['file_source'] = $node->getId();
200
+        $result['file_parent'] = $node->getParent()->getId();
201
+        $result['file_target'] = $share->getTarget();
202
+        $result['item_size'] = $node->getSize();
203
+        $result['item_mtime'] = $node->getMTime();
204
+
205
+        $expiration = $share->getExpirationDate();
206
+        if ($expiration !== null) {
207
+            $expiration->setTimezone($this->dateTimeZone->getTimeZone());
208
+            $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
209
+        }
210
+
211
+        if ($share->getShareType() === IShare::TYPE_USER) {
212
+            $sharedWith = $this->userManager->get($share->getSharedWith());
213
+            $result['share_with'] = $share->getSharedWith();
214
+            $result['share_with_displayname'] = $sharedWith !== null ? $sharedWith->getDisplayName() : $share->getSharedWith();
215
+            $result['share_with_displayname_unique'] = $sharedWith !== null ? (
216
+                !empty($sharedWith->getSystemEMailAddress()) ? $sharedWith->getSystemEMailAddress() : $sharedWith->getUID()
217
+            ) : $share->getSharedWith();
218
+
219
+            $userStatuses = $this->userStatusManager->getUserStatuses([$share->getSharedWith()]);
220
+            $userStatus = array_shift($userStatuses);
221
+            if ($userStatus) {
222
+                $result['status'] = [
223
+                    'status' => $userStatus->getStatus(),
224
+                    'message' => $userStatus->getMessage(),
225
+                    'icon' => $userStatus->getIcon(),
226
+                    'clearAt' => $userStatus->getClearAt()
227
+                        ? (int)$userStatus->getClearAt()->format('U')
228
+                        : null,
229
+                ];
230
+            }
231
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
232
+            $group = $this->groupManager->get($share->getSharedWith());
233
+            $result['share_with'] = $share->getSharedWith();
234
+            $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
235
+        } elseif ($share->getShareType() === IShare::TYPE_LINK) {
236
+
237
+            // "share_with" and "share_with_displayname" for passwords of link
238
+            // shares was deprecated in Nextcloud 15, use "password" instead.
239
+            $result['share_with'] = $share->getPassword();
240
+            $result['share_with_displayname'] = '(' . $this->l->t('Shared link') . ')';
241
+
242
+            $result['password'] = $share->getPassword();
243
+
244
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
245
+
246
+            $result['token'] = $share->getToken();
247
+            $result['url'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $share->getToken()]);
248
+        } elseif ($share->getShareType() === IShare::TYPE_REMOTE) {
249
+            $result['share_with'] = $share->getSharedWith();
250
+            $result['share_with_displayname'] = $this->getCachedFederatedDisplayName($share->getSharedWith());
251
+            $result['token'] = $share->getToken();
252
+        } elseif ($share->getShareType() === IShare::TYPE_REMOTE_GROUP) {
253
+            $result['share_with'] = $share->getSharedWith();
254
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'CLOUD');
255
+            $result['token'] = $share->getToken();
256
+        } elseif ($share->getShareType() === IShare::TYPE_EMAIL) {
257
+            $result['share_with'] = $share->getSharedWith();
258
+            $result['password'] = $share->getPassword();
259
+            $result['password_expiration_time'] = $share->getPasswordExpirationTime() !== null ? $share->getPasswordExpirationTime()->format(\DateTime::ATOM) : null;
260
+            $result['send_password_by_talk'] = $share->getSendPasswordByTalk();
261
+            $result['share_with_displayname'] = $this->getDisplayNameFromAddressBook($share->getSharedWith(), 'EMAIL');
262
+            $result['token'] = $share->getToken();
263
+        } elseif ($share->getShareType() === IShare::TYPE_CIRCLE) {
264
+            // getSharedWith() returns either "name (type, owner)" or
265
+            // "name (type, owner) [id]", depending on the Teams app version.
266
+            $hasCircleId = (substr($share->getSharedWith(), -1) === ']');
267
+
268
+            $result['share_with_displayname'] = $share->getSharedWithDisplayName();
269
+            if (empty($result['share_with_displayname'])) {
270
+                $displayNameLength = ($hasCircleId ? strrpos($share->getSharedWith(), ' ') : strlen($share->getSharedWith()));
271
+                $result['share_with_displayname'] = substr($share->getSharedWith(), 0, $displayNameLength);
272
+            }
273
+
274
+            $result['share_with_avatar'] = $share->getSharedWithAvatar();
275
+
276
+            $shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
277
+            $shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
278
+            if ($shareWithLength === false) {
279
+                $result['share_with'] = substr($share->getSharedWith(), $shareWithStart);
280
+            } else {
281
+                $result['share_with'] = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
282
+            }
283
+        } elseif ($share->getShareType() === IShare::TYPE_ROOM) {
284
+            $result['share_with'] = $share->getSharedWith();
285
+            $result['share_with_displayname'] = '';
286
+
287
+            try {
288
+                /** @var array{share_with_displayname: string, share_with_link: string, share_with?: string, token?: string} $roomShare */
289
+                $roomShare = $this->getRoomShareHelper()->formatShare($share);
290
+                $result = array_merge($result, $roomShare);
291
+            } catch (ContainerExceptionInterface $e) {
292
+            }
293
+        } elseif ($share->getShareType() === IShare::TYPE_DECK) {
294
+            $result['share_with'] = $share->getSharedWith();
295
+            $result['share_with_displayname'] = '';
296
+
297
+            try {
298
+                /** @var array{share_with: string, share_with_displayname: string, share_with_link: string} $deckShare */
299
+                $deckShare = $this->getDeckShareHelper()->formatShare($share);
300
+                $result = array_merge($result, $deckShare);
301
+            } catch (ContainerExceptionInterface $e) {
302
+            }
303
+        } elseif ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
304
+            $result['share_with'] = $share->getSharedWith();
305
+            $result['share_with_displayname'] = '';
306
+
307
+            try {
308
+                /** @var array{share_with: string, share_with_displayname: string, token: string} $scienceMeshShare */
309
+                $scienceMeshShare = $this->getSciencemeshShareHelper()->formatShare($share);
310
+                $result = array_merge($result, $scienceMeshShare);
311
+            } catch (ContainerExceptionInterface $e) {
312
+            }
313
+        }
314
+
315
+
316
+        $result['mail_send'] = $share->getMailSend() ? 1 : 0;
317
+        $result['hide_download'] = $share->getHideDownload() ? 1 : 0;
318
+
319
+        $result['attributes'] = null;
320
+        if ($attributes = $share->getAttributes()) {
321
+            $result['attributes'] = (string)\json_encode($attributes->toArray());
322
+        }
323
+
324
+        return $result;
325
+    }
326
+
327
+    /**
328
+     * Check if one of the users address books knows the exact property, if
329
+     * not we return the full name.
330
+     *
331
+     * @param string $query
332
+     * @param string $property
333
+     * @return string
334
+     */
335
+    private function getDisplayNameFromAddressBook(string $query, string $property): string {
336
+        // FIXME: If we inject the contacts manager it gets initialized before any address books are registered
337
+        try {
338
+            $result = Server::get(\OCP\Contacts\IManager::class)->search($query, [$property], [
339
+                'limit' => 1,
340
+                'enumeration' => false,
341
+                'strict_search' => true,
342
+            ]);
343
+        } catch (Exception $e) {
344
+            $this->logger->error(
345
+                $e->getMessage(),
346
+                ['exception' => $e]
347
+            );
348
+            return $query;
349
+        }
350
+
351
+        foreach ($result as $r) {
352
+            foreach ($r[$property] as $value) {
353
+                if ($value === $query && $r['FN']) {
354
+                    return $r['FN'];
355
+                }
356
+            }
357
+        }
358
+
359
+        return $query;
360
+    }
361
+
362
+
363
+    /**
364
+     * @param list<Files_SharingShare> $shares
365
+     * @param array<string, string>|null $updatedDisplayName
366
+     *
367
+     * @return list<Files_SharingShare>
368
+     */
369
+    private function fixMissingDisplayName(array $shares, ?array $updatedDisplayName = null): array {
370
+        $userIds = $updated = [];
371
+        foreach ($shares as $share) {
372
+            // share is federated and share have no display name yet
373
+            if ($share['share_type'] === IShare::TYPE_REMOTE
374
+                && ($share['share_with'] ?? '') !== ''
375
+                && ($share['share_with_displayname'] ?? '') === '') {
376
+                $userIds[] = $userId = $share['share_with'];
377
+
378
+                if ($updatedDisplayName !== null && array_key_exists($userId, $updatedDisplayName)) {
379
+                    $share['share_with_displayname'] = $updatedDisplayName[$userId];
380
+                }
381
+            }
382
+
383
+            // prepping userIds with displayName to be updated
384
+            $updated[] = $share;
385
+        }
386
+
387
+        // if $updatedDisplayName is not null, it means we should have already fixed displayNames of the shares
388
+        if ($updatedDisplayName !== null) {
389
+            return $updated;
390
+        }
391
+
392
+        // get displayName for the generated list of userId with no displayName
393
+        $displayNames = $this->retrieveFederatedDisplayName($userIds);
394
+
395
+        // if no displayName are updated, we exit
396
+        if (empty($displayNames)) {
397
+            return $updated;
398
+        }
399
+
400
+        // let's fix missing display name and returns all shares
401
+        return $this->fixMissingDisplayName($shares, $displayNames);
402
+    }
403
+
404
+
405
+    /**
406
+     * get displayName of a list of userIds from the lookup-server; through the globalsiteselector app.
407
+     * returns an array with userIds as keys and displayName as values.
408
+     *
409
+     * @param array $userIds
410
+     * @param bool $cacheOnly - do not reach LUS, get data from cache.
411
+     *
412
+     * @return array
413
+     * @throws ContainerExceptionInterface
414
+     */
415
+    private function retrieveFederatedDisplayName(array $userIds, bool $cacheOnly = false): array {
416
+        // check if gss is enabled and available
417
+        if (count($userIds) === 0
418
+            || !$this->appManager->isEnabledForAnyone('globalsiteselector')
419
+            || !class_exists('\OCA\GlobalSiteSelector\Service\SlaveService')) {
420
+            return [];
421
+        }
422
+
423
+        try {
424
+            $slaveService = Server::get(SlaveService::class);
425
+        } catch (\Throwable $e) {
426
+            $this->logger->error(
427
+                $e->getMessage(),
428
+                ['exception' => $e]
429
+            );
430
+            return [];
431
+        }
432
+
433
+        return $slaveService->getUsersDisplayName($userIds, $cacheOnly);
434
+    }
435
+
436
+
437
+    /**
438
+     * retrieve displayName from cache if available (should be used on federated shares)
439
+     * if not available in cache/lus, try for get from address-book, else returns empty string.
440
+     *
441
+     * @param string $userId
442
+     * @param bool $cacheOnly if true will not reach the lus but will only get data from cache
443
+     *
444
+     * @return string
445
+     */
446
+    private function getCachedFederatedDisplayName(string $userId, bool $cacheOnly = true): string {
447
+        $details = $this->retrieveFederatedDisplayName([$userId], $cacheOnly);
448
+        if (array_key_exists($userId, $details)) {
449
+            return $details[$userId];
450
+        }
451
+
452
+        $displayName = $this->getDisplayNameFromAddressBook($userId, 'CLOUD');
453
+        return ($displayName === $userId) ? '' : $displayName;
454
+    }
455
+
456
+
457
+
458
+    /**
459
+     * Get a specific share by id
460
+     *
461
+     * @param string $id ID of the share
462
+     * @param bool $include_tags Include tags in the share
463
+     * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
464
+     * @throws OCSNotFoundException Share not found
465
+     *
466
+     * 200: Share returned
467
+     */
468
+    #[NoAdminRequired]
469
+    public function getShare(string $id, bool $include_tags = false): DataResponse {
470
+        try {
471
+            $share = $this->getShareById($id);
472
+        } catch (ShareNotFound $e) {
473
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
474
+        }
475
+
476
+        try {
477
+            if ($this->canAccessShare($share)) {
478
+                $share = $this->formatShare($share);
479
+
480
+                if ($include_tags) {
481
+                    $share = $this->populateTags([$share]);
482
+                } else {
483
+                    $share = [$share];
484
+                }
485
+
486
+                return new DataResponse($share);
487
+            }
488
+        } catch (NotFoundException $e) {
489
+            // Fall through
490
+        }
491
+
492
+        throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
493
+    }
494
+
495
+    /**
496
+     * Delete a share
497
+     *
498
+     * @param string $id ID of the share
499
+     * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
500
+     * @throws OCSNotFoundException Share not found
501
+     * @throws OCSForbiddenException Missing permissions to delete the share
502
+     *
503
+     * 200: Share deleted successfully
504
+     */
505
+    #[NoAdminRequired]
506
+    public function deleteShare(string $id): DataResponse {
507
+        try {
508
+            $share = $this->getShareById($id);
509
+        } catch (ShareNotFound $e) {
510
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
511
+        }
512
+
513
+        try {
514
+            $this->lock($share->getNode());
515
+        } catch (LockedException $e) {
516
+            throw new OCSNotFoundException($this->l->t('Could not delete share'));
517
+        }
518
+
519
+        if (!$this->canAccessShare($share)) {
520
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
521
+        }
522
+
523
+        // if it's a group share or a room share
524
+        // we don't delete the share, but only the
525
+        // mount point. Allowing it to be restored
526
+        // from the deleted shares
527
+        if ($this->canDeleteShareFromSelf($share)) {
528
+            $this->shareManager->deleteFromSelf($share, $this->userId);
529
+        } else {
530
+            if (!$this->canDeleteShare($share)) {
531
+                throw new OCSForbiddenException($this->l->t('Could not delete share'));
532
+            }
533
+
534
+            $this->shareManager->deleteShare($share);
535
+        }
536
+
537
+        return new DataResponse();
538
+    }
539
+
540
+    /**
541
+     * Create a share
542
+     *
543
+     * @param string|null $path Path of the share
544
+     * @param int|null $permissions Permissions for the share
545
+     * @param int $shareType Type of the share
546
+     * @param ?string $shareWith The entity this should be shared with
547
+     * @param 'true'|'false'|null $publicUpload If public uploading is allowed (deprecated)
548
+     * @param string $password Password for the share
549
+     * @param string|null $sendPasswordByTalk Send the password for the share over Talk
550
+     * @param ?string $expireDate The expiry date of the share in the user's timezone at 00:00.
551
+     *                            If $expireDate is not supplied or set to `null`, the system default will be used.
552
+     * @param string $note Note for the share
553
+     * @param string $label Label for the share (only used in link and email)
554
+     * @param string|null $attributes Additional attributes for the share
555
+     * @param 'false'|'true'|null $sendMail Send a mail to the recipient
556
+     *
557
+     * @return DataResponse<Http::STATUS_OK, Files_SharingShare, array{}>
558
+     * @throws OCSBadRequestException Unknown share type
559
+     * @throws OCSException
560
+     * @throws OCSForbiddenException Creating the share is not allowed
561
+     * @throws OCSNotFoundException Creating the share failed
562
+     * @suppress PhanUndeclaredClassMethod
563
+     *
564
+     * 200: Share created
565
+     */
566
+    #[NoAdminRequired]
567
+    #[UserRateLimit(limit: 20, period: 600)]
568
+    public function createShare(
569
+        ?string $path = null,
570
+        ?int $permissions = null,
571
+        int $shareType = -1,
572
+        ?string $shareWith = null,
573
+        ?string $publicUpload = null,
574
+        string $password = '',
575
+        ?string $sendPasswordByTalk = null,
576
+        ?string $expireDate = null,
577
+        string $note = '',
578
+        string $label = '',
579
+        ?string $attributes = null,
580
+        ?string $sendMail = null,
581
+    ): DataResponse {
582
+        assert($this->userId !== null);
583
+
584
+        $share = $this->shareManager->newShare();
585
+        $hasPublicUpload = $this->getLegacyPublicUpload($publicUpload);
586
+
587
+        // Verify path
588
+        if ($path === null) {
589
+            throw new OCSNotFoundException($this->l->t('Please specify a file or folder path'));
590
+        }
591
+
592
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
593
+        try {
594
+            /** @var \OC\Files\Node\Node $node */
595
+            $node = $userFolder->get($path);
596
+        } catch (NotFoundException $e) {
597
+            throw new OCSNotFoundException($this->l->t('Wrong path, file/folder does not exist'));
598
+        }
599
+
600
+        // a user can have access to a file through different paths, with differing permissions
601
+        // combine all permissions to determine if the user can share this file
602
+        $nodes = $userFolder->getById($node->getId());
603
+        foreach ($nodes as $nodeById) {
604
+            /** @var FileInfo $fileInfo */
605
+            $fileInfo = $node->getFileInfo();
606
+            $fileInfo['permissions'] |= $nodeById->getPermissions();
607
+        }
608
+
609
+        $share->setNode($node);
610
+
611
+        try {
612
+            $this->lock($share->getNode());
613
+        } catch (LockedException $e) {
614
+            throw new OCSNotFoundException($this->l->t('Could not create share'));
615
+        }
616
+
617
+        // Set permissions
618
+        if ($shareType === IShare::TYPE_LINK || $shareType === IShare::TYPE_EMAIL) {
619
+            $permissions = $this->getLinkSharePermissions($permissions, $hasPublicUpload);
620
+            $this->validateLinkSharePermissions($node, $permissions, $hasPublicUpload);
621
+        } else {
622
+            // Use default permissions only for non-link shares to keep legacy behavior
623
+            if ($permissions === null) {
624
+                $permissions = (int)$this->config->getAppValue('core', 'shareapi_default_permissions', (string)Constants::PERMISSION_ALL);
625
+            }
626
+            // Non-link shares always require read permissions (link shares could be file drop)
627
+            $permissions |= Constants::PERMISSION_READ;
628
+        }
629
+
630
+        // For legacy reasons the API allows to pass PERMISSIONS_ALL even for single file shares (I look at you Talk)
631
+        if ($node instanceof File) {
632
+            // if this is a single file share we remove the DELETE and CREATE permissions
633
+            $permissions = $permissions & ~(Constants::PERMISSION_DELETE | Constants::PERMISSION_CREATE);
634
+        }
635
+
636
+        /**
637
+         * Hack for https://github.com/owncloud/core/issues/22587
638
+         * We check the permissions via webdav. But the permissions of the mount point
639
+         * do not equal the share permissions. Here we fix that for federated mounts.
640
+         */
641
+        if ($node->getStorage()->instanceOfStorage(Storage::class)) {
642
+            $permissions &= ~($permissions & ~$node->getPermissions());
643
+        }
644
+
645
+        if ($attributes !== null) {
646
+            $share = $this->setShareAttributes($share, $attributes);
647
+        }
648
+
649
+        // Expire date checks
650
+        // Normally, null means no expiration date but we still set the default for backwards compatibility
651
+        // If the client sends an empty string, we set noExpirationDate to true
652
+        if ($expireDate !== null) {
653
+            if ($expireDate !== '') {
654
+                try {
655
+                    $expireDateTime = $this->parseDate($expireDate);
656
+                    $share->setExpirationDate($expireDateTime);
657
+                } catch (\Exception $e) {
658
+                    throw new OCSNotFoundException($e->getMessage(), $e);
659
+                }
660
+            } else {
661
+                // Client sent empty string for expire date.
662
+                // Set noExpirationDate to true so overwrite is prevented.
663
+                $share->setNoExpirationDate(true);
664
+            }
665
+        }
666
+
667
+        $share->setSharedBy($this->userId);
668
+
669
+        // Handle mail send
670
+        if (is_null($sendMail)) {
671
+            $allowSendMail = $this->config->getSystemValueBool('sharing.enable_share_mail', true);
672
+            if ($allowSendMail !== true || $shareType === IShare::TYPE_EMAIL) {
673
+                // Define a default behavior when sendMail is not provided
674
+                // For email shares with a valid recipient, the default is to send the mail
675
+                // For all other share types, the default is to not send the mail
676
+                $allowSendMail = ($shareType === IShare::TYPE_EMAIL && $shareWith !== null && $shareWith !== '');
677
+            }
678
+            $share->setMailSend($allowSendMail);
679
+        } else {
680
+            $share->setMailSend($sendMail === 'true');
681
+        }
682
+
683
+        if ($shareType === IShare::TYPE_USER) {
684
+            // Valid user is required to share
685
+            if ($shareWith === null || !$this->userManager->userExists($shareWith)) {
686
+                throw new OCSNotFoundException($this->l->t('Please specify a valid account to share with'));
687
+            }
688
+            $share->setSharedWith($shareWith);
689
+            $share->setPermissions($permissions);
690
+        } elseif ($shareType === IShare::TYPE_GROUP) {
691
+            if (!$this->shareManager->allowGroupSharing()) {
692
+                throw new OCSNotFoundException($this->l->t('Group sharing is disabled by the administrator'));
693
+            }
694
+
695
+            // Valid group is required to share
696
+            if ($shareWith === null || !$this->groupManager->groupExists($shareWith)) {
697
+                throw new OCSNotFoundException($this->l->t('Please specify a valid group'));
698
+            }
699
+            $share->setSharedWith($shareWith);
700
+            $share->setPermissions($permissions);
701
+        } elseif ($shareType === IShare::TYPE_LINK
702
+            || $shareType === IShare::TYPE_EMAIL) {
703
+
704
+            // Can we even share links?
705
+            if (!$this->shareManager->shareApiAllowLinks()) {
706
+                throw new OCSNotFoundException($this->l->t('Public link sharing is disabled by the administrator'));
707
+            }
708
+
709
+            $this->validateLinkSharePermissions($node, $permissions, $hasPublicUpload);
710
+            $share->setPermissions($permissions);
711
+
712
+            // Set password
713
+            if ($password !== '') {
714
+                $share->setPassword($password);
715
+            }
716
+
717
+            // Only share by mail have a recipient
718
+            if (is_string($shareWith) && $shareType === IShare::TYPE_EMAIL) {
719
+                // If sending a mail have been requested, validate the mail address
720
+                if ($share->getMailSend() && !$this->mailer->validateMailAddress($shareWith)) {
721
+                    throw new OCSNotFoundException($this->l->t('Please specify a valid email address'));
722
+                }
723
+                $share->setSharedWith($shareWith);
724
+            }
725
+
726
+            // If we have a label, use it
727
+            if ($label !== '') {
728
+                if (strlen($label) > 255) {
729
+                    throw new OCSBadRequestException('Maximum label length is 255');
730
+                }
731
+                $share->setLabel($label);
732
+            }
733
+
734
+            if ($sendPasswordByTalk === 'true') {
735
+                if (!$this->appManager->isEnabledForUser('spreed')) {
736
+                    throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$node->getPath()]));
737
+                }
738
+
739
+                $share->setSendPasswordByTalk(true);
740
+            }
741
+        } elseif ($shareType === IShare::TYPE_REMOTE) {
742
+            if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
743
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
744
+            }
745
+
746
+            if ($shareWith === null) {
747
+                throw new OCSNotFoundException($this->l->t('Please specify a valid federated account ID'));
748
+            }
749
+
750
+            $share->setSharedWith($shareWith);
751
+            $share->setPermissions($permissions);
752
+            $share->setSharedWithDisplayName($this->getCachedFederatedDisplayName($shareWith, false));
753
+        } elseif ($shareType === IShare::TYPE_REMOTE_GROUP) {
754
+            if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
755
+                throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
756
+            }
757
+
758
+            if ($shareWith === null) {
759
+                throw new OCSNotFoundException($this->l->t('Please specify a valid federated group ID'));
760
+            }
761
+
762
+            $share->setSharedWith($shareWith);
763
+            $share->setPermissions($permissions);
764
+        } elseif ($shareType === IShare::TYPE_CIRCLE) {
765
+            if (!Server::get(IAppManager::class)->isEnabledForUser('circles') || !class_exists('\OCA\Circles\ShareByCircleProvider')) {
766
+                throw new OCSNotFoundException($this->l->t('You cannot share to a Team if the app is not enabled'));
767
+            }
768
+
769
+            $circle = Circles::detailsCircle($shareWith);
770
+
771
+            // Valid team is required to share
772
+            if ($circle === null) {
773
+                throw new OCSNotFoundException($this->l->t('Please specify a valid team'));
774
+            }
775
+            $share->setSharedWith($shareWith);
776
+            $share->setPermissions($permissions);
777
+        } elseif ($shareType === IShare::TYPE_ROOM) {
778
+            try {
779
+                $this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
780
+            } catch (ContainerExceptionInterface $e) {
781
+                throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
782
+            }
783
+        } elseif ($shareType === IShare::TYPE_DECK) {
784
+            try {
785
+                $this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
786
+            } catch (ContainerExceptionInterface $e) {
787
+                throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
788
+            }
789
+        } elseif ($shareType === IShare::TYPE_SCIENCEMESH) {
790
+            try {
791
+                $this->getSciencemeshShareHelper()->createShare($share, $shareWith, $permissions, $expireDate ?? '');
792
+            } catch (ContainerExceptionInterface $e) {
793
+                throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support ScienceMesh shares', [$node->getPath()]));
794
+            }
795
+        } else {
796
+            throw new OCSBadRequestException($this->l->t('Unknown share type'));
797
+        }
798
+
799
+        $share->setShareType($shareType);
800
+        $this->checkInheritedAttributes($share);
801
+
802
+        if ($note !== '') {
803
+            $share->setNote($note);
804
+        }
805
+
806
+        try {
807
+            $share = $this->shareManager->createShare($share);
808
+        } catch (HintException $e) {
809
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
810
+            throw new OCSException($e->getHint(), $code);
811
+        } catch (GenericShareException|\InvalidArgumentException $e) {
812
+            $this->logger->error($e->getMessage(), ['exception' => $e]);
813
+            throw new OCSForbiddenException($e->getMessage(), $e);
814
+        } catch (\Exception $e) {
815
+            $this->logger->error($e->getMessage(), ['exception' => $e]);
816
+            throw new OCSForbiddenException('Failed to create share.', $e);
817
+        }
818
+
819
+        $output = $this->formatShare($share);
820
+
821
+        return new DataResponse($output);
822
+    }
823
+
824
+    /**
825
+     * @param null|Node $node
826
+     * @param boolean $includeTags
827
+     *
828
+     * @return list<Files_SharingShare>
829
+     */
830
+    private function getSharedWithMe($node, bool $includeTags): array {
831
+        $userShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_USER, $node, -1, 0);
832
+        $groupShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_GROUP, $node, -1, 0);
833
+        $circleShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_CIRCLE, $node, -1, 0);
834
+        $roomShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_ROOM, $node, -1, 0);
835
+        $deckShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_DECK, $node, -1, 0);
836
+        $sciencemeshShares = $this->shareManager->getSharedWith($this->userId, IShare::TYPE_SCIENCEMESH, $node, -1, 0);
837
+
838
+        $shares = array_merge($userShares, $groupShares, $circleShares, $roomShares, $deckShares, $sciencemeshShares);
839
+
840
+        $filteredShares = array_filter($shares, function (IShare $share) {
841
+            return $share->getShareOwner() !== $this->userId;
842
+        });
843
+
844
+        $formatted = [];
845
+        foreach ($filteredShares as $share) {
846
+            if ($this->canAccessShare($share)) {
847
+                try {
848
+                    $formatted[] = $this->formatShare($share);
849
+                } catch (NotFoundException $e) {
850
+                    // Ignore this share
851
+                }
852
+            }
853
+        }
854
+
855
+        if ($includeTags) {
856
+            $formatted = $this->populateTags($formatted);
857
+        }
858
+
859
+        return $formatted;
860
+    }
861
+
862
+    /**
863
+     * @param Node $folder
864
+     *
865
+     * @return list<Files_SharingShare>
866
+     * @throws OCSBadRequestException
867
+     * @throws NotFoundException
868
+     */
869
+    private function getSharesInDir(Node $folder): array {
870
+        if (!($folder instanceof Folder)) {
871
+            throw new OCSBadRequestException($this->l->t('Not a directory'));
872
+        }
873
+
874
+        $nodes = $folder->getDirectoryListing();
875
+
876
+        /** @var IShare[] $shares */
877
+        $shares = array_reduce($nodes, function ($carry, $node) {
878
+            $carry = array_merge($carry, $this->getAllShares($node, true));
879
+            return $carry;
880
+        }, []);
881
+
882
+        // filter out duplicate shares
883
+        $known = [];
884
+
885
+        $formatted = $miniFormatted = [];
886
+        $resharingRight = false;
887
+        $known = [];
888
+        foreach ($shares as $share) {
889
+            if (in_array($share->getId(), $known) || $share->getSharedWith() === $this->userId) {
890
+                continue;
891
+            }
892
+
893
+            try {
894
+                $format = $this->formatShare($share);
895
+
896
+                $known[] = $share->getId();
897
+                $formatted[] = $format;
898
+                if ($share->getSharedBy() === $this->userId) {
899
+                    $miniFormatted[] = $format;
900
+                }
901
+                if (!$resharingRight && $this->shareProviderResharingRights($this->userId, $share, $folder)) {
902
+                    $resharingRight = true;
903
+                }
904
+            } catch (\Exception $e) {
905
+                //Ignore this share
906
+            }
907
+        }
908
+
909
+        if (!$resharingRight) {
910
+            $formatted = $miniFormatted;
911
+        }
912
+
913
+        return $formatted;
914
+    }
915
+
916
+    /**
917
+     * Get shares of the current user
918
+     *
919
+     * @param string $shared_with_me Only get shares with the current user
920
+     * @param string $reshares Only get shares by the current user and reshares
921
+     * @param string $subfiles Only get all shares in a folder
922
+     * @param string $path Get shares for a specific path
923
+     * @param string $include_tags Include tags in the share
924
+     *
925
+     * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
926
+     * @throws OCSNotFoundException The folder was not found or is inaccessible
927
+     *
928
+     * 200: Shares returned
929
+     */
930
+    #[NoAdminRequired]
931
+    public function getShares(
932
+        string $shared_with_me = 'false',
933
+        string $reshares = 'false',
934
+        string $subfiles = 'false',
935
+        string $path = '',
936
+        string $include_tags = 'false',
937
+    ): DataResponse {
938
+        $node = null;
939
+        if ($path !== '') {
940
+            $userFolder = $this->rootFolder->getUserFolder($this->userId);
941
+            try {
942
+                $node = $userFolder->get($path);
943
+                $this->lock($node);
944
+            } catch (NotFoundException $e) {
945
+                throw new OCSNotFoundException(
946
+                    $this->l->t('Wrong path, file/folder does not exist')
947
+                );
948
+            } catch (LockedException $e) {
949
+                throw new OCSNotFoundException($this->l->t('Could not lock node'));
950
+            }
951
+        }
952
+
953
+        $shares = $this->getFormattedShares(
954
+            $this->userId,
955
+            $node,
956
+            ($shared_with_me === 'true'),
957
+            ($reshares === 'true'),
958
+            ($subfiles === 'true'),
959
+            ($include_tags === 'true')
960
+        );
961
+
962
+        return new DataResponse($shares);
963
+    }
964
+
965
+    private function getLinkSharePermissions(?int $permissions, ?bool $legacyPublicUpload): int {
966
+        $permissions = $permissions ?? Constants::PERMISSION_READ;
967
+
968
+        // Legacy option handling
969
+        if ($legacyPublicUpload !== null) {
970
+            $permissions = $legacyPublicUpload
971
+                ? (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
972
+                : Constants::PERMISSION_READ;
973
+        }
974
+
975
+        if ($this->hasPermission($permissions, Constants::PERMISSION_READ)
976
+            && $this->shareManager->outgoingServer2ServerSharesAllowed()
977
+            && $this->appConfig->getValueBool('core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES)) {
978
+            $permissions |= Constants::PERMISSION_SHARE;
979
+        }
980
+
981
+        return $permissions;
982
+    }
983
+
984
+    /**
985
+     * Helper to check for legacy "publicUpload" handling.
986
+     * If the value is set to `true` or `false` then true or false are returned.
987
+     * Otherwise null is returned to indicate that the option was not (or wrong) set.
988
+     *
989
+     * @param null|string $legacyPublicUpload The value of `publicUpload`
990
+     */
991
+    private function getLegacyPublicUpload(?string $legacyPublicUpload): ?bool {
992
+        if ($legacyPublicUpload === 'true') {
993
+            return true;
994
+        } elseif ($legacyPublicUpload === 'false') {
995
+            return false;
996
+        }
997
+        // Not set at all
998
+        return null;
999
+    }
1000
+
1001
+    /**
1002
+     * For link and email shares validate that only allowed combinations are set.
1003
+     *
1004
+     * @throw OCSBadRequestException If permission combination is invalid.
1005
+     * @throw OCSForbiddenException If public upload was forbidden by the administrator.
1006
+     */
1007
+    private function validateLinkSharePermissions(Node $node, int $permissions, ?bool $legacyPublicUpload): void {
1008
+        if ($legacyPublicUpload && ($node instanceof File)) {
1009
+            throw new OCSBadRequestException($this->l->t('Public upload is only possible for publicly shared folders'));
1010
+        }
1011
+
1012
+        // We need at least READ or CREATE (file drop)
1013
+        if (!$this->hasPermission($permissions, Constants::PERMISSION_READ)
1014
+            && !$this->hasPermission($permissions, Constants::PERMISSION_CREATE)) {
1015
+            throw new OCSBadRequestException($this->l->t('Share must at least have READ or CREATE permissions'));
1016
+        }
1017
+
1018
+        // UPDATE and DELETE require a READ permission
1019
+        if (!$this->hasPermission($permissions, Constants::PERMISSION_READ)
1020
+            && ($this->hasPermission($permissions, Constants::PERMISSION_UPDATE) || $this->hasPermission($permissions, Constants::PERMISSION_DELETE))) {
1021
+            throw new OCSBadRequestException($this->l->t('Share must have READ permission if UPDATE or DELETE permission is set'));
1022
+        }
1023
+
1024
+        // Check if public uploading was disabled
1025
+        if ($this->hasPermission($permissions, Constants::PERMISSION_CREATE)
1026
+            && !$this->shareManager->shareApiLinkAllowPublicUpload()) {
1027
+            throw new OCSForbiddenException($this->l->t('Public upload disabled by the administrator'));
1028
+        }
1029
+    }
1030
+
1031
+    /**
1032
+     * @param string $viewer
1033
+     * @param Node $node
1034
+     * @param bool $sharedWithMe
1035
+     * @param bool $reShares
1036
+     * @param bool $subFiles
1037
+     * @param bool $includeTags
1038
+     *
1039
+     * @return list<Files_SharingShare>
1040
+     * @throws NotFoundException
1041
+     * @throws OCSBadRequestException
1042
+     */
1043
+    private function getFormattedShares(
1044
+        string $viewer,
1045
+        $node = null,
1046
+        bool $sharedWithMe = false,
1047
+        bool $reShares = false,
1048
+        bool $subFiles = false,
1049
+        bool $includeTags = false,
1050
+    ): array {
1051
+        if ($sharedWithMe) {
1052
+            return $this->getSharedWithMe($node, $includeTags);
1053
+        }
1054
+
1055
+        if ($subFiles) {
1056
+            return $this->getSharesInDir($node);
1057
+        }
1058
+
1059
+        $shares = $this->getSharesFromNode($viewer, $node, $reShares);
1060
+
1061
+        $known = $formatted = $miniFormatted = [];
1062
+        $resharingRight = false;
1063
+        foreach ($shares as $share) {
1064
+            try {
1065
+                $share->getNode();
1066
+            } catch (NotFoundException $e) {
1067
+                /*
1068 1068
 				 * Ignore shares where we can't get the node
1069 1069
 				 * For example deleted shares
1070 1070
 				 */
1071
-				continue;
1072
-			}
1073
-
1074
-			if (in_array($share->getId(), $known)
1075
-				|| ($share->getSharedWith() === $this->userId && $share->getShareType() === IShare::TYPE_USER)) {
1076
-				continue;
1077
-			}
1078
-
1079
-			$known[] = $share->getId();
1080
-			try {
1081
-				/** @var IShare $share */
1082
-				$format = $this->formatShare($share, $node);
1083
-				$formatted[] = $format;
1084
-
1085
-				// let's also build a list of shares created
1086
-				// by the current user only, in case
1087
-				// there is no resharing rights
1088
-				if ($share->getSharedBy() === $this->userId) {
1089
-					$miniFormatted[] = $format;
1090
-				}
1091
-
1092
-				// check if one of those share is shared with me
1093
-				// and if I have resharing rights on it
1094
-				if (!$resharingRight && $this->shareProviderResharingRights($this->userId, $share, $node)) {
1095
-					$resharingRight = true;
1096
-				}
1097
-			} catch (InvalidPathException|NotFoundException $e) {
1098
-			}
1099
-		}
1100
-
1101
-		if (!$resharingRight) {
1102
-			$formatted = $miniFormatted;
1103
-		}
1104
-
1105
-		// fix eventual missing display name from federated shares
1106
-		$formatted = $this->fixMissingDisplayName($formatted);
1107
-
1108
-		if ($includeTags) {
1109
-			$formatted = $this->populateTags($formatted);
1110
-		}
1111
-
1112
-		return $formatted;
1113
-	}
1114
-
1115
-
1116
-	/**
1117
-	 * Get all shares relative to a file, including parent folders shares rights
1118
-	 *
1119
-	 * @param string $path Path all shares will be relative to
1120
-	 *
1121
-	 * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
1122
-	 * @throws InvalidPathException
1123
-	 * @throws NotFoundException
1124
-	 * @throws OCSNotFoundException The given path is invalid
1125
-	 * @throws SharingRightsException
1126
-	 *
1127
-	 * 200: Shares returned
1128
-	 */
1129
-	#[NoAdminRequired]
1130
-	public function getInheritedShares(string $path): DataResponse {
1131
-		// get Node from (string) path.
1132
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
1133
-		try {
1134
-			$node = $userFolder->get($path);
1135
-			$this->lock($node);
1136
-		} catch (NotFoundException $e) {
1137
-			throw new OCSNotFoundException($this->l->t('Wrong path, file/folder does not exist'));
1138
-		} catch (LockedException $e) {
1139
-			throw new OCSNotFoundException($this->l->t('Could not lock path'));
1140
-		}
1141
-
1142
-		if (!($node->getPermissions() & Constants::PERMISSION_SHARE)) {
1143
-			throw new SharingRightsException($this->l->t('no sharing rights on this item'));
1144
-		}
1145
-
1146
-		// The current top parent we have access to
1147
-		$parent = $node;
1148
-
1149
-		// initiate real owner.
1150
-		$owner = $node->getOwner()
1151
-			->getUID();
1152
-		if (!$this->userManager->userExists($owner)) {
1153
-			return new DataResponse([]);
1154
-		}
1155
-
1156
-		// get node based on the owner, fix owner in case of external storage
1157
-		$userFolder = $this->rootFolder->getUserFolder($owner);
1158
-		if ($node->getId() !== $userFolder->getId() && !$userFolder->isSubNode($node)) {
1159
-			$owner = $node->getOwner()
1160
-				->getUID();
1161
-			$userFolder = $this->rootFolder->getUserFolder($owner);
1162
-			$node = $userFolder->getFirstNodeById($node->getId());
1163
-		}
1164
-		$basePath = $userFolder->getPath();
1165
-
1166
-		// generate node list for each parent folders
1167
-		/** @var Node[] $nodes */
1168
-		$nodes = [];
1169
-		while (true) {
1170
-			$node = $node->getParent();
1171
-			if ($node->getPath() === $basePath) {
1172
-				break;
1173
-			}
1174
-			$nodes[] = $node;
1175
-		}
1176
-
1177
-		// The user that is requesting this list
1178
-		$currentUserFolder = $this->rootFolder->getUserFolder($this->userId);
1179
-
1180
-		// for each nodes, retrieve shares.
1181
-		$shares = [];
1182
-
1183
-		foreach ($nodes as $node) {
1184
-			$getShares = $this->getFormattedShares($owner, $node, false, true);
1185
-
1186
-			$currentUserNode = $currentUserFolder->getFirstNodeById($node->getId());
1187
-			if ($currentUserNode) {
1188
-				$parent = $currentUserNode;
1189
-			}
1190
-
1191
-			$subPath = $currentUserFolder->getRelativePath($parent->getPath());
1192
-			foreach ($getShares as &$share) {
1193
-				$share['via_fileid'] = $parent->getId();
1194
-				$share['via_path'] = $subPath;
1195
-			}
1196
-			$this->mergeFormattedShares($shares, $getShares);
1197
-		}
1198
-
1199
-		return new DataResponse(array_values($shares));
1200
-	}
1201
-
1202
-	/**
1203
-	 * Check whether a set of permissions contains the permissions to check.
1204
-	 */
1205
-	private function hasPermission(int $permissionsSet, int $permissionsToCheck): bool {
1206
-		return ($permissionsSet & $permissionsToCheck) === $permissionsToCheck;
1207
-	}
1208
-
1209
-	/**
1210
-	 * Update a share
1211
-	 *
1212
-	 * @param string $id ID of the share
1213
-	 * @param int|null $permissions New permissions
1214
-	 * @param string|null $password New password
1215
-	 * @param string|null $sendPasswordByTalk New condition if the password should be send over Talk
1216
-	 * @param string|null $publicUpload New condition if public uploading is allowed
1217
-	 * @param string|null $expireDate New expiry date
1218
-	 * @param string|null $note New note
1219
-	 * @param string|null $label New label
1220
-	 * @param string|null $hideDownload New condition if the download should be hidden
1221
-	 * @param string|null $attributes New additional attributes
1222
-	 * @param string|null $sendMail if the share should be send by mail.
1223
-	 *                              Considering the share already exists, no mail will be send after the share is updated.
1224
-	 *                              You will have to use the sendMail action to send the mail.
1225
-	 * @param string|null $shareWith New recipient for email shares
1226
-	 * @param string|null $token New token
1227
-	 * @return DataResponse<Http::STATUS_OK, Files_SharingShare, array{}>
1228
-	 * @throws OCSBadRequestException Share could not be updated because the requested changes are invalid
1229
-	 * @throws OCSForbiddenException Missing permissions to update the share
1230
-	 * @throws OCSNotFoundException Share not found
1231
-	 *
1232
-	 * 200: Share updated successfully
1233
-	 */
1234
-	#[NoAdminRequired]
1235
-	public function updateShare(
1236
-		string $id,
1237
-		?int $permissions = null,
1238
-		?string $password = null,
1239
-		?string $sendPasswordByTalk = null,
1240
-		?string $publicUpload = null,
1241
-		?string $expireDate = null,
1242
-		?string $note = null,
1243
-		?string $label = null,
1244
-		?string $hideDownload = null,
1245
-		?string $attributes = null,
1246
-		?string $sendMail = null,
1247
-		?string $token = null,
1248
-	): DataResponse {
1249
-		try {
1250
-			$share = $this->getShareById($id);
1251
-		} catch (ShareNotFound $e) {
1252
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1253
-		}
1254
-
1255
-		$this->lock($share->getNode());
1256
-
1257
-		if (!$this->canAccessShare($share, false)) {
1258
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1259
-		}
1260
-
1261
-		if (!$this->canEditShare($share)) {
1262
-			throw new OCSForbiddenException($this->l->t('You are not allowed to edit incoming shares'));
1263
-		}
1264
-
1265
-		if (
1266
-			$permissions === null
1267
-			&& $password === null
1268
-			&& $sendPasswordByTalk === null
1269
-			&& $publicUpload === null
1270
-			&& $expireDate === null
1271
-			&& $note === null
1272
-			&& $label === null
1273
-			&& $hideDownload === null
1274
-			&& $attributes === null
1275
-			&& $sendMail === null
1276
-			&& $token === null
1277
-		) {
1278
-			throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
1279
-		}
1280
-
1281
-		if ($note !== null) {
1282
-			$share->setNote($note);
1283
-		}
1284
-
1285
-		if ($attributes !== null) {
1286
-			$share = $this->setShareAttributes($share, $attributes);
1287
-		}
1288
-
1289
-		// Handle mail send
1290
-		if ($sendMail === 'true' || $sendMail === 'false') {
1291
-			$share->setMailSend($sendMail === 'true');
1292
-		}
1293
-
1294
-		/**
1295
-		 * expiration date, password and publicUpload only make sense for link shares
1296
-		 */
1297
-		if ($share->getShareType() === IShare::TYPE_LINK
1298
-			|| $share->getShareType() === IShare::TYPE_EMAIL) {
1299
-
1300
-			// Update hide download state
1301
-			if ($hideDownload === 'true') {
1302
-				$share->setHideDownload(true);
1303
-			} elseif ($hideDownload === 'false') {
1304
-				$share->setHideDownload(false);
1305
-			}
1306
-
1307
-			// If either manual permissions are specified or publicUpload
1308
-			// then we need to also update the permissions of the share
1309
-			if ($permissions !== null || $publicUpload !== null) {
1310
-				$hasPublicUpload = $this->getLegacyPublicUpload($publicUpload);
1311
-				$permissions = $this->getLinkSharePermissions($permissions ?? Constants::PERMISSION_READ, $hasPublicUpload);
1312
-				$this->validateLinkSharePermissions($share->getNode(), $permissions, $hasPublicUpload);
1313
-				$share->setPermissions($permissions);
1314
-			}
1315
-
1316
-			if ($password === '') {
1317
-				$share->setPassword(null);
1318
-			} elseif ($password !== null) {
1319
-				$share->setPassword($password);
1320
-			}
1321
-
1322
-			if ($label !== null) {
1323
-				if (strlen($label) > 255) {
1324
-					throw new OCSBadRequestException('Maximum label length is 255');
1325
-				}
1326
-				$share->setLabel($label);
1327
-			}
1328
-
1329
-			if ($sendPasswordByTalk === 'true') {
1330
-				if (!$this->appManager->isEnabledForUser('spreed')) {
1331
-					throw new OCSForbiddenException($this->l->t('"Sending the password by Nextcloud Talk" for sharing a file or folder failed because Nextcloud Talk is not enabled.'));
1332
-				}
1333
-
1334
-				$share->setSendPasswordByTalk(true);
1335
-			} elseif ($sendPasswordByTalk !== null) {
1336
-				$share->setSendPasswordByTalk(false);
1337
-			}
1338
-
1339
-			if ($token !== null) {
1340
-				if (!$this->shareManager->allowCustomTokens()) {
1341
-					throw new OCSForbiddenException($this->l->t('Custom share link tokens have been disabled by the administrator'));
1342
-				}
1343
-				if (!$this->validateToken($token)) {
1344
-					throw new OCSBadRequestException($this->l->t('Tokens must contain at least 1 character and may only contain letters, numbers, or a hyphen'));
1345
-				}
1346
-				$share->setToken($token);
1347
-			}
1348
-		}
1349
-
1350
-		// NOT A LINK SHARE
1351
-		else {
1352
-			if ($permissions !== null) {
1353
-				$share->setPermissions($permissions);
1354
-			}
1355
-		}
1356
-
1357
-		if ($expireDate === '') {
1358
-			$share->setExpirationDate(null);
1359
-		} elseif ($expireDate !== null) {
1360
-			try {
1361
-				$expireDateTime = $this->parseDate($expireDate);
1362
-				$share->setExpirationDate($expireDateTime);
1363
-			} catch (\Exception $e) {
1364
-				throw new OCSBadRequestException($e->getMessage(), $e);
1365
-			}
1366
-		}
1367
-
1368
-		try {
1369
-			$this->checkInheritedAttributes($share);
1370
-			$share = $this->shareManager->updateShare($share);
1371
-		} catch (HintException $e) {
1372
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
1373
-			throw new OCSException($e->getHint(), (int)$code);
1374
-		} catch (\Exception $e) {
1375
-			$this->logger->error($e->getMessage(), ['exception' => $e]);
1376
-			throw new OCSBadRequestException('Failed to update share.', $e);
1377
-		}
1378
-
1379
-		return new DataResponse($this->formatShare($share));
1380
-	}
1381
-
1382
-	private function validateToken(string $token): bool {
1383
-		if (mb_strlen($token) === 0) {
1384
-			return false;
1385
-		}
1386
-		if (!preg_match('/^[a-z0-9-]+$/i', $token)) {
1387
-			return false;
1388
-		}
1389
-		return true;
1390
-	}
1391
-
1392
-	/**
1393
-	 * Get all shares that are still pending
1394
-	 *
1395
-	 * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
1396
-	 *
1397
-	 * 200: Pending shares returned
1398
-	 */
1399
-	#[NoAdminRequired]
1400
-	public function pendingShares(): DataResponse {
1401
-		$pendingShares = [];
1402
-
1403
-		$shareTypes = [
1404
-			IShare::TYPE_USER,
1405
-			IShare::TYPE_GROUP
1406
-		];
1407
-
1408
-		foreach ($shareTypes as $shareType) {
1409
-			$shares = $this->shareManager->getSharedWith($this->userId, $shareType, null, -1, 0);
1410
-
1411
-			foreach ($shares as $share) {
1412
-				if ($share->getStatus() === IShare::STATUS_PENDING || $share->getStatus() === IShare::STATUS_REJECTED) {
1413
-					$pendingShares[] = $share;
1414
-				}
1415
-			}
1416
-		}
1417
-
1418
-		$result = array_values(array_filter(array_map(function (IShare $share) {
1419
-			$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
1420
-			$node = $userFolder->getFirstNodeById($share->getNodeId());
1421
-			if (!$node) {
1422
-				// fallback to guessing the path
1423
-				$node = $userFolder->get($share->getTarget());
1424
-				if ($node === null || $share->getTarget() === '') {
1425
-					return null;
1426
-				}
1427
-			}
1428
-
1429
-			try {
1430
-				$formattedShare = $this->formatShare($share, $node);
1431
-				$formattedShare['path'] = '/' . $share->getNode()->getName();
1432
-				$formattedShare['permissions'] = 0;
1433
-				return $formattedShare;
1434
-			} catch (NotFoundException $e) {
1435
-				return null;
1436
-			}
1437
-		}, $pendingShares), function ($entry) {
1438
-			return $entry !== null;
1439
-		}));
1440
-
1441
-		return new DataResponse($result);
1442
-	}
1443
-
1444
-	/**
1445
-	 * Accept a share
1446
-	 *
1447
-	 * @param string $id ID of the share
1448
-	 * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
1449
-	 * @throws OCSNotFoundException Share not found
1450
-	 * @throws OCSException
1451
-	 * @throws OCSBadRequestException Share could not be accepted
1452
-	 *
1453
-	 * 200: Share accepted successfully
1454
-	 */
1455
-	#[NoAdminRequired]
1456
-	public function acceptShare(string $id): DataResponse {
1457
-		try {
1458
-			$share = $this->getShareById($id);
1459
-		} catch (ShareNotFound $e) {
1460
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1461
-		}
1462
-
1463
-		if (!$this->canAccessShare($share)) {
1464
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1465
-		}
1466
-
1467
-		try {
1468
-			$this->shareManager->acceptShare($share, $this->userId);
1469
-		} catch (HintException $e) {
1470
-			$code = $e->getCode() === 0 ? 403 : $e->getCode();
1471
-			throw new OCSException($e->getHint(), (int)$code);
1472
-		} catch (\Exception $e) {
1473
-			$this->logger->error($e->getMessage(), ['exception' => $e]);
1474
-			throw new OCSBadRequestException('Failed to accept share.', $e);
1475
-		}
1476
-
1477
-		return new DataResponse();
1478
-	}
1479
-
1480
-	/**
1481
-	 * Does the user have read permission on the share
1482
-	 *
1483
-	 * @param IShare $share the share to check
1484
-	 * @param boolean $checkGroups check groups as well?
1485
-	 * @return boolean
1486
-	 * @throws NotFoundException
1487
-	 *
1488
-	 * @suppress PhanUndeclaredClassMethod
1489
-	 */
1490
-	protected function canAccessShare(IShare $share, bool $checkGroups = true): bool {
1491
-		// A file with permissions 0 can't be accessed by us. So Don't show it
1492
-		if ($share->getPermissions() === 0) {
1493
-			return false;
1494
-		}
1495
-
1496
-		// Owner of the file and the sharer of the file can always get share
1497
-		if ($share->getShareOwner() === $this->userId
1498
-			|| $share->getSharedBy() === $this->userId) {
1499
-			return true;
1500
-		}
1501
-
1502
-		// If the share is shared with you, you can access it!
1503
-		if ($share->getShareType() === IShare::TYPE_USER
1504
-			&& $share->getSharedWith() === $this->userId) {
1505
-			return true;
1506
-		}
1507
-
1508
-		// Have reshare rights on the shared file/folder ?
1509
-		// Does the currentUser have access to the shared file?
1510
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
1511
-		$file = $userFolder->getFirstNodeById($share->getNodeId());
1512
-		if ($file && $this->shareProviderResharingRights($this->userId, $share, $file)) {
1513
-			return true;
1514
-		}
1515
-
1516
-		// If in the recipient group, you can see the share
1517
-		if ($checkGroups && $share->getShareType() === IShare::TYPE_GROUP) {
1518
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1519
-			$user = $this->userManager->get($this->userId);
1520
-			if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1521
-				return true;
1522
-			}
1523
-		}
1524
-
1525
-		if ($share->getShareType() === IShare::TYPE_CIRCLE) {
1526
-			// TODO: have a sanity check like above?
1527
-			return true;
1528
-		}
1529
-
1530
-		if ($share->getShareType() === IShare::TYPE_ROOM) {
1531
-			try {
1532
-				return $this->getRoomShareHelper()->canAccessShare($share, $this->userId);
1533
-			} catch (ContainerExceptionInterface $e) {
1534
-				return false;
1535
-			}
1536
-		}
1537
-
1538
-		if ($share->getShareType() === IShare::TYPE_DECK) {
1539
-			try {
1540
-				return $this->getDeckShareHelper()->canAccessShare($share, $this->userId);
1541
-			} catch (ContainerExceptionInterface $e) {
1542
-				return false;
1543
-			}
1544
-		}
1545
-
1546
-		if ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
1547
-			try {
1548
-				return $this->getSciencemeshShareHelper()->canAccessShare($share, $this->userId);
1549
-			} catch (ContainerExceptionInterface $e) {
1550
-				return false;
1551
-			}
1552
-		}
1553
-
1554
-		return false;
1555
-	}
1556
-
1557
-	/**
1558
-	 * Does the user have edit permission on the share
1559
-	 *
1560
-	 * @param IShare $share the share to check
1561
-	 * @return boolean
1562
-	 */
1563
-	protected function canEditShare(IShare $share): bool {
1564
-		// A file with permissions 0 can't be accessed by us. So Don't show it
1565
-		if ($share->getPermissions() === 0) {
1566
-			return false;
1567
-		}
1568
-
1569
-		// The owner of the file and the creator of the share
1570
-		// can always edit the share
1571
-		if ($share->getShareOwner() === $this->userId
1572
-			|| $share->getSharedBy() === $this->userId
1573
-		) {
1574
-			return true;
1575
-		}
1576
-
1577
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
1578
-		$file = $userFolder->getFirstNodeById($share->getNodeId());
1579
-		if ($file?->getMountPoint() instanceof IShareOwnerlessMount && $this->shareProviderResharingRights($this->userId, $share, $file)) {
1580
-			return true;
1581
-		}
1582
-
1583
-		//! we do NOT support some kind of `admin` in groups.
1584
-		//! You cannot edit shares shared to a group you're
1585
-		//! a member of if you're not the share owner or the file owner!
1586
-
1587
-		return false;
1588
-	}
1589
-
1590
-	/**
1591
-	 * Does the user have delete permission on the share
1592
-	 *
1593
-	 * @param IShare $share the share to check
1594
-	 * @return boolean
1595
-	 */
1596
-	protected function canDeleteShare(IShare $share): bool {
1597
-		// A file with permissions 0 can't be accessed by us. So Don't show it
1598
-		if ($share->getPermissions() === 0) {
1599
-			return false;
1600
-		}
1601
-
1602
-		// if the user is the recipient, i can unshare
1603
-		// the share with self
1604
-		if ($share->getShareType() === IShare::TYPE_USER
1605
-			&& $share->getSharedWith() === $this->userId
1606
-		) {
1607
-			return true;
1608
-		}
1609
-
1610
-		// The owner of the file and the creator of the share
1611
-		// can always delete the share
1612
-		if ($share->getShareOwner() === $this->userId
1613
-			|| $share->getSharedBy() === $this->userId
1614
-		) {
1615
-			return true;
1616
-		}
1617
-
1618
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
1619
-		$file = $userFolder->getFirstNodeById($share->getNodeId());
1620
-		if ($file?->getMountPoint() instanceof IShareOwnerlessMount && $this->shareProviderResharingRights($this->userId, $share, $file)) {
1621
-			return true;
1622
-		}
1623
-
1624
-		return false;
1625
-	}
1626
-
1627
-	/**
1628
-	 * Does the user have delete permission on the share
1629
-	 * This differs from the canDeleteShare function as it only
1630
-	 * remove the share for the current user. It does NOT
1631
-	 * completely delete the share but only the mount point.
1632
-	 * It can then be restored from the deleted shares section.
1633
-	 *
1634
-	 * @param IShare $share the share to check
1635
-	 * @return boolean
1636
-	 *
1637
-	 * @suppress PhanUndeclaredClassMethod
1638
-	 */
1639
-	protected function canDeleteShareFromSelf(IShare $share): bool {
1640
-		if ($share->getShareType() !== IShare::TYPE_GROUP
1641
-			&& $share->getShareType() !== IShare::TYPE_ROOM
1642
-			&& $share->getShareType() !== IShare::TYPE_DECK
1643
-			&& $share->getShareType() !== IShare::TYPE_SCIENCEMESH
1644
-		) {
1645
-			return false;
1646
-		}
1647
-
1648
-		if ($share->getShareOwner() === $this->userId
1649
-			|| $share->getSharedBy() === $this->userId
1650
-		) {
1651
-			// Delete the whole share, not just for self
1652
-			return false;
1653
-		}
1654
-
1655
-		// If in the recipient group, you can delete the share from self
1656
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
1657
-			$sharedWith = $this->groupManager->get($share->getSharedWith());
1658
-			$user = $this->userManager->get($this->userId);
1659
-			if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1660
-				return true;
1661
-			}
1662
-		}
1663
-
1664
-		if ($share->getShareType() === IShare::TYPE_ROOM) {
1665
-			try {
1666
-				return $this->getRoomShareHelper()->canAccessShare($share, $this->userId);
1667
-			} catch (ContainerExceptionInterface $e) {
1668
-				return false;
1669
-			}
1670
-		}
1671
-
1672
-		if ($share->getShareType() === IShare::TYPE_DECK) {
1673
-			try {
1674
-				return $this->getDeckShareHelper()->canAccessShare($share, $this->userId);
1675
-			} catch (ContainerExceptionInterface $e) {
1676
-				return false;
1677
-			}
1678
-		}
1679
-
1680
-		if ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
1681
-			try {
1682
-				return $this->getSciencemeshShareHelper()->canAccessShare($share, $this->userId);
1683
-			} catch (ContainerExceptionInterface $e) {
1684
-				return false;
1685
-			}
1686
-		}
1687
-
1688
-		return false;
1689
-	}
1690
-
1691
-	/**
1692
-	 * Make sure that the passed date is valid ISO 8601
1693
-	 * So YYYY-MM-DD
1694
-	 * If not throw an exception
1695
-	 *
1696
-	 * @param string $expireDate
1697
-	 *
1698
-	 * @throws \Exception
1699
-	 * @return \DateTime
1700
-	 */
1701
-	private function parseDate(string $expireDate): \DateTime {
1702
-		try {
1703
-			$date = new \DateTime(trim($expireDate, '"'), $this->dateTimeZone->getTimeZone());
1704
-			// Make sure it expires at midnight in owner timezone
1705
-			$date->setTime(0, 0, 0);
1706
-		} catch (\Exception $e) {
1707
-			throw new \Exception($this->l->t('Invalid date. Format must be YYYY-MM-DD'));
1708
-		}
1709
-
1710
-		return $date;
1711
-	}
1712
-
1713
-	/**
1714
-	 * Since we have multiple providers but the OCS Share API v1 does
1715
-	 * not support this we need to check all backends.
1716
-	 *
1717
-	 * @param string $id
1718
-	 * @return IShare
1719
-	 * @throws ShareNotFound
1720
-	 */
1721
-	private function getShareById(string $id): IShare {
1722
-		$share = null;
1723
-
1724
-		// First check if it is an internal share.
1725
-		try {
1726
-			$share = $this->shareManager->getShareById('ocinternal:' . $id, $this->userId);
1727
-			return $share;
1728
-		} catch (ShareNotFound $e) {
1729
-			// Do nothing, just try the other share type
1730
-		}
1731
-
1732
-
1733
-		try {
1734
-			if ($this->shareManager->shareProviderExists(IShare::TYPE_CIRCLE)) {
1735
-				$share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->userId);
1736
-				return $share;
1737
-			}
1738
-		} catch (ShareNotFound $e) {
1739
-			// Do nothing, just try the other share type
1740
-		}
1741
-
1742
-		try {
1743
-			if ($this->shareManager->shareProviderExists(IShare::TYPE_EMAIL)) {
1744
-				$share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->userId);
1745
-				return $share;
1746
-			}
1747
-		} catch (ShareNotFound $e) {
1748
-			// Do nothing, just try the other share type
1749
-		}
1750
-
1751
-		try {
1752
-			$share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->userId);
1753
-			return $share;
1754
-		} catch (ShareNotFound $e) {
1755
-			// Do nothing, just try the other share type
1756
-		}
1757
-
1758
-		try {
1759
-			if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) {
1760
-				$share = $this->shareManager->getShareById('deck:' . $id, $this->userId);
1761
-				return $share;
1762
-			}
1763
-		} catch (ShareNotFound $e) {
1764
-			// Do nothing, just try the other share type
1765
-		}
1766
-
1767
-		try {
1768
-			if ($this->shareManager->shareProviderExists(IShare::TYPE_SCIENCEMESH)) {
1769
-				$share = $this->shareManager->getShareById('sciencemesh:' . $id, $this->userId);
1770
-				return $share;
1771
-			}
1772
-		} catch (ShareNotFound $e) {
1773
-			// Do nothing, just try the other share type
1774
-		}
1775
-
1776
-		if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1777
-			throw new ShareNotFound();
1778
-		}
1779
-		$share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->userId);
1780
-
1781
-		return $share;
1782
-	}
1783
-
1784
-	/**
1785
-	 * Lock a Node
1786
-	 *
1787
-	 * @param Node $node
1788
-	 * @throws LockedException
1789
-	 */
1790
-	private function lock(Node $node) {
1791
-		$node->lock(ILockingProvider::LOCK_SHARED);
1792
-		$this->lockedNode = $node;
1793
-	}
1794
-
1795
-	/**
1796
-	 * Cleanup the remaining locks
1797
-	 * @throws LockedException
1798
-	 */
1799
-	public function cleanup() {
1800
-		if ($this->lockedNode !== null) {
1801
-			$this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1802
-		}
1803
-	}
1804
-
1805
-	/**
1806
-	 * Returns the helper of ShareAPIController for room shares.
1807
-	 *
1808
-	 * If the Talk application is not enabled or the helper is not available
1809
-	 * a ContainerExceptionInterface is thrown instead.
1810
-	 *
1811
-	 * @return \OCA\Talk\Share\Helper\ShareAPIController
1812
-	 * @throws ContainerExceptionInterface
1813
-	 */
1814
-	private function getRoomShareHelper() {
1815
-		if (!$this->appManager->isEnabledForUser('spreed')) {
1816
-			throw new QueryException();
1817
-		}
1818
-
1819
-		return $this->serverContainer->get('\OCA\Talk\Share\Helper\ShareAPIController');
1820
-	}
1821
-
1822
-	/**
1823
-	 * Returns the helper of ShareAPIHelper for deck shares.
1824
-	 *
1825
-	 * If the Deck application is not enabled or the helper is not available
1826
-	 * a ContainerExceptionInterface is thrown instead.
1827
-	 *
1828
-	 * @return ShareAPIHelper
1829
-	 * @throws ContainerExceptionInterface
1830
-	 */
1831
-	private function getDeckShareHelper() {
1832
-		if (!$this->appManager->isEnabledForUser('deck')) {
1833
-			throw new QueryException();
1834
-		}
1835
-
1836
-		return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
1837
-	}
1838
-
1839
-	/**
1840
-	 * Returns the helper of ShareAPIHelper for sciencemesh shares.
1841
-	 *
1842
-	 * If the sciencemesh application is not enabled or the helper is not available
1843
-	 * a ContainerExceptionInterface is thrown instead.
1844
-	 *
1845
-	 * @return ShareAPIHelper
1846
-	 * @throws ContainerExceptionInterface
1847
-	 */
1848
-	private function getSciencemeshShareHelper() {
1849
-		if (!$this->appManager->isEnabledForUser('sciencemesh')) {
1850
-			throw new QueryException();
1851
-		}
1852
-
1853
-		return $this->serverContainer->get('\OCA\ScienceMesh\Sharing\ShareAPIHelper');
1854
-	}
1855
-
1856
-	/**
1857
-	 * @param string $viewer
1858
-	 * @param Node $node
1859
-	 * @param bool $reShares
1860
-	 *
1861
-	 * @return IShare[]
1862
-	 */
1863
-	private function getSharesFromNode(string $viewer, $node, bool $reShares): array {
1864
-		$providers = [
1865
-			IShare::TYPE_USER,
1866
-			IShare::TYPE_GROUP,
1867
-			IShare::TYPE_LINK,
1868
-			IShare::TYPE_EMAIL,
1869
-			IShare::TYPE_CIRCLE,
1870
-			IShare::TYPE_ROOM,
1871
-			IShare::TYPE_DECK,
1872
-			IShare::TYPE_SCIENCEMESH
1873
-		];
1874
-
1875
-		// Should we assume that the (currentUser) viewer is the owner of the node !?
1876
-		$shares = [];
1877
-		foreach ($providers as $provider) {
1878
-			if (!$this->shareManager->shareProviderExists($provider)) {
1879
-				continue;
1880
-			}
1881
-
1882
-			$providerShares
1883
-				= $this->shareManager->getSharesBy($viewer, $provider, $node, $reShares, -1, 0);
1884
-			$shares = array_merge($shares, $providerShares);
1885
-		}
1886
-
1887
-		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
1888
-			$federatedShares = $this->shareManager->getSharesBy(
1889
-				$this->userId, IShare::TYPE_REMOTE, $node, $reShares, -1, 0
1890
-			);
1891
-			$shares = array_merge($shares, $federatedShares);
1892
-		}
1893
-
1894
-		if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
1895
-			$federatedShares = $this->shareManager->getSharesBy(
1896
-				$this->userId, IShare::TYPE_REMOTE_GROUP, $node, $reShares, -1, 0
1897
-			);
1898
-			$shares = array_merge($shares, $federatedShares);
1899
-		}
1900
-
1901
-		return $shares;
1902
-	}
1903
-
1904
-
1905
-	/**
1906
-	 * @param Node $node
1907
-	 *
1908
-	 * @throws SharingRightsException
1909
-	 */
1910
-	private function confirmSharingRights(Node $node): void {
1911
-		if (!$this->hasResharingRights($this->userId, $node)) {
1912
-			throw new SharingRightsException($this->l->t('No sharing rights on this item'));
1913
-		}
1914
-	}
1915
-
1916
-
1917
-	/**
1918
-	 * @param string $viewer
1919
-	 * @param Node $node
1920
-	 *
1921
-	 * @return bool
1922
-	 */
1923
-	private function hasResharingRights($viewer, $node): bool {
1924
-		if ($viewer === $node->getOwner()->getUID()) {
1925
-			return true;
1926
-		}
1927
-
1928
-		foreach ([$node, $node->getParent()] as $node) {
1929
-			$shares = $this->getSharesFromNode($viewer, $node, true);
1930
-			foreach ($shares as $share) {
1931
-				try {
1932
-					if ($this->shareProviderResharingRights($viewer, $share, $node)) {
1933
-						return true;
1934
-					}
1935
-				} catch (InvalidPathException|NotFoundException $e) {
1936
-				}
1937
-			}
1938
-		}
1939
-
1940
-		return false;
1941
-	}
1942
-
1943
-
1944
-	/**
1945
-	 * Returns if we can find resharing rights in an IShare object for a specific user.
1946
-	 *
1947
-	 * @suppress PhanUndeclaredClassMethod
1948
-	 *
1949
-	 * @param string $userId
1950
-	 * @param IShare $share
1951
-	 * @param Node $node
1952
-	 *
1953
-	 * @return bool
1954
-	 * @throws NotFoundException
1955
-	 * @throws InvalidPathException
1956
-	 */
1957
-	private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1958
-		if ($share->getShareOwner() === $userId) {
1959
-			return true;
1960
-		}
1961
-
1962
-		// we check that current user have parent resharing rights on the current file
1963
-		if ($node !== null && ($node->getPermissions() & Constants::PERMISSION_SHARE) !== 0) {
1964
-			return true;
1965
-		}
1966
-
1967
-		if ((Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1968
-			return false;
1969
-		}
1970
-
1971
-		if ($share->getShareType() === IShare::TYPE_USER && $share->getSharedWith() === $userId) {
1972
-			return true;
1973
-		}
1974
-
1975
-		if ($share->getShareType() === IShare::TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1976
-			return true;
1977
-		}
1978
-
1979
-		if ($share->getShareType() === IShare::TYPE_CIRCLE && Server::get(IAppManager::class)->isEnabledForUser('circles')
1980
-			&& class_exists('\OCA\Circles\Api\v1\Circles')) {
1981
-			$hasCircleId = (str_ends_with($share->getSharedWith(), ']'));
1982
-			$shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1983
-			$shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1984
-			if ($shareWithLength === false) {
1985
-				$sharedWith = substr($share->getSharedWith(), $shareWithStart);
1986
-			} else {
1987
-				$sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1988
-			}
1989
-			try {
1990
-				$member = Circles::getMember($sharedWith, $userId, 1);
1991
-				if ($member->getLevel() >= 4) {
1992
-					return true;
1993
-				}
1994
-				return false;
1995
-			} catch (ContainerExceptionInterface $e) {
1996
-				return false;
1997
-			}
1998
-		}
1999
-
2000
-		return false;
2001
-	}
2002
-
2003
-	/**
2004
-	 * Get all the shares for the current user
2005
-	 *
2006
-	 * @param Node|null $path
2007
-	 * @param boolean $reshares
2008
-	 * @return IShare[]
2009
-	 */
2010
-	private function getAllShares(?Node $path = null, bool $reshares = false) {
2011
-		// Get all shares
2012
-		$userShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_USER, $path, $reshares, -1, 0);
2013
-		$groupShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_GROUP, $path, $reshares, -1, 0);
2014
-		$linkShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_LINK, $path, $reshares, -1, 0);
2015
-
2016
-		// EMAIL SHARES
2017
-		$mailShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_EMAIL, $path, $reshares, -1, 0);
2018
-
2019
-		// TEAM SHARES
2020
-		$circleShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_CIRCLE, $path, $reshares, -1, 0);
2021
-
2022
-		// TALK SHARES
2023
-		$roomShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_ROOM, $path, $reshares, -1, 0);
2024
-
2025
-		// DECK SHARES
2026
-		$deckShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_DECK, $path, $reshares, -1, 0);
2027
-
2028
-		// SCIENCEMESH SHARES
2029
-		$sciencemeshShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_SCIENCEMESH, $path, $reshares, -1, 0);
2030
-
2031
-		// FEDERATION
2032
-		if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
2033
-			$federatedShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_REMOTE, $path, $reshares, -1, 0);
2034
-		} else {
2035
-			$federatedShares = [];
2036
-		}
2037
-		if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
2038
-			$federatedGroupShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
2039
-		} else {
2040
-			$federatedGroupShares = [];
2041
-		}
2042
-
2043
-		return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $deckShares, $sciencemeshShares, $federatedShares, $federatedGroupShares);
2044
-	}
2045
-
2046
-
2047
-	/**
2048
-	 * merging already formatted shares.
2049
-	 * We'll make an associative array to easily detect duplicate Ids.
2050
-	 * Keys _needs_ to be removed after all shares are retrieved and merged.
2051
-	 *
2052
-	 * @param array $shares
2053
-	 * @param array $newShares
2054
-	 */
2055
-	private function mergeFormattedShares(array &$shares, array $newShares) {
2056
-		foreach ($newShares as $newShare) {
2057
-			if (!array_key_exists($newShare['id'], $shares)) {
2058
-				$shares[$newShare['id']] = $newShare;
2059
-			}
2060
-		}
2061
-	}
2062
-
2063
-	/**
2064
-	 * @param IShare $share
2065
-	 * @param string|null $attributesString
2066
-	 * @return IShare modified share
2067
-	 */
2068
-	private function setShareAttributes(IShare $share, ?string $attributesString) {
2069
-		$newShareAttributes = null;
2070
-		if ($attributesString !== null) {
2071
-			$newShareAttributes = $this->shareManager->newShare()->newAttributes();
2072
-			$formattedShareAttributes = \json_decode($attributesString, true);
2073
-			if (is_array($formattedShareAttributes)) {
2074
-				foreach ($formattedShareAttributes as $formattedAttr) {
2075
-					$newShareAttributes->setAttribute(
2076
-						$formattedAttr['scope'],
2077
-						$formattedAttr['key'],
2078
-						$formattedAttr['value'],
2079
-					);
2080
-				}
2081
-			} else {
2082
-				throw new OCSBadRequestException($this->l->t('Invalid share attributes provided: "%s"', [$attributesString]));
2083
-			}
2084
-		}
2085
-		$share->setAttributes($newShareAttributes);
2086
-
2087
-		return $share;
2088
-	}
2089
-
2090
-	private function checkInheritedAttributes(IShare $share): void {
2091
-		if (!$share->getSharedBy()) {
2092
-			return; // Probably in a test
2093
-		}
2094
-
2095
-		$canDownload = false;
2096
-		$hideDownload = true;
2097
-
2098
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
2099
-		$nodes = $userFolder->getById($share->getNodeId());
2100
-		foreach ($nodes as $node) {
2101
-			// Owner always can download it - so allow it and break
2102
-			if ($node->getOwner()?->getUID() === $share->getSharedBy()) {
2103
-				$canDownload = true;
2104
-				$hideDownload = false;
2105
-				break;
2106
-			}
2107
-
2108
-			if ($node->getStorage()->instanceOfStorage(SharedStorage::class)) {
2109
-				$storage = $node->getStorage();
2110
-				if ($storage instanceof Wrapper) {
2111
-					$storage = $storage->getInstanceOfStorage(SharedStorage::class);
2112
-					if ($storage === null) {
2113
-						throw new \RuntimeException('Should not happen, instanceOfStorage but getInstanceOfStorage return null');
2114
-					}
2115
-				} else {
2116
-					throw new \RuntimeException('Should not happen, instanceOfStorage but not a wrapper');
2117
-				}
2118
-
2119
-				/** @var SharedStorage $storage */
2120
-				$originalShare = $storage->getShare();
2121
-				$inheritedAttributes = $originalShare->getAttributes();
2122
-				// hide if hidden and also the current share enforces hide (can only be false if one share is false or user is owner)
2123
-				$hideDownload = $hideDownload && $originalShare->getHideDownload();
2124
-				// allow download if already allowed by previous share or when the current share allows downloading
2125
-				$canDownload = $canDownload || $inheritedAttributes === null || $inheritedAttributes->getAttribute('permissions', 'download') !== false;
2126
-			} elseif ($node->getStorage()->instanceOfStorage(Storage::class)) {
2127
-				$canDownload = true; // in case of federation storage, we can expect the download to be activated by default
2128
-			}
2129
-		}
2130
-
2131
-		if ($hideDownload || !$canDownload) {
2132
-			$share->setHideDownload(true);
2133
-
2134
-			if (!$canDownload) {
2135
-				$attributes = $share->getAttributes() ?? $share->newAttributes();
2136
-				$attributes->setAttribute('permissions', 'download', false);
2137
-				$share->setAttributes($attributes);
2138
-			}
2139
-		}
2140
-	}
2141
-
2142
-	/**
2143
-	 * Send a mail notification again for a share.
2144
-	 * The mail_send option must be enabled for the given share.
2145
-	 * @param string $id the share ID
2146
-	 * @param string $password the password to check against. Necessary for password protected shares.
2147
-	 * @throws OCSNotFoundException Share not found
2148
-	 * @throws OCSForbiddenException You are not allowed to send mail notifications
2149
-	 * @throws OCSBadRequestException Invalid request or wrong password
2150
-	 * @throws OCSException Error while sending mail notification
2151
-	 * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
2152
-	 *
2153
-	 * 200: The email notification was sent successfully
2154
-	 */
2155
-	#[NoAdminRequired]
2156
-	#[UserRateLimit(limit: 10, period: 600)]
2157
-	public function sendShareEmail(string $id, $password = ''): DataResponse {
2158
-		try {
2159
-			$share = $this->getShareById($id);
2160
-
2161
-			if (!$this->canAccessShare($share, false)) {
2162
-				throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
2163
-			}
2164
-
2165
-			if (!$this->canEditShare($share)) {
2166
-				throw new OCSForbiddenException($this->l->t('You are not allowed to send mail notifications'));
2167
-			}
2168
-
2169
-			// For mail and link shares, the user must be
2170
-			// the owner of the share, not only the file owner.
2171
-			if ($share->getShareType() === IShare::TYPE_EMAIL
2172
-				|| $share->getShareType() === IShare::TYPE_LINK) {
2173
-				if ($share->getSharedBy() !== $this->userId) {
2174
-					throw new OCSForbiddenException($this->l->t('You are not allowed to send mail notifications'));
2175
-				}
2176
-			}
2177
-
2178
-			try {
2179
-				$provider = $this->factory->getProviderForType($share->getShareType());
2180
-				if (!($provider instanceof IShareProviderWithNotification)) {
2181
-					throw new OCSBadRequestException($this->l->t('No mail notification configured for this share type'));
2182
-				}
2183
-
2184
-				// Circumvent the password encrypted data by
2185
-				// setting the password clear. We're not storing
2186
-				// the password clear, it is just a temporary
2187
-				// object manipulation. The password will stay
2188
-				// encrypted in the database.
2189
-				if ($share->getPassword() !== null && $share->getPassword() !== $password) {
2190
-					if (!$this->shareManager->checkPassword($share, $password)) {
2191
-						throw new OCSBadRequestException($this->l->t('Wrong password'));
2192
-					}
2193
-					$share = $share->setPassword($password);
2194
-				}
2195
-
2196
-				$provider->sendMailNotification($share);
2197
-				return new DataResponse();
2198
-			} catch (Exception $e) {
2199
-				$this->logger->error($e->getMessage(), ['exception' => $e]);
2200
-				throw new OCSException($this->l->t('Error while sending mail notification'));
2201
-			}
2202
-
2203
-		} catch (ShareNotFound $e) {
2204
-			throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
2205
-		}
2206
-	}
2207
-
2208
-	/**
2209
-	 * Get a unique share token
2210
-	 *
2211
-	 * @throws OCSException Failed to generate a unique token
2212
-	 *
2213
-	 * @return DataResponse<Http::STATUS_OK, array{token: string}, array{}>
2214
-	 *
2215
-	 * 200: Token generated successfully
2216
-	 */
2217
-	#[ApiRoute(verb: 'GET', url: '/api/v1/token')]
2218
-	#[NoAdminRequired]
2219
-	public function generateToken(): DataResponse {
2220
-		try {
2221
-			$token = $this->shareManager->generateToken();
2222
-			return new DataResponse([
2223
-				'token' => $token,
2224
-			]);
2225
-		} catch (ShareTokenException $e) {
2226
-			throw new OCSException($this->l->t('Failed to generate a unique token'));
2227
-		}
2228
-	}
2229
-
2230
-	/**
2231
-	 * Populate the result set with file tags
2232
-	 *
2233
-	 * @psalm-template T of array{tags?: list<string>, file_source: int, ...array<string, mixed>}
2234
-	 * @param list<T> $fileList
2235
-	 * @return list<T> file list populated with tags
2236
-	 */
2237
-	private function populateTags(array $fileList): array {
2238
-		$tagger = $this->tagManager->load('files');
2239
-		$tags = $tagger->getTagsForObjects(array_map(static fn (array $fileData) => $fileData['file_source'], $fileList));
2240
-
2241
-		if (!is_array($tags)) {
2242
-			throw new \UnexpectedValueException('$tags must be an array');
2243
-		}
2244
-
2245
-		// Set empty tag array
2246
-		foreach ($fileList as &$fileData) {
2247
-			$fileData['tags'] = [];
2248
-		}
2249
-		unset($fileData);
2250
-
2251
-		if (!empty($tags)) {
2252
-			foreach ($tags as $fileId => $fileTags) {
2253
-				foreach ($fileList as &$fileData) {
2254
-					if ($fileId !== $fileData['file_source']) {
2255
-						continue;
2256
-					}
2257
-
2258
-					$fileData['tags'] = $fileTags;
2259
-				}
2260
-				unset($fileData);
2261
-			}
2262
-		}
2263
-
2264
-		return $fileList;
2265
-	}
1071
+                continue;
1072
+            }
1073
+
1074
+            if (in_array($share->getId(), $known)
1075
+                || ($share->getSharedWith() === $this->userId && $share->getShareType() === IShare::TYPE_USER)) {
1076
+                continue;
1077
+            }
1078
+
1079
+            $known[] = $share->getId();
1080
+            try {
1081
+                /** @var IShare $share */
1082
+                $format = $this->formatShare($share, $node);
1083
+                $formatted[] = $format;
1084
+
1085
+                // let's also build a list of shares created
1086
+                // by the current user only, in case
1087
+                // there is no resharing rights
1088
+                if ($share->getSharedBy() === $this->userId) {
1089
+                    $miniFormatted[] = $format;
1090
+                }
1091
+
1092
+                // check if one of those share is shared with me
1093
+                // and if I have resharing rights on it
1094
+                if (!$resharingRight && $this->shareProviderResharingRights($this->userId, $share, $node)) {
1095
+                    $resharingRight = true;
1096
+                }
1097
+            } catch (InvalidPathException|NotFoundException $e) {
1098
+            }
1099
+        }
1100
+
1101
+        if (!$resharingRight) {
1102
+            $formatted = $miniFormatted;
1103
+        }
1104
+
1105
+        // fix eventual missing display name from federated shares
1106
+        $formatted = $this->fixMissingDisplayName($formatted);
1107
+
1108
+        if ($includeTags) {
1109
+            $formatted = $this->populateTags($formatted);
1110
+        }
1111
+
1112
+        return $formatted;
1113
+    }
1114
+
1115
+
1116
+    /**
1117
+     * Get all shares relative to a file, including parent folders shares rights
1118
+     *
1119
+     * @param string $path Path all shares will be relative to
1120
+     *
1121
+     * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
1122
+     * @throws InvalidPathException
1123
+     * @throws NotFoundException
1124
+     * @throws OCSNotFoundException The given path is invalid
1125
+     * @throws SharingRightsException
1126
+     *
1127
+     * 200: Shares returned
1128
+     */
1129
+    #[NoAdminRequired]
1130
+    public function getInheritedShares(string $path): DataResponse {
1131
+        // get Node from (string) path.
1132
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
1133
+        try {
1134
+            $node = $userFolder->get($path);
1135
+            $this->lock($node);
1136
+        } catch (NotFoundException $e) {
1137
+            throw new OCSNotFoundException($this->l->t('Wrong path, file/folder does not exist'));
1138
+        } catch (LockedException $e) {
1139
+            throw new OCSNotFoundException($this->l->t('Could not lock path'));
1140
+        }
1141
+
1142
+        if (!($node->getPermissions() & Constants::PERMISSION_SHARE)) {
1143
+            throw new SharingRightsException($this->l->t('no sharing rights on this item'));
1144
+        }
1145
+
1146
+        // The current top parent we have access to
1147
+        $parent = $node;
1148
+
1149
+        // initiate real owner.
1150
+        $owner = $node->getOwner()
1151
+            ->getUID();
1152
+        if (!$this->userManager->userExists($owner)) {
1153
+            return new DataResponse([]);
1154
+        }
1155
+
1156
+        // get node based on the owner, fix owner in case of external storage
1157
+        $userFolder = $this->rootFolder->getUserFolder($owner);
1158
+        if ($node->getId() !== $userFolder->getId() && !$userFolder->isSubNode($node)) {
1159
+            $owner = $node->getOwner()
1160
+                ->getUID();
1161
+            $userFolder = $this->rootFolder->getUserFolder($owner);
1162
+            $node = $userFolder->getFirstNodeById($node->getId());
1163
+        }
1164
+        $basePath = $userFolder->getPath();
1165
+
1166
+        // generate node list for each parent folders
1167
+        /** @var Node[] $nodes */
1168
+        $nodes = [];
1169
+        while (true) {
1170
+            $node = $node->getParent();
1171
+            if ($node->getPath() === $basePath) {
1172
+                break;
1173
+            }
1174
+            $nodes[] = $node;
1175
+        }
1176
+
1177
+        // The user that is requesting this list
1178
+        $currentUserFolder = $this->rootFolder->getUserFolder($this->userId);
1179
+
1180
+        // for each nodes, retrieve shares.
1181
+        $shares = [];
1182
+
1183
+        foreach ($nodes as $node) {
1184
+            $getShares = $this->getFormattedShares($owner, $node, false, true);
1185
+
1186
+            $currentUserNode = $currentUserFolder->getFirstNodeById($node->getId());
1187
+            if ($currentUserNode) {
1188
+                $parent = $currentUserNode;
1189
+            }
1190
+
1191
+            $subPath = $currentUserFolder->getRelativePath($parent->getPath());
1192
+            foreach ($getShares as &$share) {
1193
+                $share['via_fileid'] = $parent->getId();
1194
+                $share['via_path'] = $subPath;
1195
+            }
1196
+            $this->mergeFormattedShares($shares, $getShares);
1197
+        }
1198
+
1199
+        return new DataResponse(array_values($shares));
1200
+    }
1201
+
1202
+    /**
1203
+     * Check whether a set of permissions contains the permissions to check.
1204
+     */
1205
+    private function hasPermission(int $permissionsSet, int $permissionsToCheck): bool {
1206
+        return ($permissionsSet & $permissionsToCheck) === $permissionsToCheck;
1207
+    }
1208
+
1209
+    /**
1210
+     * Update a share
1211
+     *
1212
+     * @param string $id ID of the share
1213
+     * @param int|null $permissions New permissions
1214
+     * @param string|null $password New password
1215
+     * @param string|null $sendPasswordByTalk New condition if the password should be send over Talk
1216
+     * @param string|null $publicUpload New condition if public uploading is allowed
1217
+     * @param string|null $expireDate New expiry date
1218
+     * @param string|null $note New note
1219
+     * @param string|null $label New label
1220
+     * @param string|null $hideDownload New condition if the download should be hidden
1221
+     * @param string|null $attributes New additional attributes
1222
+     * @param string|null $sendMail if the share should be send by mail.
1223
+     *                              Considering the share already exists, no mail will be send after the share is updated.
1224
+     *                              You will have to use the sendMail action to send the mail.
1225
+     * @param string|null $shareWith New recipient for email shares
1226
+     * @param string|null $token New token
1227
+     * @return DataResponse<Http::STATUS_OK, Files_SharingShare, array{}>
1228
+     * @throws OCSBadRequestException Share could not be updated because the requested changes are invalid
1229
+     * @throws OCSForbiddenException Missing permissions to update the share
1230
+     * @throws OCSNotFoundException Share not found
1231
+     *
1232
+     * 200: Share updated successfully
1233
+     */
1234
+    #[NoAdminRequired]
1235
+    public function updateShare(
1236
+        string $id,
1237
+        ?int $permissions = null,
1238
+        ?string $password = null,
1239
+        ?string $sendPasswordByTalk = null,
1240
+        ?string $publicUpload = null,
1241
+        ?string $expireDate = null,
1242
+        ?string $note = null,
1243
+        ?string $label = null,
1244
+        ?string $hideDownload = null,
1245
+        ?string $attributes = null,
1246
+        ?string $sendMail = null,
1247
+        ?string $token = null,
1248
+    ): DataResponse {
1249
+        try {
1250
+            $share = $this->getShareById($id);
1251
+        } catch (ShareNotFound $e) {
1252
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1253
+        }
1254
+
1255
+        $this->lock($share->getNode());
1256
+
1257
+        if (!$this->canAccessShare($share, false)) {
1258
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1259
+        }
1260
+
1261
+        if (!$this->canEditShare($share)) {
1262
+            throw new OCSForbiddenException($this->l->t('You are not allowed to edit incoming shares'));
1263
+        }
1264
+
1265
+        if (
1266
+            $permissions === null
1267
+            && $password === null
1268
+            && $sendPasswordByTalk === null
1269
+            && $publicUpload === null
1270
+            && $expireDate === null
1271
+            && $note === null
1272
+            && $label === null
1273
+            && $hideDownload === null
1274
+            && $attributes === null
1275
+            && $sendMail === null
1276
+            && $token === null
1277
+        ) {
1278
+            throw new OCSBadRequestException($this->l->t('Wrong or no update parameter given'));
1279
+        }
1280
+
1281
+        if ($note !== null) {
1282
+            $share->setNote($note);
1283
+        }
1284
+
1285
+        if ($attributes !== null) {
1286
+            $share = $this->setShareAttributes($share, $attributes);
1287
+        }
1288
+
1289
+        // Handle mail send
1290
+        if ($sendMail === 'true' || $sendMail === 'false') {
1291
+            $share->setMailSend($sendMail === 'true');
1292
+        }
1293
+
1294
+        /**
1295
+         * expiration date, password and publicUpload only make sense for link shares
1296
+         */
1297
+        if ($share->getShareType() === IShare::TYPE_LINK
1298
+            || $share->getShareType() === IShare::TYPE_EMAIL) {
1299
+
1300
+            // Update hide download state
1301
+            if ($hideDownload === 'true') {
1302
+                $share->setHideDownload(true);
1303
+            } elseif ($hideDownload === 'false') {
1304
+                $share->setHideDownload(false);
1305
+            }
1306
+
1307
+            // If either manual permissions are specified or publicUpload
1308
+            // then we need to also update the permissions of the share
1309
+            if ($permissions !== null || $publicUpload !== null) {
1310
+                $hasPublicUpload = $this->getLegacyPublicUpload($publicUpload);
1311
+                $permissions = $this->getLinkSharePermissions($permissions ?? Constants::PERMISSION_READ, $hasPublicUpload);
1312
+                $this->validateLinkSharePermissions($share->getNode(), $permissions, $hasPublicUpload);
1313
+                $share->setPermissions($permissions);
1314
+            }
1315
+
1316
+            if ($password === '') {
1317
+                $share->setPassword(null);
1318
+            } elseif ($password !== null) {
1319
+                $share->setPassword($password);
1320
+            }
1321
+
1322
+            if ($label !== null) {
1323
+                if (strlen($label) > 255) {
1324
+                    throw new OCSBadRequestException('Maximum label length is 255');
1325
+                }
1326
+                $share->setLabel($label);
1327
+            }
1328
+
1329
+            if ($sendPasswordByTalk === 'true') {
1330
+                if (!$this->appManager->isEnabledForUser('spreed')) {
1331
+                    throw new OCSForbiddenException($this->l->t('"Sending the password by Nextcloud Talk" for sharing a file or folder failed because Nextcloud Talk is not enabled.'));
1332
+                }
1333
+
1334
+                $share->setSendPasswordByTalk(true);
1335
+            } elseif ($sendPasswordByTalk !== null) {
1336
+                $share->setSendPasswordByTalk(false);
1337
+            }
1338
+
1339
+            if ($token !== null) {
1340
+                if (!$this->shareManager->allowCustomTokens()) {
1341
+                    throw new OCSForbiddenException($this->l->t('Custom share link tokens have been disabled by the administrator'));
1342
+                }
1343
+                if (!$this->validateToken($token)) {
1344
+                    throw new OCSBadRequestException($this->l->t('Tokens must contain at least 1 character and may only contain letters, numbers, or a hyphen'));
1345
+                }
1346
+                $share->setToken($token);
1347
+            }
1348
+        }
1349
+
1350
+        // NOT A LINK SHARE
1351
+        else {
1352
+            if ($permissions !== null) {
1353
+                $share->setPermissions($permissions);
1354
+            }
1355
+        }
1356
+
1357
+        if ($expireDate === '') {
1358
+            $share->setExpirationDate(null);
1359
+        } elseif ($expireDate !== null) {
1360
+            try {
1361
+                $expireDateTime = $this->parseDate($expireDate);
1362
+                $share->setExpirationDate($expireDateTime);
1363
+            } catch (\Exception $e) {
1364
+                throw new OCSBadRequestException($e->getMessage(), $e);
1365
+            }
1366
+        }
1367
+
1368
+        try {
1369
+            $this->checkInheritedAttributes($share);
1370
+            $share = $this->shareManager->updateShare($share);
1371
+        } catch (HintException $e) {
1372
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
1373
+            throw new OCSException($e->getHint(), (int)$code);
1374
+        } catch (\Exception $e) {
1375
+            $this->logger->error($e->getMessage(), ['exception' => $e]);
1376
+            throw new OCSBadRequestException('Failed to update share.', $e);
1377
+        }
1378
+
1379
+        return new DataResponse($this->formatShare($share));
1380
+    }
1381
+
1382
+    private function validateToken(string $token): bool {
1383
+        if (mb_strlen($token) === 0) {
1384
+            return false;
1385
+        }
1386
+        if (!preg_match('/^[a-z0-9-]+$/i', $token)) {
1387
+            return false;
1388
+        }
1389
+        return true;
1390
+    }
1391
+
1392
+    /**
1393
+     * Get all shares that are still pending
1394
+     *
1395
+     * @return DataResponse<Http::STATUS_OK, list<Files_SharingShare>, array{}>
1396
+     *
1397
+     * 200: Pending shares returned
1398
+     */
1399
+    #[NoAdminRequired]
1400
+    public function pendingShares(): DataResponse {
1401
+        $pendingShares = [];
1402
+
1403
+        $shareTypes = [
1404
+            IShare::TYPE_USER,
1405
+            IShare::TYPE_GROUP
1406
+        ];
1407
+
1408
+        foreach ($shareTypes as $shareType) {
1409
+            $shares = $this->shareManager->getSharedWith($this->userId, $shareType, null, -1, 0);
1410
+
1411
+            foreach ($shares as $share) {
1412
+                if ($share->getStatus() === IShare::STATUS_PENDING || $share->getStatus() === IShare::STATUS_REJECTED) {
1413
+                    $pendingShares[] = $share;
1414
+                }
1415
+            }
1416
+        }
1417
+
1418
+        $result = array_values(array_filter(array_map(function (IShare $share) {
1419
+            $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
1420
+            $node = $userFolder->getFirstNodeById($share->getNodeId());
1421
+            if (!$node) {
1422
+                // fallback to guessing the path
1423
+                $node = $userFolder->get($share->getTarget());
1424
+                if ($node === null || $share->getTarget() === '') {
1425
+                    return null;
1426
+                }
1427
+            }
1428
+
1429
+            try {
1430
+                $formattedShare = $this->formatShare($share, $node);
1431
+                $formattedShare['path'] = '/' . $share->getNode()->getName();
1432
+                $formattedShare['permissions'] = 0;
1433
+                return $formattedShare;
1434
+            } catch (NotFoundException $e) {
1435
+                return null;
1436
+            }
1437
+        }, $pendingShares), function ($entry) {
1438
+            return $entry !== null;
1439
+        }));
1440
+
1441
+        return new DataResponse($result);
1442
+    }
1443
+
1444
+    /**
1445
+     * Accept a share
1446
+     *
1447
+     * @param string $id ID of the share
1448
+     * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
1449
+     * @throws OCSNotFoundException Share not found
1450
+     * @throws OCSException
1451
+     * @throws OCSBadRequestException Share could not be accepted
1452
+     *
1453
+     * 200: Share accepted successfully
1454
+     */
1455
+    #[NoAdminRequired]
1456
+    public function acceptShare(string $id): DataResponse {
1457
+        try {
1458
+            $share = $this->getShareById($id);
1459
+        } catch (ShareNotFound $e) {
1460
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1461
+        }
1462
+
1463
+        if (!$this->canAccessShare($share)) {
1464
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
1465
+        }
1466
+
1467
+        try {
1468
+            $this->shareManager->acceptShare($share, $this->userId);
1469
+        } catch (HintException $e) {
1470
+            $code = $e->getCode() === 0 ? 403 : $e->getCode();
1471
+            throw new OCSException($e->getHint(), (int)$code);
1472
+        } catch (\Exception $e) {
1473
+            $this->logger->error($e->getMessage(), ['exception' => $e]);
1474
+            throw new OCSBadRequestException('Failed to accept share.', $e);
1475
+        }
1476
+
1477
+        return new DataResponse();
1478
+    }
1479
+
1480
+    /**
1481
+     * Does the user have read permission on the share
1482
+     *
1483
+     * @param IShare $share the share to check
1484
+     * @param boolean $checkGroups check groups as well?
1485
+     * @return boolean
1486
+     * @throws NotFoundException
1487
+     *
1488
+     * @suppress PhanUndeclaredClassMethod
1489
+     */
1490
+    protected function canAccessShare(IShare $share, bool $checkGroups = true): bool {
1491
+        // A file with permissions 0 can't be accessed by us. So Don't show it
1492
+        if ($share->getPermissions() === 0) {
1493
+            return false;
1494
+        }
1495
+
1496
+        // Owner of the file and the sharer of the file can always get share
1497
+        if ($share->getShareOwner() === $this->userId
1498
+            || $share->getSharedBy() === $this->userId) {
1499
+            return true;
1500
+        }
1501
+
1502
+        // If the share is shared with you, you can access it!
1503
+        if ($share->getShareType() === IShare::TYPE_USER
1504
+            && $share->getSharedWith() === $this->userId) {
1505
+            return true;
1506
+        }
1507
+
1508
+        // Have reshare rights on the shared file/folder ?
1509
+        // Does the currentUser have access to the shared file?
1510
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
1511
+        $file = $userFolder->getFirstNodeById($share->getNodeId());
1512
+        if ($file && $this->shareProviderResharingRights($this->userId, $share, $file)) {
1513
+            return true;
1514
+        }
1515
+
1516
+        // If in the recipient group, you can see the share
1517
+        if ($checkGroups && $share->getShareType() === IShare::TYPE_GROUP) {
1518
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1519
+            $user = $this->userManager->get($this->userId);
1520
+            if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1521
+                return true;
1522
+            }
1523
+        }
1524
+
1525
+        if ($share->getShareType() === IShare::TYPE_CIRCLE) {
1526
+            // TODO: have a sanity check like above?
1527
+            return true;
1528
+        }
1529
+
1530
+        if ($share->getShareType() === IShare::TYPE_ROOM) {
1531
+            try {
1532
+                return $this->getRoomShareHelper()->canAccessShare($share, $this->userId);
1533
+            } catch (ContainerExceptionInterface $e) {
1534
+                return false;
1535
+            }
1536
+        }
1537
+
1538
+        if ($share->getShareType() === IShare::TYPE_DECK) {
1539
+            try {
1540
+                return $this->getDeckShareHelper()->canAccessShare($share, $this->userId);
1541
+            } catch (ContainerExceptionInterface $e) {
1542
+                return false;
1543
+            }
1544
+        }
1545
+
1546
+        if ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
1547
+            try {
1548
+                return $this->getSciencemeshShareHelper()->canAccessShare($share, $this->userId);
1549
+            } catch (ContainerExceptionInterface $e) {
1550
+                return false;
1551
+            }
1552
+        }
1553
+
1554
+        return false;
1555
+    }
1556
+
1557
+    /**
1558
+     * Does the user have edit permission on the share
1559
+     *
1560
+     * @param IShare $share the share to check
1561
+     * @return boolean
1562
+     */
1563
+    protected function canEditShare(IShare $share): bool {
1564
+        // A file with permissions 0 can't be accessed by us. So Don't show it
1565
+        if ($share->getPermissions() === 0) {
1566
+            return false;
1567
+        }
1568
+
1569
+        // The owner of the file and the creator of the share
1570
+        // can always edit the share
1571
+        if ($share->getShareOwner() === $this->userId
1572
+            || $share->getSharedBy() === $this->userId
1573
+        ) {
1574
+            return true;
1575
+        }
1576
+
1577
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
1578
+        $file = $userFolder->getFirstNodeById($share->getNodeId());
1579
+        if ($file?->getMountPoint() instanceof IShareOwnerlessMount && $this->shareProviderResharingRights($this->userId, $share, $file)) {
1580
+            return true;
1581
+        }
1582
+
1583
+        //! we do NOT support some kind of `admin` in groups.
1584
+        //! You cannot edit shares shared to a group you're
1585
+        //! a member of if you're not the share owner or the file owner!
1586
+
1587
+        return false;
1588
+    }
1589
+
1590
+    /**
1591
+     * Does the user have delete permission on the share
1592
+     *
1593
+     * @param IShare $share the share to check
1594
+     * @return boolean
1595
+     */
1596
+    protected function canDeleteShare(IShare $share): bool {
1597
+        // A file with permissions 0 can't be accessed by us. So Don't show it
1598
+        if ($share->getPermissions() === 0) {
1599
+            return false;
1600
+        }
1601
+
1602
+        // if the user is the recipient, i can unshare
1603
+        // the share with self
1604
+        if ($share->getShareType() === IShare::TYPE_USER
1605
+            && $share->getSharedWith() === $this->userId
1606
+        ) {
1607
+            return true;
1608
+        }
1609
+
1610
+        // The owner of the file and the creator of the share
1611
+        // can always delete the share
1612
+        if ($share->getShareOwner() === $this->userId
1613
+            || $share->getSharedBy() === $this->userId
1614
+        ) {
1615
+            return true;
1616
+        }
1617
+
1618
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
1619
+        $file = $userFolder->getFirstNodeById($share->getNodeId());
1620
+        if ($file?->getMountPoint() instanceof IShareOwnerlessMount && $this->shareProviderResharingRights($this->userId, $share, $file)) {
1621
+            return true;
1622
+        }
1623
+
1624
+        return false;
1625
+    }
1626
+
1627
+    /**
1628
+     * Does the user have delete permission on the share
1629
+     * This differs from the canDeleteShare function as it only
1630
+     * remove the share for the current user. It does NOT
1631
+     * completely delete the share but only the mount point.
1632
+     * It can then be restored from the deleted shares section.
1633
+     *
1634
+     * @param IShare $share the share to check
1635
+     * @return boolean
1636
+     *
1637
+     * @suppress PhanUndeclaredClassMethod
1638
+     */
1639
+    protected function canDeleteShareFromSelf(IShare $share): bool {
1640
+        if ($share->getShareType() !== IShare::TYPE_GROUP
1641
+            && $share->getShareType() !== IShare::TYPE_ROOM
1642
+            && $share->getShareType() !== IShare::TYPE_DECK
1643
+            && $share->getShareType() !== IShare::TYPE_SCIENCEMESH
1644
+        ) {
1645
+            return false;
1646
+        }
1647
+
1648
+        if ($share->getShareOwner() === $this->userId
1649
+            || $share->getSharedBy() === $this->userId
1650
+        ) {
1651
+            // Delete the whole share, not just for self
1652
+            return false;
1653
+        }
1654
+
1655
+        // If in the recipient group, you can delete the share from self
1656
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
1657
+            $sharedWith = $this->groupManager->get($share->getSharedWith());
1658
+            $user = $this->userManager->get($this->userId);
1659
+            if ($user !== null && $sharedWith !== null && $sharedWith->inGroup($user)) {
1660
+                return true;
1661
+            }
1662
+        }
1663
+
1664
+        if ($share->getShareType() === IShare::TYPE_ROOM) {
1665
+            try {
1666
+                return $this->getRoomShareHelper()->canAccessShare($share, $this->userId);
1667
+            } catch (ContainerExceptionInterface $e) {
1668
+                return false;
1669
+            }
1670
+        }
1671
+
1672
+        if ($share->getShareType() === IShare::TYPE_DECK) {
1673
+            try {
1674
+                return $this->getDeckShareHelper()->canAccessShare($share, $this->userId);
1675
+            } catch (ContainerExceptionInterface $e) {
1676
+                return false;
1677
+            }
1678
+        }
1679
+
1680
+        if ($share->getShareType() === IShare::TYPE_SCIENCEMESH) {
1681
+            try {
1682
+                return $this->getSciencemeshShareHelper()->canAccessShare($share, $this->userId);
1683
+            } catch (ContainerExceptionInterface $e) {
1684
+                return false;
1685
+            }
1686
+        }
1687
+
1688
+        return false;
1689
+    }
1690
+
1691
+    /**
1692
+     * Make sure that the passed date is valid ISO 8601
1693
+     * So YYYY-MM-DD
1694
+     * If not throw an exception
1695
+     *
1696
+     * @param string $expireDate
1697
+     *
1698
+     * @throws \Exception
1699
+     * @return \DateTime
1700
+     */
1701
+    private function parseDate(string $expireDate): \DateTime {
1702
+        try {
1703
+            $date = new \DateTime(trim($expireDate, '"'), $this->dateTimeZone->getTimeZone());
1704
+            // Make sure it expires at midnight in owner timezone
1705
+            $date->setTime(0, 0, 0);
1706
+        } catch (\Exception $e) {
1707
+            throw new \Exception($this->l->t('Invalid date. Format must be YYYY-MM-DD'));
1708
+        }
1709
+
1710
+        return $date;
1711
+    }
1712
+
1713
+    /**
1714
+     * Since we have multiple providers but the OCS Share API v1 does
1715
+     * not support this we need to check all backends.
1716
+     *
1717
+     * @param string $id
1718
+     * @return IShare
1719
+     * @throws ShareNotFound
1720
+     */
1721
+    private function getShareById(string $id): IShare {
1722
+        $share = null;
1723
+
1724
+        // First check if it is an internal share.
1725
+        try {
1726
+            $share = $this->shareManager->getShareById('ocinternal:' . $id, $this->userId);
1727
+            return $share;
1728
+        } catch (ShareNotFound $e) {
1729
+            // Do nothing, just try the other share type
1730
+        }
1731
+
1732
+
1733
+        try {
1734
+            if ($this->shareManager->shareProviderExists(IShare::TYPE_CIRCLE)) {
1735
+                $share = $this->shareManager->getShareById('ocCircleShare:' . $id, $this->userId);
1736
+                return $share;
1737
+            }
1738
+        } catch (ShareNotFound $e) {
1739
+            // Do nothing, just try the other share type
1740
+        }
1741
+
1742
+        try {
1743
+            if ($this->shareManager->shareProviderExists(IShare::TYPE_EMAIL)) {
1744
+                $share = $this->shareManager->getShareById('ocMailShare:' . $id, $this->userId);
1745
+                return $share;
1746
+            }
1747
+        } catch (ShareNotFound $e) {
1748
+            // Do nothing, just try the other share type
1749
+        }
1750
+
1751
+        try {
1752
+            $share = $this->shareManager->getShareById('ocRoomShare:' . $id, $this->userId);
1753
+            return $share;
1754
+        } catch (ShareNotFound $e) {
1755
+            // Do nothing, just try the other share type
1756
+        }
1757
+
1758
+        try {
1759
+            if ($this->shareManager->shareProviderExists(IShare::TYPE_DECK)) {
1760
+                $share = $this->shareManager->getShareById('deck:' . $id, $this->userId);
1761
+                return $share;
1762
+            }
1763
+        } catch (ShareNotFound $e) {
1764
+            // Do nothing, just try the other share type
1765
+        }
1766
+
1767
+        try {
1768
+            if ($this->shareManager->shareProviderExists(IShare::TYPE_SCIENCEMESH)) {
1769
+                $share = $this->shareManager->getShareById('sciencemesh:' . $id, $this->userId);
1770
+                return $share;
1771
+            }
1772
+        } catch (ShareNotFound $e) {
1773
+            // Do nothing, just try the other share type
1774
+        }
1775
+
1776
+        if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
1777
+            throw new ShareNotFound();
1778
+        }
1779
+        $share = $this->shareManager->getShareById('ocFederatedSharing:' . $id, $this->userId);
1780
+
1781
+        return $share;
1782
+    }
1783
+
1784
+    /**
1785
+     * Lock a Node
1786
+     *
1787
+     * @param Node $node
1788
+     * @throws LockedException
1789
+     */
1790
+    private function lock(Node $node) {
1791
+        $node->lock(ILockingProvider::LOCK_SHARED);
1792
+        $this->lockedNode = $node;
1793
+    }
1794
+
1795
+    /**
1796
+     * Cleanup the remaining locks
1797
+     * @throws LockedException
1798
+     */
1799
+    public function cleanup() {
1800
+        if ($this->lockedNode !== null) {
1801
+            $this->lockedNode->unlock(ILockingProvider::LOCK_SHARED);
1802
+        }
1803
+    }
1804
+
1805
+    /**
1806
+     * Returns the helper of ShareAPIController for room shares.
1807
+     *
1808
+     * If the Talk application is not enabled or the helper is not available
1809
+     * a ContainerExceptionInterface is thrown instead.
1810
+     *
1811
+     * @return \OCA\Talk\Share\Helper\ShareAPIController
1812
+     * @throws ContainerExceptionInterface
1813
+     */
1814
+    private function getRoomShareHelper() {
1815
+        if (!$this->appManager->isEnabledForUser('spreed')) {
1816
+            throw new QueryException();
1817
+        }
1818
+
1819
+        return $this->serverContainer->get('\OCA\Talk\Share\Helper\ShareAPIController');
1820
+    }
1821
+
1822
+    /**
1823
+     * Returns the helper of ShareAPIHelper for deck shares.
1824
+     *
1825
+     * If the Deck application is not enabled or the helper is not available
1826
+     * a ContainerExceptionInterface is thrown instead.
1827
+     *
1828
+     * @return ShareAPIHelper
1829
+     * @throws ContainerExceptionInterface
1830
+     */
1831
+    private function getDeckShareHelper() {
1832
+        if (!$this->appManager->isEnabledForUser('deck')) {
1833
+            throw new QueryException();
1834
+        }
1835
+
1836
+        return $this->serverContainer->get('\OCA\Deck\Sharing\ShareAPIHelper');
1837
+    }
1838
+
1839
+    /**
1840
+     * Returns the helper of ShareAPIHelper for sciencemesh shares.
1841
+     *
1842
+     * If the sciencemesh application is not enabled or the helper is not available
1843
+     * a ContainerExceptionInterface is thrown instead.
1844
+     *
1845
+     * @return ShareAPIHelper
1846
+     * @throws ContainerExceptionInterface
1847
+     */
1848
+    private function getSciencemeshShareHelper() {
1849
+        if (!$this->appManager->isEnabledForUser('sciencemesh')) {
1850
+            throw new QueryException();
1851
+        }
1852
+
1853
+        return $this->serverContainer->get('\OCA\ScienceMesh\Sharing\ShareAPIHelper');
1854
+    }
1855
+
1856
+    /**
1857
+     * @param string $viewer
1858
+     * @param Node $node
1859
+     * @param bool $reShares
1860
+     *
1861
+     * @return IShare[]
1862
+     */
1863
+    private function getSharesFromNode(string $viewer, $node, bool $reShares): array {
1864
+        $providers = [
1865
+            IShare::TYPE_USER,
1866
+            IShare::TYPE_GROUP,
1867
+            IShare::TYPE_LINK,
1868
+            IShare::TYPE_EMAIL,
1869
+            IShare::TYPE_CIRCLE,
1870
+            IShare::TYPE_ROOM,
1871
+            IShare::TYPE_DECK,
1872
+            IShare::TYPE_SCIENCEMESH
1873
+        ];
1874
+
1875
+        // Should we assume that the (currentUser) viewer is the owner of the node !?
1876
+        $shares = [];
1877
+        foreach ($providers as $provider) {
1878
+            if (!$this->shareManager->shareProviderExists($provider)) {
1879
+                continue;
1880
+            }
1881
+
1882
+            $providerShares
1883
+                = $this->shareManager->getSharesBy($viewer, $provider, $node, $reShares, -1, 0);
1884
+            $shares = array_merge($shares, $providerShares);
1885
+        }
1886
+
1887
+        if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
1888
+            $federatedShares = $this->shareManager->getSharesBy(
1889
+                $this->userId, IShare::TYPE_REMOTE, $node, $reShares, -1, 0
1890
+            );
1891
+            $shares = array_merge($shares, $federatedShares);
1892
+        }
1893
+
1894
+        if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
1895
+            $federatedShares = $this->shareManager->getSharesBy(
1896
+                $this->userId, IShare::TYPE_REMOTE_GROUP, $node, $reShares, -1, 0
1897
+            );
1898
+            $shares = array_merge($shares, $federatedShares);
1899
+        }
1900
+
1901
+        return $shares;
1902
+    }
1903
+
1904
+
1905
+    /**
1906
+     * @param Node $node
1907
+     *
1908
+     * @throws SharingRightsException
1909
+     */
1910
+    private function confirmSharingRights(Node $node): void {
1911
+        if (!$this->hasResharingRights($this->userId, $node)) {
1912
+            throw new SharingRightsException($this->l->t('No sharing rights on this item'));
1913
+        }
1914
+    }
1915
+
1916
+
1917
+    /**
1918
+     * @param string $viewer
1919
+     * @param Node $node
1920
+     *
1921
+     * @return bool
1922
+     */
1923
+    private function hasResharingRights($viewer, $node): bool {
1924
+        if ($viewer === $node->getOwner()->getUID()) {
1925
+            return true;
1926
+        }
1927
+
1928
+        foreach ([$node, $node->getParent()] as $node) {
1929
+            $shares = $this->getSharesFromNode($viewer, $node, true);
1930
+            foreach ($shares as $share) {
1931
+                try {
1932
+                    if ($this->shareProviderResharingRights($viewer, $share, $node)) {
1933
+                        return true;
1934
+                    }
1935
+                } catch (InvalidPathException|NotFoundException $e) {
1936
+                }
1937
+            }
1938
+        }
1939
+
1940
+        return false;
1941
+    }
1942
+
1943
+
1944
+    /**
1945
+     * Returns if we can find resharing rights in an IShare object for a specific user.
1946
+     *
1947
+     * @suppress PhanUndeclaredClassMethod
1948
+     *
1949
+     * @param string $userId
1950
+     * @param IShare $share
1951
+     * @param Node $node
1952
+     *
1953
+     * @return bool
1954
+     * @throws NotFoundException
1955
+     * @throws InvalidPathException
1956
+     */
1957
+    private function shareProviderResharingRights(string $userId, IShare $share, $node): bool {
1958
+        if ($share->getShareOwner() === $userId) {
1959
+            return true;
1960
+        }
1961
+
1962
+        // we check that current user have parent resharing rights on the current file
1963
+        if ($node !== null && ($node->getPermissions() & Constants::PERMISSION_SHARE) !== 0) {
1964
+            return true;
1965
+        }
1966
+
1967
+        if ((Constants::PERMISSION_SHARE & $share->getPermissions()) === 0) {
1968
+            return false;
1969
+        }
1970
+
1971
+        if ($share->getShareType() === IShare::TYPE_USER && $share->getSharedWith() === $userId) {
1972
+            return true;
1973
+        }
1974
+
1975
+        if ($share->getShareType() === IShare::TYPE_GROUP && $this->groupManager->isInGroup($userId, $share->getSharedWith())) {
1976
+            return true;
1977
+        }
1978
+
1979
+        if ($share->getShareType() === IShare::TYPE_CIRCLE && Server::get(IAppManager::class)->isEnabledForUser('circles')
1980
+            && class_exists('\OCA\Circles\Api\v1\Circles')) {
1981
+            $hasCircleId = (str_ends_with($share->getSharedWith(), ']'));
1982
+            $shareWithStart = ($hasCircleId ? strrpos($share->getSharedWith(), '[') + 1 : 0);
1983
+            $shareWithLength = ($hasCircleId ? -1 : strpos($share->getSharedWith(), ' '));
1984
+            if ($shareWithLength === false) {
1985
+                $sharedWith = substr($share->getSharedWith(), $shareWithStart);
1986
+            } else {
1987
+                $sharedWith = substr($share->getSharedWith(), $shareWithStart, $shareWithLength);
1988
+            }
1989
+            try {
1990
+                $member = Circles::getMember($sharedWith, $userId, 1);
1991
+                if ($member->getLevel() >= 4) {
1992
+                    return true;
1993
+                }
1994
+                return false;
1995
+            } catch (ContainerExceptionInterface $e) {
1996
+                return false;
1997
+            }
1998
+        }
1999
+
2000
+        return false;
2001
+    }
2002
+
2003
+    /**
2004
+     * Get all the shares for the current user
2005
+     *
2006
+     * @param Node|null $path
2007
+     * @param boolean $reshares
2008
+     * @return IShare[]
2009
+     */
2010
+    private function getAllShares(?Node $path = null, bool $reshares = false) {
2011
+        // Get all shares
2012
+        $userShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_USER, $path, $reshares, -1, 0);
2013
+        $groupShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_GROUP, $path, $reshares, -1, 0);
2014
+        $linkShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_LINK, $path, $reshares, -1, 0);
2015
+
2016
+        // EMAIL SHARES
2017
+        $mailShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_EMAIL, $path, $reshares, -1, 0);
2018
+
2019
+        // TEAM SHARES
2020
+        $circleShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_CIRCLE, $path, $reshares, -1, 0);
2021
+
2022
+        // TALK SHARES
2023
+        $roomShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_ROOM, $path, $reshares, -1, 0);
2024
+
2025
+        // DECK SHARES
2026
+        $deckShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_DECK, $path, $reshares, -1, 0);
2027
+
2028
+        // SCIENCEMESH SHARES
2029
+        $sciencemeshShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_SCIENCEMESH, $path, $reshares, -1, 0);
2030
+
2031
+        // FEDERATION
2032
+        if ($this->shareManager->outgoingServer2ServerSharesAllowed()) {
2033
+            $federatedShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_REMOTE, $path, $reshares, -1, 0);
2034
+        } else {
2035
+            $federatedShares = [];
2036
+        }
2037
+        if ($this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
2038
+            $federatedGroupShares = $this->shareManager->getSharesBy($this->userId, IShare::TYPE_REMOTE_GROUP, $path, $reshares, -1, 0);
2039
+        } else {
2040
+            $federatedGroupShares = [];
2041
+        }
2042
+
2043
+        return array_merge($userShares, $groupShares, $linkShares, $mailShares, $circleShares, $roomShares, $deckShares, $sciencemeshShares, $federatedShares, $federatedGroupShares);
2044
+    }
2045
+
2046
+
2047
+    /**
2048
+     * merging already formatted shares.
2049
+     * We'll make an associative array to easily detect duplicate Ids.
2050
+     * Keys _needs_ to be removed after all shares are retrieved and merged.
2051
+     *
2052
+     * @param array $shares
2053
+     * @param array $newShares
2054
+     */
2055
+    private function mergeFormattedShares(array &$shares, array $newShares) {
2056
+        foreach ($newShares as $newShare) {
2057
+            if (!array_key_exists($newShare['id'], $shares)) {
2058
+                $shares[$newShare['id']] = $newShare;
2059
+            }
2060
+        }
2061
+    }
2062
+
2063
+    /**
2064
+     * @param IShare $share
2065
+     * @param string|null $attributesString
2066
+     * @return IShare modified share
2067
+     */
2068
+    private function setShareAttributes(IShare $share, ?string $attributesString) {
2069
+        $newShareAttributes = null;
2070
+        if ($attributesString !== null) {
2071
+            $newShareAttributes = $this->shareManager->newShare()->newAttributes();
2072
+            $formattedShareAttributes = \json_decode($attributesString, true);
2073
+            if (is_array($formattedShareAttributes)) {
2074
+                foreach ($formattedShareAttributes as $formattedAttr) {
2075
+                    $newShareAttributes->setAttribute(
2076
+                        $formattedAttr['scope'],
2077
+                        $formattedAttr['key'],
2078
+                        $formattedAttr['value'],
2079
+                    );
2080
+                }
2081
+            } else {
2082
+                throw new OCSBadRequestException($this->l->t('Invalid share attributes provided: "%s"', [$attributesString]));
2083
+            }
2084
+        }
2085
+        $share->setAttributes($newShareAttributes);
2086
+
2087
+        return $share;
2088
+    }
2089
+
2090
+    private function checkInheritedAttributes(IShare $share): void {
2091
+        if (!$share->getSharedBy()) {
2092
+            return; // Probably in a test
2093
+        }
2094
+
2095
+        $canDownload = false;
2096
+        $hideDownload = true;
2097
+
2098
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
2099
+        $nodes = $userFolder->getById($share->getNodeId());
2100
+        foreach ($nodes as $node) {
2101
+            // Owner always can download it - so allow it and break
2102
+            if ($node->getOwner()?->getUID() === $share->getSharedBy()) {
2103
+                $canDownload = true;
2104
+                $hideDownload = false;
2105
+                break;
2106
+            }
2107
+
2108
+            if ($node->getStorage()->instanceOfStorage(SharedStorage::class)) {
2109
+                $storage = $node->getStorage();
2110
+                if ($storage instanceof Wrapper) {
2111
+                    $storage = $storage->getInstanceOfStorage(SharedStorage::class);
2112
+                    if ($storage === null) {
2113
+                        throw new \RuntimeException('Should not happen, instanceOfStorage but getInstanceOfStorage return null');
2114
+                    }
2115
+                } else {
2116
+                    throw new \RuntimeException('Should not happen, instanceOfStorage but not a wrapper');
2117
+                }
2118
+
2119
+                /** @var SharedStorage $storage */
2120
+                $originalShare = $storage->getShare();
2121
+                $inheritedAttributes = $originalShare->getAttributes();
2122
+                // hide if hidden and also the current share enforces hide (can only be false if one share is false or user is owner)
2123
+                $hideDownload = $hideDownload && $originalShare->getHideDownload();
2124
+                // allow download if already allowed by previous share or when the current share allows downloading
2125
+                $canDownload = $canDownload || $inheritedAttributes === null || $inheritedAttributes->getAttribute('permissions', 'download') !== false;
2126
+            } elseif ($node->getStorage()->instanceOfStorage(Storage::class)) {
2127
+                $canDownload = true; // in case of federation storage, we can expect the download to be activated by default
2128
+            }
2129
+        }
2130
+
2131
+        if ($hideDownload || !$canDownload) {
2132
+            $share->setHideDownload(true);
2133
+
2134
+            if (!$canDownload) {
2135
+                $attributes = $share->getAttributes() ?? $share->newAttributes();
2136
+                $attributes->setAttribute('permissions', 'download', false);
2137
+                $share->setAttributes($attributes);
2138
+            }
2139
+        }
2140
+    }
2141
+
2142
+    /**
2143
+     * Send a mail notification again for a share.
2144
+     * The mail_send option must be enabled for the given share.
2145
+     * @param string $id the share ID
2146
+     * @param string $password the password to check against. Necessary for password protected shares.
2147
+     * @throws OCSNotFoundException Share not found
2148
+     * @throws OCSForbiddenException You are not allowed to send mail notifications
2149
+     * @throws OCSBadRequestException Invalid request or wrong password
2150
+     * @throws OCSException Error while sending mail notification
2151
+     * @return DataResponse<Http::STATUS_OK, list<empty>, array{}>
2152
+     *
2153
+     * 200: The email notification was sent successfully
2154
+     */
2155
+    #[NoAdminRequired]
2156
+    #[UserRateLimit(limit: 10, period: 600)]
2157
+    public function sendShareEmail(string $id, $password = ''): DataResponse {
2158
+        try {
2159
+            $share = $this->getShareById($id);
2160
+
2161
+            if (!$this->canAccessShare($share, false)) {
2162
+                throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
2163
+            }
2164
+
2165
+            if (!$this->canEditShare($share)) {
2166
+                throw new OCSForbiddenException($this->l->t('You are not allowed to send mail notifications'));
2167
+            }
2168
+
2169
+            // For mail and link shares, the user must be
2170
+            // the owner of the share, not only the file owner.
2171
+            if ($share->getShareType() === IShare::TYPE_EMAIL
2172
+                || $share->getShareType() === IShare::TYPE_LINK) {
2173
+                if ($share->getSharedBy() !== $this->userId) {
2174
+                    throw new OCSForbiddenException($this->l->t('You are not allowed to send mail notifications'));
2175
+                }
2176
+            }
2177
+
2178
+            try {
2179
+                $provider = $this->factory->getProviderForType($share->getShareType());
2180
+                if (!($provider instanceof IShareProviderWithNotification)) {
2181
+                    throw new OCSBadRequestException($this->l->t('No mail notification configured for this share type'));
2182
+                }
2183
+
2184
+                // Circumvent the password encrypted data by
2185
+                // setting the password clear. We're not storing
2186
+                // the password clear, it is just a temporary
2187
+                // object manipulation. The password will stay
2188
+                // encrypted in the database.
2189
+                if ($share->getPassword() !== null && $share->getPassword() !== $password) {
2190
+                    if (!$this->shareManager->checkPassword($share, $password)) {
2191
+                        throw new OCSBadRequestException($this->l->t('Wrong password'));
2192
+                    }
2193
+                    $share = $share->setPassword($password);
2194
+                }
2195
+
2196
+                $provider->sendMailNotification($share);
2197
+                return new DataResponse();
2198
+            } catch (Exception $e) {
2199
+                $this->logger->error($e->getMessage(), ['exception' => $e]);
2200
+                throw new OCSException($this->l->t('Error while sending mail notification'));
2201
+            }
2202
+
2203
+        } catch (ShareNotFound $e) {
2204
+            throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist'));
2205
+        }
2206
+    }
2207
+
2208
+    /**
2209
+     * Get a unique share token
2210
+     *
2211
+     * @throws OCSException Failed to generate a unique token
2212
+     *
2213
+     * @return DataResponse<Http::STATUS_OK, array{token: string}, array{}>
2214
+     *
2215
+     * 200: Token generated successfully
2216
+     */
2217
+    #[ApiRoute(verb: 'GET', url: '/api/v1/token')]
2218
+    #[NoAdminRequired]
2219
+    public function generateToken(): DataResponse {
2220
+        try {
2221
+            $token = $this->shareManager->generateToken();
2222
+            return new DataResponse([
2223
+                'token' => $token,
2224
+            ]);
2225
+        } catch (ShareTokenException $e) {
2226
+            throw new OCSException($this->l->t('Failed to generate a unique token'));
2227
+        }
2228
+    }
2229
+
2230
+    /**
2231
+     * Populate the result set with file tags
2232
+     *
2233
+     * @psalm-template T of array{tags?: list<string>, file_source: int, ...array<string, mixed>}
2234
+     * @param list<T> $fileList
2235
+     * @return list<T> file list populated with tags
2236
+     */
2237
+    private function populateTags(array $fileList): array {
2238
+        $tagger = $this->tagManager->load('files');
2239
+        $tags = $tagger->getTagsForObjects(array_map(static fn (array $fileData) => $fileData['file_source'], $fileList));
2240
+
2241
+        if (!is_array($tags)) {
2242
+            throw new \UnexpectedValueException('$tags must be an array');
2243
+        }
2244
+
2245
+        // Set empty tag array
2246
+        foreach ($fileList as &$fileData) {
2247
+            $fileData['tags'] = [];
2248
+        }
2249
+        unset($fileData);
2250
+
2251
+        if (!empty($tags)) {
2252
+            foreach ($tags as $fileId => $fileTags) {
2253
+                foreach ($fileList as &$fileData) {
2254
+                    if ($fileId !== $fileData['file_source']) {
2255
+                        continue;
2256
+                    }
2257
+
2258
+                    $fileData['tags'] = $fileTags;
2259
+                }
2260
+                unset($fileData);
2261
+            }
2262
+        }
2263
+
2264
+        return $fileList;
2265
+    }
2266 2266
 }
Please login to merge, or discard this patch.
apps/files_sharing/tests/ApiTest.php 1 patch
Indentation   +1434 added lines, -1434 removed lines patch added patch discarded remove patch
@@ -48,1451 +48,1451 @@
 block discarded – undo
48 48
  * TODO: convert to real integration tests
49 49
  */
50 50
 class ApiTest extends TestCase {
51
-	public const TEST_FOLDER_NAME = '/folder_share_api_test';
52
-	public const APP_NAME = 'files_sharing';
53
-
54
-	private static $tempStorage;
55
-
56
-	private Folder $userFolder;
57
-	private string $subsubfolder;
58
-	protected IAppConfig&MockObject $appConfig;
59
-
60
-	protected function setUp(): void {
61
-		parent::setUp();
62
-
63
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'no');
64
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_expire_after_n_days', '7');
65
-
66
-		Filesystem::getLoader()->removeStorageWrapper('sharing_mask');
67
-
68
-		$this->folder = self::TEST_FOLDER_NAME;
69
-		$this->subfolder = '/subfolder_share_api_test';
70
-		$this->subsubfolder = '/subsubfolder_share_api_test';
71
-
72
-		$this->filename = '/share-api-test.txt';
73
-
74
-		// save file with content
75
-		$this->view->file_put_contents($this->filename, $this->data);
76
-		$this->view->mkdir($this->folder);
77
-		$this->view->mkdir($this->folder . $this->subfolder);
78
-		$this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder);
79
-		$this->view->file_put_contents($this->folder . $this->filename, $this->data);
80
-		$this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data);
81
-		$mount = $this->view->getMount($this->filename);
82
-		$mount->getStorage()->getScanner()->scan('', Scanner::SCAN_RECURSIVE);
83
-
84
-		$this->userFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
85
-
86
-		$this->appConfig = $this->createMock(IAppConfig::class);
87
-	}
88
-
89
-	protected function tearDown(): void {
90
-		if ($this->view instanceof View) {
91
-			$this->view->unlink($this->filename);
92
-			$this->view->deleteAll($this->folder);
93
-		}
94
-
95
-		self::$tempStorage = null;
96
-
97
-		parent::tearDown();
98
-	}
99
-
100
-	/**
101
-	 * @param string $userId The userId of the caller
102
-	 * @return ShareAPIController
103
-	 */
104
-	private function createOCS($userId) {
105
-		$l = $this->getMockBuilder(IL10N::class)->getMock();
106
-		$l->method('t')
107
-			->willReturnCallback(function ($text, $parameters = []) {
108
-				return vsprintf($text, $parameters);
109
-			});
110
-		$config = $this->createMock(IConfig::class);
111
-		$appManager = $this->createMock(IAppManager::class);
112
-		$serverContainer = $this->createMock(ContainerInterface::class);
113
-		$userStatusManager = $this->createMock(IUserStatusManager::class);
114
-		$previewManager = $this->createMock(IPreview::class);
115
-		$dateTimeZone = $this->createMock(IDateTimeZone::class);
116
-		$logger = $this->createMock(LoggerInterface::class);
117
-		$providerFactory = $this->createMock(IProviderFactory::class);
118
-		$mailer = $this->createMock(IMailer::class);
119
-		$tagManager = $this->createMock(ITagManager::class);
120
-		$dateTimeZone->method('getTimeZone')->willReturn(new \DateTimeZone(date_default_timezone_get()));
121
-
122
-		return new ShareAPIController(
123
-			self::APP_NAME,
124
-			$this->getMockBuilder(IRequest::class)->getMock(),
125
-			$this->shareManager,
126
-			Server::get(IGroupManager::class),
127
-			Server::get(IUserManager::class),
128
-			Server::get(IRootFolder::class),
129
-			Server::get(IURLGenerator::class),
130
-			$l,
131
-			$config,
132
-			$this->appConfig,
133
-			$appManager,
134
-			$serverContainer,
135
-			$userStatusManager,
136
-			$previewManager,
137
-			$dateTimeZone,
138
-			$logger,
139
-			$providerFactory,
140
-			$mailer,
141
-			$tagManager,
142
-			$userId,
143
-		);
144
-	}
145
-
146
-	public function testCreateShareUserFile(): void {
147
-		$this->setUp(); // for some reasons phpunit refuses to do this for us only for this test
148
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
149
-		$result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
150
-		$ocs->cleanup();
151
-
152
-		$data = $result->getData();
153
-		$this->assertEquals(19, $data['permissions']);
154
-		$this->assertEmpty($data['expiration']);
155
-
156
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
157
-
158
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
159
-		$ocs->deleteShare($data['id']);
160
-
161
-		$ocs->cleanup();
162
-	}
163
-
164
-	public function testCreateShareUserFolder(): void {
165
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
166
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
167
-		$ocs->cleanup();
168
-
169
-		$data = $result->getData();
170
-		$this->assertEquals(31, $data['permissions']);
171
-		$this->assertEmpty($data['expiration']);
172
-
173
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
174
-
175
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
176
-		$ocs->deleteShare($data['id']);
177
-		$ocs->cleanup();
178
-	}
179
-
180
-
181
-	public function testCreateShareGroupFile(): void {
182
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
183
-		$result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_GROUP, self::TEST_FILES_SHARING_API_GROUP1);
184
-		$ocs->cleanup();
185
-
186
-		$data = $result->getData();
187
-		$this->assertEquals(19, $data['permissions']);
188
-		$this->assertEmpty($data['expiration']);
189
-
190
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
191
-
192
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
193
-		$ocs->deleteShare($data['id']);
194
-		$ocs->cleanup();
195
-	}
196
-
197
-	public function testCreateShareGroupFolder(): void {
198
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
199
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_GROUP, self::TEST_FILES_SHARING_API_GROUP1);
200
-		$ocs->cleanup();
201
-
202
-		$data = $result->getData();
203
-		$this->assertEquals(31, $data['permissions']);
204
-		$this->assertEmpty($data['expiration']);
205
-
206
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
207
-
208
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
209
-		$ocs->deleteShare($data['id']);
210
-		$ocs->cleanup();
211
-	}
212
-
213
-	/**
214
-	 * @group RoutingWeirdness
215
-	 */
216
-	public function testCreateShareLink(): void {
217
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
218
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
219
-		$ocs->cleanup();
220
-
221
-		$data = $result->getData();
222
-		$this->assertEquals(Constants::PERMISSION_ALL,
223
-			$data['permissions']);
224
-		$this->assertEmpty($data['expiration']);
225
-		$this->assertTrue(is_string($data['token']));
226
-
227
-		// check for correct link
228
-		$url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
229
-		$this->assertEquals($url, $data['url']);
230
-
231
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
232
-
233
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
234
-		$ocs->deleteShare($data['id']);
235
-		$ocs->cleanup();
236
-	}
237
-
238
-	/**
239
-	 * @group RoutingWeirdness
240
-	 * @dataProvider dataAllowFederationOnPublicShares
241
-	 */
242
-	public function testCreateShareLinkPublicUpload(array $appConfig, int $permissions): void {
243
-		$this->appConfig->method('getValueBool')
244
-			->willReturnMap([$appConfig]);
245
-
246
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
247
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
248
-		$ocs->cleanup();
249
-
250
-		$data = $result->getData();
251
-		$this->assertEquals(
252
-			Constants::PERMISSION_READ
253
-			| Constants::PERMISSION_CREATE
254
-			| Constants::PERMISSION_UPDATE
255
-			| Constants::PERMISSION_DELETE
256
-			| $permissions,
257
-			$data['permissions']
258
-		);
259
-		$this->assertEmpty($data['expiration']);
260
-		$this->assertTrue(is_string($data['token']));
261
-
262
-		// check for correct link
263
-		$url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
264
-		$this->assertEquals($url, $data['url']);
265
-
266
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
267
-
268
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
269
-		$ocs->deleteShare($data['id']);
270
-		$ocs->cleanup();
271
-	}
272
-
273
-	public function testEnforceLinkPassword(): void {
274
-		$password = md5(time());
275
-		$config = Server::get(IConfig::class);
276
-		$config->setAppValue('core', 'shareapi_enforce_links_password', 'yes');
277
-
278
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
279
-		try {
280
-			$ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
281
-			$this->fail();
282
-		} catch (OCSForbiddenException $e) {
283
-		}
284
-		$ocs->cleanup();
285
-
286
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
287
-		try {
288
-			$ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '');
289
-			$this->fail();
290
-		} catch (OCSForbiddenException $e) {
291
-		}
292
-		$ocs->cleanup();
293
-
294
-		// share with password should succeed
295
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
296
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', $password);
297
-		$ocs->cleanup();
298
-
299
-		$data = $result->getData();
300
-
301
-		// setting new password should succeed
302
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
303
-		$ocs->updateShare($data['id'], null, $password);
304
-		$ocs->cleanup();
305
-
306
-		// removing password should fail
307
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
308
-		try {
309
-			$ocs->updateShare($data['id']);
310
-			$this->fail();
311
-		} catch (OCSBadRequestException $e) {
312
-		}
313
-		$ocs->cleanup();
314
-
315
-		// cleanup
316
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
317
-		$ocs->deleteShare($data['id']);
318
-		$ocs->cleanup();
319
-
320
-		$config->setAppValue('core', 'shareapi_enforce_links_password', 'no');
321
-		$this->addToAssertionCount(1);
322
-	}
323
-
324
-	/**
325
-	 * @medium
326
-	 */
327
-	public function testSharePermissions(): void {
328
-		// sharing file to a user should work if shareapi_exclude_groups is set
329
-		// to no
330
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'no');
331
-
332
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
333
-		$result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
334
-		$ocs->cleanup();
335
-
336
-		$data = $result->getData();
337
-
338
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
339
-
340
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
341
-		$ocs->deleteShare($data['id']);
342
-		$ocs->cleanup();
343
-
344
-		// exclude groups, but not the group the user belongs to. Sharing should still work
345
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'yes');
346
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups_list', 'admin,group1,group2');
347
-
348
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
349
-		$result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
350
-		$ocs->cleanup();
351
-
352
-		$data = $result->getData();
353
-
354
-		$this->shareManager->getShareById('ocinternal:' . $data['id']);
355
-
356
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
357
-		$ocs->deleteShare($data['id']);
358
-		$ocs->cleanup();
359
-
360
-		// now we exclude the group the user belongs to ('group'), sharing should fail now
361
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups_list', 'admin,group');
362
-
363
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
364
-		$ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
365
-		$ocs->cleanup();
366
-
367
-		// cleanup
368
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'no');
369
-		Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups_list', '');
370
-
371
-		$this->addToAssertionCount(1);
372
-	}
373
-
374
-
375
-	/**
376
-	 * @medium
377
-	 */
378
-	public function testGetAllShares(): void {
379
-		$node = $this->userFolder->get($this->filename);
380
-
381
-		$share = $this->shareManager->newShare();
382
-		$share->setNode($node)
383
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
384
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
385
-			->setShareType(IShare::TYPE_USER)
386
-			->setPermissions(19);
387
-
388
-		$share = $this->shareManager->createShare($share);
389
-
390
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
391
-		$result = $ocs->getShares();
392
-		$ocs->cleanup();
393
-
394
-		$this->assertTrue(count($result->getData()) === 1);
395
-
396
-		$this->shareManager->deleteShare($share);
397
-	}
398
-
399
-	public function testGetAllSharesWithMe(): void {
400
-		$this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
401
-		$this->logout();
402
-
403
-		$node1 = $this->userFolder->get($this->filename);
404
-		$share1 = $this->shareManager->newShare();
405
-		$share1->setNode($node1)
406
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
407
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
408
-			->setShareType(IShare::TYPE_USER)
409
-			->setPermissions(19);
410
-		$share1 = $this->shareManager->createShare($share1);
411
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
412
-		$this->shareManager->updateShare($share1);
413
-
414
-		$node2 = $this->userFolder->get($this->folder);
415
-		$share2 = $this->shareManager->newShare();
416
-		$share2->setNode($node2)
417
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
418
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
419
-			->setShareType(IShare::TYPE_USER)
420
-			->setPermissions(31);
421
-		$share2 = $this->shareManager->createShare($share2);
422
-		$share2->setStatus(IShare::STATUS_ACCEPTED);
423
-		$this->shareManager->updateShare($share2);
424
-
425
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
426
-		$result = $ocs->getShares('true');
427
-		$ocs->cleanup();
428
-
429
-		$this->assertCount(2, $result->getData());
430
-
431
-		$this->shareManager->deleteShare($share1);
432
-		$this->shareManager->deleteShare($share2);
433
-	}
434
-
435
-	/**
436
-	 * @medium
437
-	 * @group RoutingWeirdness
438
-	 */
439
-	public function testPublicLinkUrl(): void {
440
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
441
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
442
-		$ocs->cleanup();
443
-
444
-		$data = $result->getData();
445
-
446
-		// check if we have a token
447
-		$this->assertTrue(is_string($data['token']));
448
-		$id = $data['id'];
449
-
450
-		// check for correct link
451
-		$url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
452
-		$this->assertEquals($url, $data['url']);
453
-
454
-		// check for link in getall shares
455
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
456
-		$result = $ocs->getShares();
457
-		$ocs->cleanup();
458
-
459
-		$data = $result->getData();
460
-		$this->assertEquals($url, current($data)['url']);
461
-
462
-		// check for path
463
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
464
-		$result = $ocs->getShares();
465
-		$ocs->cleanup();
466
-
467
-		$data = $result->getData();
468
-		$this->assertEquals($url, current($data)['url']);
469
-
470
-		// check in share id
471
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
472
-		$result = $ocs->getShare($id);
473
-		$ocs->cleanup();
474
-
475
-		$data = $result->getData();
476
-		$this->assertEquals($url, current($data)['url']);
477
-
478
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
479
-		$ocs->deleteShare($id);
480
-		$ocs->cleanup();
481
-	}
482
-
483
-	/**
484
-	 * @medium
485
-	 * @depends testCreateShareUserFile
486
-	 * @depends testCreateShareLink
487
-	 */
488
-	public function testGetShareFromSource(): void {
489
-		$node = $this->userFolder->get($this->filename);
490
-		$share = $this->shareManager->newShare();
491
-		$share->setNode($node)
492
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
493
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
494
-			->setShareType(IShare::TYPE_USER)
495
-			->setPermissions(19);
496
-		$share1 = $this->shareManager->createShare($share);
497
-
498
-		$share = $this->shareManager->newShare();
499
-		$share->setNode($node)
500
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
501
-			->setShareType(IShare::TYPE_LINK)
502
-			->setPermissions(1);
503
-		$share2 = $this->shareManager->createShare($share);
504
-
505
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
506
-		$result = $ocs->getShares();
507
-		$ocs->cleanup();
508
-
509
-		// test should return one share created from testCreateShare()
510
-		$this->assertTrue(count($result->getData()) === 2);
511
-
512
-		$this->shareManager->deleteShare($share1);
513
-		$this->shareManager->deleteShare($share2);
514
-	}
515
-
516
-	/**
517
-	 * @medium
518
-	 * @depends testCreateShareUserFile
519
-	 * @depends testCreateShareLink
520
-	 */
521
-	public function testGetShareFromSourceWithReshares(): void {
522
-		$node = $this->userFolder->get($this->filename);
523
-		$share1 = $this->shareManager->newShare();
524
-		$share1->setNode($node)
525
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
526
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
527
-			->setShareType(IShare::TYPE_USER)
528
-			->setPermissions(19);
529
-		$share1 = $this->shareManager->createShare($share1);
530
-
531
-		$share2 = $this->shareManager->newShare();
532
-		$share2->setNode($node)
533
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
534
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
535
-			->setShareType(IShare::TYPE_USER)
536
-			->setPermissions(19);
537
-		$share2 = $this->shareManager->createShare($share2);
538
-
539
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
540
-		$result = $ocs->getShares();
541
-		$ocs->cleanup();
542
-
543
-		// test should return one share
544
-		$this->assertTrue(count($result->getData()) === 1);
545
-
546
-		// now also ask for the reshares
547
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
548
-		$result = $ocs->getShares('false', 'true', 'false', $this->filename);
549
-		$ocs->cleanup();
550
-
551
-		// now we should get two shares, the initial share and the reshare
552
-		$this->assertCount(2, $result->getData());
553
-
554
-		$this->shareManager->deleteShare($share1);
555
-		$this->shareManager->deleteShare($share2);
556
-	}
557
-
558
-	/**
559
-	 * @medium
560
-	 * @depends testCreateShareUserFile
561
-	 */
562
-	public function testGetShareFromId(): void {
563
-		$node = $this->userFolder->get($this->filename);
564
-		$share1 = $this->shareManager->newShare();
565
-		$share1->setNode($node)
566
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
567
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
568
-			->setShareType(IShare::TYPE_USER)
569
-			->setPermissions(19);
570
-		$share1 = $this->shareManager->createShare($share1);
571
-
572
-		// call getShare() with share ID
573
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
574
-		$result = $ocs->getShare($share1->getId());
575
-		$ocs->cleanup();
576
-
577
-		// test should return one share created from testCreateShare()
578
-		$this->assertEquals(1, count($result->getData()));
579
-
580
-		$this->shareManager->deleteShare($share1);
581
-	}
582
-
583
-	/**
584
-	 * @medium
585
-	 */
586
-	public function testGetShareFromFolder(): void {
587
-		$node1 = $this->userFolder->get($this->filename);
588
-		$share1 = $this->shareManager->newShare();
589
-		$share1->setNode($node1)
590
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
591
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
592
-			->setShareType(IShare::TYPE_USER)
593
-			->setPermissions(19);
594
-		$share1 = $this->shareManager->createShare($share1);
595
-
596
-		$node2 = $this->userFolder->get($this->folder . '/' . $this->filename);
597
-		$share2 = $this->shareManager->newShare();
598
-		$share2->setNode($node2)
599
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
600
-			->setShareType(IShare::TYPE_LINK)
601
-			->setPermissions(1);
602
-		$share2 = $this->shareManager->createShare($share2);
603
-
604
-
605
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
606
-		$result = $ocs->getShares('false', 'false', 'true', $this->folder);
607
-		$ocs->cleanup();
608
-
609
-		// test should return one share within $this->folder
610
-		$this->assertTrue(count($result->getData()) === 1);
611
-
612
-		$this->shareManager->deleteShare($share1);
613
-		$this->shareManager->deleteShare($share2);
614
-	}
615
-
616
-	public function testGetShareFromFolderWithFile(): void {
617
-		$node1 = $this->userFolder->get($this->filename);
618
-		$share1 = $this->shareManager->newShare();
619
-		$share1->setNode($node1)
620
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
621
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
622
-			->setShareType(IShare::TYPE_USER)
623
-			->setPermissions(19);
624
-		$share1 = $this->shareManager->createShare($share1);
625
-
626
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
627
-		try {
628
-			$ocs->getShares('false', 'false', 'true', $this->filename);
629
-			$this->fail();
630
-		} catch (OCSBadRequestException $e) {
631
-			$this->assertEquals('Not a directory', $e->getMessage());
632
-		}
633
-		$ocs->cleanup();
634
-
635
-		$this->shareManager->deleteShare($share1);
636
-	}
637
-
638
-	/**
639
-	 * share a folder, than reshare a file within the shared folder and check if we construct the correct path
640
-	 * @medium
641
-	 */
642
-	public function testGetShareFromFolderReshares(): void {
643
-		$node1 = $this->userFolder->get($this->folder);
644
-		$share1 = $this->shareManager->newShare();
645
-		$share1->setNode($node1)
646
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
647
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
648
-			->setShareType(IShare::TYPE_USER)
649
-			->setPermissions(31);
650
-		$share1 = $this->shareManager->createShare($share1);
651
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
652
-		$this->shareManager->updateShare($share1);
653
-
654
-		$node2 = $this->userFolder->get($this->folder . '/' . $this->filename);
655
-		$share2 = $this->shareManager->newShare();
656
-		$share2->setNode($node2)
657
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
658
-			->setShareType(IShare::TYPE_LINK)
659
-			->setPermissions(1);
660
-		$share2 = $this->shareManager->createShare($share2);
661
-		$share2->setStatus(IShare::STATUS_ACCEPTED);
662
-		$this->shareManager->updateShare($share2);
663
-
664
-		$node3 = $this->userFolder->get($this->folder . '/' . $this->subfolder . '/' . $this->filename);
665
-		$share3 = $this->shareManager->newShare();
666
-		$share3->setNode($node3)
667
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
668
-			->setShareType(IShare::TYPE_LINK)
669
-			->setPermissions(1);
670
-		$share3 = $this->shareManager->createShare($share3);
671
-		$share3->setStatus(IShare::STATUS_ACCEPTED);
672
-		$this->shareManager->updateShare($share3);
673
-
674
-		$testValues = [
675
-			['query' => $this->folder,
676
-				'expectedResult' => $this->folder . $this->filename],
677
-			['query' => $this->folder . $this->subfolder,
678
-				'expectedResult' => $this->folder . $this->subfolder . $this->filename],
679
-		];
680
-
681
-		foreach ($testValues as $value) {
682
-			$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
683
-			$result = $ocs->getShares('false', 'false', 'true', $value['query']);
684
-			$ocs->cleanup();
685
-
686
-			// test should return one share within $this->folder
687
-			$data = $result->getData();
688
-
689
-			$this->assertEquals($value['expectedResult'], $data[0]['path']);
690
-		}
691
-
692
-		// cleanup
693
-		$this->shareManager->deleteShare($share1);
694
-		$this->shareManager->deleteShare($share2);
695
-		$this->shareManager->deleteShare($share3);
696
-	}
697
-
698
-	/**
699
-	 * reshare a sub folder and check if we get the correct path
700
-	 * @medium
701
-	 */
702
-	public function testGetShareFromSubFolderReShares(): void {
703
-		$node1 = $this->userFolder->get($this->folder . $this->subfolder);
704
-		$share1 = $this->shareManager->newShare();
705
-		$share1->setNode($node1)
706
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
707
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
708
-			->setShareType(IShare::TYPE_USER)
709
-			->setPermissions(31);
710
-		$share1 = $this->shareManager->createShare($share1);
711
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
712
-		$this->shareManager->updateShare($share1);
713
-
714
-		$node2 = Server::get(IRootFolder::class)->getUserFolder(self::TEST_FILES_SHARING_API_USER2)->get($this->subfolder);
715
-		$share2 = $this->shareManager->newShare();
716
-		$share2->setNode($node2)
717
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
718
-			->setShareType(IShare::TYPE_LINK)
719
-			->setPermissions(1);
720
-		$share2 = $this->shareManager->createShare($share2);
721
-		$share2->setStatus(IShare::STATUS_ACCEPTED);
722
-		$this->shareManager->updateShare($share2);
723
-
724
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
725
-		$result = $ocs->getShares();
726
-		$ocs->cleanup();
727
-
728
-		// test should return one share within $this->folder
729
-		$data = $result->getData();
730
-
731
-		// we should get exactly one result
732
-		$this->assertCount(1, $data);
733
-
734
-		$this->assertEquals($this->subfolder, $data[0]['path']);
735
-
736
-		$this->shareManager->deleteShare($share2);
737
-		$this->shareManager->deleteShare($share1);
738
-	}
739
-
740
-	/**
741
-	 * test re-re-share of folder if the path gets constructed correctly
742
-	 * @medium
743
-	 */
744
-	public function XtestGetShareFromFolderReReShares() {
745
-		$node1 = $this->userFolder->get($this->folder . $this->subfolder);
746
-		$share1 = $this->shareManager->newShare();
747
-		$share1->setNode($node1)
748
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
749
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
750
-			->setShareType(IShare::TYPE_USER)
751
-			->setPermissions(31);
752
-		$share1 = $this->shareManager->createShare($share1);
753
-
754
-		$node2 = $this->userFolder->get($this->folder . $this->subfolder . $this->subsubfolder);
755
-		$share2 = $this->shareManager->newShare();
756
-		$share2->setNode($node2)
757
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
758
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
759
-			->setShareType(IShare::TYPE_USER)
760
-			->setPermissions(31);
761
-		$share2 = $this->shareManager->createShare($share2);
762
-
763
-		$share3 = $this->shareManager->newShare();
764
-		$share3->setNode($node2)
765
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER3)
766
-			->setShareType(IShare::TYPE_LINK)
767
-			->setPermissions(1);
768
-		$share3 = $this->shareManager->createShare($share3);
769
-
770
-		/*
51
+    public const TEST_FOLDER_NAME = '/folder_share_api_test';
52
+    public const APP_NAME = 'files_sharing';
53
+
54
+    private static $tempStorage;
55
+
56
+    private Folder $userFolder;
57
+    private string $subsubfolder;
58
+    protected IAppConfig&MockObject $appConfig;
59
+
60
+    protected function setUp(): void {
61
+        parent::setUp();
62
+
63
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'no');
64
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_expire_after_n_days', '7');
65
+
66
+        Filesystem::getLoader()->removeStorageWrapper('sharing_mask');
67
+
68
+        $this->folder = self::TEST_FOLDER_NAME;
69
+        $this->subfolder = '/subfolder_share_api_test';
70
+        $this->subsubfolder = '/subsubfolder_share_api_test';
71
+
72
+        $this->filename = '/share-api-test.txt';
73
+
74
+        // save file with content
75
+        $this->view->file_put_contents($this->filename, $this->data);
76
+        $this->view->mkdir($this->folder);
77
+        $this->view->mkdir($this->folder . $this->subfolder);
78
+        $this->view->mkdir($this->folder . $this->subfolder . $this->subsubfolder);
79
+        $this->view->file_put_contents($this->folder . $this->filename, $this->data);
80
+        $this->view->file_put_contents($this->folder . $this->subfolder . $this->filename, $this->data);
81
+        $mount = $this->view->getMount($this->filename);
82
+        $mount->getStorage()->getScanner()->scan('', Scanner::SCAN_RECURSIVE);
83
+
84
+        $this->userFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
85
+
86
+        $this->appConfig = $this->createMock(IAppConfig::class);
87
+    }
88
+
89
+    protected function tearDown(): void {
90
+        if ($this->view instanceof View) {
91
+            $this->view->unlink($this->filename);
92
+            $this->view->deleteAll($this->folder);
93
+        }
94
+
95
+        self::$tempStorage = null;
96
+
97
+        parent::tearDown();
98
+    }
99
+
100
+    /**
101
+     * @param string $userId The userId of the caller
102
+     * @return ShareAPIController
103
+     */
104
+    private function createOCS($userId) {
105
+        $l = $this->getMockBuilder(IL10N::class)->getMock();
106
+        $l->method('t')
107
+            ->willReturnCallback(function ($text, $parameters = []) {
108
+                return vsprintf($text, $parameters);
109
+            });
110
+        $config = $this->createMock(IConfig::class);
111
+        $appManager = $this->createMock(IAppManager::class);
112
+        $serverContainer = $this->createMock(ContainerInterface::class);
113
+        $userStatusManager = $this->createMock(IUserStatusManager::class);
114
+        $previewManager = $this->createMock(IPreview::class);
115
+        $dateTimeZone = $this->createMock(IDateTimeZone::class);
116
+        $logger = $this->createMock(LoggerInterface::class);
117
+        $providerFactory = $this->createMock(IProviderFactory::class);
118
+        $mailer = $this->createMock(IMailer::class);
119
+        $tagManager = $this->createMock(ITagManager::class);
120
+        $dateTimeZone->method('getTimeZone')->willReturn(new \DateTimeZone(date_default_timezone_get()));
121
+
122
+        return new ShareAPIController(
123
+            self::APP_NAME,
124
+            $this->getMockBuilder(IRequest::class)->getMock(),
125
+            $this->shareManager,
126
+            Server::get(IGroupManager::class),
127
+            Server::get(IUserManager::class),
128
+            Server::get(IRootFolder::class),
129
+            Server::get(IURLGenerator::class),
130
+            $l,
131
+            $config,
132
+            $this->appConfig,
133
+            $appManager,
134
+            $serverContainer,
135
+            $userStatusManager,
136
+            $previewManager,
137
+            $dateTimeZone,
138
+            $logger,
139
+            $providerFactory,
140
+            $mailer,
141
+            $tagManager,
142
+            $userId,
143
+        );
144
+    }
145
+
146
+    public function testCreateShareUserFile(): void {
147
+        $this->setUp(); // for some reasons phpunit refuses to do this for us only for this test
148
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
149
+        $result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
150
+        $ocs->cleanup();
151
+
152
+        $data = $result->getData();
153
+        $this->assertEquals(19, $data['permissions']);
154
+        $this->assertEmpty($data['expiration']);
155
+
156
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
157
+
158
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
159
+        $ocs->deleteShare($data['id']);
160
+
161
+        $ocs->cleanup();
162
+    }
163
+
164
+    public function testCreateShareUserFolder(): void {
165
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
166
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
167
+        $ocs->cleanup();
168
+
169
+        $data = $result->getData();
170
+        $this->assertEquals(31, $data['permissions']);
171
+        $this->assertEmpty($data['expiration']);
172
+
173
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
174
+
175
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
176
+        $ocs->deleteShare($data['id']);
177
+        $ocs->cleanup();
178
+    }
179
+
180
+
181
+    public function testCreateShareGroupFile(): void {
182
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
183
+        $result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_GROUP, self::TEST_FILES_SHARING_API_GROUP1);
184
+        $ocs->cleanup();
185
+
186
+        $data = $result->getData();
187
+        $this->assertEquals(19, $data['permissions']);
188
+        $this->assertEmpty($data['expiration']);
189
+
190
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
191
+
192
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
193
+        $ocs->deleteShare($data['id']);
194
+        $ocs->cleanup();
195
+    }
196
+
197
+    public function testCreateShareGroupFolder(): void {
198
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
199
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_GROUP, self::TEST_FILES_SHARING_API_GROUP1);
200
+        $ocs->cleanup();
201
+
202
+        $data = $result->getData();
203
+        $this->assertEquals(31, $data['permissions']);
204
+        $this->assertEmpty($data['expiration']);
205
+
206
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
207
+
208
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
209
+        $ocs->deleteShare($data['id']);
210
+        $ocs->cleanup();
211
+    }
212
+
213
+    /**
214
+     * @group RoutingWeirdness
215
+     */
216
+    public function testCreateShareLink(): void {
217
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
218
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
219
+        $ocs->cleanup();
220
+
221
+        $data = $result->getData();
222
+        $this->assertEquals(Constants::PERMISSION_ALL,
223
+            $data['permissions']);
224
+        $this->assertEmpty($data['expiration']);
225
+        $this->assertTrue(is_string($data['token']));
226
+
227
+        // check for correct link
228
+        $url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
229
+        $this->assertEquals($url, $data['url']);
230
+
231
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
232
+
233
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
234
+        $ocs->deleteShare($data['id']);
235
+        $ocs->cleanup();
236
+    }
237
+
238
+    /**
239
+     * @group RoutingWeirdness
240
+     * @dataProvider dataAllowFederationOnPublicShares
241
+     */
242
+    public function testCreateShareLinkPublicUpload(array $appConfig, int $permissions): void {
243
+        $this->appConfig->method('getValueBool')
244
+            ->willReturnMap([$appConfig]);
245
+
246
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
247
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
248
+        $ocs->cleanup();
249
+
250
+        $data = $result->getData();
251
+        $this->assertEquals(
252
+            Constants::PERMISSION_READ
253
+            | Constants::PERMISSION_CREATE
254
+            | Constants::PERMISSION_UPDATE
255
+            | Constants::PERMISSION_DELETE
256
+            | $permissions,
257
+            $data['permissions']
258
+        );
259
+        $this->assertEmpty($data['expiration']);
260
+        $this->assertTrue(is_string($data['token']));
261
+
262
+        // check for correct link
263
+        $url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
264
+        $this->assertEquals($url, $data['url']);
265
+
266
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
267
+
268
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
269
+        $ocs->deleteShare($data['id']);
270
+        $ocs->cleanup();
271
+    }
272
+
273
+    public function testEnforceLinkPassword(): void {
274
+        $password = md5(time());
275
+        $config = Server::get(IConfig::class);
276
+        $config->setAppValue('core', 'shareapi_enforce_links_password', 'yes');
277
+
278
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
279
+        try {
280
+            $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
281
+            $this->fail();
282
+        } catch (OCSForbiddenException $e) {
283
+        }
284
+        $ocs->cleanup();
285
+
286
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
287
+        try {
288
+            $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '');
289
+            $this->fail();
290
+        } catch (OCSForbiddenException $e) {
291
+        }
292
+        $ocs->cleanup();
293
+
294
+        // share with password should succeed
295
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
296
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', $password);
297
+        $ocs->cleanup();
298
+
299
+        $data = $result->getData();
300
+
301
+        // setting new password should succeed
302
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
303
+        $ocs->updateShare($data['id'], null, $password);
304
+        $ocs->cleanup();
305
+
306
+        // removing password should fail
307
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
308
+        try {
309
+            $ocs->updateShare($data['id']);
310
+            $this->fail();
311
+        } catch (OCSBadRequestException $e) {
312
+        }
313
+        $ocs->cleanup();
314
+
315
+        // cleanup
316
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
317
+        $ocs->deleteShare($data['id']);
318
+        $ocs->cleanup();
319
+
320
+        $config->setAppValue('core', 'shareapi_enforce_links_password', 'no');
321
+        $this->addToAssertionCount(1);
322
+    }
323
+
324
+    /**
325
+     * @medium
326
+     */
327
+    public function testSharePermissions(): void {
328
+        // sharing file to a user should work if shareapi_exclude_groups is set
329
+        // to no
330
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'no');
331
+
332
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
333
+        $result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
334
+        $ocs->cleanup();
335
+
336
+        $data = $result->getData();
337
+
338
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
339
+
340
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
341
+        $ocs->deleteShare($data['id']);
342
+        $ocs->cleanup();
343
+
344
+        // exclude groups, but not the group the user belongs to. Sharing should still work
345
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'yes');
346
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups_list', 'admin,group1,group2');
347
+
348
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
349
+        $result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
350
+        $ocs->cleanup();
351
+
352
+        $data = $result->getData();
353
+
354
+        $this->shareManager->getShareById('ocinternal:' . $data['id']);
355
+
356
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
357
+        $ocs->deleteShare($data['id']);
358
+        $ocs->cleanup();
359
+
360
+        // now we exclude the group the user belongs to ('group'), sharing should fail now
361
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups_list', 'admin,group');
362
+
363
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
364
+        $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
365
+        $ocs->cleanup();
366
+
367
+        // cleanup
368
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups', 'no');
369
+        Server::get(IConfig::class)->setAppValue('core', 'shareapi_exclude_groups_list', '');
370
+
371
+        $this->addToAssertionCount(1);
372
+    }
373
+
374
+
375
+    /**
376
+     * @medium
377
+     */
378
+    public function testGetAllShares(): void {
379
+        $node = $this->userFolder->get($this->filename);
380
+
381
+        $share = $this->shareManager->newShare();
382
+        $share->setNode($node)
383
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
384
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
385
+            ->setShareType(IShare::TYPE_USER)
386
+            ->setPermissions(19);
387
+
388
+        $share = $this->shareManager->createShare($share);
389
+
390
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
391
+        $result = $ocs->getShares();
392
+        $ocs->cleanup();
393
+
394
+        $this->assertTrue(count($result->getData()) === 1);
395
+
396
+        $this->shareManager->deleteShare($share);
397
+    }
398
+
399
+    public function testGetAllSharesWithMe(): void {
400
+        $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
401
+        $this->logout();
402
+
403
+        $node1 = $this->userFolder->get($this->filename);
404
+        $share1 = $this->shareManager->newShare();
405
+        $share1->setNode($node1)
406
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
407
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
408
+            ->setShareType(IShare::TYPE_USER)
409
+            ->setPermissions(19);
410
+        $share1 = $this->shareManager->createShare($share1);
411
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
412
+        $this->shareManager->updateShare($share1);
413
+
414
+        $node2 = $this->userFolder->get($this->folder);
415
+        $share2 = $this->shareManager->newShare();
416
+        $share2->setNode($node2)
417
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
418
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
419
+            ->setShareType(IShare::TYPE_USER)
420
+            ->setPermissions(31);
421
+        $share2 = $this->shareManager->createShare($share2);
422
+        $share2->setStatus(IShare::STATUS_ACCEPTED);
423
+        $this->shareManager->updateShare($share2);
424
+
425
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
426
+        $result = $ocs->getShares('true');
427
+        $ocs->cleanup();
428
+
429
+        $this->assertCount(2, $result->getData());
430
+
431
+        $this->shareManager->deleteShare($share1);
432
+        $this->shareManager->deleteShare($share2);
433
+    }
434
+
435
+    /**
436
+     * @medium
437
+     * @group RoutingWeirdness
438
+     */
439
+    public function testPublicLinkUrl(): void {
440
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
441
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
442
+        $ocs->cleanup();
443
+
444
+        $data = $result->getData();
445
+
446
+        // check if we have a token
447
+        $this->assertTrue(is_string($data['token']));
448
+        $id = $data['id'];
449
+
450
+        // check for correct link
451
+        $url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
452
+        $this->assertEquals($url, $data['url']);
453
+
454
+        // check for link in getall shares
455
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
456
+        $result = $ocs->getShares();
457
+        $ocs->cleanup();
458
+
459
+        $data = $result->getData();
460
+        $this->assertEquals($url, current($data)['url']);
461
+
462
+        // check for path
463
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
464
+        $result = $ocs->getShares();
465
+        $ocs->cleanup();
466
+
467
+        $data = $result->getData();
468
+        $this->assertEquals($url, current($data)['url']);
469
+
470
+        // check in share id
471
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
472
+        $result = $ocs->getShare($id);
473
+        $ocs->cleanup();
474
+
475
+        $data = $result->getData();
476
+        $this->assertEquals($url, current($data)['url']);
477
+
478
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
479
+        $ocs->deleteShare($id);
480
+        $ocs->cleanup();
481
+    }
482
+
483
+    /**
484
+     * @medium
485
+     * @depends testCreateShareUserFile
486
+     * @depends testCreateShareLink
487
+     */
488
+    public function testGetShareFromSource(): void {
489
+        $node = $this->userFolder->get($this->filename);
490
+        $share = $this->shareManager->newShare();
491
+        $share->setNode($node)
492
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
493
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
494
+            ->setShareType(IShare::TYPE_USER)
495
+            ->setPermissions(19);
496
+        $share1 = $this->shareManager->createShare($share);
497
+
498
+        $share = $this->shareManager->newShare();
499
+        $share->setNode($node)
500
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
501
+            ->setShareType(IShare::TYPE_LINK)
502
+            ->setPermissions(1);
503
+        $share2 = $this->shareManager->createShare($share);
504
+
505
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
506
+        $result = $ocs->getShares();
507
+        $ocs->cleanup();
508
+
509
+        // test should return one share created from testCreateShare()
510
+        $this->assertTrue(count($result->getData()) === 2);
511
+
512
+        $this->shareManager->deleteShare($share1);
513
+        $this->shareManager->deleteShare($share2);
514
+    }
515
+
516
+    /**
517
+     * @medium
518
+     * @depends testCreateShareUserFile
519
+     * @depends testCreateShareLink
520
+     */
521
+    public function testGetShareFromSourceWithReshares(): void {
522
+        $node = $this->userFolder->get($this->filename);
523
+        $share1 = $this->shareManager->newShare();
524
+        $share1->setNode($node)
525
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
526
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
527
+            ->setShareType(IShare::TYPE_USER)
528
+            ->setPermissions(19);
529
+        $share1 = $this->shareManager->createShare($share1);
530
+
531
+        $share2 = $this->shareManager->newShare();
532
+        $share2->setNode($node)
533
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
534
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
535
+            ->setShareType(IShare::TYPE_USER)
536
+            ->setPermissions(19);
537
+        $share2 = $this->shareManager->createShare($share2);
538
+
539
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
540
+        $result = $ocs->getShares();
541
+        $ocs->cleanup();
542
+
543
+        // test should return one share
544
+        $this->assertTrue(count($result->getData()) === 1);
545
+
546
+        // now also ask for the reshares
547
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
548
+        $result = $ocs->getShares('false', 'true', 'false', $this->filename);
549
+        $ocs->cleanup();
550
+
551
+        // now we should get two shares, the initial share and the reshare
552
+        $this->assertCount(2, $result->getData());
553
+
554
+        $this->shareManager->deleteShare($share1);
555
+        $this->shareManager->deleteShare($share2);
556
+    }
557
+
558
+    /**
559
+     * @medium
560
+     * @depends testCreateShareUserFile
561
+     */
562
+    public function testGetShareFromId(): void {
563
+        $node = $this->userFolder->get($this->filename);
564
+        $share1 = $this->shareManager->newShare();
565
+        $share1->setNode($node)
566
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
567
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
568
+            ->setShareType(IShare::TYPE_USER)
569
+            ->setPermissions(19);
570
+        $share1 = $this->shareManager->createShare($share1);
571
+
572
+        // call getShare() with share ID
573
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
574
+        $result = $ocs->getShare($share1->getId());
575
+        $ocs->cleanup();
576
+
577
+        // test should return one share created from testCreateShare()
578
+        $this->assertEquals(1, count($result->getData()));
579
+
580
+        $this->shareManager->deleteShare($share1);
581
+    }
582
+
583
+    /**
584
+     * @medium
585
+     */
586
+    public function testGetShareFromFolder(): void {
587
+        $node1 = $this->userFolder->get($this->filename);
588
+        $share1 = $this->shareManager->newShare();
589
+        $share1->setNode($node1)
590
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
591
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
592
+            ->setShareType(IShare::TYPE_USER)
593
+            ->setPermissions(19);
594
+        $share1 = $this->shareManager->createShare($share1);
595
+
596
+        $node2 = $this->userFolder->get($this->folder . '/' . $this->filename);
597
+        $share2 = $this->shareManager->newShare();
598
+        $share2->setNode($node2)
599
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
600
+            ->setShareType(IShare::TYPE_LINK)
601
+            ->setPermissions(1);
602
+        $share2 = $this->shareManager->createShare($share2);
603
+
604
+
605
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
606
+        $result = $ocs->getShares('false', 'false', 'true', $this->folder);
607
+        $ocs->cleanup();
608
+
609
+        // test should return one share within $this->folder
610
+        $this->assertTrue(count($result->getData()) === 1);
611
+
612
+        $this->shareManager->deleteShare($share1);
613
+        $this->shareManager->deleteShare($share2);
614
+    }
615
+
616
+    public function testGetShareFromFolderWithFile(): void {
617
+        $node1 = $this->userFolder->get($this->filename);
618
+        $share1 = $this->shareManager->newShare();
619
+        $share1->setNode($node1)
620
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
621
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
622
+            ->setShareType(IShare::TYPE_USER)
623
+            ->setPermissions(19);
624
+        $share1 = $this->shareManager->createShare($share1);
625
+
626
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
627
+        try {
628
+            $ocs->getShares('false', 'false', 'true', $this->filename);
629
+            $this->fail();
630
+        } catch (OCSBadRequestException $e) {
631
+            $this->assertEquals('Not a directory', $e->getMessage());
632
+        }
633
+        $ocs->cleanup();
634
+
635
+        $this->shareManager->deleteShare($share1);
636
+    }
637
+
638
+    /**
639
+     * share a folder, than reshare a file within the shared folder and check if we construct the correct path
640
+     * @medium
641
+     */
642
+    public function testGetShareFromFolderReshares(): void {
643
+        $node1 = $this->userFolder->get($this->folder);
644
+        $share1 = $this->shareManager->newShare();
645
+        $share1->setNode($node1)
646
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
647
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
648
+            ->setShareType(IShare::TYPE_USER)
649
+            ->setPermissions(31);
650
+        $share1 = $this->shareManager->createShare($share1);
651
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
652
+        $this->shareManager->updateShare($share1);
653
+
654
+        $node2 = $this->userFolder->get($this->folder . '/' . $this->filename);
655
+        $share2 = $this->shareManager->newShare();
656
+        $share2->setNode($node2)
657
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
658
+            ->setShareType(IShare::TYPE_LINK)
659
+            ->setPermissions(1);
660
+        $share2 = $this->shareManager->createShare($share2);
661
+        $share2->setStatus(IShare::STATUS_ACCEPTED);
662
+        $this->shareManager->updateShare($share2);
663
+
664
+        $node3 = $this->userFolder->get($this->folder . '/' . $this->subfolder . '/' . $this->filename);
665
+        $share3 = $this->shareManager->newShare();
666
+        $share3->setNode($node3)
667
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
668
+            ->setShareType(IShare::TYPE_LINK)
669
+            ->setPermissions(1);
670
+        $share3 = $this->shareManager->createShare($share3);
671
+        $share3->setStatus(IShare::STATUS_ACCEPTED);
672
+        $this->shareManager->updateShare($share3);
673
+
674
+        $testValues = [
675
+            ['query' => $this->folder,
676
+                'expectedResult' => $this->folder . $this->filename],
677
+            ['query' => $this->folder . $this->subfolder,
678
+                'expectedResult' => $this->folder . $this->subfolder . $this->filename],
679
+        ];
680
+
681
+        foreach ($testValues as $value) {
682
+            $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
683
+            $result = $ocs->getShares('false', 'false', 'true', $value['query']);
684
+            $ocs->cleanup();
685
+
686
+            // test should return one share within $this->folder
687
+            $data = $result->getData();
688
+
689
+            $this->assertEquals($value['expectedResult'], $data[0]['path']);
690
+        }
691
+
692
+        // cleanup
693
+        $this->shareManager->deleteShare($share1);
694
+        $this->shareManager->deleteShare($share2);
695
+        $this->shareManager->deleteShare($share3);
696
+    }
697
+
698
+    /**
699
+     * reshare a sub folder and check if we get the correct path
700
+     * @medium
701
+     */
702
+    public function testGetShareFromSubFolderReShares(): void {
703
+        $node1 = $this->userFolder->get($this->folder . $this->subfolder);
704
+        $share1 = $this->shareManager->newShare();
705
+        $share1->setNode($node1)
706
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
707
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
708
+            ->setShareType(IShare::TYPE_USER)
709
+            ->setPermissions(31);
710
+        $share1 = $this->shareManager->createShare($share1);
711
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
712
+        $this->shareManager->updateShare($share1);
713
+
714
+        $node2 = Server::get(IRootFolder::class)->getUserFolder(self::TEST_FILES_SHARING_API_USER2)->get($this->subfolder);
715
+        $share2 = $this->shareManager->newShare();
716
+        $share2->setNode($node2)
717
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
718
+            ->setShareType(IShare::TYPE_LINK)
719
+            ->setPermissions(1);
720
+        $share2 = $this->shareManager->createShare($share2);
721
+        $share2->setStatus(IShare::STATUS_ACCEPTED);
722
+        $this->shareManager->updateShare($share2);
723
+
724
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
725
+        $result = $ocs->getShares();
726
+        $ocs->cleanup();
727
+
728
+        // test should return one share within $this->folder
729
+        $data = $result->getData();
730
+
731
+        // we should get exactly one result
732
+        $this->assertCount(1, $data);
733
+
734
+        $this->assertEquals($this->subfolder, $data[0]['path']);
735
+
736
+        $this->shareManager->deleteShare($share2);
737
+        $this->shareManager->deleteShare($share1);
738
+    }
739
+
740
+    /**
741
+     * test re-re-share of folder if the path gets constructed correctly
742
+     * @medium
743
+     */
744
+    public function XtestGetShareFromFolderReReShares() {
745
+        $node1 = $this->userFolder->get($this->folder . $this->subfolder);
746
+        $share1 = $this->shareManager->newShare();
747
+        $share1->setNode($node1)
748
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
749
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
750
+            ->setShareType(IShare::TYPE_USER)
751
+            ->setPermissions(31);
752
+        $share1 = $this->shareManager->createShare($share1);
753
+
754
+        $node2 = $this->userFolder->get($this->folder . $this->subfolder . $this->subsubfolder);
755
+        $share2 = $this->shareManager->newShare();
756
+        $share2->setNode($node2)
757
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
758
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
759
+            ->setShareType(IShare::TYPE_USER)
760
+            ->setPermissions(31);
761
+        $share2 = $this->shareManager->createShare($share2);
762
+
763
+        $share3 = $this->shareManager->newShare();
764
+        $share3->setNode($node2)
765
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER3)
766
+            ->setShareType(IShare::TYPE_LINK)
767
+            ->setPermissions(1);
768
+        $share3 = $this->shareManager->createShare($share3);
769
+
770
+        /*
771 771
 		 * Test as recipient
772 772
 		 */
773
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER3);
774
-		$result = $ocs->getShares();
775
-		$ocs->cleanup();
773
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER3);
774
+        $result = $ocs->getShares();
775
+        $ocs->cleanup();
776 776
 
777
-		// test should return one share within $this->folder
778
-		$data = $result->getData();
777
+        // test should return one share within $this->folder
778
+        $data = $result->getData();
779 779
 
780
-		// we should get exactly one result
781
-		$this->assertCount(1, $data);
782
-		$this->assertEquals($this->subsubfolder, $data[0]['path']);
780
+        // we should get exactly one result
781
+        $this->assertCount(1, $data);
782
+        $this->assertEquals($this->subsubfolder, $data[0]['path']);
783 783
 
784
-		/*
784
+        /*
785 785
 		 * Test for first owner/initiator
786 786
 		 */
787
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
788
-		$result = $ocs->getShares();
789
-		$ocs->cleanup();
787
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
788
+        $result = $ocs->getShares();
789
+        $ocs->cleanup();
790 790
 
791
-		// test should return one share within $this->folder
792
-		$data = $result->getData();
791
+        // test should return one share within $this->folder
792
+        $data = $result->getData();
793 793
 
794
-		// we should get exactly one result
795
-		$this->assertCount(1, $data);
796
-		$this->assertEquals($this->folder . $this->subfolder, $data[0]['path']);
794
+        // we should get exactly one result
795
+        $this->assertCount(1, $data);
796
+        $this->assertEquals($this->folder . $this->subfolder, $data[0]['path']);
797 797
 
798
-		/*
798
+        /*
799 799
 		 * Test for second initiator
800 800
 		 */
801
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
802
-		$result = $ocs->getShares();
803
-		$ocs->cleanup();
804
-
805
-		// test should return one share within $this->folder
806
-		$data = $result->getData();
807
-
808
-		// we should get exactly one result
809
-		$this->assertCount(1, $data);
810
-		$this->assertEquals($this->subfolder . $this->subsubfolder, $data[0]['path']);
811
-
812
-		$this->shareManager->deleteShare($share1);
813
-		$this->shareManager->deleteShare($share2);
814
-		$this->shareManager->deleteShare($share3);
815
-	}
816
-
817
-	/**
818
-	 * test multiple shared folder if the path gets constructed correctly
819
-	 * @medium
820
-	 */
821
-	public function testGetShareMultipleSharedFolder(): void {
822
-		$this->setUp();
823
-		$node1 = $this->userFolder->get($this->folder . $this->subfolder);
824
-		$share1 = $this->shareManager->newShare();
825
-		$share1->setNode($node1)
826
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
827
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
828
-			->setShareType(IShare::TYPE_USER)
829
-			->setPermissions(31);
830
-		$share1 = $this->shareManager->createShare($share1);
831
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
832
-		$this->shareManager->updateShare($share1);
833
-
834
-		$node2 = $this->userFolder->get($this->folder);
835
-		$share2 = $this->shareManager->newShare();
836
-		$share2->setNode($node2)
837
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
838
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
839
-			->setShareType(IShare::TYPE_USER)
840
-			->setPermissions(31);
841
-		$share2 = $this->shareManager->createShare($share2);
842
-		$share2->setStatus(IShare::STATUS_ACCEPTED);
843
-		$this->shareManager->updateShare($share2);
844
-
845
-		$share3 = $this->shareManager->newShare();
846
-		$share3->setNode($node1)
847
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
848
-			->setShareType(IShare::TYPE_LINK)
849
-			->setPermissions(1);
850
-		$share3 = $this->shareManager->createShare($share3);
851
-		$share3->setStatus(IShare::STATUS_ACCEPTED);
852
-		$this->shareManager->updateShare($share3);
853
-
854
-		// $request = $this->createRequest(['path' => $this->subfolder]);
855
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
856
-		$result1 = $ocs->getShares('false', 'false', 'false', $this->subfolder);
857
-		$ocs->cleanup();
858
-
859
-		// test should return one share within $this->folder
860
-		$data1 = $result1->getData();
861
-		$this->assertCount(1, $data1);
862
-		$s1 = reset($data1);
863
-
864
-		//$request = $this->createRequest(['path' => $this->folder.$this->subfolder]);
865
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
866
-		$result2 = $ocs->getShares('false', 'false', 'false', $this->folder . $this->subfolder);
867
-		$ocs->cleanup();
868
-
869
-		// test should return one share within $this->folder
870
-		$data2 = $result2->getData();
871
-		$this->assertCount(1, $data2);
872
-		$s2 = reset($data2);
873
-
874
-		$this->assertEquals($this->subfolder, $s1['path']);
875
-		$this->assertEquals($this->folder . $this->subfolder, $s2['path']);
876
-
877
-		$this->shareManager->deleteShare($share1);
878
-		$this->shareManager->deleteShare($share2);
879
-		$this->shareManager->deleteShare($share3);
880
-	}
881
-
882
-	/**
883
-	 * test re-re-share of folder if the path gets constructed correctly
884
-	 * @medium
885
-	 */
886
-	public function testGetShareFromFileReReShares(): void {
887
-		$node1 = $this->userFolder->get($this->folder . $this->subfolder);
888
-		$share1 = $this->shareManager->newShare();
889
-		$share1->setNode($node1)
890
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
891
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
892
-			->setShareType(IShare::TYPE_USER)
893
-			->setPermissions(31);
894
-		$share1 = $this->shareManager->createShare($share1);
895
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
896
-		$this->shareManager->updateShare($share1);
897
-
898
-		$user2Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2);
899
-		$node2 = $user2Folder->get($this->subfolder . $this->filename);
900
-		$share2 = $this->shareManager->newShare();
901
-		$share2->setNode($node2)
902
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
903
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
904
-			->setShareType(IShare::TYPE_USER)
905
-			->setPermissions(19);
906
-		$share2 = $this->shareManager->createShare($share2);
907
-		$share2->setStatus(IShare::STATUS_ACCEPTED);
908
-		$this->shareManager->updateShare($share2);
909
-
910
-		$user3Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER3);
911
-		$node3 = $user3Folder->get($this->filename);
912
-		$share3 = $this->shareManager->newShare();
913
-		$share3->setNode($node3)
914
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER3)
915
-			->setShareType(IShare::TYPE_LINK)
916
-			->setPermissions(1);
917
-		$share3 = $this->shareManager->createShare($share3);
918
-		$share3->setStatus(IShare::STATUS_ACCEPTED);
919
-		$this->shareManager->updateShare($share3);
920
-
921
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER3);
922
-		$result = $ocs->getShares();
923
-		$ocs->cleanup();
924
-
925
-		// test should return one share within $this->folder
926
-		$data = $result->getData();
927
-
928
-		// we should get exactly one result
929
-		$this->assertCount(1, $data);
930
-
931
-		$this->assertEquals($this->filename, $data[0]['path']);
932
-
933
-		$this->shareManager->deleteShare($share1);
934
-		$this->shareManager->deleteShare($share2);
935
-		$this->shareManager->deleteShare($share3);
936
-	}
937
-
938
-	/**
939
-	 * @medium
940
-	 */
941
-	public function testGetShareFromUnknownId(): void {
942
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER3);
943
-		try {
944
-			$ocs->getShare(0);
945
-			$this->fail();
946
-		} catch (OCSNotFoundException $e) {
947
-			$this->assertEquals('Wrong share ID, share does not exist', $e->getMessage());
948
-		}
949
-		$ocs->cleanup();
950
-	}
951
-
952
-	/**
953
-	 * @medium
954
-	 * @depends testCreateShareUserFile
955
-	 * @depends testCreateShareLink
956
-	 */
957
-	public function testUpdateShare(): void {
958
-		$password = md5(time());
959
-
960
-		$node1 = $this->userFolder->get($this->filename);
961
-		$share1 = $this->shareManager->newShare();
962
-		$share1->setNode($node1)
963
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
964
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
965
-			->setShareType(IShare::TYPE_USER)
966
-			->setPermissions(19)
967
-			->setAttributes($this->shareManager->newShare()->newAttributes());
968
-
969
-		$this->assertNotNull($share1->getAttributes());
970
-		$share1 = $this->shareManager->createShare($share1);
971
-		$this->assertEquals(19, $share1->getPermissions());
972
-
973
-		$share2 = $this->shareManager->newShare();
974
-		$share2->setNode($node1)
975
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
976
-			->setShareType(IShare::TYPE_LINK)
977
-			->setPermissions(1);
978
-		$share2 = $this->shareManager->createShare($share2);
979
-		$this->assertEquals(1, $share2->getPermissions());
980
-
981
-		// update permissions
982
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
983
-		$ocs->updateShare(
984
-			$share1->getId(), 1, null, null, null, null, null, null, null,
985
-			'[{"scope": "app1", "key": "attr1", "value": true}]'
986
-		);
987
-		$ocs->cleanup();
988
-
989
-		$share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId());
990
-		$this->assertEquals(1, $share1->getPermissions());
991
-		$this->assertEquals(true, $share1->getAttributes()->getAttribute('app1', 'attr1'));
992
-
993
-		// update password for link share
994
-		$this->assertNull($share2->getPassword());
995
-
996
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
997
-		$ocs->updateShare($share2->getId(), null, $password);
998
-		$ocs->cleanup();
999
-
1000
-		$share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId());
1001
-		$this->assertNotNull($share2->getPassword());
1002
-
1003
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1004
-		$ocs->updateShare($share2->getId(), null, '');
1005
-		$ocs->cleanup();
1006
-
1007
-		$share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId());
1008
-		$this->assertNull($share2->getPassword());
1009
-
1010
-		$this->shareManager->deleteShare($share1);
1011
-		$this->shareManager->deleteShare($share2);
1012
-	}
1013
-
1014
-	/**
1015
-	 * @medium
1016
-	 * @dataProvider dataAllowFederationOnPublicShares
1017
-	 */
1018
-	public function testUpdateShareUpload(array $appConfig, int $permissions): void {
1019
-		$this->appConfig->method('getValueBool')->willReturnMap([
1020
-			$appConfig,
1021
-		]);
1022
-
1023
-		$node1 = $this->userFolder->get($this->folder);
1024
-		$share1 = $this->shareManager->newShare();
1025
-		$share1->setNode($node1)
1026
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1027
-			->setShareType(IShare::TYPE_LINK)
1028
-			->setPermissions(1);
1029
-		$share1 = $this->shareManager->createShare($share1);
1030
-
1031
-		// update public upload
1032
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1033
-		$ocs->updateShare($share1->getId(), null, null, null, 'true');
1034
-		$ocs->cleanup();
1035
-
1036
-		$share1 = $this->shareManager->getShareById($share1->getFullId());
1037
-		$this->assertEquals(
1038
-			Constants::PERMISSION_READ
1039
-			| Constants::PERMISSION_CREATE
1040
-			| Constants::PERMISSION_UPDATE
1041
-			| Constants::PERMISSION_DELETE
1042
-			| $permissions,
1043
-			$share1->getPermissions()
1044
-		);
1045
-
1046
-		// cleanup
1047
-		$this->shareManager->deleteShare($share1);
1048
-	}
1049
-
1050
-	public static function dataAllowFederationOnPublicShares(): array {
1051
-		return [
1052
-			[['core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES, false, false], 0],
1053
-			[['core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES, false, true], Constants::PERMISSION_SHARE],
1054
-		];
1055
-	}
1056
-
1057
-	/**
1058
-	 * @medium
1059
-	 */
1060
-	public function testUpdateShareExpireDate(): void {
1061
-		$node1 = $this->userFolder->get($this->folder);
1062
-		$share1 = $this->shareManager->newShare();
1063
-		$share1->setNode($node1)
1064
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1065
-			->setShareType(IShare::TYPE_LINK)
1066
-			->setPermissions(1);
1067
-		$share1 = $this->shareManager->createShare($share1);
1068
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
1069
-		$this->shareManager->updateShare($share1);
1070
-
1071
-		$config = Server::get(IConfig::class);
1072
-
1073
-		// enforce expire date, by default 7 days after the file was shared
1074
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
1075
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes');
1076
-
1077
-		$dateWithinRange = new \DateTime();
1078
-		$dateWithinRange->add(new \DateInterval('P6D'));
1079
-
1080
-		$dateOutOfRange = new \DateTime();
1081
-		$dateOutOfRange->add(new \DateInterval('P8D'));
1082
-
1083
-		// update expire date to a valid value
1084
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1085
-		$ocs->updateShare($share1->getId(), null, null, null, null, $dateWithinRange->format('Y-m-d'));
1086
-		$ocs->cleanup();
1087
-
1088
-		$share1 = $this->shareManager->getShareById($share1->getFullId());
1089
-
1090
-		// date should be changed
1091
-		$dateWithinRange->setTime(0, 0, 0);
1092
-		$dateWithinRange->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1093
-		$this->assertEquals($dateWithinRange, $share1->getExpirationDate());
1094
-
1095
-		// update expire date to a value out of range
1096
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1097
-		try {
1098
-			$ocs->updateShare($share1->getId());
1099
-			$this->fail();
1100
-		} catch (OCSBadRequestException $e) {
1101
-		}
1102
-		$ocs->cleanup();
1103
-
1104
-		$share1 = $this->shareManager->getShareById($share1->getFullId());
1105
-
1106
-		// date shouldn't be changed
1107
-		$this->assertEquals($dateWithinRange, $share1->getExpirationDate());
1108
-
1109
-		// Try to remove expire date
1110
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1111
-		try {
1112
-			$ocs->updateShare($share1->getId());
1113
-			$this->fail();
1114
-		} catch (OCSBadRequestException $e) {
1115
-		}
1116
-		$ocs->cleanup();
1117
-
1118
-		$share1 = $this->shareManager->getShareById($share1->getFullId());
1119
-
1120
-
1121
-		// date shouldn't be changed
1122
-		$this->assertEquals($dateWithinRange, $share1->getExpirationDate());
1123
-		// cleanup
1124
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1125
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1126
-		$this->shareManager->deleteShare($share1);
1127
-	}
1128
-
1129
-	/**
1130
-	 * @medium
1131
-	 * @depends testCreateShareUserFile
1132
-	 */
1133
-	public function testDeleteShare(): void {
1134
-		$node1 = $this->userFolder->get($this->filename);
1135
-		$share1 = $this->shareManager->newShare();
1136
-		$share1->setNode($node1)
1137
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1138
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
1139
-			->setShareType(IShare::TYPE_USER)
1140
-			->setPermissions(19);
1141
-		$share1 = $this->shareManager->createShare($share1);
1142
-
1143
-		$share2 = $this->shareManager->newShare();
1144
-		$share2->setNode($node1)
1145
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1146
-			->setShareType(IShare::TYPE_LINK)
1147
-			->setPermissions(1);
1148
-		$share2 = $this->shareManager->createShare($share2);
1149
-
1150
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1151
-		$ocs->deleteShare($share1->getId());
1152
-		$ocs->cleanup();
1153
-
1154
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1155
-		$ocs->deleteShare($share2->getId());
1156
-		$ocs->cleanup();
1157
-
1158
-		$this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, IShare::TYPE_USER));
1159
-		$this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, IShare::TYPE_LINK));
1160
-	}
1161
-
1162
-	/**
1163
-	 * test unshare of a reshared file
1164
-	 */
1165
-	public function testDeleteReshare(): void {
1166
-		$node1 = $this->userFolder->get($this->folder);
1167
-		$share1 = $this->shareManager->newShare();
1168
-		$share1->setNode($node1)
1169
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1170
-			->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
1171
-			->setShareType(IShare::TYPE_USER)
1172
-			->setPermissions(31);
1173
-		$share1 = $this->shareManager->createShare($share1);
1174
-		$share1->setStatus(IShare::STATUS_ACCEPTED);
1175
-		$this->shareManager->updateShare($share1);
1176
-
1177
-		$user2folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2);
1178
-		$node2 = $user2folder->get($this->folder . '/' . $this->filename);
1179
-		$share2 = $this->shareManager->newShare();
1180
-		$share2->setNode($node2)
1181
-			->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
1182
-			->setShareType(IShare::TYPE_LINK)
1183
-			->setPermissions(1);
1184
-		$share2 = $this->shareManager->createShare($share2);
1185
-		$share2->setStatus(IShare::STATUS_ACCEPTED);
1186
-		$this->shareManager->updateShare($share2);
1187
-
1188
-		// test if we can unshare the link again
1189
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1190
-		$ocs->deleteShare($share2->getId());
1191
-		$ocs->cleanup();
1192
-
1193
-		$this->shareManager->deleteShare($share1);
1194
-		$this->addToAssertionCount(1);
1195
-	}
1196
-
1197
-	/**
1198
-	 * share a folder which contains a share mount point, should be forbidden
1199
-	 */
1200
-	public function testShareFolderWithAMountPoint(): void {
1201
-		// user 1 shares a folder with user2
1202
-		self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1203
-
1204
-		$share = $this->share(
1205
-			IShare::TYPE_USER,
1206
-			$this->folder,
1207
-			self::TEST_FILES_SHARING_API_USER1,
1208
-			self::TEST_FILES_SHARING_API_USER2,
1209
-			Constants::PERMISSION_ALL
1210
-		);
1211
-		$share->setStatus(IShare::STATUS_ACCEPTED);
1212
-		$this->shareManager->updateShare($share);
1213
-
1214
-		// user2 shares a file from the folder as link
1215
-		self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
1216
-
1217
-		$view = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
1218
-		$view->mkdir('localDir');
1219
-
1220
-		// move mount point to the folder "localDir"
1221
-		$result = $view->rename($this->folder, 'localDir/' . $this->folder);
1222
-		$this->assertTrue($result !== false);
1223
-
1224
-		// try to share "localDir"
1225
-		$fileInfo2 = $view->getFileInfo('localDir');
1226
-
1227
-		$this->assertTrue($fileInfo2 instanceof FileInfo);
1228
-
1229
-		$pass = true;
1230
-		try {
1231
-			$this->share(
1232
-				IShare::TYPE_USER,
1233
-				'localDir',
1234
-				self::TEST_FILES_SHARING_API_USER2,
1235
-				self::TEST_FILES_SHARING_API_USER3,
1236
-				Constants::PERMISSION_ALL
1237
-			);
1238
-		} catch (\Exception $e) {
1239
-			$pass = false;
1240
-		}
1241
-
1242
-		$this->assertFalse($pass);
1243
-
1244
-		//cleanup
1245
-
1246
-		$result = $view->rename('localDir/' . $this->folder, $this->folder);
1247
-		$this->assertTrue($result !== false);
1248
-		$view->unlink('localDir');
1249
-
1250
-		self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1251
-
1252
-		$this->shareManager->deleteShare($share);
1253
-	}
1254
-
1255
-	/**
1256
-	 * Post init mount points hook for mounting simulated ext storage
1257
-	 */
1258
-	public static function initTestMountPointsHook($data) {
1259
-		if ($data['user'] === self::TEST_FILES_SHARING_API_USER1) {
1260
-			Filesystem::mount(self::$tempStorage, [], '/' . self::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME);
1261
-		}
1262
-	}
1263
-
1264
-	/**
1265
-	 * Tests mounting a folder that is an external storage mount point.
1266
-	 */
1267
-	public function testShareStorageMountPoint(): void {
1268
-		$tempStorage = new Temporary([]);
1269
-		$tempStorage->file_put_contents('test.txt', 'abcdef');
1270
-		$tempStorage->getScanner()->scan('');
1271
-
1272
-		$this->registerMount(self::TEST_FILES_SHARING_API_USER1, $tempStorage, self::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME);
1273
-
1274
-		// logging in will auto-mount the temp storage for user1 as well
1275
-		self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1276
-
1277
-		// user 1 shares the mount point folder with user2
1278
-		$share = $this->share(
1279
-			IShare::TYPE_USER,
1280
-			$this->folder,
1281
-			self::TEST_FILES_SHARING_API_USER1,
1282
-			self::TEST_FILES_SHARING_API_USER2,
1283
-			Constants::PERMISSION_ALL
1284
-		);
1285
-		$share->setStatus(IShare::STATUS_ACCEPTED);
1286
-		$this->shareManager->updateShare($share);
1287
-
1288
-		// user2: check that mount point name appears correctly
1289
-		self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
1290
-
1291
-		$view = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
1292
-
1293
-		$this->assertTrue($view->file_exists($this->folder));
1294
-		$this->assertTrue($view->file_exists($this->folder . '/test.txt'));
1295
-
1296
-		self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1297
-
1298
-		$this->shareManager->deleteShare($share);
1299
-
1300
-		\OC_Hook::clear('OC_Filesystem', 'post_initMountPoints');
1301
-		\OC_Hook::clear('\OCA\Files_Sharing\Tests\ApiTest', 'initTestMountPointsHook');
1302
-	}
1303
-
1304
-	public static function datesProvider() {
1305
-		$date = new \DateTime();
1306
-		$date->setTime(0, 0);
1307
-		$date->add(new \DateInterval('P5D'));
1308
-		$date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1309
-
1310
-		return [
1311
-			[$date->format('Y-m-d H:i:s'), true],
1312
-			['abc', false],
1313
-			[$date->format('Y-m-d H:i:s') . 'xyz', false],
1314
-		];
1315
-	}
1316
-
1317
-	/**
1318
-	 * Make sure only ISO 8601 dates are accepted
1319
-	 *
1320
-	 * @group RoutingWeirdness
1321
-	 */
1322
-	#[\PHPUnit\Framework\Attributes\DataProvider('datesProvider')]
1323
-	public function testPublicLinkExpireDate($date, $valid): void {
1324
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1325
-
1326
-		try {
1327
-			$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date);
1328
-			$this->assertTrue($valid);
1329
-		} catch (OCSNotFoundException $e) {
1330
-			$this->assertFalse($valid);
1331
-			$this->assertEquals('Invalid date. Format must be YYYY-MM-DD', $e->getMessage());
1332
-			$ocs->cleanup();
1333
-			return;
1334
-		}
1335
-		$ocs->cleanup();
1336
-
1337
-		$data = $result->getData();
1338
-		$this->assertTrue(is_string($data['token']));
1339
-		$this->assertEquals(substr($date, 0, 10), substr($data['expiration'], 0, 10));
1340
-
1341
-		// check for correct link
1342
-		$url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
1343
-		$this->assertEquals($url, $data['url']);
1344
-
1345
-		$share = $this->shareManager->getShareById('ocinternal:' . $data['id']);
1346
-
1347
-		$this->assertEquals($date, $share->getExpirationDate()->format('Y-m-d H:i:s'));
1348
-
1349
-		$this->shareManager->deleteShare($share);
1350
-	}
1351
-
1352
-	/**
1353
-	 * @group RoutingWeirdness
1354
-	 */
1355
-	public function testCreatePublicLinkExpireDateValid(): void {
1356
-		$config = Server::get(IConfig::class);
1357
-
1358
-		// enforce expire date, by default 7 days after the file was shared
1359
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
1360
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes');
1361
-
1362
-		$date = new \DateTime();
1363
-		$date->add(new \DateInterval('P5D'));
1364
-
1365
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1366
-		$result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date->format('Y-m-d'));
1367
-		$ocs->cleanup();
1368
-
1369
-		$data = $result->getData();
1370
-		$this->assertTrue(is_string($data['token']));
1371
-		$this->assertEquals($date->format('Y-m-d 00:00:00'), $data['expiration']);
1372
-
1373
-		// check for correct link
1374
-		$url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
1375
-		$this->assertEquals($url, $data['url']);
1376
-
1377
-		$share = $this->shareManager->getShareById('ocinternal:' . $data['id']);
1378
-		$date->setTime(0, 0, 0);
1379
-		$this->assertEquals($date, $share->getExpirationDate());
1380
-
1381
-		$this->shareManager->deleteShare($share);
1382
-
1383
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1384
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1385
-	}
1386
-
1387
-	public function testCreatePublicLinkExpireDateInvalidFuture(): void {
1388
-		$config = Server::get(IConfig::class);
1389
-
1390
-		// enforce expire date, by default 7 days after the file was shared
1391
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
1392
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes');
1393
-
1394
-		$date = new \DateTime();
1395
-		$date->add(new \DateInterval('P8D'));
1396
-
1397
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1398
-
1399
-		try {
1400
-			$ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date->format('Y-m-d'));
1401
-			$this->fail();
1402
-		} catch (OCSException $e) {
1403
-			$this->assertEquals(404, $e->getCode());
1404
-			$this->assertEquals('Cannot set expiration date more than 7 days in the future', $e->getMessage());
1405
-		}
1406
-		$ocs->cleanup();
1407
-
1408
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1409
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1410
-	}
1411
-
1412
-	public function XtestCreatePublicLinkExpireDateInvalidPast() {
1413
-		$config = Server::get(IConfig::class);
1414
-
1415
-		$date = new \DateTime();
1416
-		$date->sub(new \DateInterval('P8D'));
1417
-
1418
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1419
-
1420
-		try {
1421
-			$ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date->format('Y-m-d'));
1422
-			$this->fail();
1423
-		} catch (OCSException $e) {
1424
-			$this->assertEquals(404, $e->getCode());
1425
-			$this->assertEquals('Expiration date is in the past', $e->getMessage());
1426
-		}
1427
-		$ocs->cleanup();
1428
-
1429
-		$config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1430
-		$config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1431
-	}
1432
-
1433
-	/**
1434
-	 * test for no invisible shares
1435
-	 * See: https://github.com/owncloud/core/issues/22295
1436
-	 */
1437
-	public function testInvisibleSharesUser(): void {
1438
-		// simulate a post request
1439
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1440
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
1441
-		$ocs->cleanup();
1442
-		$data = $result->getData();
801
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
802
+        $result = $ocs->getShares();
803
+        $ocs->cleanup();
804
+
805
+        // test should return one share within $this->folder
806
+        $data = $result->getData();
807
+
808
+        // we should get exactly one result
809
+        $this->assertCount(1, $data);
810
+        $this->assertEquals($this->subfolder . $this->subsubfolder, $data[0]['path']);
811
+
812
+        $this->shareManager->deleteShare($share1);
813
+        $this->shareManager->deleteShare($share2);
814
+        $this->shareManager->deleteShare($share3);
815
+    }
816
+
817
+    /**
818
+     * test multiple shared folder if the path gets constructed correctly
819
+     * @medium
820
+     */
821
+    public function testGetShareMultipleSharedFolder(): void {
822
+        $this->setUp();
823
+        $node1 = $this->userFolder->get($this->folder . $this->subfolder);
824
+        $share1 = $this->shareManager->newShare();
825
+        $share1->setNode($node1)
826
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
827
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
828
+            ->setShareType(IShare::TYPE_USER)
829
+            ->setPermissions(31);
830
+        $share1 = $this->shareManager->createShare($share1);
831
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
832
+        $this->shareManager->updateShare($share1);
833
+
834
+        $node2 = $this->userFolder->get($this->folder);
835
+        $share2 = $this->shareManager->newShare();
836
+        $share2->setNode($node2)
837
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
838
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
839
+            ->setShareType(IShare::TYPE_USER)
840
+            ->setPermissions(31);
841
+        $share2 = $this->shareManager->createShare($share2);
842
+        $share2->setStatus(IShare::STATUS_ACCEPTED);
843
+        $this->shareManager->updateShare($share2);
844
+
845
+        $share3 = $this->shareManager->newShare();
846
+        $share3->setNode($node1)
847
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
848
+            ->setShareType(IShare::TYPE_LINK)
849
+            ->setPermissions(1);
850
+        $share3 = $this->shareManager->createShare($share3);
851
+        $share3->setStatus(IShare::STATUS_ACCEPTED);
852
+        $this->shareManager->updateShare($share3);
853
+
854
+        // $request = $this->createRequest(['path' => $this->subfolder]);
855
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
856
+        $result1 = $ocs->getShares('false', 'false', 'false', $this->subfolder);
857
+        $ocs->cleanup();
858
+
859
+        // test should return one share within $this->folder
860
+        $data1 = $result1->getData();
861
+        $this->assertCount(1, $data1);
862
+        $s1 = reset($data1);
863
+
864
+        //$request = $this->createRequest(['path' => $this->folder.$this->subfolder]);
865
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
866
+        $result2 = $ocs->getShares('false', 'false', 'false', $this->folder . $this->subfolder);
867
+        $ocs->cleanup();
868
+
869
+        // test should return one share within $this->folder
870
+        $data2 = $result2->getData();
871
+        $this->assertCount(1, $data2);
872
+        $s2 = reset($data2);
873
+
874
+        $this->assertEquals($this->subfolder, $s1['path']);
875
+        $this->assertEquals($this->folder . $this->subfolder, $s2['path']);
876
+
877
+        $this->shareManager->deleteShare($share1);
878
+        $this->shareManager->deleteShare($share2);
879
+        $this->shareManager->deleteShare($share3);
880
+    }
881
+
882
+    /**
883
+     * test re-re-share of folder if the path gets constructed correctly
884
+     * @medium
885
+     */
886
+    public function testGetShareFromFileReReShares(): void {
887
+        $node1 = $this->userFolder->get($this->folder . $this->subfolder);
888
+        $share1 = $this->shareManager->newShare();
889
+        $share1->setNode($node1)
890
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
891
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
892
+            ->setShareType(IShare::TYPE_USER)
893
+            ->setPermissions(31);
894
+        $share1 = $this->shareManager->createShare($share1);
895
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
896
+        $this->shareManager->updateShare($share1);
897
+
898
+        $user2Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2);
899
+        $node2 = $user2Folder->get($this->subfolder . $this->filename);
900
+        $share2 = $this->shareManager->newShare();
901
+        $share2->setNode($node2)
902
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
903
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
904
+            ->setShareType(IShare::TYPE_USER)
905
+            ->setPermissions(19);
906
+        $share2 = $this->shareManager->createShare($share2);
907
+        $share2->setStatus(IShare::STATUS_ACCEPTED);
908
+        $this->shareManager->updateShare($share2);
909
+
910
+        $user3Folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER3);
911
+        $node3 = $user3Folder->get($this->filename);
912
+        $share3 = $this->shareManager->newShare();
913
+        $share3->setNode($node3)
914
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER3)
915
+            ->setShareType(IShare::TYPE_LINK)
916
+            ->setPermissions(1);
917
+        $share3 = $this->shareManager->createShare($share3);
918
+        $share3->setStatus(IShare::STATUS_ACCEPTED);
919
+        $this->shareManager->updateShare($share3);
920
+
921
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER3);
922
+        $result = $ocs->getShares();
923
+        $ocs->cleanup();
924
+
925
+        // test should return one share within $this->folder
926
+        $data = $result->getData();
927
+
928
+        // we should get exactly one result
929
+        $this->assertCount(1, $data);
930
+
931
+        $this->assertEquals($this->filename, $data[0]['path']);
932
+
933
+        $this->shareManager->deleteShare($share1);
934
+        $this->shareManager->deleteShare($share2);
935
+        $this->shareManager->deleteShare($share3);
936
+    }
937
+
938
+    /**
939
+     * @medium
940
+     */
941
+    public function testGetShareFromUnknownId(): void {
942
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER3);
943
+        try {
944
+            $ocs->getShare(0);
945
+            $this->fail();
946
+        } catch (OCSNotFoundException $e) {
947
+            $this->assertEquals('Wrong share ID, share does not exist', $e->getMessage());
948
+        }
949
+        $ocs->cleanup();
950
+    }
951
+
952
+    /**
953
+     * @medium
954
+     * @depends testCreateShareUserFile
955
+     * @depends testCreateShareLink
956
+     */
957
+    public function testUpdateShare(): void {
958
+        $password = md5(time());
959
+
960
+        $node1 = $this->userFolder->get($this->filename);
961
+        $share1 = $this->shareManager->newShare();
962
+        $share1->setNode($node1)
963
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
964
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
965
+            ->setShareType(IShare::TYPE_USER)
966
+            ->setPermissions(19)
967
+            ->setAttributes($this->shareManager->newShare()->newAttributes());
968
+
969
+        $this->assertNotNull($share1->getAttributes());
970
+        $share1 = $this->shareManager->createShare($share1);
971
+        $this->assertEquals(19, $share1->getPermissions());
972
+
973
+        $share2 = $this->shareManager->newShare();
974
+        $share2->setNode($node1)
975
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
976
+            ->setShareType(IShare::TYPE_LINK)
977
+            ->setPermissions(1);
978
+        $share2 = $this->shareManager->createShare($share2);
979
+        $this->assertEquals(1, $share2->getPermissions());
980
+
981
+        // update permissions
982
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
983
+        $ocs->updateShare(
984
+            $share1->getId(), 1, null, null, null, null, null, null, null,
985
+            '[{"scope": "app1", "key": "attr1", "value": true}]'
986
+        );
987
+        $ocs->cleanup();
988
+
989
+        $share1 = $this->shareManager->getShareById('ocinternal:' . $share1->getId());
990
+        $this->assertEquals(1, $share1->getPermissions());
991
+        $this->assertEquals(true, $share1->getAttributes()->getAttribute('app1', 'attr1'));
992
+
993
+        // update password for link share
994
+        $this->assertNull($share2->getPassword());
995
+
996
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
997
+        $ocs->updateShare($share2->getId(), null, $password);
998
+        $ocs->cleanup();
999
+
1000
+        $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId());
1001
+        $this->assertNotNull($share2->getPassword());
1002
+
1003
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1004
+        $ocs->updateShare($share2->getId(), null, '');
1005
+        $ocs->cleanup();
1006
+
1007
+        $share2 = $this->shareManager->getShareById('ocinternal:' . $share2->getId());
1008
+        $this->assertNull($share2->getPassword());
1009
+
1010
+        $this->shareManager->deleteShare($share1);
1011
+        $this->shareManager->deleteShare($share2);
1012
+    }
1013
+
1014
+    /**
1015
+     * @medium
1016
+     * @dataProvider dataAllowFederationOnPublicShares
1017
+     */
1018
+    public function testUpdateShareUpload(array $appConfig, int $permissions): void {
1019
+        $this->appConfig->method('getValueBool')->willReturnMap([
1020
+            $appConfig,
1021
+        ]);
1022
+
1023
+        $node1 = $this->userFolder->get($this->folder);
1024
+        $share1 = $this->shareManager->newShare();
1025
+        $share1->setNode($node1)
1026
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1027
+            ->setShareType(IShare::TYPE_LINK)
1028
+            ->setPermissions(1);
1029
+        $share1 = $this->shareManager->createShare($share1);
1030
+
1031
+        // update public upload
1032
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1033
+        $ocs->updateShare($share1->getId(), null, null, null, 'true');
1034
+        $ocs->cleanup();
1035
+
1036
+        $share1 = $this->shareManager->getShareById($share1->getFullId());
1037
+        $this->assertEquals(
1038
+            Constants::PERMISSION_READ
1039
+            | Constants::PERMISSION_CREATE
1040
+            | Constants::PERMISSION_UPDATE
1041
+            | Constants::PERMISSION_DELETE
1042
+            | $permissions,
1043
+            $share1->getPermissions()
1044
+        );
1045
+
1046
+        // cleanup
1047
+        $this->shareManager->deleteShare($share1);
1048
+    }
1049
+
1050
+    public static function dataAllowFederationOnPublicShares(): array {
1051
+        return [
1052
+            [['core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES, false, false], 0],
1053
+            [['core', ConfigLexicon::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES, false, true], Constants::PERMISSION_SHARE],
1054
+        ];
1055
+    }
1056
+
1057
+    /**
1058
+     * @medium
1059
+     */
1060
+    public function testUpdateShareExpireDate(): void {
1061
+        $node1 = $this->userFolder->get($this->folder);
1062
+        $share1 = $this->shareManager->newShare();
1063
+        $share1->setNode($node1)
1064
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1065
+            ->setShareType(IShare::TYPE_LINK)
1066
+            ->setPermissions(1);
1067
+        $share1 = $this->shareManager->createShare($share1);
1068
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
1069
+        $this->shareManager->updateShare($share1);
1070
+
1071
+        $config = Server::get(IConfig::class);
1072
+
1073
+        // enforce expire date, by default 7 days after the file was shared
1074
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
1075
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes');
1076
+
1077
+        $dateWithinRange = new \DateTime();
1078
+        $dateWithinRange->add(new \DateInterval('P6D'));
1079
+
1080
+        $dateOutOfRange = new \DateTime();
1081
+        $dateOutOfRange->add(new \DateInterval('P8D'));
1082
+
1083
+        // update expire date to a valid value
1084
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1085
+        $ocs->updateShare($share1->getId(), null, null, null, null, $dateWithinRange->format('Y-m-d'));
1086
+        $ocs->cleanup();
1087
+
1088
+        $share1 = $this->shareManager->getShareById($share1->getFullId());
1089
+
1090
+        // date should be changed
1091
+        $dateWithinRange->setTime(0, 0, 0);
1092
+        $dateWithinRange->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1093
+        $this->assertEquals($dateWithinRange, $share1->getExpirationDate());
1094
+
1095
+        // update expire date to a value out of range
1096
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1097
+        try {
1098
+            $ocs->updateShare($share1->getId());
1099
+            $this->fail();
1100
+        } catch (OCSBadRequestException $e) {
1101
+        }
1102
+        $ocs->cleanup();
1103
+
1104
+        $share1 = $this->shareManager->getShareById($share1->getFullId());
1105
+
1106
+        // date shouldn't be changed
1107
+        $this->assertEquals($dateWithinRange, $share1->getExpirationDate());
1108
+
1109
+        // Try to remove expire date
1110
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1111
+        try {
1112
+            $ocs->updateShare($share1->getId());
1113
+            $this->fail();
1114
+        } catch (OCSBadRequestException $e) {
1115
+        }
1116
+        $ocs->cleanup();
1117
+
1118
+        $share1 = $this->shareManager->getShareById($share1->getFullId());
1119
+
1120
+
1121
+        // date shouldn't be changed
1122
+        $this->assertEquals($dateWithinRange, $share1->getExpirationDate());
1123
+        // cleanup
1124
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1125
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1126
+        $this->shareManager->deleteShare($share1);
1127
+    }
1128
+
1129
+    /**
1130
+     * @medium
1131
+     * @depends testCreateShareUserFile
1132
+     */
1133
+    public function testDeleteShare(): void {
1134
+        $node1 = $this->userFolder->get($this->filename);
1135
+        $share1 = $this->shareManager->newShare();
1136
+        $share1->setNode($node1)
1137
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1138
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
1139
+            ->setShareType(IShare::TYPE_USER)
1140
+            ->setPermissions(19);
1141
+        $share1 = $this->shareManager->createShare($share1);
1142
+
1143
+        $share2 = $this->shareManager->newShare();
1144
+        $share2->setNode($node1)
1145
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1146
+            ->setShareType(IShare::TYPE_LINK)
1147
+            ->setPermissions(1);
1148
+        $share2 = $this->shareManager->createShare($share2);
1149
+
1150
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1151
+        $ocs->deleteShare($share1->getId());
1152
+        $ocs->cleanup();
1153
+
1154
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1155
+        $ocs->deleteShare($share2->getId());
1156
+        $ocs->cleanup();
1157
+
1158
+        $this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, IShare::TYPE_USER));
1159
+        $this->assertEmpty($this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER2, IShare::TYPE_LINK));
1160
+    }
1161
+
1162
+    /**
1163
+     * test unshare of a reshared file
1164
+     */
1165
+    public function testDeleteReshare(): void {
1166
+        $node1 = $this->userFolder->get($this->folder);
1167
+        $share1 = $this->shareManager->newShare();
1168
+        $share1->setNode($node1)
1169
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
1170
+            ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
1171
+            ->setShareType(IShare::TYPE_USER)
1172
+            ->setPermissions(31);
1173
+        $share1 = $this->shareManager->createShare($share1);
1174
+        $share1->setStatus(IShare::STATUS_ACCEPTED);
1175
+        $this->shareManager->updateShare($share1);
1176
+
1177
+        $user2folder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER2);
1178
+        $node2 = $user2folder->get($this->folder . '/' . $this->filename);
1179
+        $share2 = $this->shareManager->newShare();
1180
+        $share2->setNode($node2)
1181
+            ->setSharedBy(self::TEST_FILES_SHARING_API_USER2)
1182
+            ->setShareType(IShare::TYPE_LINK)
1183
+            ->setPermissions(1);
1184
+        $share2 = $this->shareManager->createShare($share2);
1185
+        $share2->setStatus(IShare::STATUS_ACCEPTED);
1186
+        $this->shareManager->updateShare($share2);
1187
+
1188
+        // test if we can unshare the link again
1189
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1190
+        $ocs->deleteShare($share2->getId());
1191
+        $ocs->cleanup();
1192
+
1193
+        $this->shareManager->deleteShare($share1);
1194
+        $this->addToAssertionCount(1);
1195
+    }
1196
+
1197
+    /**
1198
+     * share a folder which contains a share mount point, should be forbidden
1199
+     */
1200
+    public function testShareFolderWithAMountPoint(): void {
1201
+        // user 1 shares a folder with user2
1202
+        self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1203
+
1204
+        $share = $this->share(
1205
+            IShare::TYPE_USER,
1206
+            $this->folder,
1207
+            self::TEST_FILES_SHARING_API_USER1,
1208
+            self::TEST_FILES_SHARING_API_USER2,
1209
+            Constants::PERMISSION_ALL
1210
+        );
1211
+        $share->setStatus(IShare::STATUS_ACCEPTED);
1212
+        $this->shareManager->updateShare($share);
1213
+
1214
+        // user2 shares a file from the folder as link
1215
+        self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
1216
+
1217
+        $view = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
1218
+        $view->mkdir('localDir');
1219
+
1220
+        // move mount point to the folder "localDir"
1221
+        $result = $view->rename($this->folder, 'localDir/' . $this->folder);
1222
+        $this->assertTrue($result !== false);
1223
+
1224
+        // try to share "localDir"
1225
+        $fileInfo2 = $view->getFileInfo('localDir');
1226
+
1227
+        $this->assertTrue($fileInfo2 instanceof FileInfo);
1228
+
1229
+        $pass = true;
1230
+        try {
1231
+            $this->share(
1232
+                IShare::TYPE_USER,
1233
+                'localDir',
1234
+                self::TEST_FILES_SHARING_API_USER2,
1235
+                self::TEST_FILES_SHARING_API_USER3,
1236
+                Constants::PERMISSION_ALL
1237
+            );
1238
+        } catch (\Exception $e) {
1239
+            $pass = false;
1240
+        }
1241
+
1242
+        $this->assertFalse($pass);
1243
+
1244
+        //cleanup
1245
+
1246
+        $result = $view->rename('localDir/' . $this->folder, $this->folder);
1247
+        $this->assertTrue($result !== false);
1248
+        $view->unlink('localDir');
1249
+
1250
+        self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1251
+
1252
+        $this->shareManager->deleteShare($share);
1253
+    }
1254
+
1255
+    /**
1256
+     * Post init mount points hook for mounting simulated ext storage
1257
+     */
1258
+    public static function initTestMountPointsHook($data) {
1259
+        if ($data['user'] === self::TEST_FILES_SHARING_API_USER1) {
1260
+            Filesystem::mount(self::$tempStorage, [], '/' . self::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME);
1261
+        }
1262
+    }
1263
+
1264
+    /**
1265
+     * Tests mounting a folder that is an external storage mount point.
1266
+     */
1267
+    public function testShareStorageMountPoint(): void {
1268
+        $tempStorage = new Temporary([]);
1269
+        $tempStorage->file_put_contents('test.txt', 'abcdef');
1270
+        $tempStorage->getScanner()->scan('');
1271
+
1272
+        $this->registerMount(self::TEST_FILES_SHARING_API_USER1, $tempStorage, self::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME);
1273
+
1274
+        // logging in will auto-mount the temp storage for user1 as well
1275
+        self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1276
+
1277
+        // user 1 shares the mount point folder with user2
1278
+        $share = $this->share(
1279
+            IShare::TYPE_USER,
1280
+            $this->folder,
1281
+            self::TEST_FILES_SHARING_API_USER1,
1282
+            self::TEST_FILES_SHARING_API_USER2,
1283
+            Constants::PERMISSION_ALL
1284
+        );
1285
+        $share->setStatus(IShare::STATUS_ACCEPTED);
1286
+        $this->shareManager->updateShare($share);
1287
+
1288
+        // user2: check that mount point name appears correctly
1289
+        self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
1290
+
1291
+        $view = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
1292
+
1293
+        $this->assertTrue($view->file_exists($this->folder));
1294
+        $this->assertTrue($view->file_exists($this->folder . '/test.txt'));
1295
+
1296
+        self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
1297
+
1298
+        $this->shareManager->deleteShare($share);
1299
+
1300
+        \OC_Hook::clear('OC_Filesystem', 'post_initMountPoints');
1301
+        \OC_Hook::clear('\OCA\Files_Sharing\Tests\ApiTest', 'initTestMountPointsHook');
1302
+    }
1303
+
1304
+    public static function datesProvider() {
1305
+        $date = new \DateTime();
1306
+        $date->setTime(0, 0);
1307
+        $date->add(new \DateInterval('P5D'));
1308
+        $date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1309
+
1310
+        return [
1311
+            [$date->format('Y-m-d H:i:s'), true],
1312
+            ['abc', false],
1313
+            [$date->format('Y-m-d H:i:s') . 'xyz', false],
1314
+        ];
1315
+    }
1316
+
1317
+    /**
1318
+     * Make sure only ISO 8601 dates are accepted
1319
+     *
1320
+     * @group RoutingWeirdness
1321
+     */
1322
+    #[\PHPUnit\Framework\Attributes\DataProvider('datesProvider')]
1323
+    public function testPublicLinkExpireDate($date, $valid): void {
1324
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1325
+
1326
+        try {
1327
+            $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date);
1328
+            $this->assertTrue($valid);
1329
+        } catch (OCSNotFoundException $e) {
1330
+            $this->assertFalse($valid);
1331
+            $this->assertEquals('Invalid date. Format must be YYYY-MM-DD', $e->getMessage());
1332
+            $ocs->cleanup();
1333
+            return;
1334
+        }
1335
+        $ocs->cleanup();
1336
+
1337
+        $data = $result->getData();
1338
+        $this->assertTrue(is_string($data['token']));
1339
+        $this->assertEquals(substr($date, 0, 10), substr($data['expiration'], 0, 10));
1340
+
1341
+        // check for correct link
1342
+        $url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
1343
+        $this->assertEquals($url, $data['url']);
1344
+
1345
+        $share = $this->shareManager->getShareById('ocinternal:' . $data['id']);
1346
+
1347
+        $this->assertEquals($date, $share->getExpirationDate()->format('Y-m-d H:i:s'));
1348
+
1349
+        $this->shareManager->deleteShare($share);
1350
+    }
1351
+
1352
+    /**
1353
+     * @group RoutingWeirdness
1354
+     */
1355
+    public function testCreatePublicLinkExpireDateValid(): void {
1356
+        $config = Server::get(IConfig::class);
1357
+
1358
+        // enforce expire date, by default 7 days after the file was shared
1359
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
1360
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes');
1361
+
1362
+        $date = new \DateTime();
1363
+        $date->add(new \DateInterval('P5D'));
1364
+
1365
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1366
+        $result = $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date->format('Y-m-d'));
1367
+        $ocs->cleanup();
1368
+
1369
+        $data = $result->getData();
1370
+        $this->assertTrue(is_string($data['token']));
1371
+        $this->assertEquals($date->format('Y-m-d 00:00:00'), $data['expiration']);
1372
+
1373
+        // check for correct link
1374
+        $url = Server::get(IURLGenerator::class)->getAbsoluteURL('/index.php/s/' . $data['token']);
1375
+        $this->assertEquals($url, $data['url']);
1376
+
1377
+        $share = $this->shareManager->getShareById('ocinternal:' . $data['id']);
1378
+        $date->setTime(0, 0, 0);
1379
+        $this->assertEquals($date, $share->getExpirationDate());
1380
+
1381
+        $this->shareManager->deleteShare($share);
1382
+
1383
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1384
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1385
+    }
1386
+
1387
+    public function testCreatePublicLinkExpireDateInvalidFuture(): void {
1388
+        $config = Server::get(IConfig::class);
1389
+
1390
+        // enforce expire date, by default 7 days after the file was shared
1391
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'yes');
1392
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'yes');
1393
+
1394
+        $date = new \DateTime();
1395
+        $date->add(new \DateInterval('P8D'));
1396
+
1397
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1398
+
1399
+        try {
1400
+            $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date->format('Y-m-d'));
1401
+            $this->fail();
1402
+        } catch (OCSException $e) {
1403
+            $this->assertEquals(404, $e->getCode());
1404
+            $this->assertEquals('Cannot set expiration date more than 7 days in the future', $e->getMessage());
1405
+        }
1406
+        $ocs->cleanup();
1407
+
1408
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1409
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1410
+    }
1411
+
1412
+    public function XtestCreatePublicLinkExpireDateInvalidPast() {
1413
+        $config = Server::get(IConfig::class);
1414
+
1415
+        $date = new \DateTime();
1416
+        $date->sub(new \DateInterval('P8D'));
1417
+
1418
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1419
+
1420
+        try {
1421
+            $ocs->createShare($this->filename, Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, $date->format('Y-m-d'));
1422
+            $this->fail();
1423
+        } catch (OCSException $e) {
1424
+            $this->assertEquals(404, $e->getCode());
1425
+            $this->assertEquals('Expiration date is in the past', $e->getMessage());
1426
+        }
1427
+        $ocs->cleanup();
1428
+
1429
+        $config->setAppValue('core', 'shareapi_default_expire_date', 'no');
1430
+        $config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
1431
+    }
1432
+
1433
+    /**
1434
+     * test for no invisible shares
1435
+     * See: https://github.com/owncloud/core/issues/22295
1436
+     */
1437
+    public function testInvisibleSharesUser(): void {
1438
+        // simulate a post request
1439
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1440
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_USER, self::TEST_FILES_SHARING_API_USER2);
1441
+        $ocs->cleanup();
1442
+        $data = $result->getData();
1443 1443
 
1444
-		$topId = $data['id'];
1445
-
1446
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1447
-		$ocs->acceptShare($topId);
1448
-		$ocs->cleanup();
1449
-
1450
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1451
-		$ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
1452
-		$ocs->cleanup();
1453
-
1454
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1455
-		$ocs->deleteShare($topId);
1456
-		$ocs->cleanup();
1457
-
1458
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1459
-		$result = $ocs->getShares();
1460
-		$ocs->cleanup();
1461
-
1462
-		$this->assertEmpty($result->getData());
1463
-	}
1464
-
1465
-	/**
1466
-	 * test for no invisible shares
1467
-	 * See: https://github.com/owncloud/core/issues/22295
1468
-	 */
1469
-	public function testInvisibleSharesGroup(): void {
1470
-		// simulate a post request
1471
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1472
-		$result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_GROUP, self::TEST_FILES_SHARING_API_GROUP1);
1473
-		$ocs->cleanup();
1474
-		$data = $result->getData();
1475
-
1476
-		$topId = $data['id'];
1477
-
1478
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1479
-		$ocs->acceptShare($topId);
1480
-		$ocs->cleanup();
1481
-
1482
-		\OC_Util::tearDownFS();
1483
-
1484
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1485
-		$ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
1486
-		$ocs->cleanup();
1487
-
1488
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1489
-		$ocs->deleteShare($topId);
1490
-		$ocs->cleanup();
1491
-
1492
-		$ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1493
-		$result = $ocs->getShares();
1494
-		$ocs->cleanup();
1495
-
1496
-		$this->assertEmpty($result->getData());
1497
-	}
1444
+        $topId = $data['id'];
1445
+
1446
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1447
+        $ocs->acceptShare($topId);
1448
+        $ocs->cleanup();
1449
+
1450
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1451
+        $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
1452
+        $ocs->cleanup();
1453
+
1454
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1455
+        $ocs->deleteShare($topId);
1456
+        $ocs->cleanup();
1457
+
1458
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1459
+        $result = $ocs->getShares();
1460
+        $ocs->cleanup();
1461
+
1462
+        $this->assertEmpty($result->getData());
1463
+    }
1464
+
1465
+    /**
1466
+     * test for no invisible shares
1467
+     * See: https://github.com/owncloud/core/issues/22295
1468
+     */
1469
+    public function testInvisibleSharesGroup(): void {
1470
+        // simulate a post request
1471
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1472
+        $result = $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_GROUP, self::TEST_FILES_SHARING_API_GROUP1);
1473
+        $ocs->cleanup();
1474
+        $data = $result->getData();
1475
+
1476
+        $topId = $data['id'];
1477
+
1478
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1479
+        $ocs->acceptShare($topId);
1480
+        $ocs->cleanup();
1481
+
1482
+        \OC_Util::tearDownFS();
1483
+
1484
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER2);
1485
+        $ocs->createShare($this->folder, Constants::PERMISSION_ALL, IShare::TYPE_LINK);
1486
+        $ocs->cleanup();
1487
+
1488
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1489
+        $ocs->deleteShare($topId);
1490
+        $ocs->cleanup();
1491
+
1492
+        $ocs = $this->createOCS(self::TEST_FILES_SHARING_API_USER1);
1493
+        $result = $ocs->getShares();
1494
+        $ocs->cleanup();
1495
+
1496
+        $this->assertEmpty($result->getData());
1497
+    }
1498 1498
 }
Please login to merge, or discard this patch.
apps/files_sharing/tests/Controller/ShareAPIControllerTest.php 1 patch
Indentation   +5155 added lines, -5155 removed lines patch added patch discarded remove patch
@@ -59,508 +59,508 @@  discard block
 block discarded – undo
59 59
  */
60 60
 class ShareAPIControllerTest extends TestCase {
61 61
 
62
-	private string $appName = 'files_sharing';
63
-	private string $currentUser;
64
-
65
-	private ShareAPIController $ocs;
66
-
67
-	private IManager&MockObject $shareManager;
68
-	private IGroupManager&MockObject $groupManager;
69
-	private IUserManager&MockObject $userManager;
70
-	private IRequest&MockObject $request;
71
-	private IRootFolder&MockObject $rootFolder;
72
-	private IURLGenerator&MockObject $urlGenerator;
73
-	private IL10N&MockObject $l;
74
-	private IConfig&MockObject $config;
75
-	private IAppConfig&MockObject $appConfig;
76
-	private IAppManager&MockObject $appManager;
77
-	private ContainerInterface&MockObject $serverContainer;
78
-	private IUserStatusManager&MockObject $userStatusManager;
79
-	private IPreview&MockObject $previewManager;
80
-	private IDateTimeZone&MockObject $dateTimeZone;
81
-	private LoggerInterface&MockObject $logger;
82
-	private IProviderFactory&MockObject $factory;
83
-	private IMailer&MockObject $mailer;
84
-	private ITagManager&MockObject $tagManager;
85
-
86
-	protected function setUp(): void {
87
-		$this->shareManager = $this->createMock(IManager::class);
88
-		$this->shareManager
89
-			->expects($this->any())
90
-			->method('shareApiEnabled')
91
-			->willReturn(true);
92
-		$this->shareManager
93
-			->expects($this->any())
94
-			->method('shareProviderExists')->willReturn(true);
95
-		$this->groupManager = $this->createMock(IGroupManager::class);
96
-		$this->userManager = $this->createMock(IUserManager::class);
97
-		$this->request = $this->createMock(IRequest::class);
98
-		$this->rootFolder = $this->createMock(IRootFolder::class);
99
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
100
-		$this->currentUser = 'currentUser';
101
-
102
-		$this->l = $this->createMock(IL10N::class);
103
-		$this->l->method('t')
104
-			->willReturnCallback(function ($text, $parameters = []) {
105
-				return vsprintf($text, $parameters);
106
-			});
107
-		$this->config = $this->createMock(IConfig::class);
108
-		$this->appConfig = $this->createMock(IAppConfig::class);
109
-		$this->appManager = $this->createMock(IAppManager::class);
110
-		$this->serverContainer = $this->createMock(ContainerInterface::class);
111
-		$this->userStatusManager = $this->createMock(IUserStatusManager::class);
112
-		$this->previewManager = $this->createMock(IPreview::class);
113
-		$this->previewManager->method('isAvailable')
114
-			->willReturnCallback(function ($fileInfo) {
115
-				return $fileInfo->getMimeType() === 'mimeWithPreview';
116
-			});
117
-		$this->dateTimeZone = $this->createMock(IDateTimeZone::class);
118
-		$this->logger = $this->createMock(LoggerInterface::class);
119
-		$this->factory = $this->createMock(IProviderFactory::class);
120
-		$this->mailer = $this->createMock(IMailer::class);
121
-		$this->tagManager = $this->createMock(ITagManager::class);
122
-
123
-		$this->ocs = new ShareAPIController(
124
-			$this->appName,
125
-			$this->request,
126
-			$this->shareManager,
127
-			$this->groupManager,
128
-			$this->userManager,
129
-			$this->rootFolder,
130
-			$this->urlGenerator,
131
-			$this->l,
132
-			$this->config,
133
-			$this->appConfig,
134
-			$this->appManager,
135
-			$this->serverContainer,
136
-			$this->userStatusManager,
137
-			$this->previewManager,
138
-			$this->dateTimeZone,
139
-			$this->logger,
140
-			$this->factory,
141
-			$this->mailer,
142
-			$this->tagManager,
143
-			$this->currentUser,
144
-		);
145
-	}
146
-
147
-	/**
148
-	 * @return ShareAPIController&MockObject
149
-	 */
150
-	private function mockFormatShare() {
151
-		return $this->getMockBuilder(ShareAPIController::class)
152
-			->setConstructorArgs([
153
-				$this->appName,
154
-				$this->request,
155
-				$this->shareManager,
156
-				$this->groupManager,
157
-				$this->userManager,
158
-				$this->rootFolder,
159
-				$this->urlGenerator,
160
-				$this->l,
161
-				$this->config,
162
-				$this->appConfig,
163
-				$this->appManager,
164
-				$this->serverContainer,
165
-				$this->userStatusManager,
166
-				$this->previewManager,
167
-				$this->dateTimeZone,
168
-				$this->logger,
169
-				$this->factory,
170
-				$this->mailer,
171
-				$this->tagManager,
172
-				$this->currentUser,
173
-			])->onlyMethods(['formatShare'])
174
-			->getMock();
175
-	}
176
-
177
-	private function newShare() {
178
-		return Server::get(IManager::class)->newShare();
179
-	}
180
-
181
-
182
-	private function mockShareAttributes() {
183
-		$formattedShareAttributes = [
184
-			[
185
-				'scope' => 'permissions',
186
-				'key' => 'download',
187
-				'value' => true
188
-			]
189
-		];
190
-
191
-		$shareAttributes = $this->createMock(IShareAttributes::class);
192
-		$shareAttributes->method('toArray')->willReturn($formattedShareAttributes);
193
-		$shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
194
-
195
-		// send both IShare attributes class and expected json string
196
-		return [$shareAttributes, \json_encode($formattedShareAttributes)];
197
-	}
198
-
199
-	public function testDeleteShareShareNotFound(): void {
200
-		$this->expectException(OCSNotFoundException::class);
201
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
202
-
203
-		$this->shareManager
204
-			->expects($this->exactly(7))
205
-			->method('getShareById')
206
-			->willReturnCallback(function ($id): void {
207
-				if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42' || $id === 'deck:42' || $id === 'sciencemesh:42') {
208
-					throw new ShareNotFound();
209
-				} else {
210
-					throw new \Exception();
211
-				}
212
-			});
213
-
214
-		$this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
215
-
216
-		$this->ocs->deleteShare(42);
217
-	}
218
-
219
-	public function testDeleteShare(): void {
220
-		$node = $this->getMockBuilder(File::class)->getMock();
221
-
222
-		$share = $this->newShare();
223
-		$share->setSharedBy($this->currentUser)
224
-			->setNode($node);
225
-		$this->shareManager
226
-			->expects($this->once())
227
-			->method('getShareById')
228
-			->with('ocinternal:42')
229
-			->willReturn($share);
230
-		$this->shareManager
231
-			->expects($this->once())
232
-			->method('deleteShare')
233
-			->with($share);
234
-
235
-		$node->expects($this->once())
236
-			->method('lock')
237
-			->with(ILockingProvider::LOCK_SHARED);
238
-
239
-		$expected = new DataResponse();
240
-		$result = $this->ocs->deleteShare(42);
241
-
242
-		$this->assertInstanceOf(get_class($expected), $result);
243
-		$this->assertEquals($expected->getData(), $result->getData());
244
-	}
245
-
246
-
247
-	public function testDeleteShareLocked(): void {
248
-		$this->expectException(OCSNotFoundException::class);
249
-		$this->expectExceptionMessage('Could not delete share');
250
-
251
-		$node = $this->getMockBuilder(File::class)->getMock();
252
-		$node->method('getId')->willReturn(1);
253
-
254
-		$share = $this->newShare();
255
-		$share->setNode($node);
256
-
257
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
258
-		$this->rootFolder->method('getUserFolder')
259
-			->with($this->currentUser)
260
-			->willReturn($userFolder);
261
-
262
-		$userFolder->method('getById')
263
-			->with($share->getNodeId())
264
-			->willReturn([$node]);
265
-
266
-		$this->shareManager
267
-			->expects($this->once())
268
-			->method('getShareById')
269
-			->with('ocinternal:42')
270
-			->willReturn($share);
271
-
272
-		$this->shareManager
273
-			->expects($this->never())
274
-			->method('deleteShare')
275
-			->with($share);
276
-
277
-		$node->expects($this->once())
278
-			->method('lock')
279
-			->with(ILockingProvider::LOCK_SHARED)
280
-			->willThrowException(new LockedException('mypath'));
281
-
282
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
283
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
284
-
285
-		$this->ocs->deleteShare(42);
286
-	}
287
-
288
-	/**
289
-	 * You can always remove a share that was shared with you
290
-	 */
291
-	public function testDeleteShareWithMe(): void {
292
-		$node = $this->getMockBuilder(File::class)->getMock();
293
-
294
-		$share = $this->newShare();
295
-		$share->setSharedWith($this->currentUser)
296
-			->setShareType(IShare::TYPE_USER)
297
-			->setNode($node);
298
-
299
-		$this->shareManager
300
-			->expects($this->once())
301
-			->method('getShareById')
302
-			->with('ocinternal:42')
303
-			->willReturn($share);
304
-
305
-		$this->shareManager
306
-			->expects($this->once())
307
-			->method('deleteShare')
308
-			->with($share);
309
-
310
-		$node->expects($this->once())
311
-			->method('lock')
312
-			->with(ILockingProvider::LOCK_SHARED);
313
-
314
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
315
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
316
-
317
-		$this->ocs->deleteShare(42);
318
-	}
319
-
320
-	/**
321
-	 * You can always delete a share you own
322
-	 */
323
-	public function testDeleteShareOwner(): void {
324
-		$node = $this->getMockBuilder(File::class)->getMock();
325
-
326
-		$share = $this->newShare();
327
-		$share->setSharedBy($this->currentUser)
328
-			->setNode($node);
329
-
330
-		$this->shareManager
331
-			->expects($this->once())
332
-			->method('getShareById')
333
-			->with('ocinternal:42')
334
-			->willReturn($share);
335
-
336
-		$this->shareManager
337
-			->expects($this->once())
338
-			->method('deleteShare')
339
-			->with($share);
340
-
341
-		$node->expects($this->once())
342
-			->method('lock')
343
-			->with(ILockingProvider::LOCK_SHARED);
344
-
345
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
346
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
347
-
348
-		$this->ocs->deleteShare(42);
349
-	}
350
-
351
-	/**
352
-	 * You can always delete a share when you own
353
-	 * the file path it belong to
354
-	 */
355
-	public function testDeleteShareFileOwner(): void {
356
-		$node = $this->getMockBuilder(File::class)->getMock();
357
-		$node->method('getId')->willReturn(1);
358
-
359
-		$share = $this->newShare();
360
-		$share->setShareOwner($this->currentUser)
361
-			->setNode($node);
362
-
363
-		$this->shareManager
364
-			->expects($this->once())
365
-			->method('getShareById')
366
-			->with('ocinternal:42')
367
-			->willReturn($share);
368
-
369
-		$this->shareManager
370
-			->expects($this->once())
371
-			->method('deleteShare')
372
-			->with($share);
373
-
374
-		$node->expects($this->once())
375
-			->method('lock')
376
-			->with(ILockingProvider::LOCK_SHARED);
377
-
378
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
379
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
380
-
381
-		$this->ocs->deleteShare(42);
382
-	}
383
-
384
-	/**
385
-	 * You can remove (the mountpoint, not the share)
386
-	 * a share if you're in the group the share is shared with
387
-	 */
388
-	public function testDeleteSharedWithMyGroup(): void {
389
-		$node = $this->getMockBuilder(File::class)->getMock();
390
-		$node->method('getId')->willReturn(1);
391
-
392
-		$share = $this->newShare();
393
-		$share->setShareType(IShare::TYPE_GROUP)
394
-			->setSharedWith('group')
395
-			->setNode($node);
396
-
397
-		$this->shareManager
398
-			->expects($this->once())
399
-			->method('getShareById')
400
-			->with('ocinternal:42')
401
-			->willReturn($share);
402
-
403
-		// canDeleteShareFromSelf
404
-		$user = $this->createMock(IUser::class);
405
-		$group = $this->getMockBuilder(IGroup::class)->getMock();
406
-		$this->groupManager
407
-			->method('get')
408
-			->with('group')
409
-			->willReturn($group);
410
-		$this->userManager
411
-			->method('get')
412
-			->with($this->currentUser)
413
-			->willReturn($user);
414
-		$group->method('inGroup')
415
-			->with($user)
416
-			->willReturn(true);
417
-
418
-		$node->expects($this->once())
419
-			->method('lock')
420
-			->with(ILockingProvider::LOCK_SHARED);
421
-
422
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
423
-		$this->rootFolder->method('getUserFolder')
424
-			->with($this->currentUser)
425
-			->willReturn($userFolder);
426
-
427
-		$userFolder->method('getById')
428
-			->with($share->getNodeId())
429
-			->willReturn([$share->getNode()]);
430
-
431
-		$this->shareManager->expects($this->once())
432
-			->method('deleteFromSelf')
433
-			->with($share, $this->currentUser);
434
-
435
-		$this->shareManager->expects($this->never())
436
-			->method('deleteShare');
437
-
438
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
439
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
440
-
441
-		$this->ocs->deleteShare(42);
442
-	}
443
-
444
-	/**
445
-	 * You cannot remove a share if you're not
446
-	 * in the group the share is shared with
447
-	 */
448
-	public function testDeleteSharedWithGroupIDontBelongTo(): void {
449
-		$this->expectException(OCSNotFoundException::class);
450
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
451
-
452
-		$node = $this->getMockBuilder(File::class)->getMock();
453
-		$node->method('getId')->willReturn(42);
454
-
455
-		$share = $this->newShare();
456
-		$share->setShareType(IShare::TYPE_GROUP)
457
-			->setSharedWith('group')
458
-			->setNode($node);
459
-
460
-		$this->shareManager
461
-			->expects($this->once())
462
-			->method('getShareById')
463
-			->with('ocinternal:42')
464
-			->willReturn($share);
465
-
466
-		// canDeleteShareFromSelf
467
-		$user = $this->createMock(IUser::class);
468
-		$group = $this->getMockBuilder(IGroup::class)->getMock();
469
-		$this->groupManager
470
-			->method('get')
471
-			->with('group')
472
-			->willReturn($group);
473
-		$this->userManager
474
-			->method('get')
475
-			->with($this->currentUser)
476
-			->willReturn($user);
477
-		$group->method('inGroup')
478
-			->with($user)
479
-			->willReturn(false);
480
-
481
-		$node->expects($this->once())
482
-			->method('lock')
483
-			->with(ILockingProvider::LOCK_SHARED);
484
-
485
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
486
-		$this->rootFolder->method('getUserFolder')
487
-			->with($this->currentUser)
488
-			->willReturn($userFolder);
489
-
490
-		$userFolder->method('getById')
491
-			->with($share->getNodeId())
492
-			->willReturn([$share->getNode()]);
493
-
494
-		$this->shareManager->expects($this->never())
495
-			->method('deleteFromSelf');
496
-
497
-		$this->shareManager->expects($this->never())
498
-			->method('deleteShare');
499
-
500
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
501
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
502
-
503
-		$this->ocs->deleteShare(42);
504
-	}
505
-
506
-	public function testDeleteShareOwnerless(): void {
507
-		$ocs = $this->mockFormatShare();
508
-
509
-		$mount = $this->createMock(IShareOwnerlessMount::class);
510
-
511
-		$file = $this->createMock(File::class);
512
-		$file
513
-			->expects($this->exactly(2))
514
-			->method('getPermissions')
515
-			->willReturn(Constants::PERMISSION_SHARE);
516
-		$file
517
-			->expects($this->once())
518
-			->method('getMountPoint')
519
-			->willReturn($mount);
520
-
521
-		$userFolder = $this->createMock(Folder::class);
522
-		$userFolder->method('getById')
523
-			->with(2)
524
-			->willReturn([$file]);
525
-		$userFolder->method('getFirstNodeById')
526
-			->with(2)
527
-			->willReturn($file);
528
-
529
-		$this->rootFolder
530
-			->method('getUserFolder')
531
-			->with($this->currentUser)
532
-			->willReturn($userFolder);
533
-
534
-		$share = $this->createMock(IShare::class);
535
-		$share
536
-			->expects($this->once())
537
-			->method('getNode')
538
-			->willReturn($file);
539
-		$share
540
-			->expects($this->exactly(2))
541
-			->method('getNodeId')
542
-			->willReturn(2);
543
-		$share
544
-			->expects($this->exactly(2))
545
-			->method('getPermissions')
546
-			->willReturn(Constants::PERMISSION_SHARE);
547
-
548
-		$this->shareManager
549
-			->expects($this->once())
550
-			->method('getShareById')
551
-			->with('ocinternal:1', $this->currentUser)
552
-			->willReturn($share);
553
-
554
-		$this->shareManager
555
-			->expects($this->once())
556
-			->method('deleteShare')
557
-			->with($share);
558
-
559
-		$result = $ocs->deleteShare(1);
560
-		$this->assertInstanceOf(DataResponse::class, $result);
561
-	}
562
-
563
-	/*
62
+    private string $appName = 'files_sharing';
63
+    private string $currentUser;
64
+
65
+    private ShareAPIController $ocs;
66
+
67
+    private IManager&MockObject $shareManager;
68
+    private IGroupManager&MockObject $groupManager;
69
+    private IUserManager&MockObject $userManager;
70
+    private IRequest&MockObject $request;
71
+    private IRootFolder&MockObject $rootFolder;
72
+    private IURLGenerator&MockObject $urlGenerator;
73
+    private IL10N&MockObject $l;
74
+    private IConfig&MockObject $config;
75
+    private IAppConfig&MockObject $appConfig;
76
+    private IAppManager&MockObject $appManager;
77
+    private ContainerInterface&MockObject $serverContainer;
78
+    private IUserStatusManager&MockObject $userStatusManager;
79
+    private IPreview&MockObject $previewManager;
80
+    private IDateTimeZone&MockObject $dateTimeZone;
81
+    private LoggerInterface&MockObject $logger;
82
+    private IProviderFactory&MockObject $factory;
83
+    private IMailer&MockObject $mailer;
84
+    private ITagManager&MockObject $tagManager;
85
+
86
+    protected function setUp(): void {
87
+        $this->shareManager = $this->createMock(IManager::class);
88
+        $this->shareManager
89
+            ->expects($this->any())
90
+            ->method('shareApiEnabled')
91
+            ->willReturn(true);
92
+        $this->shareManager
93
+            ->expects($this->any())
94
+            ->method('shareProviderExists')->willReturn(true);
95
+        $this->groupManager = $this->createMock(IGroupManager::class);
96
+        $this->userManager = $this->createMock(IUserManager::class);
97
+        $this->request = $this->createMock(IRequest::class);
98
+        $this->rootFolder = $this->createMock(IRootFolder::class);
99
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
100
+        $this->currentUser = 'currentUser';
101
+
102
+        $this->l = $this->createMock(IL10N::class);
103
+        $this->l->method('t')
104
+            ->willReturnCallback(function ($text, $parameters = []) {
105
+                return vsprintf($text, $parameters);
106
+            });
107
+        $this->config = $this->createMock(IConfig::class);
108
+        $this->appConfig = $this->createMock(IAppConfig::class);
109
+        $this->appManager = $this->createMock(IAppManager::class);
110
+        $this->serverContainer = $this->createMock(ContainerInterface::class);
111
+        $this->userStatusManager = $this->createMock(IUserStatusManager::class);
112
+        $this->previewManager = $this->createMock(IPreview::class);
113
+        $this->previewManager->method('isAvailable')
114
+            ->willReturnCallback(function ($fileInfo) {
115
+                return $fileInfo->getMimeType() === 'mimeWithPreview';
116
+            });
117
+        $this->dateTimeZone = $this->createMock(IDateTimeZone::class);
118
+        $this->logger = $this->createMock(LoggerInterface::class);
119
+        $this->factory = $this->createMock(IProviderFactory::class);
120
+        $this->mailer = $this->createMock(IMailer::class);
121
+        $this->tagManager = $this->createMock(ITagManager::class);
122
+
123
+        $this->ocs = new ShareAPIController(
124
+            $this->appName,
125
+            $this->request,
126
+            $this->shareManager,
127
+            $this->groupManager,
128
+            $this->userManager,
129
+            $this->rootFolder,
130
+            $this->urlGenerator,
131
+            $this->l,
132
+            $this->config,
133
+            $this->appConfig,
134
+            $this->appManager,
135
+            $this->serverContainer,
136
+            $this->userStatusManager,
137
+            $this->previewManager,
138
+            $this->dateTimeZone,
139
+            $this->logger,
140
+            $this->factory,
141
+            $this->mailer,
142
+            $this->tagManager,
143
+            $this->currentUser,
144
+        );
145
+    }
146
+
147
+    /**
148
+     * @return ShareAPIController&MockObject
149
+     */
150
+    private function mockFormatShare() {
151
+        return $this->getMockBuilder(ShareAPIController::class)
152
+            ->setConstructorArgs([
153
+                $this->appName,
154
+                $this->request,
155
+                $this->shareManager,
156
+                $this->groupManager,
157
+                $this->userManager,
158
+                $this->rootFolder,
159
+                $this->urlGenerator,
160
+                $this->l,
161
+                $this->config,
162
+                $this->appConfig,
163
+                $this->appManager,
164
+                $this->serverContainer,
165
+                $this->userStatusManager,
166
+                $this->previewManager,
167
+                $this->dateTimeZone,
168
+                $this->logger,
169
+                $this->factory,
170
+                $this->mailer,
171
+                $this->tagManager,
172
+                $this->currentUser,
173
+            ])->onlyMethods(['formatShare'])
174
+            ->getMock();
175
+    }
176
+
177
+    private function newShare() {
178
+        return Server::get(IManager::class)->newShare();
179
+    }
180
+
181
+
182
+    private function mockShareAttributes() {
183
+        $formattedShareAttributes = [
184
+            [
185
+                'scope' => 'permissions',
186
+                'key' => 'download',
187
+                'value' => true
188
+            ]
189
+        ];
190
+
191
+        $shareAttributes = $this->createMock(IShareAttributes::class);
192
+        $shareAttributes->method('toArray')->willReturn($formattedShareAttributes);
193
+        $shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
194
+
195
+        // send both IShare attributes class and expected json string
196
+        return [$shareAttributes, \json_encode($formattedShareAttributes)];
197
+    }
198
+
199
+    public function testDeleteShareShareNotFound(): void {
200
+        $this->expectException(OCSNotFoundException::class);
201
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
202
+
203
+        $this->shareManager
204
+            ->expects($this->exactly(7))
205
+            ->method('getShareById')
206
+            ->willReturnCallback(function ($id): void {
207
+                if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42' || $id === 'deck:42' || $id === 'sciencemesh:42') {
208
+                    throw new ShareNotFound();
209
+                } else {
210
+                    throw new \Exception();
211
+                }
212
+            });
213
+
214
+        $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
215
+
216
+        $this->ocs->deleteShare(42);
217
+    }
218
+
219
+    public function testDeleteShare(): void {
220
+        $node = $this->getMockBuilder(File::class)->getMock();
221
+
222
+        $share = $this->newShare();
223
+        $share->setSharedBy($this->currentUser)
224
+            ->setNode($node);
225
+        $this->shareManager
226
+            ->expects($this->once())
227
+            ->method('getShareById')
228
+            ->with('ocinternal:42')
229
+            ->willReturn($share);
230
+        $this->shareManager
231
+            ->expects($this->once())
232
+            ->method('deleteShare')
233
+            ->with($share);
234
+
235
+        $node->expects($this->once())
236
+            ->method('lock')
237
+            ->with(ILockingProvider::LOCK_SHARED);
238
+
239
+        $expected = new DataResponse();
240
+        $result = $this->ocs->deleteShare(42);
241
+
242
+        $this->assertInstanceOf(get_class($expected), $result);
243
+        $this->assertEquals($expected->getData(), $result->getData());
244
+    }
245
+
246
+
247
+    public function testDeleteShareLocked(): void {
248
+        $this->expectException(OCSNotFoundException::class);
249
+        $this->expectExceptionMessage('Could not delete share');
250
+
251
+        $node = $this->getMockBuilder(File::class)->getMock();
252
+        $node->method('getId')->willReturn(1);
253
+
254
+        $share = $this->newShare();
255
+        $share->setNode($node);
256
+
257
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
258
+        $this->rootFolder->method('getUserFolder')
259
+            ->with($this->currentUser)
260
+            ->willReturn($userFolder);
261
+
262
+        $userFolder->method('getById')
263
+            ->with($share->getNodeId())
264
+            ->willReturn([$node]);
265
+
266
+        $this->shareManager
267
+            ->expects($this->once())
268
+            ->method('getShareById')
269
+            ->with('ocinternal:42')
270
+            ->willReturn($share);
271
+
272
+        $this->shareManager
273
+            ->expects($this->never())
274
+            ->method('deleteShare')
275
+            ->with($share);
276
+
277
+        $node->expects($this->once())
278
+            ->method('lock')
279
+            ->with(ILockingProvider::LOCK_SHARED)
280
+            ->willThrowException(new LockedException('mypath'));
281
+
282
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
283
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
284
+
285
+        $this->ocs->deleteShare(42);
286
+    }
287
+
288
+    /**
289
+     * You can always remove a share that was shared with you
290
+     */
291
+    public function testDeleteShareWithMe(): void {
292
+        $node = $this->getMockBuilder(File::class)->getMock();
293
+
294
+        $share = $this->newShare();
295
+        $share->setSharedWith($this->currentUser)
296
+            ->setShareType(IShare::TYPE_USER)
297
+            ->setNode($node);
298
+
299
+        $this->shareManager
300
+            ->expects($this->once())
301
+            ->method('getShareById')
302
+            ->with('ocinternal:42')
303
+            ->willReturn($share);
304
+
305
+        $this->shareManager
306
+            ->expects($this->once())
307
+            ->method('deleteShare')
308
+            ->with($share);
309
+
310
+        $node->expects($this->once())
311
+            ->method('lock')
312
+            ->with(ILockingProvider::LOCK_SHARED);
313
+
314
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
315
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
316
+
317
+        $this->ocs->deleteShare(42);
318
+    }
319
+
320
+    /**
321
+     * You can always delete a share you own
322
+     */
323
+    public function testDeleteShareOwner(): void {
324
+        $node = $this->getMockBuilder(File::class)->getMock();
325
+
326
+        $share = $this->newShare();
327
+        $share->setSharedBy($this->currentUser)
328
+            ->setNode($node);
329
+
330
+        $this->shareManager
331
+            ->expects($this->once())
332
+            ->method('getShareById')
333
+            ->with('ocinternal:42')
334
+            ->willReturn($share);
335
+
336
+        $this->shareManager
337
+            ->expects($this->once())
338
+            ->method('deleteShare')
339
+            ->with($share);
340
+
341
+        $node->expects($this->once())
342
+            ->method('lock')
343
+            ->with(ILockingProvider::LOCK_SHARED);
344
+
345
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
346
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
347
+
348
+        $this->ocs->deleteShare(42);
349
+    }
350
+
351
+    /**
352
+     * You can always delete a share when you own
353
+     * the file path it belong to
354
+     */
355
+    public function testDeleteShareFileOwner(): void {
356
+        $node = $this->getMockBuilder(File::class)->getMock();
357
+        $node->method('getId')->willReturn(1);
358
+
359
+        $share = $this->newShare();
360
+        $share->setShareOwner($this->currentUser)
361
+            ->setNode($node);
362
+
363
+        $this->shareManager
364
+            ->expects($this->once())
365
+            ->method('getShareById')
366
+            ->with('ocinternal:42')
367
+            ->willReturn($share);
368
+
369
+        $this->shareManager
370
+            ->expects($this->once())
371
+            ->method('deleteShare')
372
+            ->with($share);
373
+
374
+        $node->expects($this->once())
375
+            ->method('lock')
376
+            ->with(ILockingProvider::LOCK_SHARED);
377
+
378
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
379
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
380
+
381
+        $this->ocs->deleteShare(42);
382
+    }
383
+
384
+    /**
385
+     * You can remove (the mountpoint, not the share)
386
+     * a share if you're in the group the share is shared with
387
+     */
388
+    public function testDeleteSharedWithMyGroup(): void {
389
+        $node = $this->getMockBuilder(File::class)->getMock();
390
+        $node->method('getId')->willReturn(1);
391
+
392
+        $share = $this->newShare();
393
+        $share->setShareType(IShare::TYPE_GROUP)
394
+            ->setSharedWith('group')
395
+            ->setNode($node);
396
+
397
+        $this->shareManager
398
+            ->expects($this->once())
399
+            ->method('getShareById')
400
+            ->with('ocinternal:42')
401
+            ->willReturn($share);
402
+
403
+        // canDeleteShareFromSelf
404
+        $user = $this->createMock(IUser::class);
405
+        $group = $this->getMockBuilder(IGroup::class)->getMock();
406
+        $this->groupManager
407
+            ->method('get')
408
+            ->with('group')
409
+            ->willReturn($group);
410
+        $this->userManager
411
+            ->method('get')
412
+            ->with($this->currentUser)
413
+            ->willReturn($user);
414
+        $group->method('inGroup')
415
+            ->with($user)
416
+            ->willReturn(true);
417
+
418
+        $node->expects($this->once())
419
+            ->method('lock')
420
+            ->with(ILockingProvider::LOCK_SHARED);
421
+
422
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
423
+        $this->rootFolder->method('getUserFolder')
424
+            ->with($this->currentUser)
425
+            ->willReturn($userFolder);
426
+
427
+        $userFolder->method('getById')
428
+            ->with($share->getNodeId())
429
+            ->willReturn([$share->getNode()]);
430
+
431
+        $this->shareManager->expects($this->once())
432
+            ->method('deleteFromSelf')
433
+            ->with($share, $this->currentUser);
434
+
435
+        $this->shareManager->expects($this->never())
436
+            ->method('deleteShare');
437
+
438
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
439
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
440
+
441
+        $this->ocs->deleteShare(42);
442
+    }
443
+
444
+    /**
445
+     * You cannot remove a share if you're not
446
+     * in the group the share is shared with
447
+     */
448
+    public function testDeleteSharedWithGroupIDontBelongTo(): void {
449
+        $this->expectException(OCSNotFoundException::class);
450
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
451
+
452
+        $node = $this->getMockBuilder(File::class)->getMock();
453
+        $node->method('getId')->willReturn(42);
454
+
455
+        $share = $this->newShare();
456
+        $share->setShareType(IShare::TYPE_GROUP)
457
+            ->setSharedWith('group')
458
+            ->setNode($node);
459
+
460
+        $this->shareManager
461
+            ->expects($this->once())
462
+            ->method('getShareById')
463
+            ->with('ocinternal:42')
464
+            ->willReturn($share);
465
+
466
+        // canDeleteShareFromSelf
467
+        $user = $this->createMock(IUser::class);
468
+        $group = $this->getMockBuilder(IGroup::class)->getMock();
469
+        $this->groupManager
470
+            ->method('get')
471
+            ->with('group')
472
+            ->willReturn($group);
473
+        $this->userManager
474
+            ->method('get')
475
+            ->with($this->currentUser)
476
+            ->willReturn($user);
477
+        $group->method('inGroup')
478
+            ->with($user)
479
+            ->willReturn(false);
480
+
481
+        $node->expects($this->once())
482
+            ->method('lock')
483
+            ->with(ILockingProvider::LOCK_SHARED);
484
+
485
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
486
+        $this->rootFolder->method('getUserFolder')
487
+            ->with($this->currentUser)
488
+            ->willReturn($userFolder);
489
+
490
+        $userFolder->method('getById')
491
+            ->with($share->getNodeId())
492
+            ->willReturn([$share->getNode()]);
493
+
494
+        $this->shareManager->expects($this->never())
495
+            ->method('deleteFromSelf');
496
+
497
+        $this->shareManager->expects($this->never())
498
+            ->method('deleteShare');
499
+
500
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
501
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
502
+
503
+        $this->ocs->deleteShare(42);
504
+    }
505
+
506
+    public function testDeleteShareOwnerless(): void {
507
+        $ocs = $this->mockFormatShare();
508
+
509
+        $mount = $this->createMock(IShareOwnerlessMount::class);
510
+
511
+        $file = $this->createMock(File::class);
512
+        $file
513
+            ->expects($this->exactly(2))
514
+            ->method('getPermissions')
515
+            ->willReturn(Constants::PERMISSION_SHARE);
516
+        $file
517
+            ->expects($this->once())
518
+            ->method('getMountPoint')
519
+            ->willReturn($mount);
520
+
521
+        $userFolder = $this->createMock(Folder::class);
522
+        $userFolder->method('getById')
523
+            ->with(2)
524
+            ->willReturn([$file]);
525
+        $userFolder->method('getFirstNodeById')
526
+            ->with(2)
527
+            ->willReturn($file);
528
+
529
+        $this->rootFolder
530
+            ->method('getUserFolder')
531
+            ->with($this->currentUser)
532
+            ->willReturn($userFolder);
533
+
534
+        $share = $this->createMock(IShare::class);
535
+        $share
536
+            ->expects($this->once())
537
+            ->method('getNode')
538
+            ->willReturn($file);
539
+        $share
540
+            ->expects($this->exactly(2))
541
+            ->method('getNodeId')
542
+            ->willReturn(2);
543
+        $share
544
+            ->expects($this->exactly(2))
545
+            ->method('getPermissions')
546
+            ->willReturn(Constants::PERMISSION_SHARE);
547
+
548
+        $this->shareManager
549
+            ->expects($this->once())
550
+            ->method('getShareById')
551
+            ->with('ocinternal:1', $this->currentUser)
552
+            ->willReturn($share);
553
+
554
+        $this->shareManager
555
+            ->expects($this->once())
556
+            ->method('deleteShare')
557
+            ->with($share);
558
+
559
+        $result = $ocs->deleteShare(1);
560
+        $this->assertInstanceOf(DataResponse::class, $result);
561
+    }
562
+
563
+    /*
564 564
 	 * FIXME: Enable once we have a federated Share Provider
565 565
 
566 566
 	public function testGetGetShareNotExists() {
@@ -575,4657 +575,4657 @@  discard block
 block discarded – undo
575 575
 	}
576 576
 	*/
577 577
 
578
-	public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions,
579
-		$shareTime, $expiration, $parent, $target, $mail_send, $note = '', $token = null,
580
-		$password = null, $label = '', $attributes = null) {
581
-		$share = $this->getMockBuilder(IShare::class)->getMock();
582
-		$share->method('getId')->willReturn($id);
583
-		$share->method('getShareType')->willReturn($shareType);
584
-		$share->method('getSharedWith')->willReturn($sharedWith);
585
-		$share->method('getSharedBy')->willReturn($sharedBy);
586
-		$share->method('getShareOwner')->willReturn($shareOwner);
587
-		$share->method('getNode')->willReturn($path);
588
-		$share->method('getPermissions')->willReturn($permissions);
589
-		$share->method('getNote')->willReturn($note);
590
-		$share->method('getLabel')->willReturn($label);
591
-		$share->method('getAttributes')->willReturn($attributes);
592
-		$time = new \DateTime();
593
-		$time->setTimestamp($shareTime);
594
-		$share->method('getShareTime')->willReturn($time);
595
-		$share->method('getExpirationDate')->willReturn($expiration);
596
-		$share->method('getTarget')->willReturn($target);
597
-		$share->method('getMailSend')->willReturn($mail_send);
598
-		$share->method('getToken')->willReturn($token);
599
-		$share->method('getPassword')->willReturn($password);
600
-
601
-		if ($shareType === IShare::TYPE_USER
602
-			|| $shareType === IShare::TYPE_GROUP
603
-			|| $shareType === IShare::TYPE_LINK) {
604
-			$share->method('getFullId')->willReturn('ocinternal:' . $id);
605
-		}
606
-
607
-		return $share;
608
-	}
609
-
610
-	public function dataGetShare() {
611
-		$data = [];
612
-
613
-		$cache = $this->getMockBuilder('OC\Files\Cache\Cache')
614
-			->disableOriginalConstructor()
615
-			->getMock();
616
-		$cache->method('getNumericStorageId')->willReturn(101);
617
-
618
-		$storage = $this->getMockBuilder(IStorage::class)
619
-			->disableOriginalConstructor()
620
-			->getMock();
621
-		$storage->method('getId')->willReturn('STORAGE');
622
-		$storage->method('getCache')->willReturn($cache);
623
-
624
-		$parentFolder = $this->getMockBuilder(Folder::class)->getMock();
625
-		$parentFolder->method('getId')->willReturn(3);
626
-		$mountPoint = $this->createMock(IMountPoint::class);
627
-		$mountPoint->method('getMountType')->willReturn('');
628
-
629
-		$file = $this->getMockBuilder('OCP\Files\File')->getMock();
630
-		$file->method('getId')->willReturn(1);
631
-		$file->method('getPath')->willReturn('file');
632
-		$file->method('getStorage')->willReturn($storage);
633
-		$file->method('getParent')->willReturn($parentFolder);
634
-		$file->method('getSize')->willReturn(123465);
635
-		$file->method('getMTime')->willReturn(1234567890);
636
-		$file->method('getMimeType')->willReturn('myMimeType');
637
-		$file->method('getMountPoint')->willReturn($mountPoint);
638
-
639
-		$folder = $this->getMockBuilder(Folder::class)->getMock();
640
-		$folder->method('getId')->willReturn(2);
641
-		$folder->method('getPath')->willReturn('folder');
642
-		$folder->method('getStorage')->willReturn($storage);
643
-		$folder->method('getParent')->willReturn($parentFolder);
644
-		$folder->method('getSize')->willReturn(123465);
645
-		$folder->method('getMTime')->willReturn(1234567890);
646
-		$folder->method('getMimeType')->willReturn('myFolderMimeType');
647
-		$folder->method('getMountPoint')->willReturn($mountPoint);
648
-
649
-		[$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
650
-
651
-		// File shared with user
652
-		$share = $this->createShare(
653
-			100,
654
-			IShare::TYPE_USER,
655
-			'userId',
656
-			'initiatorId',
657
-			'ownerId',
658
-			$file,
659
-			4,
660
-			5,
661
-			null,
662
-			6,
663
-			'target',
664
-			0,
665
-			'personal note',
666
-			$shareAttributes,
667
-		);
668
-		$expected = [
669
-			'id' => 100,
670
-			'share_type' => IShare::TYPE_USER,
671
-			'share_with' => 'userId',
672
-			'share_with_displayname' => 'userDisplay',
673
-			'share_with_displayname_unique' => '[email protected]',
674
-			'uid_owner' => 'initiatorId',
675
-			'displayname_owner' => 'initiatorDisplay',
676
-			'item_type' => 'file',
677
-			'item_source' => 1,
678
-			'file_source' => 1,
679
-			'file_target' => 'target',
680
-			'file_parent' => 3,
681
-			'token' => null,
682
-			'expiration' => null,
683
-			'permissions' => 4,
684
-			'attributes' => $shareAttributesReturnJson,
685
-			'stime' => 5,
686
-			'parent' => null,
687
-			'storage_id' => 'STORAGE',
688
-			'path' => 'file',
689
-			'storage' => 101,
690
-			'mail_send' => 0,
691
-			'uid_file_owner' => 'ownerId',
692
-			'note' => 'personal note',
693
-			'label' => '',
694
-			'displayname_file_owner' => 'ownerDisplay',
695
-			'mimetype' => 'myMimeType',
696
-			'has_preview' => false,
697
-			'hide_download' => 0,
698
-			'can_edit' => false,
699
-			'can_delete' => false,
700
-			'item_size' => 123465,
701
-			'item_mtime' => 1234567890,
702
-			'attributes' => null,
703
-			'item_permissions' => 4,
704
-			'is-mount-root' => false,
705
-			'mount-type' => '',
706
-		];
707
-		$data[] = [$share, $expected];
708
-
709
-		// Folder shared with group
710
-		$share = $this->createShare(
711
-			101,
712
-			IShare::TYPE_GROUP,
713
-			'groupId',
714
-			'initiatorId',
715
-			'ownerId',
716
-			$folder,
717
-			4,
718
-			5,
719
-			null,
720
-			6,
721
-			'target',
722
-			0,
723
-			'personal note',
724
-			$shareAttributes,
725
-		);
726
-		$expected = [
727
-			'id' => 101,
728
-			'share_type' => IShare::TYPE_GROUP,
729
-			'share_with' => 'groupId',
730
-			'share_with_displayname' => 'groupId',
731
-			'uid_owner' => 'initiatorId',
732
-			'displayname_owner' => 'initiatorDisplay',
733
-			'item_type' => 'folder',
734
-			'item_source' => 2,
735
-			'file_source' => 2,
736
-			'file_target' => 'target',
737
-			'file_parent' => 3,
738
-			'token' => null,
739
-			'expiration' => null,
740
-			'permissions' => 4,
741
-			'attributes' => $shareAttributesReturnJson,
742
-			'stime' => 5,
743
-			'parent' => null,
744
-			'storage_id' => 'STORAGE',
745
-			'path' => 'folder',
746
-			'storage' => 101,
747
-			'mail_send' => 0,
748
-			'uid_file_owner' => 'ownerId',
749
-			'note' => 'personal note',
750
-			'label' => '',
751
-			'displayname_file_owner' => 'ownerDisplay',
752
-			'mimetype' => 'myFolderMimeType',
753
-			'has_preview' => false,
754
-			'hide_download' => 0,
755
-			'can_edit' => false,
756
-			'can_delete' => false,
757
-			'item_size' => 123465,
758
-			'item_mtime' => 1234567890,
759
-			'attributes' => null,
760
-			'item_permissions' => 4,
761
-			'is-mount-root' => false,
762
-			'mount-type' => '',
763
-		];
764
-		$data[] = [$share, $expected];
765
-
766
-		// File shared by link with Expire
767
-		$expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03');
768
-		$share = $this->createShare(
769
-			101,
770
-			IShare::TYPE_LINK,
771
-			null,
772
-			'initiatorId',
773
-			'ownerId',
774
-			$folder,
775
-			4,
776
-			5,
777
-			$expire,
778
-			6,
779
-			'target',
780
-			0,
781
-			'personal note',
782
-			'token',
783
-			'password',
784
-			'first link share'
785
-		);
786
-		$expected = [
787
-			'id' => 101,
788
-			'share_type' => IShare::TYPE_LINK,
789
-			'password' => 'password',
790
-			'share_with' => 'password',
791
-			'share_with_displayname' => '(Shared link)',
792
-			'send_password_by_talk' => false,
793
-			'uid_owner' => 'initiatorId',
794
-			'displayname_owner' => 'initiatorDisplay',
795
-			'item_type' => 'folder',
796
-			'item_source' => 2,
797
-			'file_source' => 2,
798
-			'file_target' => 'target',
799
-			'file_parent' => 3,
800
-			'token' => 'token',
801
-			'expiration' => '2000-01-02 00:00:00',
802
-			'permissions' => 4,
803
-			'attributes' => null,
804
-			'stime' => 5,
805
-			'parent' => null,
806
-			'storage_id' => 'STORAGE',
807
-			'path' => 'folder',
808
-			'storage' => 101,
809
-			'mail_send' => 0,
810
-			'url' => 'url',
811
-			'uid_file_owner' => 'ownerId',
812
-			'note' => 'personal note',
813
-			'label' => 'first link share',
814
-			'displayname_file_owner' => 'ownerDisplay',
815
-			'mimetype' => 'myFolderMimeType',
816
-			'has_preview' => false,
817
-			'hide_download' => 0,
818
-			'can_edit' => false,
819
-			'can_delete' => false,
820
-			'item_size' => 123465,
821
-			'item_mtime' => 1234567890,
822
-			'attributes' => null,
823
-			'item_permissions' => 4,
824
-			'is-mount-root' => false,
825
-			'mount-type' => '',
826
-		];
827
-		$data[] = [$share, $expected];
828
-
829
-		return $data;
830
-	}
831
-
832
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataGetShare')]
833
-	public function testGetShare(IShare $share, array $result): void {
834
-		/** @var ShareAPIController&MockObject $ocs */
835
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
836
-			->setConstructorArgs([
837
-				$this->appName,
838
-				$this->request,
839
-				$this->shareManager,
840
-				$this->groupManager,
841
-				$this->userManager,
842
-				$this->rootFolder,
843
-				$this->urlGenerator,
844
-				$this->l,
845
-				$this->config,
846
-				$this->appConfig,
847
-				$this->appManager,
848
-				$this->serverContainer,
849
-				$this->userStatusManager,
850
-				$this->previewManager,
851
-				$this->dateTimeZone,
852
-				$this->logger,
853
-				$this->factory,
854
-				$this->mailer,
855
-				$this->tagManager,
856
-				$this->currentUser,
857
-			])
858
-			->onlyMethods(['canAccessShare'])
859
-			->getMock();
860
-
861
-		$ocs->expects($this->any())
862
-			->method('canAccessShare')
863
-			->willReturn(true);
864
-
865
-		$this->shareManager
866
-			->expects($this->any())
867
-			->method('getShareById')
868
-			->with($share->getFullId(), 'currentUser')
869
-			->willReturn($share);
870
-
871
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
872
-		$userFolder
873
-			->method('getRelativePath')
874
-			->willReturnArgument(0);
875
-
876
-		$userFolder->method('getById')
877
-			->with($share->getNodeId())
878
-			->willReturn([$share->getNode()]);
879
-		$userFolder->method('getFirstNodeById')
880
-			->with($share->getNodeId())
881
-			->willReturn($share->getNode());
882
-
883
-		$this->rootFolder->method('getUserFolder')
884
-			->with($this->currentUser)
885
-			->willReturn($userFolder);
886
-
887
-		$this->urlGenerator
888
-			->method('linkToRouteAbsolute')
889
-			->willReturn('url');
890
-
891
-		$initiator = $this->getMockBuilder(IUser::class)->getMock();
892
-		$initiator->method('getUID')->willReturn('initiatorId');
893
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
894
-
895
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
896
-		$owner->method('getUID')->willReturn('ownerId');
897
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
898
-
899
-		$user = $this->getMockBuilder(IUser::class)->getMock();
900
-		$user->method('getUID')->willReturn('userId');
901
-		$user->method('getDisplayName')->willReturn('userDisplay');
902
-		$user->method('getSystemEMailAddress')->willReturn('[email protected]');
903
-
904
-		$group = $this->getMockBuilder(IGroup::class)->getMock();
905
-		$group->method('getGID')->willReturn('groupId');
906
-
907
-		$this->userManager->method('get')->willReturnMap([
908
-			['userId', $user],
909
-			['initiatorId', $initiator],
910
-			['ownerId', $owner],
911
-		]);
912
-		$this->groupManager->method('get')->willReturnMap([
913
-			['group', $group],
914
-		]);
915
-		$this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
916
-
917
-		$data = $ocs->getShare($share->getId())->getData()[0];
918
-		$this->assertEquals($result, $data);
919
-	}
920
-
921
-
922
-	public function testGetShareInvalidNode(): void {
923
-		$this->expectException(OCSNotFoundException::class);
924
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
925
-
926
-		$share = Server::get(IManager::class)->newShare();
927
-		$share->setSharedBy('initiator')
928
-			->setSharedWith('recipient')
929
-			->setShareOwner('owner');
930
-
931
-		$this->shareManager
932
-			->expects($this->once())
933
-			->method('getShareById')
934
-			->with('ocinternal:42', 'currentUser')
935
-			->willReturn($share);
936
-
937
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
938
-		$this->rootFolder->method('getUserFolder')
939
-			->with($this->currentUser)
940
-			->willReturn($userFolder);
941
-
942
-		$this->ocs->getShare(42);
943
-	}
944
-
945
-	public function dataGetShares() {
946
-		$folder = $this->getMockBuilder(Folder::class)->getMock();
947
-		$file1 = $this->getMockBuilder(File::class)->getMock();
948
-		$file1->method('getName')
949
-			->willReturn('file1');
950
-		$file2 = $this->getMockBuilder(File::class)->getMock();
951
-		$file2->method('getName')
952
-			->willReturn('file2');
953
-
954
-		$folder->method('getDirectoryListing')
955
-			->willReturn([$file1, $file2]);
956
-
957
-		$file1UserShareOwner = Server::get(IManager::class)->newShare();
958
-		$file1UserShareOwner->setShareType(IShare::TYPE_USER)
959
-			->setSharedWith('recipient')
960
-			->setSharedBy('initiator')
961
-			->setShareOwner('currentUser')
962
-			->setPermissions(Constants::PERMISSION_READ)
963
-			->setNode($file1)
964
-			->setId(4);
965
-
966
-		$file1UserShareOwnerExpected = [
967
-			'id' => 4,
968
-			'share_type' => IShare::TYPE_USER,
969
-		];
970
-
971
-		$file1UserShareInitiator = Server::get(IManager::class)->newShare();
972
-		$file1UserShareInitiator->setShareType(IShare::TYPE_USER)
973
-			->setSharedWith('recipient')
974
-			->setSharedBy('currentUser')
975
-			->setShareOwner('owner')
976
-			->setPermissions(Constants::PERMISSION_READ)
977
-			->setNode($file1)
978
-			->setId(8);
979
-
980
-		$file1UserShareInitiatorExpected = [
981
-			'id' => 8,
982
-			'share_type' => IShare::TYPE_USER,
983
-		];
984
-
985
-		$file1UserShareRecipient = Server::get(IManager::class)->newShare();
986
-		$file1UserShareRecipient->setShareType(IShare::TYPE_USER)
987
-			->setSharedWith('currentUser')
988
-			->setSharedBy('initiator')
989
-			->setShareOwner('owner')
990
-			->setPermissions(Constants::PERMISSION_READ)
991
-			->setNode($file1)
992
-			->setId(15);
993
-
994
-		$file1UserShareRecipientExpected = [
995
-			'id' => 15,
996
-			'share_type' => IShare::TYPE_USER,
997
-		];
998
-
999
-		$file1UserShareOther = Server::get(IManager::class)->newShare();
1000
-		$file1UserShareOther->setShareType(IShare::TYPE_USER)
1001
-			->setSharedWith('recipient')
1002
-			->setSharedBy('initiator')
1003
-			->setShareOwner('owner')
1004
-			->setPermissions(Constants::PERMISSION_READ)
1005
-			->setNode($file1)
1006
-			->setId(16);
1007
-
1008
-		$file1UserShareOtherExpected = [
1009
-			'id' => 16,
1010
-			'share_type' => IShare::TYPE_USER,
1011
-		];
1012
-
1013
-		$file1GroupShareOwner = Server::get(IManager::class)->newShare();
1014
-		$file1GroupShareOwner->setShareType(IShare::TYPE_GROUP)
1015
-			->setSharedWith('recipient')
1016
-			->setSharedBy('initiator')
1017
-			->setShareOwner('currentUser')
1018
-			->setPermissions(Constants::PERMISSION_READ)
1019
-			->setNode($file1)
1020
-			->setId(23);
1021
-
1022
-		$file1GroupShareOwnerExpected = [
1023
-			'id' => 23,
1024
-			'share_type' => IShare::TYPE_GROUP,
1025
-		];
1026
-
1027
-		$file1GroupShareRecipient = Server::get(IManager::class)->newShare();
1028
-		$file1GroupShareRecipient->setShareType(IShare::TYPE_GROUP)
1029
-			->setSharedWith('currentUserGroup')
1030
-			->setSharedBy('initiator')
1031
-			->setShareOwner('owner')
1032
-			->setPermissions(Constants::PERMISSION_READ)
1033
-			->setNode($file1)
1034
-			->setId(42);
1035
-
1036
-		$file1GroupShareRecipientExpected = [
1037
-			'id' => 42,
1038
-			'share_type' => IShare::TYPE_GROUP,
1039
-		];
1040
-
1041
-		$file1GroupShareOther = Server::get(IManager::class)->newShare();
1042
-		$file1GroupShareOther->setShareType(IShare::TYPE_GROUP)
1043
-			->setSharedWith('recipient')
1044
-			->setSharedBy('initiator')
1045
-			->setShareOwner('owner')
1046
-			->setPermissions(Constants::PERMISSION_READ)
1047
-			->setNode($file1)
1048
-			->setId(108);
1049
-
1050
-		$file1LinkShareOwner = Server::get(IManager::class)->newShare();
1051
-		$file1LinkShareOwner->setShareType(IShare::TYPE_LINK)
1052
-			->setSharedWith('recipient')
1053
-			->setSharedBy('initiator')
1054
-			->setShareOwner('currentUser')
1055
-			->setPermissions(Constants::PERMISSION_READ)
1056
-			->setNode($file1)
1057
-			->setId(415);
1058
-
1059
-		$file1LinkShareOwnerExpected = [
1060
-			'id' => 415,
1061
-			'share_type' => IShare::TYPE_LINK,
1062
-		];
1063
-
1064
-		$file1EmailShareOwner = Server::get(IManager::class)->newShare();
1065
-		$file1EmailShareOwner->setShareType(IShare::TYPE_EMAIL)
1066
-			->setSharedWith('recipient')
1067
-			->setSharedBy('initiator')
1068
-			->setShareOwner('currentUser')
1069
-			->setPermissions(Constants::PERMISSION_READ)
1070
-			->setNode($file1)
1071
-			->setId(416);
1072
-
1073
-		$file1EmailShareOwnerExpected = [
1074
-			'id' => 416,
1075
-			'share_type' => IShare::TYPE_EMAIL,
1076
-		];
1077
-
1078
-		$file1CircleShareOwner = Server::get(IManager::class)->newShare();
1079
-		$file1CircleShareOwner->setShareType(IShare::TYPE_CIRCLE)
1080
-			->setSharedWith('recipient')
1081
-			->setSharedBy('initiator')
1082
-			->setShareOwner('currentUser')
1083
-			->setPermissions(Constants::PERMISSION_READ)
1084
-			->setNode($file1)
1085
-			->setId(423);
1086
-
1087
-		$file1CircleShareOwnerExpected = [
1088
-			'id' => 423,
1089
-			'share_type' => IShare::TYPE_CIRCLE,
1090
-		];
1091
-
1092
-		$file1RoomShareOwner = Server::get(IManager::class)->newShare();
1093
-		$file1RoomShareOwner->setShareType(IShare::TYPE_ROOM)
1094
-			->setSharedWith('recipient')
1095
-			->setSharedBy('initiator')
1096
-			->setShareOwner('currentUser')
1097
-			->setPermissions(Constants::PERMISSION_READ)
1098
-			->setNode($file1)
1099
-			->setId(442);
1100
-
1101
-		$file1RoomShareOwnerExpected = [
1102
-			'id' => 442,
1103
-			'share_type' => IShare::TYPE_ROOM,
1104
-		];
1105
-
1106
-		$file1RemoteShareOwner = Server::get(IManager::class)->newShare();
1107
-		$file1RemoteShareOwner->setShareType(IShare::TYPE_REMOTE)
1108
-			->setSharedWith('recipient')
1109
-			->setSharedBy('initiator')
1110
-			->setShareOwner('currentUser')
1111
-			->setPermissions(Constants::PERMISSION_READ)
1112
-			->setExpirationDate(new \DateTime('2000-01-01T01:02:03'))
1113
-			->setNode($file1)
1114
-			->setId(815);
1115
-
1116
-		$file1RemoteShareOwnerExpected = [
1117
-			'id' => 815,
1118
-			'share_type' => IShare::TYPE_REMOTE,
1119
-		];
1120
-
1121
-		$file1RemoteGroupShareOwner = Server::get(IManager::class)->newShare();
1122
-		$file1RemoteGroupShareOwner->setShareType(IShare::TYPE_REMOTE_GROUP)
1123
-			->setSharedWith('recipient')
1124
-			->setSharedBy('initiator')
1125
-			->setShareOwner('currentUser')
1126
-			->setPermissions(Constants::PERMISSION_READ)
1127
-			->setExpirationDate(new \DateTime('2000-01-02T01:02:03'))
1128
-			->setNode($file1)
1129
-			->setId(816);
1130
-
1131
-		$file1RemoteGroupShareOwnerExpected = [
1132
-			'id' => 816,
1133
-			'share_type' => IShare::TYPE_REMOTE_GROUP,
1134
-		];
1135
-
1136
-		$file2UserShareOwner = Server::get(IManager::class)->newShare();
1137
-		$file2UserShareOwner->setShareType(IShare::TYPE_USER)
1138
-			->setSharedWith('recipient')
1139
-			->setSharedBy('initiator')
1140
-			->setShareOwner('currentUser')
1141
-			->setPermissions(Constants::PERMISSION_READ)
1142
-			->setNode($file2)
1143
-			->setId(823);
1144
-
1145
-		$file2UserShareOwnerExpected = [
1146
-			'id' => 823,
1147
-			'share_type' => IShare::TYPE_USER,
1148
-		];
1149
-
1150
-		$data = [
1151
-			[
1152
-				[
1153
-					'path' => $file1,
1154
-				],
1155
-				[
1156
-					'file1' => [
1157
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1158
-					],
1159
-				],
1160
-				[
1161
-				],
1162
-				[
1163
-					$file1UserShareOwnerExpected
1164
-				]
1165
-			],
1166
-			[
1167
-				[
1168
-					'path' => $file1,
1169
-				],
1170
-				[
1171
-					'file1' => [
1172
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1173
-					],
1174
-				],
1175
-				[
1176
-				],
1177
-				[
1178
-					$file1UserShareOwnerExpected,
1179
-				]
1180
-			],
1181
-			[
1182
-				[
1183
-					'path' => $file1,
1184
-				],
1185
-				[
1186
-					'file1' => [
1187
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1188
-					],
1189
-				],
1190
-				[
1191
-				],
1192
-				[
1193
-					$file1UserShareOwnerExpected,
1194
-					$file1UserShareInitiatorExpected,
1195
-					$file1UserShareOtherExpected,
1196
-				]
1197
-			],
1198
-			[
1199
-				[
1200
-					'path' => $file1,
1201
-				],
1202
-				[
1203
-					'file1' => [
1204
-						IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1205
-					],
1206
-				],
1207
-				[
1208
-				],
1209
-				[
1210
-					$file1UserShareInitiatorExpected,
1211
-				]
1212
-			],
1213
-			[
1214
-				[
1215
-					'path' => $file1,
1216
-				],
1217
-				[
1218
-					'file1' => [
1219
-						IShare::TYPE_USER => [$file1UserShareOwner],
1220
-						IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1221
-					],
1222
-				],
1223
-				[
1224
-				],
1225
-				[
1226
-					$file1UserShareOwnerExpected,
1227
-					$file1GroupShareRecipientExpected,
1228
-				]
1229
-			],
1230
-			[
1231
-				[
1232
-					'path' => $file1,
1233
-				],
1234
-				[
1235
-					'file1' => [
1236
-						IShare::TYPE_USER => [$file1UserShareOwner],
1237
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1238
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1239
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1240
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1241
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1242
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1243
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1244
-					],
1245
-				],
1246
-				[
1247
-				],
1248
-				[
1249
-					$file1UserShareOwnerExpected,
1250
-					$file1GroupShareOwnerExpected,
1251
-					$file1LinkShareOwnerExpected,
1252
-					$file1EmailShareOwnerExpected,
1253
-					$file1CircleShareOwnerExpected,
1254
-					$file1RoomShareOwnerExpected,
1255
-				]
1256
-			],
1257
-			[
1258
-				[
1259
-					'path' => $file1,
1260
-				],
1261
-				[
1262
-					'file1' => [
1263
-						IShare::TYPE_USER => [$file1UserShareOwner],
1264
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1265
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1266
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1267
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1268
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1269
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1270
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1271
-					],
1272
-				],
1273
-				[
1274
-					IShare::TYPE_REMOTE => true,
1275
-					IShare::TYPE_REMOTE_GROUP => true,
1276
-				],
1277
-				[
1278
-					$file1UserShareOwnerExpected,
1279
-					$file1GroupShareOwnerExpected,
1280
-					$file1LinkShareOwnerExpected,
1281
-					$file1EmailShareOwnerExpected,
1282
-					$file1CircleShareOwnerExpected,
1283
-					$file1RoomShareOwnerExpected,
1284
-					$file1RemoteShareOwnerExpected,
1285
-					$file1RemoteGroupShareOwnerExpected,
1286
-				]
1287
-			],
1288
-			[
1289
-				[
1290
-					'path' => $folder,
1291
-					'subfiles' => 'true',
1292
-				],
1293
-				[
1294
-					'file1' => [
1295
-						IShare::TYPE_USER => [$file1UserShareOwner],
1296
-					],
1297
-					'file2' => [
1298
-						IShare::TYPE_USER => [$file2UserShareOwner],
1299
-					],
1300
-				],
1301
-				[
1302
-				],
1303
-				[
1304
-					$file1UserShareOwnerExpected,
1305
-					$file2UserShareOwnerExpected,
1306
-				]
1307
-			],
1308
-			[
1309
-				[
1310
-					'path' => $folder,
1311
-					'subfiles' => 'true',
1312
-				],
1313
-				[
1314
-					'file1' => [
1315
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1316
-					],
1317
-				],
1318
-				[
1319
-				],
1320
-				[
1321
-					$file1UserShareOwnerExpected,
1322
-				]
1323
-			],
1324
-			[
1325
-				[
1326
-					'path' => $folder,
1327
-					'subfiles' => 'true',
1328
-				],
1329
-				[
1330
-					'file1' => [
1331
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1332
-					],
1333
-				],
1334
-				[
1335
-				],
1336
-				[
1337
-					$file1UserShareOwnerExpected
1338
-				]
1339
-			],
1340
-			[
1341
-				[
1342
-					'path' => $folder,
1343
-					'subfiles' => 'true',
1344
-				],
1345
-				[
1346
-					'file1' => [
1347
-						IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1348
-					],
1349
-					'file2' => [
1350
-						IShare::TYPE_USER => [$file2UserShareOwner],
1351
-					],
1352
-				],
1353
-				[
1354
-				],
1355
-				[
1356
-					$file1UserShareInitiatorExpected,
1357
-					$file1UserShareOtherExpected,
1358
-					$file2UserShareOwnerExpected,
1359
-				]
1360
-			],
1361
-			// This might not happen in a real environment, as the combination
1362
-			// of shares does not seem to be possible on a folder without
1363
-			// resharing rights; if the folder has resharing rights then the
1364
-			// share with others would be included too in the results.
1365
-			[
1366
-				[
1367
-					'path' => $folder,
1368
-					'subfiles' => 'true',
1369
-				],
1370
-				[
1371
-					'file1' => [
1372
-						IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1373
-					],
1374
-				],
1375
-				[
1376
-				],
1377
-				[
1378
-					$file1UserShareInitiatorExpected,
1379
-				]
1380
-			],
1381
-			[
1382
-				[
1383
-					'path' => $folder,
1384
-					'subfiles' => 'true',
1385
-				],
1386
-				[
1387
-					'file1' => [
1388
-						IShare::TYPE_USER => [$file1UserShareOwner],
1389
-						IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1390
-					],
1391
-				],
1392
-				[
1393
-				],
1394
-				[
1395
-					$file1UserShareOwnerExpected,
1396
-					$file1GroupShareRecipientExpected,
1397
-				]
1398
-			],
1399
-			[
1400
-				[
1401
-					'path' => $folder,
1402
-					'subfiles' => 'true',
1403
-				],
1404
-				[
1405
-					'file1' => [
1406
-						IShare::TYPE_USER => [$file1UserShareOwner],
1407
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1408
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1409
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1410
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1411
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1412
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1413
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1414
-					],
1415
-				],
1416
-				[
1417
-				],
1418
-				[
1419
-					$file1UserShareOwnerExpected,
1420
-					$file1GroupShareOwnerExpected,
1421
-					$file1LinkShareOwnerExpected,
1422
-					$file1EmailShareOwnerExpected,
1423
-					$file1CircleShareOwnerExpected,
1424
-					$file1RoomShareOwnerExpected,
1425
-				]
1426
-			],
1427
-			[
1428
-				[
1429
-					'path' => $folder,
1430
-					'subfiles' => 'true',
1431
-				],
1432
-				[
1433
-					'file1' => [
1434
-						IShare::TYPE_USER => [$file1UserShareOwner],
1435
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1436
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1437
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1438
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1439
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1440
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1441
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1442
-					],
1443
-				],
1444
-				[
1445
-					IShare::TYPE_REMOTE => true,
1446
-					IShare::TYPE_REMOTE_GROUP => true,
1447
-				],
1448
-				[
1449
-					$file1UserShareOwnerExpected,
1450
-					$file1GroupShareOwnerExpected,
1451
-					$file1LinkShareOwnerExpected,
1452
-					$file1EmailShareOwnerExpected,
1453
-					$file1CircleShareOwnerExpected,
1454
-					$file1RoomShareOwnerExpected,
1455
-					$file1RemoteShareOwnerExpected,
1456
-					$file1RemoteGroupShareOwnerExpected,
1457
-				]
1458
-			],
1459
-		];
1460
-
1461
-		return $data;
1462
-	}
1463
-
1464
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataGetShares')]
1465
-	public function testGetShares(array $getSharesParameters, array $shares, array $extraShareTypes, array $expected): void {
1466
-		/** @var ShareAPIController&MockObject $ocs */
1467
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
1468
-			->setConstructorArgs([
1469
-				$this->appName,
1470
-				$this->request,
1471
-				$this->shareManager,
1472
-				$this->groupManager,
1473
-				$this->userManager,
1474
-				$this->rootFolder,
1475
-				$this->urlGenerator,
1476
-				$this->l,
1477
-				$this->config,
1478
-				$this->appConfig,
1479
-				$this->appManager,
1480
-				$this->serverContainer,
1481
-				$this->userStatusManager,
1482
-				$this->previewManager,
1483
-				$this->dateTimeZone,
1484
-				$this->logger,
1485
-				$this->factory,
1486
-				$this->mailer,
1487
-				$this->tagManager,
1488
-				$this->currentUser,
1489
-			])
1490
-			->onlyMethods(['formatShare'])
1491
-			->getMock();
1492
-
1493
-		$ocs->method('formatShare')
1494
-			->willReturnCallback(
1495
-				function ($share) {
1496
-					return [
1497
-						'id' => $share->getId(),
1498
-						'share_type' => $share->getShareType()
1499
-					];
1500
-				}
1501
-			);
1502
-
1503
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1504
-		$userFolder->method('get')
1505
-			->with('path')
1506
-			->willReturn($getSharesParameters['path']);
1507
-
1508
-		$this->rootFolder->method('getUserFolder')
1509
-			->with($this->currentUser)
1510
-			->willReturn($userFolder);
1511
-
1512
-		$this->shareManager
1513
-			->method('getSharesBy')
1514
-			->willReturnCallback(
1515
-				function ($user, $shareType, $node) use ($shares) {
1516
-					if (!isset($shares[$node->getName()]) || !isset($shares[$node->getName()][$shareType])) {
1517
-						return [];
1518
-					}
1519
-					return $shares[$node->getName()][$shareType];
1520
-				}
1521
-			);
1522
-
1523
-		$this->shareManager
1524
-			->method('outgoingServer2ServerSharesAllowed')
1525
-			->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE] ?? false);
1526
-
1527
-		$this->shareManager
1528
-			->method('outgoingServer2ServerGroupSharesAllowed')
1529
-			->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE_GROUP] ?? false);
1530
-
1531
-		$this->groupManager
1532
-			->method('isInGroup')
1533
-			->willReturnCallback(
1534
-				function ($user, $group) {
1535
-					return $group === 'currentUserGroup';
1536
-				}
1537
-			);
1538
-
1539
-		$result = $ocs->getShares(
1540
-			$getSharesParameters['sharedWithMe'] ?? 'false',
1541
-			$getSharesParameters['reshares'] ?? 'false',
1542
-			$getSharesParameters['subfiles'] ?? 'false',
1543
-			'path'
1544
-		);
1545
-
1546
-		$this->assertEquals($expected, $result->getData());
1547
-	}
1548
-
1549
-	public function testCanAccessShareAsOwner(): void {
1550
-		$share = $this->createMock(IShare::class);
1551
-		$share->method('getShareOwner')->willReturn($this->currentUser);
1552
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1553
-	}
1554
-
1555
-	public function testCanAccessShareAsSharer(): void {
1556
-		$share = $this->createMock(IShare::class);
1557
-		$share->method('getSharedBy')->willReturn($this->currentUser);
1558
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1559
-	}
1560
-
1561
-	public function testCanAccessShareAsSharee(): void {
1562
-		$share = $this->createMock(IShare::class);
1563
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
1564
-		$share->method('getSharedWith')->willReturn($this->currentUser);
1565
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1566
-	}
1567
-
1568
-	public function testCannotAccessLinkShare(): void {
1569
-		$share = $this->createMock(IShare::class);
1570
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
1571
-		$share->method('getNodeId')->willReturn(42);
1572
-
1573
-		$userFolder = $this->createMock(Folder::class);
1574
-		$this->rootFolder->method('getUserFolder')
1575
-			->with($this->currentUser)
1576
-			->willReturn($userFolder);
1577
-
1578
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1579
-	}
1580
-
1581
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataCanAccessShareWithPermissions')]
1582
-	public function testCanAccessShareWithPermissions(int $permissions, bool $expected): void {
1583
-		$share = $this->createMock(IShare::class);
1584
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
1585
-		$share->method('getSharedWith')->willReturn($this->createMock(IUser::class));
1586
-		$share->method('getNodeId')->willReturn(42);
1587
-
1588
-		$file = $this->createMock(File::class);
1589
-
1590
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1591
-		$userFolder->method('getFirstNodeById')
1592
-			->with($share->getNodeId())
1593
-			->willReturn($file);
1594
-		$userFolder->method('getById')
1595
-			->with($share->getNodeId())
1596
-			->willReturn([$file]);
1597
-		$this->rootFolder->method('getUserFolder')
1598
-			->with($this->currentUser)
1599
-			->willReturn($userFolder);
1600
-
1601
-		$file->method('getPermissions')
1602
-			->willReturn($permissions);
1603
-
1604
-		if ($expected) {
1605
-			$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1606
-		} else {
1607
-			$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1608
-		}
1609
-	}
1610
-
1611
-	public static function dataCanAccessShareWithPermissions(): array {
1612
-		return [
1613
-			[Constants::PERMISSION_SHARE, true],
1614
-			[Constants::PERMISSION_READ, false],
1615
-			[Constants::PERMISSION_READ | Constants::PERMISSION_SHARE, true],
1616
-		];
1617
-	}
1618
-
1619
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataCanAccessShareAsGroupMember')]
1620
-	public function testCanAccessShareAsGroupMember(string $group, bool $expected): void {
1621
-		$share = $this->createMock(IShare::class);
1622
-		$share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
1623
-		$share->method('getSharedWith')->willReturn($group);
1624
-		$share->method('getNodeId')->willReturn(42);
1625
-
1626
-		$file = $this->createMock(File::class);
1627
-
1628
-		$userFolder = $this->createMock(Folder::class);
1629
-		$userFolder->method('getFirstNodeById')
1630
-			->with($share->getNodeId())
1631
-			->willReturn($file);
1632
-		$userFolder->method('getById')
1633
-			->with($share->getNodeId())
1634
-			->willReturn([$file]);
1635
-		$this->rootFolder->method('getUserFolder')
1636
-			->with($this->currentUser)
1637
-			->willReturn($userFolder);
1638
-
1639
-		$user = $this->createMock(IUser::class);
1640
-		$this->userManager->method('get')
1641
-			->with($this->currentUser)
1642
-			->willReturn($user);
1643
-
1644
-		$group = $this->createMock(IGroup::class);
1645
-		$group->method('inGroup')->with($user)->willReturn(true);
1646
-		$group2 = $this->createMock(IGroup::class);
1647
-		$group2->method('inGroup')->with($user)->willReturn(false);
1648
-
1649
-		$this->groupManager->method('get')->willReturnMap([
1650
-			['group', $group],
1651
-			['group2', $group2],
1652
-			['group-null', null],
1653
-		]);
1654
-
1655
-		if ($expected) {
1656
-			$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1657
-		} else {
1658
-			$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1659
-		}
1660
-	}
1661
-
1662
-	public static function dataCanAccessShareAsGroupMember(): array {
1663
-		return [
1664
-			['group', true],
1665
-			['group2', false],
1666
-			['group-null', false],
1667
-		];
1668
-	}
1669
-
1670
-	public function dataCanAccessRoomShare() {
1671
-		$result = [];
1672
-
1673
-		$share = $this->createMock(IShare::class);
1674
-		$share->method('getShareType')->willReturn(IShare::TYPE_ROOM);
1675
-		$share->method('getSharedWith')->willReturn('recipientRoom');
1676
-
1677
-		$result[] = [
1678
-			false, $share, false, false
1679
-		];
1680
-
1681
-		$result[] = [
1682
-			false, $share, false, true
1683
-		];
1684
-
1685
-		$result[] = [
1686
-			true, $share, true, true
1687
-		];
1688
-
1689
-		$result[] = [
1690
-			false, $share, true, false
1691
-		];
1692
-
1693
-		return $result;
1694
-	}
1695
-
1696
-	/**
1697
-	 *
1698
-	 * @param bool $expects
1699
-	 * @param IShare $share
1700
-	 * @param bool helperAvailable
1701
-	 * @param bool canAccessShareByHelper
1702
-	 */
1703
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataCanAccessRoomShare')]
1704
-	public function testCanAccessRoomShare(bool $expected, IShare $share, bool $helperAvailable, bool $canAccessShareByHelper): void {
1705
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1706
-		$this->rootFolder->method('getUserFolder')
1707
-			->with($this->currentUser)
1708
-			->willReturn($userFolder);
1709
-
1710
-		$userFolder->method('getById')
1711
-			->with($share->getNodeId())
1712
-			->willReturn([$share->getNode()]);
1713
-
1714
-		if (!$helperAvailable) {
1715
-			$this->appManager->method('isEnabledForUser')
1716
-				->with('spreed')
1717
-				->willReturn(false);
1718
-		} else {
1719
-			$this->appManager->method('isEnabledForUser')
1720
-				->with('spreed')
1721
-				->willReturn(true);
1722
-
1723
-			// This is not possible anymore with PHPUnit 10+
1724
-			// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
1725
-			// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
1726
-			$helper = $this->getMockBuilder(\stdClass::class)
1727
-				->addMethods(['canAccessShare'])
1728
-				->getMock();
1729
-			$helper->method('canAccessShare')
1730
-				->with($share, $this->currentUser)
1731
-				->willReturn($canAccessShareByHelper);
1732
-
1733
-			$this->serverContainer->method('get')
1734
-				->with('\OCA\Talk\Share\Helper\ShareAPIController')
1735
-				->willReturn($helper);
1736
-		}
1737
-
1738
-		$this->assertEquals($expected, $this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1739
-	}
1740
-
1741
-
1742
-	public function testCreateShareNoPath(): void {
1743
-		$this->expectException(OCSNotFoundException::class);
1744
-		$this->expectExceptionMessage('Please specify a file or folder path');
1745
-
1746
-		$this->ocs->createShare();
1747
-	}
1748
-
1749
-
1750
-	public function testCreateShareInvalidPath(): void {
1751
-		$this->expectException(OCSNotFoundException::class);
1752
-		$this->expectExceptionMessage('Wrong path, file/folder does not exist');
1753
-
1754
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1755
-		$this->rootFolder->expects($this->once())
1756
-			->method('getUserFolder')
1757
-			->with('currentUser')
1758
-			->willReturn($userFolder);
1759
-
1760
-		$userFolder->expects($this->once())
1761
-			->method('get')
1762
-			->with('invalid-path')
1763
-			->willThrowException(new NotFoundException());
1764
-
1765
-		$this->ocs->createShare('invalid-path');
1766
-	}
1767
-
1768
-	public function testCreateShareInvalidShareType(): void {
1769
-		$this->expectException(OCSBadRequestException::class);
1770
-		$this->expectExceptionMessage('Unknown share type');
1771
-
1772
-		$share = $this->newShare();
1773
-		$this->shareManager->method('newShare')->willReturn($share);
1774
-
1775
-		[$userFolder, $file] = $this->getNonSharedUserFile();
1776
-		$this->rootFolder->expects($this->atLeastOnce())
1777
-			->method('getUserFolder')
1778
-			->with('currentUser')
1779
-			->willReturn($userFolder);
1780
-
1781
-		$userFolder->expects($this->atLeastOnce())
1782
-			->method('get')
1783
-			->with('valid-path')
1784
-			->willReturn($file);
1785
-		$userFolder->method('getById')
1786
-			->willReturn([]);
1787
-
1788
-		$file->expects($this->once())
1789
-			->method('lock')
1790
-			->with(ILockingProvider::LOCK_SHARED);
1791
-
1792
-		$this->ocs->createShare('valid-path', 31);
1793
-	}
1794
-
1795
-	public function testCreateShareUserNoShareWith(): void {
1796
-		$this->expectException(OCSNotFoundException::class);
1797
-		$this->expectExceptionMessage('Please specify a valid account to share with');
1798
-
1799
-		$share = $this->newShare();
1800
-		$this->shareManager->method('newShare')->willReturn($share);
1801
-
1802
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1803
-		$this->rootFolder->method('getUserFolder')
1804
-			->with('currentUser')
1805
-			->willReturn($userFolder);
1806
-
1807
-		$userFolder->expects($this->once())
1808
-			->method('get')
1809
-			->with('valid-path')
1810
-			->willReturn($path);
1811
-		$userFolder->method('getById')
1812
-			->willReturn([]);
1813
-
1814
-		$path->expects($this->once())
1815
-			->method('lock')
1816
-			->with(ILockingProvider::LOCK_SHARED);
1817
-
1818
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER);
1819
-	}
1820
-
1821
-
1822
-	public function testCreateShareUserNoValidShareWith(): void {
1823
-		$this->expectException(OCSNotFoundException::class);
1824
-		$this->expectExceptionMessage('Please specify a valid account to share with');
1825
-
1826
-		$share = $this->newShare();
1827
-		$this->shareManager->method('newShare')->willReturn($share);
1828
-
1829
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1830
-		$this->rootFolder->method('getUserFolder')
1831
-			->with('currentUser')
1832
-			->willReturn($userFolder);
1833
-
1834
-		$userFolder->expects($this->once())
1835
-			->method('get')
1836
-			->with('valid-path')
1837
-			->willReturn($path);
1838
-		$userFolder->method('getById')
1839
-			->willReturn([]);
1840
-		$path->expects($this->once())
1841
-			->method('lock')
1842
-			->with(ILockingProvider::LOCK_SHARED);
1843
-		$this->userManager->method('userExists')
1844
-			->with('invalidUser')
1845
-			->willReturn(false);
1846
-
1847
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'invalidUser');
1848
-	}
1849
-
1850
-	public function testCreateShareUser(): void {
1851
-		$share = $this->newShare();
1852
-		$this->shareManager->method('newShare')->willReturn($share);
1853
-
1854
-		/** @var ShareAPIController $ocs */
1855
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
1856
-			->setConstructorArgs([
1857
-				$this->appName,
1858
-				$this->request,
1859
-				$this->shareManager,
1860
-				$this->groupManager,
1861
-				$this->userManager,
1862
-				$this->rootFolder,
1863
-				$this->urlGenerator,
1864
-				$this->l,
1865
-				$this->config,
1866
-				$this->appConfig,
1867
-				$this->appManager,
1868
-				$this->serverContainer,
1869
-				$this->userStatusManager,
1870
-				$this->previewManager,
1871
-				$this->dateTimeZone,
1872
-				$this->logger,
1873
-				$this->factory,
1874
-				$this->mailer,
1875
-				$this->tagManager,
1876
-				$this->currentUser,
1877
-			])->onlyMethods(['formatShare'])
1878
-			->getMock();
1879
-
1880
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1881
-		$this->rootFolder->expects($this->exactly(2))
1882
-			->method('getUserFolder')
1883
-			->with('currentUser')
1884
-			->willReturn($userFolder);
1885
-
1886
-		$userFolder->expects($this->once())
1887
-			->method('get')
1888
-			->with('valid-path')
1889
-			->willReturn($path);
1890
-		$userFolder->method('getById')
1891
-			->willReturn([]);
1892
-
1893
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
1894
-
1895
-		$path->expects($this->once())
1896
-			->method('lock')
1897
-			->with(ILockingProvider::LOCK_SHARED);
1898
-
1899
-		$this->shareManager->method('createShare')
1900
-			->with($this->callback(function (IShare $share) use ($path) {
1901
-				return $share->getNode() === $path
1902
-					&& $share->getPermissions() === (
1903
-						Constants::PERMISSION_ALL
1904
-						& ~Constants::PERMISSION_DELETE
1905
-						& ~Constants::PERMISSION_CREATE
1906
-					)
1907
-					&& $share->getShareType() === IShare::TYPE_USER
1908
-					&& $share->getSharedWith() === 'validUser'
1909
-					&& $share->getSharedBy() === 'currentUser';
1910
-			}))
1911
-			->willReturnArgument(0);
1912
-
1913
-		$expected = new DataResponse([]);
1914
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
1915
-
1916
-		$this->assertInstanceOf(get_class($expected), $result);
1917
-		$this->assertEquals($expected->getData(), $result->getData());
1918
-	}
1919
-
1920
-
1921
-	public function testCreateShareGroupNoValidShareWith(): void {
1922
-		$this->expectException(OCSNotFoundException::class);
1923
-		$this->expectExceptionMessage('Please specify a valid group');
1924
-
1925
-		$share = $this->newShare();
1926
-		$this->shareManager->method('newShare')->willReturn($share);
1927
-		$this->shareManager->method('createShare')->willReturnArgument(0);
1928
-		$this->shareManager->method('allowGroupSharing')->willReturn(true);
1929
-
1930
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1931
-		$this->rootFolder->method('getUserFolder')
1932
-			->with('currentUser')
1933
-			->willReturn($userFolder);
1934
-
1935
-		$userFolder->expects($this->once())
1936
-			->method('get')
1937
-			->with('valid-path')
1938
-			->willReturn($path);
1939
-		$userFolder->method('getById')
1940
-			->willReturn([]);
1941
-
1942
-		$path->expects($this->once())
1943
-			->method('lock')
1944
-			->with(ILockingProvider::LOCK_SHARED);
1945
-
1946
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
1947
-	}
1948
-
1949
-	public function testCreateShareGroup(): void {
1950
-		$share = $this->newShare();
1951
-		$this->shareManager->method('newShare')->willReturn($share);
1952
-
1953
-		/** @var ShareAPIController&MockObject $ocs */
1954
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
1955
-			->setConstructorArgs([
1956
-				$this->appName,
1957
-				$this->request,
1958
-				$this->shareManager,
1959
-				$this->groupManager,
1960
-				$this->userManager,
1961
-				$this->rootFolder,
1962
-				$this->urlGenerator,
1963
-				$this->l,
1964
-				$this->config,
1965
-				$this->appConfig,
1966
-				$this->appManager,
1967
-				$this->serverContainer,
1968
-				$this->userStatusManager,
1969
-				$this->previewManager,
1970
-				$this->dateTimeZone,
1971
-				$this->logger,
1972
-				$this->factory,
1973
-				$this->mailer,
1974
-				$this->tagManager,
1975
-				$this->currentUser,
1976
-			])->onlyMethods(['formatShare'])
1977
-			->getMock();
1978
-
1979
-		$this->request
1980
-			->method('getParam')
1981
-			->willReturnMap([
1982
-				['path', null, 'valid-path'],
1983
-				['permissions', null, Constants::PERMISSION_ALL],
1984
-				['shareType', '-1', IShare::TYPE_GROUP],
1985
-				['shareWith', null, 'validGroup'],
1986
-			]);
1987
-
1988
-		[$userFolder, $path] = $this->getNonSharedUserFolder();
1989
-		$this->rootFolder->expects($this->exactly(2))
1990
-			->method('getUserFolder')
1991
-			->with('currentUser')
1992
-			->willReturn($userFolder);
1993
-
1994
-		$userFolder->expects($this->once())
1995
-			->method('get')
1996
-			->with('valid-path')
1997
-			->willReturn($path);
1998
-		$userFolder->method('getById')
1999
-			->willReturn([]);
2000
-
2001
-		$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2002
-
2003
-		$this->shareManager->expects($this->once())
2004
-			->method('allowGroupSharing')
2005
-			->willReturn(true);
2006
-
2007
-		$path->expects($this->once())
2008
-			->method('lock')
2009
-			->with(ILockingProvider::LOCK_SHARED);
2010
-
2011
-		$this->shareManager->method('createShare')
2012
-			->with($this->callback(function (IShare $share) use ($path) {
2013
-				return $share->getNode() === $path
2014
-				&& $share->getPermissions() === Constants::PERMISSION_ALL
2015
-				&& $share->getShareType() === IShare::TYPE_GROUP
2016
-				&& $share->getSharedWith() === 'validGroup'
2017
-				&& $share->getSharedBy() === 'currentUser';
2018
-			}))
2019
-			->willReturnArgument(0);
2020
-
2021
-		$expected = new DataResponse([]);
2022
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'validGroup');
2023
-
2024
-		$this->assertInstanceOf(get_class($expected), $result);
2025
-		$this->assertEquals($expected->getData(), $result->getData());
2026
-	}
2027
-
2028
-
2029
-	public function testCreateShareGroupNotAllowed(): void {
2030
-		$this->expectException(OCSNotFoundException::class);
2031
-		$this->expectExceptionMessage('Group sharing is disabled by the administrator');
2032
-
2033
-		$share = $this->newShare();
2034
-		$this->shareManager->method('newShare')->willReturn($share);
2035
-
2036
-		[$userFolder, $path] = $this->getNonSharedUserFolder();
2037
-		$this->rootFolder->method('getUserFolder')
2038
-			->with('currentUser')
2039
-			->willReturn($userFolder);
2040
-
2041
-		$userFolder->expects($this->once())
2042
-			->method('get')
2043
-			->with('valid-path')
2044
-			->willReturn($path);
2045
-		$userFolder->method('getById')
2046
-			->willReturn([]);
2047
-
2048
-		$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2049
-
2050
-		$this->shareManager->expects($this->once())
2051
-			->method('allowGroupSharing')
2052
-			->willReturn(false);
2053
-
2054
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
2055
-	}
2056
-
2057
-
2058
-	public function testCreateShareLinkNoLinksAllowed(): void {
2059
-		$this->expectException(OCSNotFoundException::class);
2060
-		$this->expectExceptionMessage('Public link sharing is disabled by the administrator');
2061
-
2062
-		$this->request
2063
-			->method('getParam')
2064
-			->willReturnMap([
2065
-				['path', null, 'valid-path'],
2066
-				['shareType', '-1', IShare::TYPE_LINK],
2067
-			]);
2068
-
2069
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2070
-		$path->method('getId')->willReturn(42);
2071
-		$storage = $this->createMock(IStorage::class);
2072
-		$storage->method('instanceOfStorage')
2073
-			->willReturnMap([
2074
-				['OCA\Files_Sharing\External\Storage', false],
2075
-				['OCA\Files_Sharing\SharedStorage', false],
2076
-			]);
2077
-		$path->method('getStorage')->willReturn($storage);
2078
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2079
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2080
-		$this->rootFolder->method('getById')
2081
-			->willReturn([]);
2082
-
2083
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2084
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2085
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(false);
2086
-
2087
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK);
2088
-	}
2089
-
2090
-
2091
-	public function testCreateShareLinkNoPublicUpload(): void {
2092
-		$this->expectException(OCSForbiddenException::class);
2093
-		$this->expectExceptionMessage('Public upload disabled by the administrator');
2094
-
2095
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2096
-		$path->method('getId')->willReturn(42);
2097
-		$storage = $this->createMock(IStorage::class);
2098
-		$storage->method('instanceOfStorage')
2099
-			->willReturnMap([
2100
-				['OCA\Files_Sharing\External\Storage', false],
2101
-				['OCA\Files_Sharing\SharedStorage', false],
2102
-			]);
2103
-		$path->method('getStorage')->willReturn($storage);
2104
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2105
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2106
-		$this->rootFolder->method('getById')
2107
-			->willReturn([]);
2108
-
2109
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2110
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2111
-
2112
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2113
-	}
2114
-
2115
-
2116
-	public function testCreateShareLinkPublicUploadFile(): void {
2117
-		$this->expectException(OCSBadRequestException::class);
2118
-		$this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
2119
-
2120
-		$storage = $this->createMock(IStorage::class);
2121
-		$storage->method('instanceOfStorage')
2122
-			->willReturnMap([
2123
-				['OCA\Files_Sharing\External\Storage', false],
2124
-				['OCA\Files_Sharing\SharedStorage', false],
2125
-			]);
2126
-
2127
-		$file = $this->createMock(File::class);
2128
-		$file->method('getId')->willReturn(42);
2129
-		$file->method('getStorage')->willReturn($storage);
2130
-
2131
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2132
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($file);
2133
-		$this->rootFolder->method('getById')
2134
-			->willReturn([]);
2135
-
2136
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2137
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2138
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2139
-
2140
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2141
-	}
2142
-
2143
-	public function testCreateShareLinkPublicUploadFolder(): void {
2144
-		$ocs = $this->mockFormatShare();
2145
-
2146
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2147
-		$path->method('getId')->willReturn(1);
2148
-		$storage = $this->createMock(IStorage::class);
2149
-		$storage->method('instanceOfStorage')
2150
-			->willReturnMap([
2151
-				['OCA\Files_Sharing\External\Storage', false],
2152
-				['OCA\Files_Sharing\SharedStorage', false],
2153
-			]);
2154
-		$path->method('getStorage')->willReturn($storage);
2155
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2156
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2157
-		$this->rootFolder->method('getById')
2158
-			->willReturn([]);
2159
-
2160
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2161
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2162
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2163
-
2164
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2165
-			$this->callback(function (IShare $share) use ($path) {
2166
-				return $share->getNode() === $path
2167
-					&& $share->getShareType() === IShare::TYPE_LINK
2168
-					&& $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2169
-					&& $share->getSharedBy() === 'currentUser'
2170
-					&& $share->getPassword() === null
2171
-					&& $share->getExpirationDate() === null;
2172
-			})
2173
-		)->willReturnArgument(0);
2174
-
2175
-		$expected = new DataResponse([]);
2176
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', '', null, '');
2177
-
2178
-		$this->assertInstanceOf(get_class($expected), $result);
2179
-		$this->assertEquals($expected->getData(), $result->getData());
2180
-	}
2181
-
2182
-	public function testCreateShareLinkPassword(): void {
2183
-		$ocs = $this->mockFormatShare();
2184
-
2185
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2186
-		$path->method('getId')->willReturn(42);
2187
-		$storage = $this->createMock(IStorage::class);
2188
-		$storage->method('instanceOfStorage')
2189
-			->willReturnMap([
2190
-				['OCA\Files_Sharing\External\Storage', false],
2191
-				['OCA\Files_Sharing\SharedStorage', false],
2192
-			]);
2193
-		$path->method('getStorage')->willReturn($storage);
2194
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2195
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2196
-		$this->rootFolder->method('getById')
2197
-			->willReturn([]);
2198
-
2199
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2200
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2201
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2202
-
2203
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2204
-			$this->callback(function (IShare $share) use ($path) {
2205
-				return $share->getNode() === $path
2206
-				&& $share->getShareType() === IShare::TYPE_LINK
2207
-				&& $share->getPermissions() === Constants::PERMISSION_READ // publicUpload was set to false
2208
-				&& $share->getSharedBy() === 'currentUser'
2209
-				&& $share->getPassword() === 'password'
2210
-				&& $share->getExpirationDate() === null;
2211
-			})
2212
-		)->willReturnArgument(0);
2213
-
2214
-		$expected = new DataResponse([]);
2215
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_READ, IShare::TYPE_LINK, null, 'false', 'password', null, '');
2216
-
2217
-		$this->assertInstanceOf(get_class($expected), $result);
2218
-		$this->assertEquals($expected->getData(), $result->getData());
2219
-	}
2220
-
2221
-	public function testCreateShareLinkSendPasswordByTalk(): void {
2222
-		$ocs = $this->mockFormatShare();
2223
-
2224
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2225
-		$path->method('getId')->willReturn(42);
2226
-		$storage = $this->createMock(IStorage::class);
2227
-		$storage->method('instanceOfStorage')
2228
-			->willReturnMap([
2229
-				['OCA\Files_Sharing\External\Storage', false],
2230
-				['OCA\Files_Sharing\SharedStorage', false],
2231
-			]);
2232
-		$path->method('getStorage')->willReturn($storage);
2233
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2234
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2235
-		$this->rootFolder->method('getById')
2236
-			->willReturn([]);
2237
-
2238
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2239
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2240
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2241
-
2242
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
2243
-
2244
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2245
-			$this->callback(function (IShare $share) use ($path) {
2246
-				return $share->getNode() === $path
2247
-				&& $share->getShareType() === IShare::TYPE_LINK
2248
-				&& $share->getPermissions() === (Constants::PERMISSION_ALL & ~(Constants::PERMISSION_SHARE))
2249
-				&& $share->getSharedBy() === 'currentUser'
2250
-				&& $share->getPassword() === 'password'
2251
-				&& $share->getSendPasswordByTalk() === true
2252
-				&& $share->getExpirationDate() === null;
2253
-			})
2254
-		)->willReturnArgument(0);
2255
-
2256
-		$expected = new DataResponse([]);
2257
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', 'password', 'true', '');
2258
-
2259
-		$this->assertInstanceOf(get_class($expected), $result);
2260
-		$this->assertEquals($expected->getData(), $result->getData());
2261
-	}
2262
-
2263
-
2264
-	public function testCreateShareLinkSendPasswordByTalkWithTalkDisabled(): void {
2265
-		$this->expectException(OCSForbiddenException::class);
2266
-		$this->expectExceptionMessage('Sharing valid-path sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled');
2267
-
2268
-		$ocs = $this->mockFormatShare();
2269
-
2270
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2271
-		$path->method('getId')->willReturn(42);
2272
-		$storage = $this->createMock(IStorage::class);
2273
-		$storage->method('instanceOfStorage')
2274
-			->willReturnMap([
2275
-				['OCA\Files_Sharing\External\Storage', false],
2276
-				['OCA\Files_Sharing\SharedStorage', false],
2277
-			]);
2278
-		$path->method('getStorage')->willReturn($storage);
2279
-		$path->method('getPath')->willReturn('valid-path');
2280
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2281
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2282
-		$this->rootFolder->method('getById')
2283
-			->willReturn([]);
2284
-
2285
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2286
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2287
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2288
-
2289
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
2290
-
2291
-		$this->shareManager->expects($this->never())->method('createShare');
2292
-
2293
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', 'password', 'true', '');
2294
-	}
2295
-
2296
-	public function testCreateShareValidExpireDate(): void {
2297
-		$ocs = $this->mockFormatShare();
2298
-
2299
-		$this->request
2300
-			->method('getParam')
2301
-			->willReturnMap([
2302
-				['path', null, 'valid-path'],
2303
-				['shareType', '-1', IShare::TYPE_LINK],
2304
-				['publicUpload', null, 'false'],
2305
-				['expireDate', '', '2000-01-01'],
2306
-				['password', '', ''],
2307
-			]);
2308
-
2309
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2310
-		$path->method('getId')->willReturn(42);
2311
-		$storage = $this->createMock(IStorage::class);
2312
-		$storage->method('instanceOfStorage')
2313
-			->willReturnMap([
2314
-				['OCA\Files_Sharing\External\Storage', false],
2315
-				['OCA\Files_Sharing\SharedStorage', false],
2316
-			]);
2317
-		$path->method('getStorage')->willReturn($storage);
2318
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2319
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2320
-		$this->rootFolder->method('getById')
2321
-			->willReturn([]);
2322
-
2323
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2324
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2325
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2326
-
2327
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2328
-			$this->callback(function (IShare $share) use ($path) {
2329
-				$date = new \DateTime('2000-01-01');
2330
-				$date->setTime(0, 0, 0);
2331
-
2332
-				return $share->getNode() === $path
2333
-				&& $share->getShareType() === IShare::TYPE_LINK
2334
-				&& $share->getPermissions() === Constants::PERMISSION_READ | Constants::PERMISSION_SHARE
2335
-				&& $share->getSharedBy() === 'currentUser'
2336
-				&& $share->getPassword() === null
2337
-				&& $share->getExpirationDate() == $date;
2338
-			})
2339
-		)->willReturnArgument(0);
2340
-
2341
-		$expected = new DataResponse([]);
2342
-		$result = $ocs->createShare('valid-path', null, IShare::TYPE_LINK, null, 'false', '', null, '2000-01-01');
2343
-
2344
-		$this->assertInstanceOf(get_class($expected), $result);
2345
-		$this->assertEquals($expected->getData(), $result->getData());
2346
-	}
2347
-
2348
-
2349
-	public function testCreateShareInvalidExpireDate(): void {
2350
-		$this->expectException(OCSNotFoundException::class);
2351
-		$this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
2352
-
2353
-		$ocs = $this->mockFormatShare();
2354
-
2355
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2356
-		$path->method('getId')->willReturn(42);
2357
-		$storage = $this->createMock(IStorage::class);
2358
-		$storage->method('instanceOfStorage')
2359
-			->willReturnMap([
2360
-				['OCA\Files_Sharing\External\Storage', false],
2361
-				['OCA\Files_Sharing\SharedStorage', false],
2362
-			]);
2363
-		$path->method('getStorage')->willReturn($storage);
2364
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2365
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2366
-		$this->rootFolder->method('getById')
2367
-			->willReturn([]);
2368
-
2369
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2370
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2371
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2372
-
2373
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, 'a1b2d3');
2374
-	}
2375
-
2376
-	public function testCreateShareRemote(): void {
2377
-		$share = $this->newShare();
2378
-		$this->shareManager->method('newShare')->willReturn($share);
2379
-
2380
-		/** @var ShareAPIController $ocs */
2381
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2382
-			->setConstructorArgs([
2383
-				$this->appName,
2384
-				$this->request,
2385
-				$this->shareManager,
2386
-				$this->groupManager,
2387
-				$this->userManager,
2388
-				$this->rootFolder,
2389
-				$this->urlGenerator,
2390
-				$this->l,
2391
-				$this->config,
2392
-				$this->appConfig,
2393
-				$this->appManager,
2394
-				$this->serverContainer,
2395
-				$this->userStatusManager,
2396
-				$this->previewManager,
2397
-				$this->dateTimeZone,
2398
-				$this->logger,
2399
-				$this->factory,
2400
-				$this->mailer,
2401
-				$this->tagManager,
2402
-				$this->currentUser,
2403
-			])->onlyMethods(['formatShare'])
2404
-			->getMock();
2405
-
2406
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2407
-		$this->rootFolder->expects($this->exactly(2))
2408
-			->method('getUserFolder')
2409
-			->with('currentUser')
2410
-			->willReturn($userFolder);
2411
-
2412
-		$userFolder->expects($this->once())
2413
-			->method('get')
2414
-			->with('valid-path')
2415
-			->willReturn($path);
2416
-		$userFolder->method('getById')
2417
-			->willReturn([]);
2418
-
2419
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2420
-
2421
-		$path->expects($this->once())
2422
-			->method('lock')
2423
-			->with(ILockingProvider::LOCK_SHARED);
2424
-
2425
-		$this->shareManager->method('createShare')
2426
-			->with($this->callback(function (IShare $share) use ($path) {
2427
-				return $share->getNode() === $path
2428
-					&& $share->getPermissions() === (
2429
-						Constants::PERMISSION_ALL
2430
-						& ~Constants::PERMISSION_DELETE
2431
-						& ~Constants::PERMISSION_CREATE
2432
-					)
2433
-					&& $share->getShareType() === IShare::TYPE_REMOTE
2434
-					&& $share->getSharedWith() === '[email protected]'
2435
-					&& $share->getSharedBy() === 'currentUser';
2436
-			}))
2437
-			->willReturnArgument(0);
2438
-
2439
-		$this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
2440
-
2441
-		$expected = new DataResponse([]);
2442
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE, '[email protected]');
2443
-
2444
-		$this->assertInstanceOf(get_class($expected), $result);
2445
-		$this->assertEquals($expected->getData(), $result->getData());
2446
-	}
2447
-
2448
-	public function testCreateShareRemoteGroup(): void {
2449
-		$share = $this->newShare();
2450
-		$this->shareManager->method('newShare')->willReturn($share);
2451
-
2452
-		/** @var ShareAPIController $ocs */
2453
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2454
-			->setConstructorArgs([
2455
-				$this->appName,
2456
-				$this->request,
2457
-				$this->shareManager,
2458
-				$this->groupManager,
2459
-				$this->userManager,
2460
-				$this->rootFolder,
2461
-				$this->urlGenerator,
2462
-				$this->l,
2463
-				$this->config,
2464
-				$this->appConfig,
2465
-				$this->appManager,
2466
-				$this->serverContainer,
2467
-				$this->userStatusManager,
2468
-				$this->previewManager,
2469
-				$this->dateTimeZone,
2470
-				$this->logger,
2471
-				$this->factory,
2472
-				$this->mailer,
2473
-				$this->tagManager,
2474
-				$this->currentUser,
2475
-			])->onlyMethods(['formatShare'])
2476
-			->getMock();
2477
-
2478
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2479
-		$this->rootFolder->expects($this->exactly(2))
2480
-			->method('getUserFolder')
2481
-			->with('currentUser')
2482
-			->willReturn($userFolder);
2483
-
2484
-		$userFolder->expects($this->once())
2485
-			->method('get')
2486
-			->with('valid-path')
2487
-			->willReturn($path);
2488
-		$userFolder->method('getById')
2489
-			->willReturn([]);
2490
-
2491
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2492
-
2493
-		$path->expects($this->once())
2494
-			->method('lock')
2495
-			->with(ILockingProvider::LOCK_SHARED);
2496
-
2497
-		$this->shareManager->method('createShare')
2498
-			->with($this->callback(function (IShare $share) use ($path) {
2499
-				return $share->getNode() === $path
2500
-					&& $share->getPermissions() === (
2501
-						Constants::PERMISSION_ALL
2502
-						& ~Constants::PERMISSION_DELETE
2503
-						& ~Constants::PERMISSION_CREATE
2504
-					)
2505
-					&& $share->getShareType() === IShare::TYPE_REMOTE_GROUP
2506
-					&& $share->getSharedWith() === '[email protected]'
2507
-					&& $share->getSharedBy() === 'currentUser';
2508
-			}))
2509
-			->willReturnArgument(0);
2510
-
2511
-		$this->shareManager->method('outgoingServer2ServerGroupSharesAllowed')->willReturn(true);
2512
-
2513
-		$expected = new DataResponse([]);
2514
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE_GROUP, '[email protected]');
2515
-
2516
-		$this->assertInstanceOf(get_class($expected), $result);
2517
-		$this->assertEquals($expected->getData(), $result->getData());
2518
-	}
2519
-
2520
-	public function testCreateShareRoom(): void {
2521
-		$ocs = $this->mockFormatShare();
2522
-
2523
-		$share = $this->newShare();
2524
-		$this->shareManager->method('newShare')->willReturn($share);
2525
-
2526
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2527
-		$this->rootFolder->expects($this->exactly(2))
2528
-			->method('getUserFolder')
2529
-			->with('currentUser')
2530
-			->willReturn($userFolder);
2531
-
2532
-		$userFolder->expects($this->once())
2533
-			->method('get')
2534
-			->with('valid-path')
2535
-			->willReturn($path);
2536
-		$userFolder->method('getById')
2537
-			->willReturn([]);
2538
-
2539
-		$path->expects($this->once())
2540
-			->method('lock')
2541
-			->with(ILockingProvider::LOCK_SHARED);
2542
-
2543
-		$this->appManager->method('isEnabledForUser')
2544
-			->with('spreed')
2545
-			->willReturn(true);
2546
-
2547
-		// This is not possible anymore with PHPUnit 10+
2548
-		// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2549
-		// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2550
-		$helper = $this->getMockBuilder(\stdClass::class)
2551
-			->addMethods(['createShare'])
2552
-			->getMock();
2553
-		$helper->method('createShare')
2554
-			->with(
2555
-				$share,
2556
-				'recipientRoom',
2557
-				Constants::PERMISSION_ALL
2558
-				& ~Constants::PERMISSION_DELETE
2559
-				& ~Constants::PERMISSION_CREATE,
2560
-				''
2561
-			)->willReturnCallback(
2562
-				function ($share): void {
2563
-					$share->setSharedWith('recipientRoom');
2564
-					$share->setPermissions(Constants::PERMISSION_ALL);
2565
-				}
2566
-			);
2567
-
2568
-		$this->serverContainer->method('get')
2569
-			->with('\OCA\Talk\Share\Helper\ShareAPIController')
2570
-			->willReturn($helper);
2571
-
2572
-		$this->shareManager->method('createShare')
2573
-			->with($this->callback(function (IShare $share) use ($path) {
2574
-				return $share->getNode() === $path
2575
-					&& $share->getPermissions() === Constants::PERMISSION_ALL
2576
-					&& $share->getShareType() === IShare::TYPE_ROOM
2577
-					&& $share->getSharedWith() === 'recipientRoom'
2578
-					&& $share->getSharedBy() === 'currentUser';
2579
-			}))
2580
-			->willReturnArgument(0);
2581
-
2582
-		$expected = new DataResponse([]);
2583
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2584
-
2585
-		$this->assertInstanceOf(get_class($expected), $result);
2586
-		$this->assertEquals($expected->getData(), $result->getData());
2587
-	}
2588
-
2589
-
2590
-	public function testCreateShareRoomHelperNotAvailable(): void {
2591
-		$this->expectException(OCSForbiddenException::class);
2592
-		$this->expectExceptionMessage('Sharing valid-path failed because the back end does not support room shares');
2593
-
2594
-		$ocs = $this->mockFormatShare();
2595
-
2596
-		$share = $this->newShare();
2597
-		$this->shareManager->method('newShare')->willReturn($share);
2598
-
2599
-		[$userFolder, $path] = $this->getNonSharedUserFolder();
2600
-		$this->rootFolder->method('getUserFolder')
2601
-			->with('currentUser')
2602
-			->willReturn($userFolder);
2603
-
2604
-		$path->method('getPath')->willReturn('valid-path');
2605
-		$userFolder->expects($this->once())
2606
-			->method('get')
2607
-			->with('valid-path')
2608
-			->willReturn($path);
2609
-		$userFolder->method('getById')
2610
-			->willReturn([]);
2611
-
2612
-		$path->expects($this->once())
2613
-			->method('lock')
2614
-			->with(ILockingProvider::LOCK_SHARED);
2615
-
2616
-		$this->appManager->method('isEnabledForUser')
2617
-			->with('spreed')
2618
-			->willReturn(false);
2619
-
2620
-		$this->shareManager->expects($this->never())->method('createShare');
2621
-
2622
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2623
-	}
2624
-
2625
-
2626
-	public function testCreateShareRoomHelperThrowException(): void {
2627
-		$this->expectException(OCSNotFoundException::class);
2628
-		$this->expectExceptionMessage('Exception thrown by the helper');
2629
-
2630
-		$ocs = $this->mockFormatShare();
2631
-
2632
-		$share = $this->newShare();
2633
-		$share->setSharedBy('currentUser');
2634
-		$this->shareManager->method('newShare')->willReturn($share);
2635
-
2636
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2637
-		$this->rootFolder->method('getUserFolder')
2638
-			->with('currentUser')
2639
-			->willReturn($userFolder);
2640
-
2641
-		$userFolder->expects($this->once())
2642
-			->method('get')
2643
-			->with('valid-path')
2644
-			->willReturn($path);
2645
-		$userFolder->method('getById')
2646
-			->willReturn([]);
2647
-
2648
-		$path->expects($this->once())
2649
-			->method('lock')
2650
-			->with(ILockingProvider::LOCK_SHARED);
2651
-
2652
-		$this->appManager->method('isEnabledForUser')
2653
-			->with('spreed')
2654
-			->willReturn(true);
2655
-
2656
-		// This is not possible anymore with PHPUnit 10+
2657
-		// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2658
-		// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2659
-		$helper = $this->getMockBuilder(\stdClass::class)
2660
-			->addMethods(['createShare'])
2661
-			->getMock();
2662
-		$helper->method('createShare')
2663
-			->with(
2664
-				$share,
2665
-				'recipientRoom',
2666
-				Constants::PERMISSION_ALL & ~(Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE),
2667
-				''
2668
-			)->willReturnCallback(
2669
-				function ($share): void {
2670
-					throw new OCSNotFoundException('Exception thrown by the helper');
2671
-				}
2672
-			);
2673
-
2674
-		$this->serverContainer->method('get')
2675
-			->with('\OCA\Talk\Share\Helper\ShareAPIController')
2676
-			->willReturn($helper);
2677
-
2678
-		$this->shareManager->expects($this->never())->method('createShare');
2679
-
2680
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2681
-	}
2682
-
2683
-	/**
2684
-	 * Test for https://github.com/owncloud/core/issues/22587
2685
-	 * TODO: Remove once proper solution is in place
2686
-	 */
2687
-	public function testCreateReshareOfFederatedMountNoDeletePermissions(): void {
2688
-		$share = Server::get(IManager::class)->newShare();
2689
-		$this->shareManager->method('newShare')->willReturn($share);
2690
-
2691
-		/** @var ShareAPIController&MockObject $ocs */
2692
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2693
-			->setConstructorArgs([
2694
-				$this->appName,
2695
-				$this->request,
2696
-				$this->shareManager,
2697
-				$this->groupManager,
2698
-				$this->userManager,
2699
-				$this->rootFolder,
2700
-				$this->urlGenerator,
2701
-				$this->l,
2702
-				$this->config,
2703
-				$this->appConfig,
2704
-				$this->appManager,
2705
-				$this->serverContainer,
2706
-				$this->userStatusManager,
2707
-				$this->previewManager,
2708
-				$this->dateTimeZone,
2709
-				$this->logger,
2710
-				$this->factory,
2711
-				$this->mailer,
2712
-				$this->tagManager,
2713
-				$this->currentUser,
2714
-			])->onlyMethods(['formatShare'])
2715
-			->getMock();
2716
-
2717
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
2718
-		$this->rootFolder->expects($this->exactly(2))
2719
-			->method('getUserFolder')
2720
-			->with('currentUser')
2721
-			->willReturn($userFolder);
2722
-
2723
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2724
-		$path->method('getId')->willReturn(42);
2725
-
2726
-		$storage = $this->createMock(IStorage::class);
2727
-		$storage->method('instanceOfStorage')
2728
-			->willReturnMap([
2729
-				['OCA\Files_Sharing\External\Storage', true],
2730
-				['OCA\Files_Sharing\SharedStorage', false],
2731
-			]);
2732
-		$userFolder->method('getStorage')->willReturn($storage);
2733
-		$path->method('getStorage')->willReturn($storage);
2734
-
2735
-		$path->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
2736
-		$userFolder->expects($this->once())
2737
-			->method('get')
2738
-			->with('valid-path')
2739
-			->willReturn($path);
2740
-		$userFolder->method('getById')
2741
-			->willReturn([]);
2742
-
2743
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2744
-
2745
-		$this->shareManager
2746
-			->expects($this->once())
2747
-			->method('createShare')
2748
-			->with($this->callback(function (IShare $share) {
2749
-				return $share->getPermissions() === Constants::PERMISSION_READ;
2750
-			}))
2751
-			->willReturnArgument(0);
2752
-
2753
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
2754
-	}
2755
-
2756
-
2757
-	public function testUpdateShareCantAccess(): void {
2758
-		$this->expectException(OCSNotFoundException::class);
2759
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
2760
-
2761
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
2762
-		$share = $this->newShare();
2763
-		$share->setNode($node);
2764
-
2765
-		$node->expects($this->once())
2766
-			->method('lock')
2767
-			->with(ILockingProvider::LOCK_SHARED);
2768
-
2769
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2770
-
2771
-		$this->rootFolder->method('getUserFolder')
2772
-			->with($this->currentUser)
2773
-			->willReturn($userFolder);
2774
-
2775
-		$userFolder->method('getById')
2776
-			->with($share->getNodeId())
2777
-			->willReturn([$share->getNode()]);
2778
-
2779
-		$this->ocs->updateShare(42);
2780
-	}
2781
-
2782
-
2783
-	public function testUpdateNoParametersLink(): void {
2784
-		$this->expectException(OCSBadRequestException::class);
2785
-		$this->expectExceptionMessage('Wrong or no update parameter given');
2786
-
2787
-		$node = $this->getMockBuilder(Folder::class)->getMock();
2788
-		$share = $this->newShare();
2789
-		$share->setPermissions(Constants::PERMISSION_ALL)
2790
-			->setSharedBy($this->currentUser)
2791
-			->setShareType(IShare::TYPE_LINK)
2792
-			->setNode($node);
2793
-
2794
-		$node->expects($this->once())
2795
-			->method('lock')
2796
-			->with(ILockingProvider::LOCK_SHARED);
2797
-
2798
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2799
-
2800
-		$this->ocs->updateShare(42);
2801
-	}
2802
-
2803
-
2804
-	public function testUpdateNoParametersOther(): void {
2805
-		$this->expectException(OCSBadRequestException::class);
2806
-		$this->expectExceptionMessage('Wrong or no update parameter given');
2807
-
2808
-		$node = $this->getMockBuilder(Folder::class)->getMock();
2809
-		$share = $this->newShare();
2810
-		$share->setPermissions(Constants::PERMISSION_ALL)
2811
-			->setSharedBy($this->currentUser)
2812
-			->setShareType(IShare::TYPE_GROUP)
2813
-			->setNode($node);
2814
-
2815
-		$node->expects($this->once())
2816
-			->method('lock')
2817
-			->with(ILockingProvider::LOCK_SHARED);
2818
-
2819
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2820
-
2821
-		$this->ocs->updateShare(42);
2822
-	}
2823
-
2824
-	public function testUpdateLinkShareClear(): void {
2825
-		$ocs = $this->mockFormatShare();
2826
-
2827
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
2828
-		$node->method('getId')
2829
-			->willReturn(42);
2830
-		$share = $this->newShare();
2831
-		$share->setPermissions(Constants::PERMISSION_ALL)
2832
-			->setSharedBy($this->currentUser)
2833
-			->setShareType(IShare::TYPE_LINK)
2834
-			->setPassword('password')
2835
-			->setExpirationDate(new \DateTime())
2836
-			->setNote('note')
2837
-			->setLabel('label')
2838
-			->setHideDownload(true)
2839
-			->setPermissions(Constants::PERMISSION_ALL)
2840
-			->setNode($node);
2841
-
2842
-		$node->expects($this->once())
2843
-			->method('lock')
2844
-			->with(ILockingProvider::LOCK_SHARED);
2845
-
2846
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2847
-
2848
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
2849
-			$this->callback(function (IShare $share) {
2850
-				return $share->getPermissions() === Constants::PERMISSION_READ
2851
-				&& $share->getPassword() === null
2852
-				&& $share->getExpirationDate() === null
2853
-				// Once set a note or a label are never back to null, only to an
2854
-				// empty string.
2855
-				&& $share->getNote() === ''
2856
-				&& $share->getLabel() === ''
2857
-				&& $share->getHideDownload() === false;
2858
-			})
2859
-		)->willReturnArgument(0);
2860
-
2861
-		$this->shareManager->method('getSharedWith')
2862
-			->willReturn([]);
2863
-
2864
-		$this->rootFolder->method('getUserFolder')
2865
-			->with($this->currentUser)
2866
-			->willReturn($userFolder);
2867
-
2868
-		$userFolder->method('getById')
2869
-			->with(42)
2870
-			->willReturn([$node]);
2871
-		$userFolder->method('getFirstNodeById')
2872
-			->with(42)
2873
-			->willReturn($node);
2874
-
2875
-		$mountPoint = $this->createMock(IMountPoint::class);
2876
-		$node->method('getMountPoint')
2877
-			->willReturn($mountPoint);
2878
-		$mountPoint->method('getStorageRootId')
2879
-			->willReturn(42);
2880
-
2881
-		$expected = new DataResponse([]);
2882
-		$result = $ocs->updateShare(42, null, '', null, 'false', '', '', '', 'false');
2883
-
2884
-		$this->assertInstanceOf(get_class($expected), $result);
2885
-		$this->assertEquals($expected->getData(), $result->getData());
2886
-	}
2887
-
2888
-	public function testUpdateLinkShareSet(): void {
2889
-		$ocs = $this->mockFormatShare();
2890
-
2891
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
2892
-		$folder->method('getId')
2893
-			->willReturn(42);
2894
-
2895
-		$share = Server::get(IManager::class)->newShare();
2896
-		$share->setPermissions(Constants::PERMISSION_ALL)
2897
-			->setSharedBy($this->currentUser)
2898
-			->setShareType(IShare::TYPE_LINK)
2899
-			->setNode($folder);
2900
-
2901
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2902
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2903
-
2904
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
2905
-			$this->callback(function (IShare $share) {
2906
-				$date = new \DateTime('2000-01-01');
2907
-				$date->setTime(0, 0, 0);
2908
-
2909
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2910
-				&& $share->getPassword() === 'password'
2911
-				&& $share->getExpirationDate() == $date
2912
-				&& $share->getNote() === 'note'
2913
-				&& $share->getLabel() === 'label'
2914
-				&& $share->getHideDownload() === true;
2915
-			})
2916
-		)->willReturnArgument(0);
2917
-
2918
-		$this->shareManager->method('getSharedWith')
2919
-			->willReturn([]);
2920
-
2921
-		$this->rootFolder->method('getUserFolder')
2922
-			->with($this->currentUser)
2923
-			->willReturn($userFolder);
2924
-
2925
-		$userFolder->method('getById')
2926
-			->with(42)
2927
-			->willReturn([$folder]);
2928
-
2929
-		$mountPoint = $this->createMock(IMountPoint::class);
2930
-		$folder->method('getMountPoint')
2931
-			->willReturn($mountPoint);
2932
-		$mountPoint->method('getStorageRootId')
2933
-			->willReturn(42);
2934
-
2935
-		$expected = new DataResponse([]);
2936
-		$result = $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-01', 'note', 'label', 'true');
2937
-
2938
-		$this->assertInstanceOf(get_class($expected), $result);
2939
-		$this->assertEquals($expected->getData(), $result->getData());
2940
-	}
2941
-
2942
-	#[\PHPUnit\Framework\Attributes\DataProvider('publicUploadParamsProvider')]
2943
-	public function testUpdateLinkShareEnablePublicUpload($permissions, $publicUpload, $expireDate, $password): void {
2944
-		$ocs = $this->mockFormatShare();
2945
-
2946
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
2947
-		$folder->method('getId')
2948
-			->willReturn(42);
2949
-
2950
-		$share = Server::get(IManager::class)->newShare();
2951
-		$share->setPermissions(Constants::PERMISSION_ALL)
2952
-			->setSharedBy($this->currentUser)
2953
-			->setShareType(IShare::TYPE_LINK)
2954
-			->setPassword('password')
2955
-			->setNode($folder);
2956
-
2957
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2958
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2959
-		$this->shareManager->method('getSharedWith')->willReturn([]);
2960
-
2961
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
2962
-			$this->callback(function (IShare $share) {
2963
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2964
-				&& $share->getPassword() === 'password'
2965
-				&& $share->getExpirationDate() === null;
2966
-			})
2967
-		)->willReturnArgument(0);
2968
-
2969
-		$this->rootFolder->method('getUserFolder')
2970
-			->with($this->currentUser)
2971
-			->willReturn($userFolder);
2972
-
2973
-		$userFolder->method('getById')
2974
-			->with(42)
2975
-			->willReturn([$folder]);
2976
-
2977
-		$mountPoint = $this->createMock(IMountPoint::class);
2978
-		$folder->method('getMountPoint')
2979
-			->willReturn($mountPoint);
2980
-		$mountPoint->method('getStorageRootId')
2981
-			->willReturn(42);
2982
-
2983
-		$expected = new DataResponse([]);
2984
-		$result = $ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
2985
-
2986
-		$this->assertInstanceOf(get_class($expected), $result);
2987
-		$this->assertEquals($expected->getData(), $result->getData());
2988
-	}
2989
-
2990
-
2991
-	public static function publicLinkValidPermissionsProvider() {
2992
-		return [
2993
-			[Constants::PERMISSION_CREATE],
2994
-			[Constants::PERMISSION_READ],
2995
-			[Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE],
2996
-			[Constants::PERMISSION_READ | Constants::PERMISSION_DELETE],
2997
-			[Constants::PERMISSION_READ | Constants::PERMISSION_CREATE],
2998
-		];
2999
-	}
3000
-
3001
-	#[\PHPUnit\Framework\Attributes\DataProvider('publicLinkValidPermissionsProvider')]
3002
-	public function testUpdateLinkShareSetCRUDPermissions($permissions): void {
3003
-		$ocs = $this->mockFormatShare();
3004
-
3005
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3006
-		$folder->method('getId')
3007
-			->willReturn(42);
3008
-
3009
-		$share = Server::get(IManager::class)->newShare();
3010
-		$share->setPermissions(Constants::PERMISSION_ALL)
3011
-			->setSharedBy($this->currentUser)
3012
-			->setShareType(IShare::TYPE_LINK)
3013
-			->setPassword('password')
3014
-			->setNode($folder);
3015
-
3016
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3017
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3018
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3019
-
3020
-		$this->shareManager
3021
-			->expects($this->any())
3022
-			->method('updateShare')
3023
-			->willReturnArgument(0);
3024
-
3025
-		$this->rootFolder->method('getUserFolder')
3026
-			->with($this->currentUser)
3027
-			->willReturn($userFolder);
3028
-
3029
-		$userFolder->method('getById')
3030
-			->with(42)
3031
-			->willReturn([$folder]);
3032
-
3033
-		$mountPoint = $this->createMock(IMountPoint::class);
3034
-		$folder->method('getMountPoint')
3035
-			->willReturn($mountPoint);
3036
-		$mountPoint->method('getStorageRootId')
3037
-			->willReturn(42);
3038
-
3039
-		$expected = new DataResponse([]);
3040
-		$result = $ocs->updateShare(42, $permissions, 'password', null, null, null);
3041
-
3042
-		$this->assertInstanceOf(get_class($expected), $result);
3043
-		$this->assertEquals($expected->getData(), $result->getData());
3044
-	}
3045
-
3046
-	public static function publicLinkInvalidPermissionsProvider1() {
3047
-		return [
3048
-			[Constants::PERMISSION_DELETE],
3049
-			[Constants::PERMISSION_UPDATE],
3050
-			[Constants::PERMISSION_SHARE],
3051
-		];
3052
-	}
3053
-
3054
-	#[\PHPUnit\Framework\Attributes\DataProvider('publicLinkInvalidPermissionsProvider1')]
3055
-	public function testUpdateLinkShareSetInvalidCRUDPermissions1($permissions): void {
3056
-		$this->expectException(OCSBadRequestException::class);
3057
-		$this->expectExceptionMessage('Share must at least have READ or CREATE permissions');
3058
-
3059
-		$this->testUpdateLinkShareSetCRUDPermissions($permissions, null);
3060
-	}
3061
-
3062
-	public static function publicLinkInvalidPermissionsProvider2() {
3063
-		return [
3064
-			[Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE],
3065
-			[Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE],
3066
-		];
3067
-	}
3068
-
3069
-	#[\PHPUnit\Framework\Attributes\DataProvider('publicLinkInvalidPermissionsProvider2')]
3070
-	public function testUpdateLinkShareSetInvalidCRUDPermissions2($permissions): void {
3071
-		$this->expectException(OCSBadRequestException::class);
3072
-		$this->expectExceptionMessage('Share must have READ permission if UPDATE or DELETE permission is set');
3073
-
3074
-		$this->testUpdateLinkShareSetCRUDPermissions($permissions);
3075
-	}
3076
-
3077
-	public function testUpdateLinkShareInvalidDate(): void {
3078
-		$this->expectException(OCSBadRequestException::class);
3079
-		$this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
3080
-
3081
-		$ocs = $this->mockFormatShare();
3082
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3083
-		$userFolder->method('getById')
3084
-			->with(42)
3085
-			->willReturn([$folder]);
3086
-		$this->rootFolder->method('getUserFolder')
3087
-			->with($this->currentUser)
3088
-			->willReturn($userFolder);
3089
-
3090
-		$folder->method('getId')
3091
-			->willReturn(42);
3092
-
3093
-		$share = Server::get(IManager::class)->newShare();
3094
-		$share->setPermissions(Constants::PERMISSION_ALL)
3095
-			->setSharedBy($this->currentUser)
3096
-			->setShareType(IShare::TYPE_LINK)
3097
-			->setNode($folder);
3098
-
3099
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3100
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3101
-
3102
-		$ocs->updateShare(42, null, 'password', null, 'true', '2000-01-a');
3103
-	}
3104
-
3105
-	public static function publicUploadParamsProvider() {
3106
-		return [
3107
-			[null, 'true', null, 'password'],
3108
-			// legacy had no delete
3109
-			[
3110
-				Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE,
3111
-				'true', null, 'password'
3112
-			],
3113
-			// correct
3114
-			[
3115
-				Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE,
3116
-				null, null, 'password'
3117
-			],
3118
-		];
3119
-	}
3120
-
3121
-	#[\PHPUnit\Framework\Attributes\DataProvider('publicUploadParamsProvider')]
3122
-	public function testUpdateLinkSharePublicUploadNotAllowed($permissions, $publicUpload, $expireDate, $password): void {
3123
-		$this->expectException(OCSForbiddenException::class);
3124
-		$this->expectExceptionMessage('Public upload disabled by the administrator');
3125
-
3126
-		$ocs = $this->mockFormatShare();
3127
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3128
-		$userFolder->method('getById')
3129
-			->with(42)
3130
-			->willReturn([$folder]);
3131
-		$this->rootFolder->method('getUserFolder')
3132
-			->with($this->currentUser)
3133
-			->willReturn($userFolder);
3134
-
3135
-		$folder->method('getId')->willReturn(42);
3136
-
3137
-		$share = Server::get(IManager::class)->newShare();
3138
-		$share->setPermissions(Constants::PERMISSION_ALL)
3139
-			->setSharedBy($this->currentUser)
3140
-			->setShareType(IShare::TYPE_LINK)
3141
-			->setNode($folder);
3142
-
3143
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3144
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false);
3145
-
3146
-		$ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
3147
-	}
3148
-
3149
-
3150
-	public function testUpdateLinkSharePublicUploadOnFile(): void {
3151
-		$this->expectException(OCSBadRequestException::class);
3152
-		$this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
3153
-
3154
-		$ocs = $this->mockFormatShare();
3155
-
3156
-		$file = $this->getMockBuilder(File::class)->getMock();
3157
-		$file->method('getId')
3158
-			->willReturn(42);
3159
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3160
-		$userFolder->method('getById')
3161
-			->with(42)
3162
-			->willReturn([$folder]);
3163
-		$this->rootFolder->method('getUserFolder')
3164
-			->with($this->currentUser)
3165
-			->willReturn($userFolder);
3166
-
3167
-		$share = Server::get(IManager::class)->newShare();
3168
-		$share->setPermissions(Constants::PERMISSION_ALL)
3169
-			->setSharedBy($this->currentUser)
3170
-			->setShareType(IShare::TYPE_LINK)
3171
-			->setNode($file);
3172
-
3173
-		$this->shareManager
3174
-			->method('getShareById')
3175
-			->with('ocinternal:42')
3176
-			->willReturn($share);
3177
-		$this->shareManager
3178
-			->method('shareApiLinkAllowPublicUpload')
3179
-			->willReturn(true);
3180
-		$this->shareManager
3181
-			->method('updateShare')
3182
-			->with($share)
3183
-			->willThrowException(new \InvalidArgumentException('File shares cannot have create or delete permissions'));
3184
-
3185
-		$ocs->updateShare(42, null, 'password', null, 'true', '');
3186
-	}
3187
-
3188
-	public function testUpdateLinkSharePasswordDoesNotChangeOther(): void {
3189
-		$ocs = $this->mockFormatShare();
3190
-
3191
-		$date = new \DateTime('2000-01-01');
3192
-		$date->setTime(0, 0, 0);
3193
-
3194
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3195
-		$node->method('getId')->willReturn(42);
3196
-		$userFolder->method('getById')
3197
-			->with(42)
3198
-			->willReturn([$node]);
3199
-		$this->rootFolder->method('getUserFolder')
3200
-			->with($this->currentUser)
3201
-			->willReturn($userFolder);
3202
-		$share = $this->newShare();
3203
-		$share->setPermissions(Constants::PERMISSION_ALL)
3204
-			->setSharedBy($this->currentUser)
3205
-			->setShareType(IShare::TYPE_LINK)
3206
-			->setPassword('password')
3207
-			->setSendPasswordByTalk(true)
3208
-			->setExpirationDate($date)
3209
-			->setNote('note')
3210
-			->setLabel('label')
3211
-			->setHideDownload(true)
3212
-			->setPermissions(Constants::PERMISSION_ALL)
3213
-			->setNode($node);
3214
-
3215
-		$node->expects($this->once())
3216
-			->method('lock')
3217
-			->with(ILockingProvider::LOCK_SHARED);
3218
-
3219
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3220
-
3221
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3222
-			$this->callback(function (IShare $share) use ($date) {
3223
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3224
-				&& $share->getPassword() === 'newpassword'
3225
-				&& $share->getSendPasswordByTalk() === true
3226
-				&& $share->getExpirationDate() === $date
3227
-				&& $share->getNote() === 'note'
3228
-				&& $share->getLabel() === 'label'
3229
-				&& $share->getHideDownload() === true;
3230
-			})
3231
-		)->willReturnArgument(0);
3232
-
3233
-		$expected = new DataResponse([]);
3234
-		$result = $ocs->updateShare(42, null, 'newpassword', null, null, null, null, null, null);
3235
-
3236
-		$this->assertInstanceOf(get_class($expected), $result);
3237
-		$this->assertEquals($expected->getData(), $result->getData());
3238
-	}
3239
-
3240
-	public function testUpdateLinkShareSendPasswordByTalkDoesNotChangeOther(): void {
3241
-		$ocs = $this->mockFormatShare();
3242
-
3243
-		$date = new \DateTime('2000-01-01');
3244
-		$date->setTime(0, 0, 0);
3245
-
3246
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3247
-		$userFolder->method('getById')
3248
-			->with(42)
3249
-			->willReturn([$node]);
3250
-		$this->rootFolder->method('getUserFolder')
3251
-			->with($this->currentUser)
3252
-			->willReturn($userFolder);
3253
-		$node->method('getId')->willReturn(42);
3254
-		$share = $this->newShare();
3255
-		$share->setPermissions(Constants::PERMISSION_ALL)
3256
-			->setSharedBy($this->currentUser)
3257
-			->setShareType(IShare::TYPE_LINK)
3258
-			->setPassword('password')
3259
-			->setSendPasswordByTalk(false)
3260
-			->setExpirationDate($date)
3261
-			->setNote('note')
3262
-			->setLabel('label')
3263
-			->setHideDownload(true)
3264
-			->setPermissions(Constants::PERMISSION_ALL)
3265
-			->setNode($node);
3266
-
3267
-		$node->expects($this->once())
3268
-			->method('lock')
3269
-			->with(ILockingProvider::LOCK_SHARED);
3270
-
3271
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3272
-
3273
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3274
-
3275
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3276
-			$this->callback(function (IShare $share) use ($date) {
3277
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3278
-				&& $share->getPassword() === 'password'
3279
-				&& $share->getSendPasswordByTalk() === true
3280
-				&& $share->getExpirationDate() === $date
3281
-				&& $share->getNote() === 'note'
3282
-				&& $share->getLabel() === 'label'
3283
-				&& $share->getHideDownload() === true;
3284
-			})
3285
-		)->willReturnArgument(0);
3286
-
3287
-		$expected = new DataResponse([]);
3288
-		$result = $ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3289
-
3290
-		$this->assertInstanceOf(get_class($expected), $result);
3291
-		$this->assertEquals($expected->getData(), $result->getData());
3292
-	}
3293
-
3294
-
3295
-	public function testUpdateLinkShareSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3296
-		$this->expectException(OCSForbiddenException::class);
3297
-		$this->expectExceptionMessage('"Sending the password by Nextcloud Talk" for sharing a file or folder failed because Nextcloud Talk is not enabled.');
3298
-
3299
-		$ocs = $this->mockFormatShare();
3300
-
3301
-		$date = new \DateTime('2000-01-01');
3302
-		$date->setTime(0, 0, 0);
3303
-
3304
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3305
-		$userFolder->method('getById')
3306
-			->with(42)
3307
-			->willReturn([$node]);
3308
-		$this->rootFolder->method('getUserFolder')
3309
-			->with($this->currentUser)
3310
-			->willReturn($userFolder);
3311
-		$node->method('getId')->willReturn(42);
3312
-		$share = $this->newShare();
3313
-		$share->setPermissions(Constants::PERMISSION_ALL)
3314
-			->setSharedBy($this->currentUser)
3315
-			->setShareType(IShare::TYPE_LINK)
3316
-			->setPassword('password')
3317
-			->setSendPasswordByTalk(false)
3318
-			->setExpirationDate($date)
3319
-			->setNote('note')
3320
-			->setLabel('label')
3321
-			->setHideDownload(true)
3322
-			->setPermissions(Constants::PERMISSION_ALL)
3323
-			->setNode($node);
3324
-
3325
-		$node->expects($this->once())
3326
-			->method('lock')
3327
-			->with(ILockingProvider::LOCK_SHARED);
3328
-
3329
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3330
-
3331
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3332
-
3333
-		$this->shareManager->expects($this->never())->method('updateShare');
3334
-
3335
-		$ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3336
-	}
3337
-
3338
-	public function testUpdateLinkShareDoNotSendPasswordByTalkDoesNotChangeOther(): void {
3339
-		$ocs = $this->mockFormatShare();
3340
-
3341
-		$date = new \DateTime('2000-01-01');
3342
-		$date->setTime(0, 0, 0);
3343
-
3344
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3345
-		$userFolder->method('getById')
3346
-			->with(42)
3347
-			->willReturn([$node]);
3348
-		$this->rootFolder->method('getUserFolder')
3349
-			->with($this->currentUser)
3350
-			->willReturn($userFolder);
3351
-		$node->method('getId')->willReturn(42);
3352
-		$share = $this->newShare();
3353
-		$share->setPermissions(Constants::PERMISSION_ALL)
3354
-			->setSharedBy($this->currentUser)
3355
-			->setShareType(IShare::TYPE_LINK)
3356
-			->setPassword('password')
3357
-			->setSendPasswordByTalk(true)
3358
-			->setExpirationDate($date)
3359
-			->setNote('note')
3360
-			->setLabel('label')
3361
-			->setHideDownload(true)
3362
-			->setPermissions(Constants::PERMISSION_ALL)
3363
-			->setNode($node);
3364
-
3365
-		$node->expects($this->once())
3366
-			->method('lock')
3367
-			->with(ILockingProvider::LOCK_SHARED);
3368
-
3369
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3370
-
3371
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3372
-
3373
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3374
-			$this->callback(function (IShare $share) use ($date) {
3375
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3376
-				&& $share->getPassword() === 'password'
3377
-				&& $share->getSendPasswordByTalk() === false
3378
-				&& $share->getExpirationDate() === $date
3379
-				&& $share->getNote() === 'note'
3380
-				&& $share->getLabel() === 'label'
3381
-				&& $share->getHideDownload() === true;
3382
-			})
3383
-		)->willReturnArgument(0);
3384
-
3385
-		$expected = new DataResponse([]);
3386
-		$result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3387
-
3388
-		$this->assertInstanceOf(get_class($expected), $result);
3389
-		$this->assertEquals($expected->getData(), $result->getData());
3390
-	}
3391
-
3392
-	public function testUpdateLinkShareDoNotSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3393
-		$ocs = $this->mockFormatShare();
3394
-
3395
-		$date = new \DateTime('2000-01-01');
3396
-		$date->setTime(0, 0, 0);
3397
-
3398
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3399
-		$node->method('getId')
3400
-			->willReturn(42);
3401
-
3402
-		$share = $this->newShare();
3403
-		$share->setPermissions(Constants::PERMISSION_ALL)
3404
-			->setSharedBy($this->currentUser)
3405
-			->setShareType(IShare::TYPE_LINK)
3406
-			->setPassword('password')
3407
-			->setSendPasswordByTalk(true)
3408
-			->setExpirationDate($date)
3409
-			->setNote('note')
3410
-			->setLabel('label')
3411
-			->setHideDownload(true)
3412
-			->setPermissions(Constants::PERMISSION_ALL)
3413
-			->setNode($node);
3414
-
3415
-		$node->expects($this->once())
3416
-			->method('lock')
3417
-			->with(ILockingProvider::LOCK_SHARED);
3418
-
3419
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3420
-
3421
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3422
-
3423
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3424
-			$this->callback(function (IShare $share) use ($date) {
3425
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3426
-				&& $share->getPassword() === 'password'
3427
-				&& $share->getSendPasswordByTalk() === false
3428
-				&& $share->getExpirationDate() === $date
3429
-				&& $share->getNote() === 'note'
3430
-				&& $share->getLabel() === 'label'
3431
-				&& $share->getHideDownload() === true;
3432
-			})
3433
-		)->willReturnArgument(0);
3434
-
3435
-		$this->rootFolder->method('getUserFolder')
3436
-			->with($this->currentUser)
3437
-			->willReturn($userFolder);
3438
-
3439
-		$userFolder->method('getById')
3440
-			->with(42)
3441
-			->willReturn([$node]);
3442
-
3443
-		$mountPoint = $this->createMock(IMountPoint::class);
3444
-		$node->method('getMountPoint')
3445
-			->willReturn($mountPoint);
3446
-		$mountPoint->method('getStorageRootId')
3447
-			->willReturn(42);
3448
-
3449
-		$mountPoint = $this->createMock(IMountPoint::class);
3450
-		$node->method('getMountPoint')
3451
-			->willReturn($mountPoint);
3452
-		$mountPoint->method('getStorageRootId')
3453
-			->willReturn(42);
3454
-
3455
-		$expected = new DataResponse([]);
3456
-		$result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3457
-
3458
-		$this->assertInstanceOf(get_class($expected), $result);
3459
-		$this->assertEquals($expected->getData(), $result->getData());
3460
-	}
3461
-
3462
-	public function testUpdateLinkShareExpireDateDoesNotChangeOther(): void {
3463
-		$ocs = $this->mockFormatShare();
3464
-
3465
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3466
-		$node->method('getId')
3467
-			->willReturn(42);
3468
-
3469
-		$share = $this->newShare();
3470
-		$share->setPermissions(Constants::PERMISSION_ALL)
3471
-			->setSharedBy($this->currentUser)
3472
-			->setShareType(IShare::TYPE_LINK)
3473
-			->setPassword('password')
3474
-			->setSendPasswordByTalk(true)
3475
-			->setExpirationDate(new \DateTime())
3476
-			->setNote('note')
3477
-			->setLabel('label')
3478
-			->setHideDownload(true)
3479
-			->setPermissions(Constants::PERMISSION_ALL)
3480
-			->setNode($node);
3481
-
3482
-		$node->expects($this->once())
3483
-			->method('lock')
3484
-			->with(ILockingProvider::LOCK_SHARED);
3485
-
3486
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3487
-
3488
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3489
-			$this->callback(function (IShare $share) {
3490
-				$date = new \DateTime('2010-12-23');
3491
-				$date->setTime(0, 0, 0);
3492
-
3493
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3494
-				&& $share->getPassword() === 'password'
3495
-				&& $share->getSendPasswordByTalk() === true
3496
-				&& $share->getExpirationDate() == $date
3497
-				&& $share->getNote() === 'note'
3498
-				&& $share->getLabel() === 'label'
3499
-				&& $share->getHideDownload() === true;
3500
-			})
3501
-		)->willReturnArgument(0);
3502
-
3503
-		$this->rootFolder->method('getUserFolder')
3504
-			->with($this->currentUser)
3505
-			->willReturn($userFolder);
3506
-
3507
-		$userFolder->method('getById')
3508
-			->with(42)
3509
-			->willReturn([$node]);
3510
-
3511
-		$mountPoint = $this->createMock(IMountPoint::class);
3512
-		$node->method('getMountPoint')
3513
-			->willReturn($mountPoint);
3514
-		$mountPoint->method('getStorageRootId')
3515
-			->willReturn(42);
3516
-
3517
-		$expected = new DataResponse([]);
3518
-		$result = $ocs->updateShare(42, null, null, null, null, '2010-12-23', null, null, null);
3519
-
3520
-		$this->assertInstanceOf(get_class($expected), $result);
3521
-		$this->assertEquals($expected->getData(), $result->getData());
3522
-	}
3523
-
3524
-	public function testUpdateLinkSharePublicUploadDoesNotChangeOther(): void {
3525
-		$ocs = $this->mockFormatShare();
3526
-
3527
-		$date = new \DateTime('2000-01-01');
3528
-
3529
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3530
-		$folder->method('getId')
3531
-			->willReturn(42);
3532
-
3533
-		$share = Server::get(IManager::class)->newShare();
3534
-		$share->setPermissions(Constants::PERMISSION_ALL)
3535
-			->setSharedBy($this->currentUser)
3536
-			->setShareType(IShare::TYPE_LINK)
3537
-			->setPassword('password')
3538
-			->setSendPasswordByTalk(true)
3539
-			->setExpirationDate($date)
3540
-			->setNote('note')
3541
-			->setLabel('label')
3542
-			->setHideDownload(true)
3543
-			->setPermissions(Constants::PERMISSION_ALL)
3544
-			->setNode($folder);
3545
-
3546
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3547
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3548
-
3549
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3550
-			$this->callback(function (IShare $share) use ($date) {
3551
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3552
-				&& $share->getPassword() === 'password'
3553
-				&& $share->getSendPasswordByTalk() === true
3554
-				&& $share->getExpirationDate() === $date
3555
-				&& $share->getNote() === 'note'
3556
-				&& $share->getLabel() === 'label'
3557
-				&& $share->getHideDownload() === true;
3558
-			})
3559
-		)->willReturnArgument(0);
3560
-
3561
-		$this->shareManager->method('getSharedWith')
3562
-			->willReturn([]);
3563
-
3564
-		$this->rootFolder->method('getUserFolder')
3565
-			->with($this->currentUser)
3566
-			->willReturn($userFolder);
3567
-
3568
-		$userFolder->method('getById')
3569
-			->with(42)
3570
-			->willReturn([$folder]);
3571
-
3572
-		$mountPoint = $this->createMock(IMountPoint::class);
3573
-		$folder->method('getMountPoint')
3574
-			->willReturn($mountPoint);
3575
-		$mountPoint->method('getStorageRootId')
3576
-			->willReturn(42);
3577
-
3578
-		$expected = new DataResponse([]);
3579
-		$result = $ocs->updateShare(42, null, null, null, 'true', null, null, null, null);
3580
-
3581
-		$this->assertInstanceOf(get_class($expected), $result);
3582
-		$this->assertEquals($expected->getData(), $result->getData());
3583
-	}
3584
-
3585
-	public function testUpdateLinkSharePermissions(): void {
3586
-		$ocs = $this->mockFormatShare();
3587
-
3588
-		$date = new \DateTime('2000-01-01');
3589
-
3590
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3591
-		$folder->method('getId')
3592
-			->willReturn(42);
3593
-
3594
-		$share = Server::get(IManager::class)->newShare();
3595
-		$share->setPermissions(Constants::PERMISSION_ALL)
3596
-			->setSharedBy($this->currentUser)
3597
-			->setShareType(IShare::TYPE_LINK)
3598
-			->setPassword('password')
3599
-			->setSendPasswordByTalk(true)
3600
-			->setExpirationDate($date)
3601
-			->setNote('note')
3602
-			->setLabel('label')
3603
-			->setHideDownload(true)
3604
-			->setPermissions(Constants::PERMISSION_ALL)
3605
-			->setNode($folder);
3606
-
3607
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3608
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3609
-
3610
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3611
-			$this->callback(function (IShare $share) use ($date): bool {
3612
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3613
-				&& $share->getPassword() === 'password'
3614
-				&& $share->getSendPasswordByTalk() === true
3615
-				&& $share->getExpirationDate() === $date
3616
-				&& $share->getNote() === 'note'
3617
-				&& $share->getLabel() === 'label'
3618
-				&& $share->getHideDownload() === true;
3619
-			})
3620
-		)->willReturnArgument(0);
3621
-
3622
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3623
-
3624
-		$this->rootFolder->method('getUserFolder')
3625
-			->with($this->currentUser)
3626
-			->willReturn($userFolder);
3627
-
3628
-		$userFolder->method('getById')
3629
-			->with(42)
3630
-			->willReturn([$folder]);
3631
-
3632
-		$mountPoint = $this->createMock(IMountPoint::class);
3633
-		$folder->method('getMountPoint')
3634
-			->willReturn($mountPoint);
3635
-		$mountPoint->method('getStorageRootId')
3636
-			->willReturn(42);
3637
-
3638
-		$expected = new DataResponse([]);
3639
-		$result = $ocs->updateShare(42, 7, null, null, 'true', null, null, null, null);
3640
-
3641
-		$this->assertInstanceOf(get_class($expected), $result);
3642
-		$this->assertEquals($expected->getData(), $result->getData());
3643
-	}
3644
-
3645
-	public function testUpdateLinkSharePermissionsShare(): void {
3646
-		$ocs = $this->mockFormatShare();
3647
-
3648
-		$date = new \DateTime('2000-01-01');
3649
-
3650
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3651
-		$folder->method('getId')
3652
-			->willReturn(42);
3653
-
3654
-		$share = Server::get(IManager::class)->newShare();
3655
-		$share->setPermissions(Constants::PERMISSION_ALL)
3656
-			->setSharedBy($this->currentUser)
3657
-			->setShareType(IShare::TYPE_LINK)
3658
-			->setPassword('password')
3659
-			->setSendPasswordByTalk(true)
3660
-			->setExpirationDate($date)
3661
-			->setNote('note')
3662
-			->setLabel('label')
3663
-			->setHideDownload(true)
3664
-			->setPermissions(Constants::PERMISSION_READ)
3665
-			->setNode($folder);
3666
-
3667
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3668
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3669
-
3670
-		$this->shareManager->expects($this->once())
3671
-			->method('updateShare')
3672
-			->with(
3673
-				$this->callback(function (IShare $share) use ($date) {
3674
-					return $share->getPermissions() === Constants::PERMISSION_ALL
3675
-						&& $share->getPassword() === 'password'
3676
-						&& $share->getSendPasswordByTalk() === true
3677
-						&& $share->getExpirationDate() === $date
3678
-						&& $share->getNote() === 'note'
3679
-						&& $share->getLabel() === 'label'
3680
-						&& $share->getHideDownload() === true;
3681
-				})
3682
-			)->willReturnArgument(0);
3683
-
3684
-		$this->rootFolder->method('getUserFolder')
3685
-			->with($this->currentUser)
3686
-			->willReturn($userFolder);
3687
-
3688
-		$userFolder->method('getById')
3689
-			->with(42)
3690
-			->willReturn([$folder]);
3691
-
3692
-		$mountPoint = $this->createMock(IMountPoint::class);
3693
-		$folder->method('getMountPoint')
3694
-			->willReturn($mountPoint);
3695
-		$mountPoint->method('getStorageRootId')
3696
-			->willReturn(42);
3697
-
3698
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3699
-
3700
-		$expected = new DataResponse([]);
3701
-		$result = $ocs->updateShare(42, Constants::PERMISSION_ALL, null, null, null, null, null, null, null);
3702
-
3703
-		$this->assertInstanceOf(get_class($expected), $result);
3704
-		$this->assertEquals($expected->getData(), $result->getData());
3705
-	}
3706
-
3707
-	public function testUpdateOtherPermissions(): void {
3708
-		$ocs = $this->mockFormatShare();
3709
-
3710
-		[$userFolder, $file] = $this->getNonSharedUserFolder();
3711
-		$file->method('getId')
3712
-			->willReturn(42);
3713
-
3714
-		$share = Server::get(IManager::class)->newShare();
3715
-		$share->setPermissions(Constants::PERMISSION_ALL)
3716
-			->setSharedBy($this->currentUser)
3717
-			->setShareType(IShare::TYPE_USER)
3718
-			->setNode($file);
3719
-
3720
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3721
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3722
-
3723
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3724
-			$this->callback(function (IShare $share) {
3725
-				return $share->getPermissions() === Constants::PERMISSION_ALL;
3726
-			})
3727
-		)->willReturnArgument(0);
3728
-
3729
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3730
-
3731
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3732
-		$this->rootFolder->method('getUserFolder')
3733
-			->with($this->currentUser)
3734
-			->willReturn($userFolder);
3735
-
3736
-		$userFolder->method('getById')
3737
-			->with(42)
3738
-			->willReturn([$file]);
3739
-
3740
-		$mountPoint = $this->createMock(IMountPoint::class);
3741
-		$file->method('getMountPoint')
3742
-			->willReturn($mountPoint);
3743
-		$mountPoint->method('getStorageRootId')
3744
-			->willReturn(42);
3745
-
3746
-		$expected = new DataResponse([]);
3747
-		$result = $ocs->updateShare(42, 31, null, null, null, null);
3748
-
3749
-		$this->assertInstanceOf(get_class($expected), $result);
3750
-		$this->assertEquals($expected->getData(), $result->getData());
3751
-	}
3752
-
3753
-	public function testUpdateShareCannotIncreasePermissions(): void {
3754
-		$ocs = $this->mockFormatShare();
3755
-
3756
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3757
-		$folder->method('getId')
3758
-			->willReturn(42);
3759
-
3760
-		$share = Server::get(IManager::class)->newShare();
3761
-		$share
3762
-			->setId(42)
3763
-			->setSharedBy($this->currentUser)
3764
-			->setShareOwner('anotheruser')
3765
-			->setShareType(IShare::TYPE_GROUP)
3766
-			->setSharedWith('group1')
3767
-			->setPermissions(Constants::PERMISSION_READ)
3768
-			->setNode($folder);
3769
-
3770
-		// note: updateShare will modify the received instance but getSharedWith will reread from the database,
3771
-		// so their values will be different
3772
-		$incomingShare = Server::get(IManager::class)->newShare();
3773
-		$incomingShare
3774
-			->setId(42)
3775
-			->setSharedBy($this->currentUser)
3776
-			->setShareOwner('anotheruser')
3777
-			->setShareType(IShare::TYPE_GROUP)
3778
-			->setSharedWith('group1')
3779
-			->setPermissions(Constants::PERMISSION_READ)
3780
-			->setNode($folder);
3781
-
3782
-		$this->request
3783
-			->method('getParam')
3784
-			->willReturnMap([
3785
-				['permissions', null, '31'],
3786
-			]);
3787
-
3788
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3789
-
3790
-		$this->shareManager->expects($this->any())
3791
-			->method('getSharedWith')
3792
-			->willReturnMap([
3793
-				['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3794
-				['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]],
3795
-				['currentUser', IShare::TYPE_ROOM, $share->getNode(), -1, 0, []]
3796
-			]);
3797
-
3798
-		$this->rootFolder->method('getUserFolder')
3799
-			->with($this->currentUser)
3800
-			->willReturn($userFolder);
3801
-
3802
-		$userFolder->method('getById')
3803
-			->with(42)
3804
-			->willReturn([$folder]);
3805
-		$userFolder->method('getFirstNodeById')
3806
-			->with(42)
3807
-			->willReturn($folder);
3808
-
3809
-		$mountPoint = $this->createMock(IMountPoint::class);
3810
-		$folder->method('getMountPoint')
3811
-			->willReturn($mountPoint);
3812
-		$mountPoint->method('getStorageRootId')
3813
-			->willReturn(42);
3814
-
3815
-		$this->shareManager->expects($this->once())
3816
-			->method('updateShare')
3817
-			->with($share)
3818
-			->willThrowException(new GenericShareException('Cannot increase permissions of path/file', 'Cannot increase permissions of path/file', 404));
3819
-
3820
-		try {
3821
-			$ocs->updateShare(42, 31);
3822
-			$this->fail();
3823
-		} catch (OCSException $e) {
3824
-			$this->assertEquals('Cannot increase permissions of path/file', $e->getMessage());
3825
-		}
3826
-	}
3827
-
3828
-	public function testUpdateShareCanIncreasePermissionsIfOwner(): void {
3829
-		$ocs = $this->mockFormatShare();
3830
-
3831
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3832
-		$folder->method('getId')
3833
-			->willReturn(42);
3834
-
3835
-		$share = Server::get(IManager::class)->newShare();
3836
-		$share
3837
-			->setId(42)
3838
-			->setSharedBy($this->currentUser)
3839
-			->setShareOwner($this->currentUser)
3840
-			->setShareType(IShare::TYPE_GROUP)
3841
-			->setSharedWith('group1')
3842
-			->setPermissions(Constants::PERMISSION_READ)
3843
-			->setNode($folder);
3844
-
3845
-		// note: updateShare will modify the received instance but getSharedWith will reread from the database,
3846
-		// so their values will be different
3847
-		$incomingShare = Server::get(IManager::class)->newShare();
3848
-		$incomingShare
3849
-			->setId(42)
3850
-			->setSharedBy($this->currentUser)
3851
-			->setShareOwner($this->currentUser)
3852
-			->setShareType(IShare::TYPE_GROUP)
3853
-			->setSharedWith('group1')
3854
-			->setPermissions(Constants::PERMISSION_READ)
3855
-			->setNode($folder);
3856
-
3857
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3858
-
3859
-		$this->shareManager->expects($this->any())
3860
-			->method('getSharedWith')
3861
-			->willReturnMap([
3862
-				['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3863
-				['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]]
3864
-			]);
3865
-
3866
-		$this->shareManager->expects($this->once())
3867
-			->method('updateShare')
3868
-			->with($share)
3869
-			->willReturn($share);
3870
-
3871
-		$this->rootFolder->method('getUserFolder')
3872
-			->with($this->currentUser)
3873
-			->willReturn($userFolder);
3874
-
3875
-		$userFolder->method('getById')
3876
-			->with(42)
3877
-			->willReturn([$folder]);
3878
-
3879
-		$mountPoint = $this->createMock(IMountPoint::class);
3880
-		$folder->method('getMountPoint')
3881
-			->willReturn($mountPoint);
3882
-		$mountPoint->method('getStorageRootId')
3883
-			->willReturn(42);
3884
-
3885
-		$result = $ocs->updateShare(42, 31);
3886
-		$this->assertInstanceOf(DataResponse::class, $result);
3887
-	}
3888
-
3889
-	public function testUpdateShareOwnerless(): void {
3890
-		$ocs = $this->mockFormatShare();
3891
-
3892
-		$mount = $this->createMock(IShareOwnerlessMount::class);
3893
-
3894
-		$file = $this->createMock(File::class);
3895
-		$file
3896
-			->expects($this->exactly(2))
3897
-			->method('getPermissions')
3898
-			->willReturn(Constants::PERMISSION_SHARE);
3899
-		$file
3900
-			->expects($this->once())
3901
-			->method('getMountPoint')
3902
-			->willReturn($mount);
3903
-
3904
-		$userFolder = $this->createMock(Folder::class);
3905
-		$userFolder->method('getById')
3906
-			->with(2)
3907
-			->willReturn([$file]);
3908
-		$userFolder->method('getFirstNodeById')
3909
-			->with(2)
3910
-			->willReturn($file);
3911
-
3912
-		$this->rootFolder
3913
-			->method('getUserFolder')
3914
-			->with($this->currentUser)
3915
-			->willReturn($userFolder);
3916
-
3917
-		$share = $this->createMock(IShare::class);
3918
-		$share
3919
-			->expects($this->once())
3920
-			->method('getNode')
3921
-			->willReturn($file);
3922
-		$share
3923
-			->expects($this->exactly(2))
3924
-			->method('getNodeId')
3925
-			->willReturn(2);
3926
-		$share
3927
-			->expects($this->exactly(2))
3928
-			->method('getPermissions')
3929
-			->willReturn(Constants::PERMISSION_SHARE);
3930
-
3931
-		$this->shareManager
3932
-			->expects($this->once())
3933
-			->method('getShareById')
3934
-			->with('ocinternal:1', $this->currentUser)
3935
-			->willReturn($share);
3936
-
3937
-		$this->shareManager
3938
-			->expects($this->once())
3939
-			->method('updateShare')
3940
-			->with($share)
3941
-			->willReturn($share);
3942
-
3943
-		$result = $ocs->updateShare(1, Constants::PERMISSION_ALL);
3944
-		$this->assertInstanceOf(DataResponse::class, $result);
3945
-	}
3946
-
3947
-	public function dataFormatShare() {
3948
-		$file = $this->getMockBuilder(File::class)->getMock();
3949
-		$folder = $this->getMockBuilder(Folder::class)->getMock();
3950
-		$parent = $this->getMockBuilder(Folder::class)->getMock();
3951
-		$fileWithPreview = $this->getMockBuilder(File::class)->getMock();
3952
-
3953
-		$file->method('getMimeType')->willReturn('myMimeType');
3954
-		$folder->method('getMimeType')->willReturn('myFolderMimeType');
3955
-		$fileWithPreview->method('getMimeType')->willReturn('mimeWithPreview');
3956
-
3957
-		$mountPoint = $this->createMock(IMountPoint::class);
3958
-		$mountPoint->method('getMountType')->willReturn('');
3959
-		$file->method('getMountPoint')->willReturn($mountPoint);
3960
-		$folder->method('getMountPoint')->willReturn($mountPoint);
3961
-		$fileWithPreview->method('getMountPoint')->willReturn($mountPoint);
3962
-
3963
-		$file->method('getPath')->willReturn('file');
3964
-		$folder->method('getPath')->willReturn('folder');
3965
-		$fileWithPreview->method('getPath')->willReturn('fileWithPreview');
3966
-
3967
-		$parent->method('getId')->willReturn(1);
3968
-		$folder->method('getId')->willReturn(2);
3969
-		$file->method('getId')->willReturn(3);
3970
-		$fileWithPreview->method('getId')->willReturn(4);
3971
-
3972
-		$file->method('getParent')->willReturn($parent);
3973
-		$folder->method('getParent')->willReturn($parent);
3974
-		$fileWithPreview->method('getParent')->willReturn($parent);
3975
-
3976
-		$file->method('getSize')->willReturn(123456);
3977
-		$folder->method('getSize')->willReturn(123456);
3978
-		$fileWithPreview->method('getSize')->willReturn(123456);
3979
-		$file->method('getMTime')->willReturn(1234567890);
3980
-		$folder->method('getMTime')->willReturn(1234567890);
3981
-		$fileWithPreview->method('getMTime')->willReturn(1234567890);
3982
-
3983
-		$cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
3984
-		$cache->method('getNumericStorageId')->willReturn(100);
3985
-		$storage = $this->createMock(IStorage::class);
3986
-		$storage->method('getId')->willReturn('storageId');
3987
-		$storage->method('getCache')->willReturn($cache);
3988
-
3989
-		$file->method('getStorage')->willReturn($storage);
3990
-		$folder->method('getStorage')->willReturn($storage);
3991
-		$fileWithPreview->method('getStorage')->willReturn($storage);
3992
-
3993
-
3994
-		$mountPoint = $this->getMockBuilder(IMountPoint::class)->getMock();
3995
-		$mountPoint->method('getMountType')->willReturn('');
3996
-		$file->method('getMountPoint')->willReturn($mountPoint);
3997
-		$folder->method('getMountPoint')->willReturn($mountPoint);
3998
-
3999
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
4000
-		$owner->method('getDisplayName')->willReturn('ownerDN');
4001
-		$initiator = $this->getMockBuilder(IUser::class)->getMock();
4002
-		$initiator->method('getDisplayName')->willReturn('initiatorDN');
4003
-		$recipient = $this->getMockBuilder(IUser::class)->getMock();
4004
-		$recipient->method('getDisplayName')->willReturn('recipientDN');
4005
-		$recipient->method('getSystemEMailAddress')->willReturn('recipient');
4006
-		[$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
4007
-
4008
-		$result = [];
4009
-
4010
-		$share = Server::get(IManager::class)->newShare();
4011
-		$share->setShareType(IShare::TYPE_USER)
4012
-			->setSharedWith('recipient')
4013
-			->setSharedBy('initiator')
4014
-			->setShareOwner('owner')
4015
-			->setPermissions(Constants::PERMISSION_READ)
4016
-			->setAttributes($shareAttributes)
4017
-			->setNode($file)
4018
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4019
-			->setTarget('myTarget')
4020
-			->setNote('personal note')
4021
-			->setId(42);
4022
-
4023
-		// User backend down
4024
-		$result[] = [
4025
-			[
4026
-				'id' => '42',
4027
-				'share_type' => IShare::TYPE_USER,
4028
-				'uid_owner' => 'initiator',
4029
-				'displayname_owner' => 'initiator',
4030
-				'permissions' => 1,
4031
-				'attributes' => $shareAttributesReturnJson,
4032
-				'stime' => 946684862,
4033
-				'parent' => null,
4034
-				'expiration' => null,
4035
-				'token' => null,
4036
-				'uid_file_owner' => 'owner',
4037
-				'displayname_file_owner' => 'owner',
4038
-				'path' => 'file',
4039
-				'item_type' => 'file',
4040
-				'storage_id' => 'storageId',
4041
-				'storage' => 100,
4042
-				'item_source' => 3,
4043
-				'file_source' => 3,
4044
-				'file_parent' => 1,
4045
-				'file_target' => 'myTarget',
4046
-				'share_with' => 'recipient',
4047
-				'share_with_displayname' => 'recipient',
4048
-				'share_with_displayname_unique' => 'recipient',
4049
-				'note' => 'personal note',
4050
-				'label' => '',
4051
-				'mail_send' => 0,
4052
-				'mimetype' => 'myMimeType',
4053
-				'has_preview' => false,
4054
-				'hide_download' => 0,
4055
-				'can_edit' => false,
4056
-				'can_delete' => false,
4057
-				'item_size' => 123456,
4058
-				'item_mtime' => 1234567890,
4059
-				'is-mount-root' => false,
4060
-				'mount-type' => '',
4061
-				'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4062
-				'item_permissions' => 1,
4063
-			], $share, [], false
4064
-		];
4065
-		// User backend up
4066
-		$result[] = [
4067
-			[
4068
-				'id' => '42',
4069
-				'share_type' => IShare::TYPE_USER,
4070
-				'uid_owner' => 'initiator',
4071
-				'displayname_owner' => 'initiatorDN',
4072
-				'permissions' => 1,
4073
-				'attributes' => $shareAttributesReturnJson,
4074
-				'stime' => 946684862,
4075
-				'parent' => null,
4076
-				'expiration' => null,
4077
-				'token' => null,
4078
-				'uid_file_owner' => 'owner',
4079
-				'displayname_file_owner' => 'ownerDN',
4080
-				'note' => 'personal note',
4081
-				'label' => '',
4082
-				'path' => 'file',
4083
-				'item_type' => 'file',
4084
-				'storage_id' => 'storageId',
4085
-				'storage' => 100,
4086
-				'item_source' => 3,
4087
-				'file_source' => 3,
4088
-				'file_parent' => 1,
4089
-				'file_target' => 'myTarget',
4090
-				'share_with' => 'recipient',
4091
-				'share_with_displayname' => 'recipientDN',
4092
-				'share_with_displayname_unique' => 'recipient',
4093
-				'mail_send' => 0,
4094
-				'mimetype' => 'myMimeType',
4095
-				'has_preview' => false,
4096
-				'hide_download' => 0,
4097
-				'can_edit' => false,
4098
-				'can_delete' => false,
4099
-				'item_size' => 123456,
4100
-				'item_mtime' => 1234567890,
4101
-				'is-mount-root' => false,
4102
-				'mount-type' => '',
4103
-				'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4104
-				'item_permissions' => 1,
4105
-			], $share, [
4106
-				['owner', $owner],
4107
-				['initiator', $initiator],
4108
-				['recipient', $recipient],
4109
-			], false
4110
-		];
4111
-
4112
-		$share = Server::get(IManager::class)->newShare();
4113
-		$share->setShareType(IShare::TYPE_USER)
4114
-			->setSharedWith('recipient')
4115
-			->setSharedBy('initiator')
4116
-			->setShareOwner('owner')
4117
-			->setPermissions(Constants::PERMISSION_READ)
4118
-			->setNode($file)
4119
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4120
-			->setTarget('myTarget')
4121
-			->setNote('personal note')
4122
-			->setId(42);
4123
-		// User backend down
4124
-		$result[] = [
4125
-			[
4126
-				'id' => '42',
4127
-				'share_type' => IShare::TYPE_USER,
4128
-				'uid_owner' => 'initiator',
4129
-				'displayname_owner' => 'initiator',
4130
-				'permissions' => 1,
4131
-				'attributes' => null,
4132
-				'stime' => 946684862,
4133
-				'parent' => null,
4134
-				'expiration' => null,
4135
-				'token' => null,
4136
-				'uid_file_owner' => 'owner',
4137
-				'displayname_file_owner' => 'owner',
4138
-				'note' => 'personal note',
4139
-				'label' => '',
4140
-				'path' => 'file',
4141
-				'item_type' => 'file',
4142
-				'storage_id' => 'storageId',
4143
-				'storage' => 100,
4144
-				'item_source' => 3,
4145
-				'file_source' => 3,
4146
-				'file_parent' => 1,
4147
-				'file_target' => 'myTarget',
4148
-				'share_with' => 'recipient',
4149
-				'share_with_displayname' => 'recipient',
4150
-				'share_with_displayname_unique' => 'recipient',
4151
-				'mail_send' => 0,
4152
-				'mimetype' => 'myMimeType',
4153
-				'has_preview' => false,
4154
-				'hide_download' => 0,
4155
-				'can_edit' => false,
4156
-				'can_delete' => false,
4157
-				'item_size' => 123456,
4158
-				'item_mtime' => 1234567890,
4159
-				'is-mount-root' => false,
4160
-				'mount-type' => '',
4161
-				'attributes' => null,
4162
-				'item_permissions' => 1,
4163
-			], $share, [], false
4164
-		];
4165
-
4166
-		$share = Server::get(IManager::class)->newShare();
4167
-		$share->setShareType(IShare::TYPE_USER)
4168
-			->setSharedWith('recipient')
4169
-			->setSharedBy('initiator')
4170
-			->setShareOwner('currentUser')
4171
-			->setPermissions(Constants::PERMISSION_READ)
4172
-			->setNode($file)
4173
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4174
-			->setTarget('myTarget')
4175
-			->setNote('personal note')
4176
-			->setId(42);
4177
-		// User backend down
4178
-		$result[] = [
4179
-			[
4180
-				'id' => '42',
4181
-				'share_type' => IShare::TYPE_USER,
4182
-				'uid_owner' => 'initiator',
4183
-				'displayname_owner' => 'initiator',
4184
-				'permissions' => 1,
4185
-				'attributes' => null,
4186
-				'stime' => 946684862,
4187
-				'parent' => null,
4188
-				'expiration' => null,
4189
-				'token' => null,
4190
-				'uid_file_owner' => 'currentUser',
4191
-				'displayname_file_owner' => 'currentUser',
4192
-				'note' => 'personal note',
4193
-				'label' => '',
4194
-				'path' => 'file',
4195
-				'item_type' => 'file',
4196
-				'storage_id' => 'storageId',
4197
-				'storage' => 100,
4198
-				'item_source' => 3,
4199
-				'file_source' => 3,
4200
-				'file_parent' => 1,
4201
-				'file_target' => 'myTarget',
4202
-				'share_with' => 'recipient',
4203
-				'share_with_displayname' => 'recipient',
4204
-				'share_with_displayname_unique' => 'recipient',
4205
-				'mail_send' => 0,
4206
-				'mimetype' => 'myMimeType',
4207
-				'has_preview' => false,
4208
-				'hide_download' => 0,
4209
-				'can_edit' => true,
4210
-				'can_delete' => true,
4211
-				'item_size' => 123456,
4212
-				'item_mtime' => 1234567890,
4213
-				'is-mount-root' => false,
4214
-				'mount-type' => '',
4215
-				'attributes' => null,
4216
-				'item_permissions' => 11,
4217
-			], $share, [], false
4218
-		];
4219
-
4220
-		// with existing group
4221
-
4222
-		$share = Server::get(IManager::class)->newShare();
4223
-		$share->setShareType(IShare::TYPE_GROUP)
4224
-			->setSharedWith('recipientGroup')
4225
-			->setSharedBy('initiator')
4226
-			->setShareOwner('owner')
4227
-			->setPermissions(Constants::PERMISSION_READ)
4228
-			->setNode($file)
4229
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4230
-			->setTarget('myTarget')
4231
-			->setNote('personal note')
4232
-			->setId(42);
4233
-
4234
-		$result[] = [
4235
-			[
4236
-				'id' => '42',
4237
-				'share_type' => IShare::TYPE_GROUP,
4238
-				'uid_owner' => 'initiator',
4239
-				'displayname_owner' => 'initiator',
4240
-				'permissions' => 1,
4241
-				'attributes' => null,
4242
-				'stime' => 946684862,
4243
-				'parent' => null,
4244
-				'expiration' => null,
4245
-				'token' => null,
4246
-				'uid_file_owner' => 'owner',
4247
-				'displayname_file_owner' => 'owner',
4248
-				'note' => 'personal note',
4249
-				'label' => '',
4250
-				'path' => 'file',
4251
-				'item_type' => 'file',
4252
-				'storage_id' => 'storageId',
4253
-				'storage' => 100,
4254
-				'item_source' => 3,
4255
-				'file_source' => 3,
4256
-				'file_parent' => 1,
4257
-				'file_target' => 'myTarget',
4258
-				'share_with' => 'recipientGroup',
4259
-				'share_with_displayname' => 'recipientGroupDisplayName',
4260
-				'mail_send' => 0,
4261
-				'mimetype' => 'myMimeType',
4262
-				'has_preview' => false,
4263
-				'hide_download' => 0,
4264
-				'can_edit' => false,
4265
-				'can_delete' => false,
4266
-				'item_size' => 123456,
4267
-				'item_mtime' => 1234567890,
4268
-				'is-mount-root' => false,
4269
-				'mount-type' => '',
4270
-				'attributes' => null,
4271
-				'item_permissions' => 1,
4272
-			], $share, [], false
4273
-		];
4274
-
4275
-		// with unknown group / no group backend
4276
-		$share = Server::get(IManager::class)->newShare();
4277
-		$share->setShareType(IShare::TYPE_GROUP)
4278
-			->setSharedWith('recipientGroup2')
4279
-			->setSharedBy('initiator')
4280
-			->setShareOwner('owner')
4281
-			->setPermissions(Constants::PERMISSION_READ)
4282
-			->setNode($file)
4283
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4284
-			->setTarget('myTarget')
4285
-			->setNote('personal note')
4286
-			->setId(42);
4287
-		$result[] = [
4288
-			[
4289
-				'id' => '42',
4290
-				'share_type' => IShare::TYPE_GROUP,
4291
-				'uid_owner' => 'initiator',
4292
-				'displayname_owner' => 'initiator',
4293
-				'permissions' => 1,
4294
-				'stime' => 946684862,
4295
-				'parent' => null,
4296
-				'expiration' => null,
4297
-				'token' => null,
4298
-				'uid_file_owner' => 'owner',
4299
-				'displayname_file_owner' => 'owner',
4300
-				'note' => 'personal note',
4301
-				'label' => '',
4302
-				'path' => 'file',
4303
-				'item_type' => 'file',
4304
-				'storage_id' => 'storageId',
4305
-				'storage' => 100,
4306
-				'item_source' => 3,
4307
-				'file_source' => 3,
4308
-				'file_parent' => 1,
4309
-				'file_target' => 'myTarget',
4310
-				'share_with' => 'recipientGroup2',
4311
-				'share_with_displayname' => 'recipientGroup2',
4312
-				'mail_send' => 0,
4313
-				'mimetype' => 'myMimeType',
4314
-				'has_preview' => false,
4315
-				'hide_download' => 0,
4316
-				'can_edit' => false,
4317
-				'can_delete' => false,
4318
-				'item_size' => 123456,
4319
-				'item_mtime' => 1234567890,
4320
-				'is-mount-root' => false,
4321
-				'mount-type' => '',
4322
-				'attributes' => null,
4323
-				'item_permissions' => 1,
4324
-			], $share, [], false
4325
-		];
4326
-
4327
-		$share = Server::get(IManager::class)->newShare();
4328
-		$share->setShareType(IShare::TYPE_LINK)
4329
-			->setSharedBy('initiator')
4330
-			->setShareOwner('owner')
4331
-			->setPermissions(Constants::PERMISSION_READ)
4332
-			->setNode($file)
4333
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4334
-			->setTarget('myTarget')
4335
-			->setPassword('mypassword')
4336
-			->setExpirationDate(new \DateTime('2001-01-02T00:00:00'))
4337
-			->setToken('myToken')
4338
-			->setNote('personal note')
4339
-			->setLabel('new link share')
4340
-			->setId(42);
4341
-
4342
-		$result[] = [
4343
-			[
4344
-				'id' => '42',
4345
-				'share_type' => IShare::TYPE_LINK,
4346
-				'uid_owner' => 'initiator',
4347
-				'displayname_owner' => 'initiator',
4348
-				'permissions' => 1,
4349
-				'attributes' => null,
4350
-				'stime' => 946684862,
4351
-				'parent' => null,
4352
-				'expiration' => '2001-01-02 00:00:00',
4353
-				'token' => 'myToken',
4354
-				'uid_file_owner' => 'owner',
4355
-				'displayname_file_owner' => 'owner',
4356
-				'note' => 'personal note',
4357
-				'label' => 'new link share',
4358
-				'path' => 'file',
4359
-				'item_type' => 'file',
4360
-				'storage_id' => 'storageId',
4361
-				'storage' => 100,
4362
-				'item_source' => 3,
4363
-				'file_source' => 3,
4364
-				'file_parent' => 1,
4365
-				'file_target' => 'myTarget',
4366
-				'password' => 'mypassword',
4367
-				'share_with' => 'mypassword',
4368
-				'share_with_displayname' => '(Shared link)',
4369
-				'send_password_by_talk' => false,
4370
-				'mail_send' => 0,
4371
-				'url' => 'myLink',
4372
-				'mimetype' => 'myMimeType',
4373
-				'has_preview' => false,
4374
-				'hide_download' => 0,
4375
-				'can_edit' => false,
4376
-				'can_delete' => false,
4377
-				'item_size' => 123456,
4378
-				'item_mtime' => 1234567890,
4379
-				'is-mount-root' => false,
4380
-				'mount-type' => '',
4381
-				'attributes' => null,
4382
-				'item_permissions' => 1,
4383
-			], $share, [], false
4384
-		];
4385
-
4386
-		$share = Server::get(IManager::class)->newShare();
4387
-		$share->setShareType(IShare::TYPE_LINK)
4388
-			->setSharedBy('initiator')
4389
-			->setShareOwner('owner')
4390
-			->setPermissions(Constants::PERMISSION_READ)
4391
-			->setNode($file)
4392
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4393
-			->setTarget('myTarget')
4394
-			->setPassword('mypassword')
4395
-			->setSendPasswordByTalk(true)
4396
-			->setExpirationDate(new \DateTime('2001-01-02T00:00:00'))
4397
-			->setToken('myToken')
4398
-			->setNote('personal note')
4399
-			->setLabel('new link share')
4400
-			->setId(42);
4401
-
4402
-		$result[] = [
4403
-			[
4404
-				'id' => '42',
4405
-				'share_type' => IShare::TYPE_LINK,
4406
-				'uid_owner' => 'initiator',
4407
-				'displayname_owner' => 'initiator',
4408
-				'permissions' => 1,
4409
-				'stime' => 946684862,
4410
-				'parent' => null,
4411
-				'expiration' => '2001-01-02 00:00:00',
4412
-				'token' => 'myToken',
4413
-				'uid_file_owner' => 'owner',
4414
-				'displayname_file_owner' => 'owner',
4415
-				'note' => 'personal note',
4416
-				'label' => 'new link share',
4417
-				'path' => 'file',
4418
-				'item_type' => 'file',
4419
-				'storage_id' => 'storageId',
4420
-				'storage' => 100,
4421
-				'item_source' => 3,
4422
-				'file_source' => 3,
4423
-				'file_parent' => 1,
4424
-				'file_target' => 'myTarget',
4425
-				'password' => 'mypassword',
4426
-				'share_with' => 'mypassword',
4427
-				'share_with_displayname' => '(Shared link)',
4428
-				'send_password_by_talk' => true,
4429
-				'mail_send' => 0,
4430
-				'url' => 'myLink',
4431
-				'mimetype' => 'myMimeType',
4432
-				'has_preview' => false,
4433
-				'hide_download' => 0,
4434
-				'can_edit' => false,
4435
-				'can_delete' => false,
4436
-				'item_size' => 123456,
4437
-				'item_mtime' => 1234567890,
4438
-				'is-mount-root' => false,
4439
-				'mount-type' => '',
4440
-				'attributes' => null,
4441
-				'item_permissions' => 1,
4442
-			], $share, [], false
4443
-		];
4444
-
4445
-		$share = Server::get(IManager::class)->newShare();
4446
-		$share->setShareType(IShare::TYPE_REMOTE)
4447
-			->setSharedBy('initiator')
4448
-			->setSharedWith('[email protected]')
4449
-			->setShareOwner('owner')
4450
-			->setPermissions(Constants::PERMISSION_READ)
4451
-			->setNode($folder)
4452
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4453
-			->setExpirationDate(new \DateTime('2001-02-03T04:05:06'))
4454
-			->setTarget('myTarget')
4455
-			->setNote('personal note')
4456
-			->setId(42);
4457
-
4458
-		$result[] = [
4459
-			[
4460
-				'id' => '42',
4461
-				'share_type' => IShare::TYPE_REMOTE,
4462
-				'uid_owner' => 'initiator',
4463
-				'displayname_owner' => 'initiator',
4464
-				'permissions' => 1,
4465
-				'stime' => 946684862,
4466
-				'parent' => null,
4467
-				'expiration' => '2001-02-03 00:00:00',
4468
-				'token' => null,
4469
-				'uid_file_owner' => 'owner',
4470
-				'displayname_file_owner' => 'owner',
4471
-				'note' => 'personal note',
4472
-				'label' => '',
4473
-				'path' => 'folder',
4474
-				'item_type' => 'folder',
4475
-				'storage_id' => 'storageId',
4476
-				'storage' => 100,
4477
-				'item_source' => 2,
4478
-				'file_source' => 2,
4479
-				'file_parent' => 1,
4480
-				'file_target' => 'myTarget',
4481
-				'share_with' => '[email protected]',
4482
-				'share_with_displayname' => 'foobar',
4483
-				'mail_send' => 0,
4484
-				'mimetype' => 'myFolderMimeType',
4485
-				'has_preview' => false,
4486
-				'hide_download' => 0,
4487
-				'can_edit' => false,
4488
-				'can_delete' => false,
4489
-				'item_size' => 123456,
4490
-				'item_mtime' => 1234567890,
4491
-				'is-mount-root' => false,
4492
-				'mount-type' => '',
4493
-				'attributes' => null,
4494
-				'item_permissions' => 1,
4495
-			], $share, [], false
4496
-		];
4497
-
4498
-		$share = Server::get(IManager::class)->newShare();
4499
-		$share->setShareType(IShare::TYPE_REMOTE_GROUP)
4500
-			->setSharedBy('initiator')
4501
-			->setSharedWith('[email protected]')
4502
-			->setShareOwner('owner')
4503
-			->setPermissions(Constants::PERMISSION_READ)
4504
-			->setNode($folder)
4505
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4506
-			->setExpirationDate(new \DateTime('2001-02-03T04:05:06'))
4507
-			->setTarget('myTarget')
4508
-			->setNote('personal note')
4509
-			->setId(42);
4510
-
4511
-		$result[] = [
4512
-			[
4513
-				'id' => '42',
4514
-				'share_type' => IShare::TYPE_REMOTE_GROUP,
4515
-				'uid_owner' => 'initiator',
4516
-				'displayname_owner' => 'initiator',
4517
-				'permissions' => 1,
4518
-				'stime' => 946684862,
4519
-				'parent' => null,
4520
-				'expiration' => '2001-02-03 00:00:00',
4521
-				'token' => null,
4522
-				'uid_file_owner' => 'owner',
4523
-				'displayname_file_owner' => 'owner',
4524
-				'note' => 'personal note',
4525
-				'label' => '',
4526
-				'path' => 'folder',
4527
-				'item_type' => 'folder',
4528
-				'storage_id' => 'storageId',
4529
-				'storage' => 100,
4530
-				'item_source' => 2,
4531
-				'file_source' => 2,
4532
-				'file_parent' => 1,
4533
-				'file_target' => 'myTarget',
4534
-				'share_with' => '[email protected]',
4535
-				'share_with_displayname' => 'foobar',
4536
-				'mail_send' => 0,
4537
-				'mimetype' => 'myFolderMimeType',
4538
-				'has_preview' => false,
4539
-				'hide_download' => 0,
4540
-				'can_edit' => false,
4541
-				'can_delete' => false,
4542
-				'item_size' => 123456,
4543
-				'item_mtime' => 1234567890,
4544
-				'is-mount-root' => false,
4545
-				'mount-type' => '',
4546
-				'attributes' => null,
4547
-				'item_permissions' => 1,
4548
-			], $share, [], false
4549
-		];
4550
-
4551
-		// Circle with id, display name and avatar set by the Circles app
4552
-		$share = Server::get(IManager::class)->newShare();
4553
-		$share->setShareType(IShare::TYPE_CIRCLE)
4554
-			->setSharedBy('initiator')
4555
-			->setSharedWith('Circle (Public circle, circleOwner) [4815162342]')
4556
-			->setSharedWithDisplayName('The display name')
4557
-			->setSharedWithAvatar('path/to/the/avatar')
4558
-			->setShareOwner('owner')
4559
-			->setPermissions(Constants::PERMISSION_READ)
4560
-			->setNode($folder)
4561
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4562
-			->setTarget('myTarget')
4563
-			->setId(42);
4564
-
4565
-		$result[] = [
4566
-			[
4567
-				'id' => '42',
4568
-				'share_type' => IShare::TYPE_CIRCLE,
4569
-				'uid_owner' => 'initiator',
4570
-				'displayname_owner' => 'initiator',
4571
-				'permissions' => 1,
4572
-				'attributes' => null,
4573
-				'stime' => 946684862,
4574
-				'parent' => null,
4575
-				'expiration' => null,
4576
-				'token' => null,
4577
-				'uid_file_owner' => 'owner',
4578
-				'displayname_file_owner' => 'owner',
4579
-				'note' => '',
4580
-				'label' => '',
4581
-				'path' => 'folder',
4582
-				'item_type' => 'folder',
4583
-				'storage_id' => 'storageId',
4584
-				'storage' => 100,
4585
-				'item_source' => 2,
4586
-				'file_source' => 2,
4587
-				'file_parent' => 1,
4588
-				'file_target' => 'myTarget',
4589
-				'share_with' => '4815162342',
4590
-				'share_with_displayname' => 'The display name',
4591
-				'share_with_avatar' => 'path/to/the/avatar',
4592
-				'mail_send' => 0,
4593
-				'mimetype' => 'myFolderMimeType',
4594
-				'has_preview' => false,
4595
-				'hide_download' => 0,
4596
-				'can_edit' => false,
4597
-				'can_delete' => false,
4598
-				'item_size' => 123456,
4599
-				'item_mtime' => 1234567890,
4600
-				'is-mount-root' => false,
4601
-				'mount-type' => '',
4602
-				'attributes' => null,
4603
-				'item_permissions' => 1,
4604
-			], $share, [], false
4605
-		];
4606
-
4607
-		// Circle with id set by the Circles app
4608
-		$share = Server::get(IManager::class)->newShare();
4609
-		$share->setShareType(IShare::TYPE_CIRCLE)
4610
-			->setSharedBy('initiator')
4611
-			->setSharedWith('Circle (Public circle, circleOwner) [4815162342]')
4612
-			->setShareOwner('owner')
4613
-			->setPermissions(Constants::PERMISSION_READ)
4614
-			->setNode($folder)
4615
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4616
-			->setTarget('myTarget')
4617
-			->setId(42);
4618
-
4619
-		$result[] = [
4620
-			[
4621
-				'id' => '42',
4622
-				'share_type' => IShare::TYPE_CIRCLE,
4623
-				'uid_owner' => 'initiator',
4624
-				'displayname_owner' => 'initiator',
4625
-				'permissions' => 1,
4626
-				'stime' => 946684862,
4627
-				'parent' => null,
4628
-				'expiration' => null,
4629
-				'token' => null,
4630
-				'uid_file_owner' => 'owner',
4631
-				'displayname_file_owner' => 'owner',
4632
-				'note' => '',
4633
-				'label' => '',
4634
-				'path' => 'folder',
4635
-				'item_type' => 'folder',
4636
-				'storage_id' => 'storageId',
4637
-				'storage' => 100,
4638
-				'item_source' => 2,
4639
-				'file_source' => 2,
4640
-				'file_parent' => 1,
4641
-				'file_target' => 'myTarget',
4642
-				'share_with' => '4815162342',
4643
-				'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4644
-				'share_with_avatar' => '',
4645
-				'mail_send' => 0,
4646
-				'mimetype' => 'myFolderMimeType',
4647
-				'has_preview' => false,
4648
-				'hide_download' => 0,
4649
-				'can_edit' => false,
4650
-				'can_delete' => false,
4651
-				'item_size' => 123456,
4652
-				'item_mtime' => 1234567890,
4653
-				'is-mount-root' => false,
4654
-				'mount-type' => '',
4655
-				'attributes' => null,
4656
-				'item_permissions' => 1,
4657
-			], $share, [], false
4658
-		];
4659
-
4660
-		// Circle with id not set by the Circles app
4661
-		$share = Server::get(IManager::class)->newShare();
4662
-		$share->setShareType(IShare::TYPE_CIRCLE)
4663
-			->setSharedBy('initiator')
4664
-			->setSharedWith('Circle (Public circle, circleOwner)')
4665
-			->setShareOwner('owner')
4666
-			->setPermissions(Constants::PERMISSION_READ)
4667
-			->setNode($folder)
4668
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4669
-			->setTarget('myTarget')
4670
-			->setId(42);
4671
-
4672
-		$result[] = [
4673
-			[
4674
-				'id' => '42',
4675
-				'share_type' => IShare::TYPE_CIRCLE,
4676
-				'uid_owner' => 'initiator',
4677
-				'displayname_owner' => 'initiator',
4678
-				'permissions' => 1,
4679
-				'stime' => 946684862,
4680
-				'parent' => null,
4681
-				'expiration' => null,
4682
-				'token' => null,
4683
-				'uid_file_owner' => 'owner',
4684
-				'displayname_file_owner' => 'owner',
4685
-				'note' => '',
4686
-				'label' => '',
4687
-				'path' => 'folder',
4688
-				'item_type' => 'folder',
4689
-				'storage_id' => 'storageId',
4690
-				'storage' => 100,
4691
-				'item_source' => 2,
4692
-				'file_source' => 2,
4693
-				'file_parent' => 1,
4694
-				'file_target' => 'myTarget',
4695
-				'share_with' => 'Circle',
4696
-				'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4697
-				'share_with_avatar' => '',
4698
-				'mail_send' => 0,
4699
-				'mimetype' => 'myFolderMimeType',
4700
-				'has_preview' => false,
4701
-				'hide_download' => 0,
4702
-				'can_edit' => false,
4703
-				'can_delete' => false,
4704
-				'item_size' => 123456,
4705
-				'item_mtime' => 1234567890,
4706
-				'is-mount-root' => false,
4707
-				'mount-type' => '',
4708
-				'attributes' => null,
4709
-				'item_permissions' => 1,
4710
-			], $share, [], false
4711
-		];
4712
-
4713
-		$share = Server::get(IManager::class)->newShare();
4714
-		$share->setShareType(IShare::TYPE_USER)
4715
-			->setSharedBy('initiator')
4716
-			->setSharedWith('recipient')
4717
-			->setShareOwner('owner')
4718
-			->setPermissions(Constants::PERMISSION_READ)
4719
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4720
-			->setTarget('myTarget')
4721
-			->setNote('personal note')
4722
-			->setId(42);
4723
-
4724
-		$result[] = [
4725
-			[], $share, [], true
4726
-		];
4727
-
4728
-		$share = Server::get(IManager::class)->newShare();
4729
-		$share->setShareType(IShare::TYPE_EMAIL)
4730
-			->setSharedBy('initiator')
4731
-			->setSharedWith('[email protected]')
4732
-			->setShareOwner('owner')
4733
-			->setPermissions(Constants::PERMISSION_READ)
4734
-			->setNode($folder)
4735
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4736
-			->setTarget('myTarget')
4737
-			->setId(42)
4738
-			->setPassword('password');
4739
-
4740
-		$result[] = [
4741
-			[
4742
-				'id' => '42',
4743
-				'share_type' => IShare::TYPE_EMAIL,
4744
-				'uid_owner' => 'initiator',
4745
-				'displayname_owner' => 'initiator',
4746
-				'permissions' => 1,
4747
-				'stime' => 946684862,
4748
-				'parent' => null,
4749
-				'expiration' => null,
4750
-				'token' => null,
4751
-				'uid_file_owner' => 'owner',
4752
-				'displayname_file_owner' => 'owner',
4753
-				'note' => '',
4754
-				'label' => '',
4755
-				'path' => 'folder',
4756
-				'item_type' => 'folder',
4757
-				'storage_id' => 'storageId',
4758
-				'storage' => 100,
4759
-				'item_source' => 2,
4760
-				'file_source' => 2,
4761
-				'file_parent' => 1,
4762
-				'file_target' => 'myTarget',
4763
-				'share_with' => '[email protected]',
4764
-				'share_with_displayname' => 'mail display name',
4765
-				'mail_send' => 0,
4766
-				'mimetype' => 'myFolderMimeType',
4767
-				'has_preview' => false,
4768
-				'password' => 'password',
4769
-				'send_password_by_talk' => false,
4770
-				'hide_download' => 0,
4771
-				'can_edit' => false,
4772
-				'can_delete' => false,
4773
-				'password_expiration_time' => null,
4774
-				'item_size' => 123456,
4775
-				'item_mtime' => 1234567890,
4776
-				'is-mount-root' => false,
4777
-				'mount-type' => '',
4778
-				'attributes' => null,
4779
-				'item_permissions' => 1,
4780
-			], $share, [], false
4781
-		];
4782
-
4783
-		$share = Server::get(IManager::class)->newShare();
4784
-		$share->setShareType(IShare::TYPE_EMAIL)
4785
-			->setSharedBy('initiator')
4786
-			->setSharedWith('[email protected]')
4787
-			->setShareOwner('owner')
4788
-			->setPermissions(Constants::PERMISSION_READ)
4789
-			->setNode($folder)
4790
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4791
-			->setTarget('myTarget')
4792
-			->setId(42)
4793
-			->setPassword('password')
4794
-			->setSendPasswordByTalk(true);
4795
-
4796
-		$result[] = [
4797
-			[
4798
-				'id' => '42',
4799
-				'share_type' => IShare::TYPE_EMAIL,
4800
-				'uid_owner' => 'initiator',
4801
-				'displayname_owner' => 'initiator',
4802
-				'permissions' => 1,
4803
-				'stime' => 946684862,
4804
-				'parent' => null,
4805
-				'expiration' => null,
4806
-				'token' => null,
4807
-				'uid_file_owner' => 'owner',
4808
-				'displayname_file_owner' => 'owner',
4809
-				'note' => '',
4810
-				'label' => '',
4811
-				'path' => 'folder',
4812
-				'item_type' => 'folder',
4813
-				'storage_id' => 'storageId',
4814
-				'storage' => 100,
4815
-				'item_source' => 2,
4816
-				'file_source' => 2,
4817
-				'file_parent' => 1,
4818
-				'file_target' => 'myTarget',
4819
-				'share_with' => '[email protected]',
4820
-				'share_with_displayname' => 'mail display name',
4821
-				'mail_send' => 0,
4822
-				'mimetype' => 'myFolderMimeType',
4823
-				'has_preview' => false,
4824
-				'password' => 'password',
4825
-				'send_password_by_talk' => true,
4826
-				'hide_download' => 0,
4827
-				'can_edit' => false,
4828
-				'can_delete' => false,
4829
-				'password_expiration_time' => null,
4830
-				'item_size' => 123456,
4831
-				'item_mtime' => 1234567890,
4832
-				'is-mount-root' => false,
4833
-				'mount-type' => '',
4834
-				'attributes' => null,
4835
-				'item_permissions' => 1,
4836
-			], $share, [], false
4837
-		];
4838
-
4839
-		// Preview is available
4840
-		$share = Server::get(IManager::class)->newShare();
4841
-		$share->setShareType(IShare::TYPE_USER)
4842
-			->setSharedWith('recipient')
4843
-			->setSharedBy('initiator')
4844
-			->setShareOwner('currentUser')
4845
-			->setPermissions(Constants::PERMISSION_READ)
4846
-			->setNode($fileWithPreview)
4847
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4848
-			->setTarget('myTarget')
4849
-			->setNote('personal note')
4850
-			->setId(42);
4851
-
4852
-		$result[] = [
4853
-			[
4854
-				'id' => '42',
4855
-				'share_type' => IShare::TYPE_USER,
4856
-				'uid_owner' => 'initiator',
4857
-				'displayname_owner' => 'initiator',
4858
-				'permissions' => 1,
4859
-				'stime' => 946684862,
4860
-				'parent' => null,
4861
-				'expiration' => null,
4862
-				'token' => null,
4863
-				'uid_file_owner' => 'currentUser',
4864
-				'displayname_file_owner' => 'currentUser',
4865
-				'note' => 'personal note',
4866
-				'label' => '',
4867
-				'path' => 'fileWithPreview',
4868
-				'item_type' => 'file',
4869
-				'storage_id' => 'storageId',
4870
-				'storage' => 100,
4871
-				'item_source' => 4,
4872
-				'file_source' => 4,
4873
-				'file_parent' => 1,
4874
-				'file_target' => 'myTarget',
4875
-				'share_with' => 'recipient',
4876
-				'share_with_displayname' => 'recipient',
4877
-				'share_with_displayname_unique' => 'recipient',
4878
-				'mail_send' => 0,
4879
-				'mimetype' => 'mimeWithPreview',
4880
-				'has_preview' => true,
4881
-				'hide_download' => 0,
4882
-				'can_edit' => true,
4883
-				'can_delete' => true,
4884
-				'item_size' => 123456,
4885
-				'item_mtime' => 1234567890,
4886
-				'is-mount-root' => false,
4887
-				'mount-type' => '',
4888
-				'attributes' => null,
4889
-				'item_permissions' => 11,
4890
-			], $share, [], false
4891
-		];
4892
-
4893
-		return $result;
4894
-	}
4895
-
4896
-	/**
4897
-	 *
4898
-	 * @param array $expects
4899
-	 * @param IShare $share
4900
-	 * @param array $users
4901
-	 * @param $exception
4902
-	 */
4903
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataFormatShare')]
4904
-	public function testFormatShare(array $expects, IShare $share, array $users, $exception): void {
4905
-		$this->userManager->method('get')->willReturnMap($users);
4906
-
4907
-		$recipientGroup = $this->createMock(IGroup::class);
4908
-		$recipientGroup->method('getDisplayName')->willReturn('recipientGroupDisplayName');
4909
-		$this->groupManager->method('get')->willReturnMap([
4910
-			['recipientGroup', $recipientGroup],
4911
-		]);
4912
-
4913
-		$this->urlGenerator->method('linkToRouteAbsolute')
4914
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken'])
4915
-			->willReturn('myLink');
4916
-
4917
-		$this->rootFolder->method('getUserFolder')
4918
-			->with($this->currentUser)
4919
-			->willReturnSelf();
4920
-		$this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
4921
-
4922
-		if (!$exception) {
4923
-			$this->rootFolder->method('getFirstNodeById')
4924
-				->with($share->getNodeId())
4925
-				->willReturn($share->getNode());
4926
-
4927
-			$this->rootFolder->method('getRelativePath')
4928
-				->with($share->getNode()->getPath())
4929
-				->willReturnArgument(0);
4930
-		}
4931
-
4932
-		$cm = $this->createMock(\OCP\Contacts\IManager::class);
4933
-		$this->overwriteService(\OCP\Contacts\IManager::class, $cm);
4934
-
4935
-		$cm->method('search')
4936
-			->willReturnMap([
4937
-				['[email protected]', ['CLOUD'], [
4938
-					'limit' => 1,
4939
-					'enumeration' => false,
4940
-					'strict_search' => true,
4941
-				],
4942
-					[
4943
-						[
4944
-							'CLOUD' => [
4945
-								'[email protected]',
4946
-							],
4947
-							'FN' => 'foobar',
4948
-						],
4949
-					],
4950
-				],
4951
-				['[email protected]', ['EMAIL'], [
4952
-					'limit' => 1,
4953
-					'enumeration' => false,
4954
-					'strict_search' => true,
4955
-				],
4956
-					[
4957
-						[
4958
-							'EMAIL' => [
4959
-								'[email protected]',
4960
-							],
4961
-							'FN' => 'mail display name',
4962
-						],
4963
-					],
4964
-				],
4965
-			]);
4966
-
4967
-		try {
4968
-			$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
4969
-			$this->assertFalse($exception);
4970
-			$this->assertEquals($expects, $result);
4971
-		} catch (NotFoundException $e) {
4972
-			$this->assertTrue($exception);
4973
-		}
4974
-	}
4975
-
4976
-	public function dataFormatRoomShare() {
4977
-		$file = $this->getMockBuilder(File::class)->getMock();
4978
-		$parent = $this->getMockBuilder(Folder::class)->getMock();
4979
-
4980
-		$file->method('getMimeType')->willReturn('myMimeType');
4981
-
4982
-		$file->method('getPath')->willReturn('file');
4983
-
4984
-		$parent->method('getId')->willReturn(1);
4985
-		$file->method('getId')->willReturn(3);
4986
-
4987
-		$file->method('getParent')->willReturn($parent);
4988
-
4989
-		$file->method('getSize')->willReturn(123456);
4990
-		$file->method('getMTime')->willReturn(1234567890);
4991
-
4992
-		$mountPoint = $this->getMockBuilder(IMountPoint::class)->getMock();
4993
-		$mountPoint->method('getMountType')->willReturn('');
4994
-		$file->method('getMountPoint')->willReturn($mountPoint);
4995
-
4996
-		$cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
4997
-		$cache->method('getNumericStorageId')->willReturn(100);
4998
-		$storage = $this->createMock(IStorage::class);
4999
-		$storage->method('getId')->willReturn('storageId');
5000
-		$storage->method('getCache')->willReturn($cache);
5001
-
5002
-		$file->method('getStorage')->willReturn($storage);
5003
-
5004
-		$result = [];
5005
-
5006
-		$share = Server::get(IManager::class)->newShare();
5007
-		$share->setShareType(IShare::TYPE_ROOM)
5008
-			->setSharedWith('recipientRoom')
5009
-			->setSharedBy('initiator')
5010
-			->setShareOwner('owner')
5011
-			->setPermissions(Constants::PERMISSION_READ)
5012
-			->setNode($file)
5013
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
5014
-			->setTarget('myTarget')
5015
-			->setNote('personal note')
5016
-			->setId(42);
5017
-
5018
-		$result[] = [
5019
-			[
5020
-				'id' => '42',
5021
-				'share_type' => IShare::TYPE_ROOM,
5022
-				'uid_owner' => 'initiator',
5023
-				'displayname_owner' => 'initiator',
5024
-				'permissions' => 1,
5025
-				'stime' => 946684862,
5026
-				'parent' => null,
5027
-				'expiration' => null,
5028
-				'token' => null,
5029
-				'uid_file_owner' => 'owner',
5030
-				'displayname_file_owner' => 'owner',
5031
-				'note' => 'personal note',
5032
-				'path' => 'file',
5033
-				'item_type' => 'file',
5034
-				'storage_id' => 'storageId',
5035
-				'storage' => 100,
5036
-				'item_source' => 3,
5037
-				'file_source' => 3,
5038
-				'file_parent' => 1,
5039
-				'file_target' => 'myTarget',
5040
-				'share_with' => 'recipientRoom',
5041
-				'share_with_displayname' => '',
5042
-				'mail_send' => 0,
5043
-				'mimetype' => 'myMimeType',
5044
-				'has_preview' => false,
5045
-				'hide_download' => 0,
5046
-				'label' => '',
5047
-				'can_edit' => false,
5048
-				'can_delete' => false,
5049
-				'item_size' => 123456,
5050
-				'item_mtime' => 1234567890,
5051
-				'is-mount-root' => false,
5052
-				'mount-type' => '',
5053
-				'attributes' => null,
5054
-				'item_permissions' => 1,
5055
-			], $share, false, []
5056
-		];
5057
-
5058
-		$share = Server::get(IManager::class)->newShare();
5059
-		$share->setShareType(IShare::TYPE_ROOM)
5060
-			->setSharedWith('recipientRoom')
5061
-			->setSharedBy('initiator')
5062
-			->setShareOwner('owner')
5063
-			->setPermissions(Constants::PERMISSION_READ)
5064
-			->setNode($file)
5065
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
5066
-			->setTarget('myTarget')
5067
-			->setNote('personal note')
5068
-			->setId(42);
5069
-
5070
-		$result[] = [
5071
-			[
5072
-				'id' => '42',
5073
-				'share_type' => IShare::TYPE_ROOM,
5074
-				'uid_owner' => 'initiator',
5075
-				'displayname_owner' => 'initiator',
5076
-				'permissions' => 1,
5077
-				'stime' => 946684862,
5078
-				'parent' => null,
5079
-				'expiration' => null,
5080
-				'token' => null,
5081
-				'uid_file_owner' => 'owner',
5082
-				'displayname_file_owner' => 'owner',
5083
-				'note' => 'personal note',
5084
-				'path' => 'file',
5085
-				'item_type' => 'file',
5086
-				'storage_id' => 'storageId',
5087
-				'storage' => 100,
5088
-				'item_source' => 3,
5089
-				'file_source' => 3,
5090
-				'file_parent' => 1,
5091
-				'file_target' => 'myTarget',
5092
-				'share_with' => 'recipientRoom',
5093
-				'share_with_displayname' => 'recipientRoomName',
5094
-				'mail_send' => 0,
5095
-				'mimetype' => 'myMimeType',
5096
-				'has_preview' => false,
5097
-				'hide_download' => 0,
5098
-				'label' => '',
5099
-				'can_edit' => false,
5100
-				'can_delete' => false,
5101
-				'item_size' => 123456,
5102
-				'item_mtime' => 1234567890,
5103
-				'is-mount-root' => false,
5104
-				'mount-type' => '',
5105
-				'attributes' => null,
5106
-				'item_permissions' => 9,
5107
-			], $share, true, [
5108
-				'share_with_displayname' => 'recipientRoomName'
5109
-			]
5110
-		];
5111
-
5112
-		return $result;
5113
-	}
5114
-
5115
-	/**
5116
-	 *
5117
-	 * @param array $expects
5118
-	 * @param IShare $share
5119
-	 * @param bool $helperAvailable
5120
-	 * @param array $formatShareByHelper
5121
-	 */
5122
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataFormatRoomShare')]
5123
-	public function testFormatRoomShare(array $expects, IShare $share, bool $helperAvailable, array $formatShareByHelper): void {
5124
-		$this->rootFolder->method('getUserFolder')
5125
-			->with($this->currentUser)
5126
-			->willReturnSelf();
5127
-
5128
-		$this->rootFolder->method('getFirstNodeById')
5129
-			->with($share->getNodeId())
5130
-			->willReturn($share->getNode());
5131
-
5132
-		$this->rootFolder->method('getRelativePath')
5133
-			->with($share->getNode()->getPath())
5134
-			->willReturnArgument(0);
5135
-
5136
-		if (!$helperAvailable) {
5137
-			$this->appManager->method('isEnabledForUser')
5138
-				->with('spreed')
5139
-				->willReturn(false);
5140
-		} else {
5141
-			$this->appManager->method('isEnabledForUser')
5142
-				->with('spreed')
5143
-				->willReturn(true);
5144
-
5145
-			// This is not possible anymore with PHPUnit 10+
5146
-			// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
5147
-			// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
5148
-			$helper = $this->getMockBuilder(\stdClass::class)
5149
-				->addMethods(['formatShare', 'canAccessShare'])
5150
-				->getMock();
5151
-			$helper->method('formatShare')
5152
-				->with($share)
5153
-				->willReturn($formatShareByHelper);
5154
-			$helper->method('canAccessShare')
5155
-				->with($share)
5156
-				->willReturn(true);
5157
-
5158
-			$this->serverContainer->method('get')
5159
-				->with('\OCA\Talk\Share\Helper\ShareAPIController')
5160
-				->willReturn($helper);
5161
-		}
5162
-
5163
-		$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5164
-		$this->assertEquals($expects, $result);
5165
-	}
5166
-
5167
-	/**
5168
-	 * @return list{Folder, Folder}
5169
-	 */
5170
-	private function getNonSharedUserFolder(): array {
5171
-		$node = $this->getMockBuilder(Folder::class)->getMock();
5172
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
5173
-		$storage = $this->createMock(IStorage::class);
5174
-		$storage->method('instanceOfStorage')
5175
-			->willReturnMap([
5176
-				['OCA\Files_Sharing\External\Storage', false],
5177
-				['OCA\Files_Sharing\SharedStorage', false],
5178
-			]);
5179
-		$userFolder->method('getStorage')->willReturn($storage);
5180
-		$node->method('getStorage')->willReturn($storage);
5181
-		$node->method('getId')->willReturn(42);
5182
-		$user = $this->createMock(IUser::class);
5183
-		$user->method('getUID')->willReturn($this->currentUser);
5184
-		$node->method('getOwner')->willReturn($user);
5185
-		return [$userFolder, $node];
5186
-	}
5187
-
5188
-	/**
5189
-	 * @return list{Folder, File}
5190
-	 */
5191
-	private function getNonSharedUserFile(): array {
5192
-		$node = $this->getMockBuilder(File::class)->getMock();
5193
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
5194
-		$storage = $this->createMock(IStorage::class);
5195
-		$storage->method('instanceOfStorage')
5196
-			->willReturnMap([
5197
-				['OCA\Files_Sharing\External\Storage', false],
5198
-				['OCA\Files_Sharing\SharedStorage', false],
5199
-			]);
5200
-		$userFolder->method('getStorage')->willReturn($storage);
5201
-		$node->method('getStorage')->willReturn($storage);
5202
-		$node->method('getId')->willReturn(42);
5203
-		return [$userFolder, $node];
5204
-	}
5205
-
5206
-	public function testPopulateTags(): void {
5207
-		$tagger = $this->createMock(ITags::class);
5208
-		$this->tagManager->method('load')
5209
-			->with('files')
5210
-			->willReturn($tagger);
5211
-		$data = [
5212
-			['file_source' => 10],
5213
-			['file_source' => 22, 'foo' => 'bar'],
5214
-			['file_source' => 42, 'x' => 'y'],
5215
-		];
5216
-		$tags = [
5217
-			10 => ['tag3'],
5218
-			42 => ['tag1', 'tag2'],
5219
-		];
5220
-		$tagger->method('getTagsForObjects')
5221
-			->with([10, 22, 42])
5222
-			->willReturn($tags);
5223
-
5224
-		$result = self::invokePrivate($this->ocs, 'populateTags', [$data]);
5225
-		$this->assertSame([
5226
-			['file_source' => 10, 'tags' => ['tag3']],
5227
-			['file_source' => 22, 'foo' => 'bar', 'tags' => []],
5228
-			['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']],
5229
-		], $result);
5230
-	}
578
+    public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions,
579
+        $shareTime, $expiration, $parent, $target, $mail_send, $note = '', $token = null,
580
+        $password = null, $label = '', $attributes = null) {
581
+        $share = $this->getMockBuilder(IShare::class)->getMock();
582
+        $share->method('getId')->willReturn($id);
583
+        $share->method('getShareType')->willReturn($shareType);
584
+        $share->method('getSharedWith')->willReturn($sharedWith);
585
+        $share->method('getSharedBy')->willReturn($sharedBy);
586
+        $share->method('getShareOwner')->willReturn($shareOwner);
587
+        $share->method('getNode')->willReturn($path);
588
+        $share->method('getPermissions')->willReturn($permissions);
589
+        $share->method('getNote')->willReturn($note);
590
+        $share->method('getLabel')->willReturn($label);
591
+        $share->method('getAttributes')->willReturn($attributes);
592
+        $time = new \DateTime();
593
+        $time->setTimestamp($shareTime);
594
+        $share->method('getShareTime')->willReturn($time);
595
+        $share->method('getExpirationDate')->willReturn($expiration);
596
+        $share->method('getTarget')->willReturn($target);
597
+        $share->method('getMailSend')->willReturn($mail_send);
598
+        $share->method('getToken')->willReturn($token);
599
+        $share->method('getPassword')->willReturn($password);
600
+
601
+        if ($shareType === IShare::TYPE_USER
602
+            || $shareType === IShare::TYPE_GROUP
603
+            || $shareType === IShare::TYPE_LINK) {
604
+            $share->method('getFullId')->willReturn('ocinternal:' . $id);
605
+        }
606
+
607
+        return $share;
608
+    }
609
+
610
+    public function dataGetShare() {
611
+        $data = [];
612
+
613
+        $cache = $this->getMockBuilder('OC\Files\Cache\Cache')
614
+            ->disableOriginalConstructor()
615
+            ->getMock();
616
+        $cache->method('getNumericStorageId')->willReturn(101);
617
+
618
+        $storage = $this->getMockBuilder(IStorage::class)
619
+            ->disableOriginalConstructor()
620
+            ->getMock();
621
+        $storage->method('getId')->willReturn('STORAGE');
622
+        $storage->method('getCache')->willReturn($cache);
623
+
624
+        $parentFolder = $this->getMockBuilder(Folder::class)->getMock();
625
+        $parentFolder->method('getId')->willReturn(3);
626
+        $mountPoint = $this->createMock(IMountPoint::class);
627
+        $mountPoint->method('getMountType')->willReturn('');
628
+
629
+        $file = $this->getMockBuilder('OCP\Files\File')->getMock();
630
+        $file->method('getId')->willReturn(1);
631
+        $file->method('getPath')->willReturn('file');
632
+        $file->method('getStorage')->willReturn($storage);
633
+        $file->method('getParent')->willReturn($parentFolder);
634
+        $file->method('getSize')->willReturn(123465);
635
+        $file->method('getMTime')->willReturn(1234567890);
636
+        $file->method('getMimeType')->willReturn('myMimeType');
637
+        $file->method('getMountPoint')->willReturn($mountPoint);
638
+
639
+        $folder = $this->getMockBuilder(Folder::class)->getMock();
640
+        $folder->method('getId')->willReturn(2);
641
+        $folder->method('getPath')->willReturn('folder');
642
+        $folder->method('getStorage')->willReturn($storage);
643
+        $folder->method('getParent')->willReturn($parentFolder);
644
+        $folder->method('getSize')->willReturn(123465);
645
+        $folder->method('getMTime')->willReturn(1234567890);
646
+        $folder->method('getMimeType')->willReturn('myFolderMimeType');
647
+        $folder->method('getMountPoint')->willReturn($mountPoint);
648
+
649
+        [$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
650
+
651
+        // File shared with user
652
+        $share = $this->createShare(
653
+            100,
654
+            IShare::TYPE_USER,
655
+            'userId',
656
+            'initiatorId',
657
+            'ownerId',
658
+            $file,
659
+            4,
660
+            5,
661
+            null,
662
+            6,
663
+            'target',
664
+            0,
665
+            'personal note',
666
+            $shareAttributes,
667
+        );
668
+        $expected = [
669
+            'id' => 100,
670
+            'share_type' => IShare::TYPE_USER,
671
+            'share_with' => 'userId',
672
+            'share_with_displayname' => 'userDisplay',
673
+            'share_with_displayname_unique' => '[email protected]',
674
+            'uid_owner' => 'initiatorId',
675
+            'displayname_owner' => 'initiatorDisplay',
676
+            'item_type' => 'file',
677
+            'item_source' => 1,
678
+            'file_source' => 1,
679
+            'file_target' => 'target',
680
+            'file_parent' => 3,
681
+            'token' => null,
682
+            'expiration' => null,
683
+            'permissions' => 4,
684
+            'attributes' => $shareAttributesReturnJson,
685
+            'stime' => 5,
686
+            'parent' => null,
687
+            'storage_id' => 'STORAGE',
688
+            'path' => 'file',
689
+            'storage' => 101,
690
+            'mail_send' => 0,
691
+            'uid_file_owner' => 'ownerId',
692
+            'note' => 'personal note',
693
+            'label' => '',
694
+            'displayname_file_owner' => 'ownerDisplay',
695
+            'mimetype' => 'myMimeType',
696
+            'has_preview' => false,
697
+            'hide_download' => 0,
698
+            'can_edit' => false,
699
+            'can_delete' => false,
700
+            'item_size' => 123465,
701
+            'item_mtime' => 1234567890,
702
+            'attributes' => null,
703
+            'item_permissions' => 4,
704
+            'is-mount-root' => false,
705
+            'mount-type' => '',
706
+        ];
707
+        $data[] = [$share, $expected];
708
+
709
+        // Folder shared with group
710
+        $share = $this->createShare(
711
+            101,
712
+            IShare::TYPE_GROUP,
713
+            'groupId',
714
+            'initiatorId',
715
+            'ownerId',
716
+            $folder,
717
+            4,
718
+            5,
719
+            null,
720
+            6,
721
+            'target',
722
+            0,
723
+            'personal note',
724
+            $shareAttributes,
725
+        );
726
+        $expected = [
727
+            'id' => 101,
728
+            'share_type' => IShare::TYPE_GROUP,
729
+            'share_with' => 'groupId',
730
+            'share_with_displayname' => 'groupId',
731
+            'uid_owner' => 'initiatorId',
732
+            'displayname_owner' => 'initiatorDisplay',
733
+            'item_type' => 'folder',
734
+            'item_source' => 2,
735
+            'file_source' => 2,
736
+            'file_target' => 'target',
737
+            'file_parent' => 3,
738
+            'token' => null,
739
+            'expiration' => null,
740
+            'permissions' => 4,
741
+            'attributes' => $shareAttributesReturnJson,
742
+            'stime' => 5,
743
+            'parent' => null,
744
+            'storage_id' => 'STORAGE',
745
+            'path' => 'folder',
746
+            'storage' => 101,
747
+            'mail_send' => 0,
748
+            'uid_file_owner' => 'ownerId',
749
+            'note' => 'personal note',
750
+            'label' => '',
751
+            'displayname_file_owner' => 'ownerDisplay',
752
+            'mimetype' => 'myFolderMimeType',
753
+            'has_preview' => false,
754
+            'hide_download' => 0,
755
+            'can_edit' => false,
756
+            'can_delete' => false,
757
+            'item_size' => 123465,
758
+            'item_mtime' => 1234567890,
759
+            'attributes' => null,
760
+            'item_permissions' => 4,
761
+            'is-mount-root' => false,
762
+            'mount-type' => '',
763
+        ];
764
+        $data[] = [$share, $expected];
765
+
766
+        // File shared by link with Expire
767
+        $expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03');
768
+        $share = $this->createShare(
769
+            101,
770
+            IShare::TYPE_LINK,
771
+            null,
772
+            'initiatorId',
773
+            'ownerId',
774
+            $folder,
775
+            4,
776
+            5,
777
+            $expire,
778
+            6,
779
+            'target',
780
+            0,
781
+            'personal note',
782
+            'token',
783
+            'password',
784
+            'first link share'
785
+        );
786
+        $expected = [
787
+            'id' => 101,
788
+            'share_type' => IShare::TYPE_LINK,
789
+            'password' => 'password',
790
+            'share_with' => 'password',
791
+            'share_with_displayname' => '(Shared link)',
792
+            'send_password_by_talk' => false,
793
+            'uid_owner' => 'initiatorId',
794
+            'displayname_owner' => 'initiatorDisplay',
795
+            'item_type' => 'folder',
796
+            'item_source' => 2,
797
+            'file_source' => 2,
798
+            'file_target' => 'target',
799
+            'file_parent' => 3,
800
+            'token' => 'token',
801
+            'expiration' => '2000-01-02 00:00:00',
802
+            'permissions' => 4,
803
+            'attributes' => null,
804
+            'stime' => 5,
805
+            'parent' => null,
806
+            'storage_id' => 'STORAGE',
807
+            'path' => 'folder',
808
+            'storage' => 101,
809
+            'mail_send' => 0,
810
+            'url' => 'url',
811
+            'uid_file_owner' => 'ownerId',
812
+            'note' => 'personal note',
813
+            'label' => 'first link share',
814
+            'displayname_file_owner' => 'ownerDisplay',
815
+            'mimetype' => 'myFolderMimeType',
816
+            'has_preview' => false,
817
+            'hide_download' => 0,
818
+            'can_edit' => false,
819
+            'can_delete' => false,
820
+            'item_size' => 123465,
821
+            'item_mtime' => 1234567890,
822
+            'attributes' => null,
823
+            'item_permissions' => 4,
824
+            'is-mount-root' => false,
825
+            'mount-type' => '',
826
+        ];
827
+        $data[] = [$share, $expected];
828
+
829
+        return $data;
830
+    }
831
+
832
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataGetShare')]
833
+    public function testGetShare(IShare $share, array $result): void {
834
+        /** @var ShareAPIController&MockObject $ocs */
835
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
836
+            ->setConstructorArgs([
837
+                $this->appName,
838
+                $this->request,
839
+                $this->shareManager,
840
+                $this->groupManager,
841
+                $this->userManager,
842
+                $this->rootFolder,
843
+                $this->urlGenerator,
844
+                $this->l,
845
+                $this->config,
846
+                $this->appConfig,
847
+                $this->appManager,
848
+                $this->serverContainer,
849
+                $this->userStatusManager,
850
+                $this->previewManager,
851
+                $this->dateTimeZone,
852
+                $this->logger,
853
+                $this->factory,
854
+                $this->mailer,
855
+                $this->tagManager,
856
+                $this->currentUser,
857
+            ])
858
+            ->onlyMethods(['canAccessShare'])
859
+            ->getMock();
860
+
861
+        $ocs->expects($this->any())
862
+            ->method('canAccessShare')
863
+            ->willReturn(true);
864
+
865
+        $this->shareManager
866
+            ->expects($this->any())
867
+            ->method('getShareById')
868
+            ->with($share->getFullId(), 'currentUser')
869
+            ->willReturn($share);
870
+
871
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
872
+        $userFolder
873
+            ->method('getRelativePath')
874
+            ->willReturnArgument(0);
875
+
876
+        $userFolder->method('getById')
877
+            ->with($share->getNodeId())
878
+            ->willReturn([$share->getNode()]);
879
+        $userFolder->method('getFirstNodeById')
880
+            ->with($share->getNodeId())
881
+            ->willReturn($share->getNode());
882
+
883
+        $this->rootFolder->method('getUserFolder')
884
+            ->with($this->currentUser)
885
+            ->willReturn($userFolder);
886
+
887
+        $this->urlGenerator
888
+            ->method('linkToRouteAbsolute')
889
+            ->willReturn('url');
890
+
891
+        $initiator = $this->getMockBuilder(IUser::class)->getMock();
892
+        $initiator->method('getUID')->willReturn('initiatorId');
893
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
894
+
895
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
896
+        $owner->method('getUID')->willReturn('ownerId');
897
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
898
+
899
+        $user = $this->getMockBuilder(IUser::class)->getMock();
900
+        $user->method('getUID')->willReturn('userId');
901
+        $user->method('getDisplayName')->willReturn('userDisplay');
902
+        $user->method('getSystemEMailAddress')->willReturn('[email protected]');
903
+
904
+        $group = $this->getMockBuilder(IGroup::class)->getMock();
905
+        $group->method('getGID')->willReturn('groupId');
906
+
907
+        $this->userManager->method('get')->willReturnMap([
908
+            ['userId', $user],
909
+            ['initiatorId', $initiator],
910
+            ['ownerId', $owner],
911
+        ]);
912
+        $this->groupManager->method('get')->willReturnMap([
913
+            ['group', $group],
914
+        ]);
915
+        $this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
916
+
917
+        $data = $ocs->getShare($share->getId())->getData()[0];
918
+        $this->assertEquals($result, $data);
919
+    }
920
+
921
+
922
+    public function testGetShareInvalidNode(): void {
923
+        $this->expectException(OCSNotFoundException::class);
924
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
925
+
926
+        $share = Server::get(IManager::class)->newShare();
927
+        $share->setSharedBy('initiator')
928
+            ->setSharedWith('recipient')
929
+            ->setShareOwner('owner');
930
+
931
+        $this->shareManager
932
+            ->expects($this->once())
933
+            ->method('getShareById')
934
+            ->with('ocinternal:42', 'currentUser')
935
+            ->willReturn($share);
936
+
937
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
938
+        $this->rootFolder->method('getUserFolder')
939
+            ->with($this->currentUser)
940
+            ->willReturn($userFolder);
941
+
942
+        $this->ocs->getShare(42);
943
+    }
944
+
945
+    public function dataGetShares() {
946
+        $folder = $this->getMockBuilder(Folder::class)->getMock();
947
+        $file1 = $this->getMockBuilder(File::class)->getMock();
948
+        $file1->method('getName')
949
+            ->willReturn('file1');
950
+        $file2 = $this->getMockBuilder(File::class)->getMock();
951
+        $file2->method('getName')
952
+            ->willReturn('file2');
953
+
954
+        $folder->method('getDirectoryListing')
955
+            ->willReturn([$file1, $file2]);
956
+
957
+        $file1UserShareOwner = Server::get(IManager::class)->newShare();
958
+        $file1UserShareOwner->setShareType(IShare::TYPE_USER)
959
+            ->setSharedWith('recipient')
960
+            ->setSharedBy('initiator')
961
+            ->setShareOwner('currentUser')
962
+            ->setPermissions(Constants::PERMISSION_READ)
963
+            ->setNode($file1)
964
+            ->setId(4);
965
+
966
+        $file1UserShareOwnerExpected = [
967
+            'id' => 4,
968
+            'share_type' => IShare::TYPE_USER,
969
+        ];
970
+
971
+        $file1UserShareInitiator = Server::get(IManager::class)->newShare();
972
+        $file1UserShareInitiator->setShareType(IShare::TYPE_USER)
973
+            ->setSharedWith('recipient')
974
+            ->setSharedBy('currentUser')
975
+            ->setShareOwner('owner')
976
+            ->setPermissions(Constants::PERMISSION_READ)
977
+            ->setNode($file1)
978
+            ->setId(8);
979
+
980
+        $file1UserShareInitiatorExpected = [
981
+            'id' => 8,
982
+            'share_type' => IShare::TYPE_USER,
983
+        ];
984
+
985
+        $file1UserShareRecipient = Server::get(IManager::class)->newShare();
986
+        $file1UserShareRecipient->setShareType(IShare::TYPE_USER)
987
+            ->setSharedWith('currentUser')
988
+            ->setSharedBy('initiator')
989
+            ->setShareOwner('owner')
990
+            ->setPermissions(Constants::PERMISSION_READ)
991
+            ->setNode($file1)
992
+            ->setId(15);
993
+
994
+        $file1UserShareRecipientExpected = [
995
+            'id' => 15,
996
+            'share_type' => IShare::TYPE_USER,
997
+        ];
998
+
999
+        $file1UserShareOther = Server::get(IManager::class)->newShare();
1000
+        $file1UserShareOther->setShareType(IShare::TYPE_USER)
1001
+            ->setSharedWith('recipient')
1002
+            ->setSharedBy('initiator')
1003
+            ->setShareOwner('owner')
1004
+            ->setPermissions(Constants::PERMISSION_READ)
1005
+            ->setNode($file1)
1006
+            ->setId(16);
1007
+
1008
+        $file1UserShareOtherExpected = [
1009
+            'id' => 16,
1010
+            'share_type' => IShare::TYPE_USER,
1011
+        ];
1012
+
1013
+        $file1GroupShareOwner = Server::get(IManager::class)->newShare();
1014
+        $file1GroupShareOwner->setShareType(IShare::TYPE_GROUP)
1015
+            ->setSharedWith('recipient')
1016
+            ->setSharedBy('initiator')
1017
+            ->setShareOwner('currentUser')
1018
+            ->setPermissions(Constants::PERMISSION_READ)
1019
+            ->setNode($file1)
1020
+            ->setId(23);
1021
+
1022
+        $file1GroupShareOwnerExpected = [
1023
+            'id' => 23,
1024
+            'share_type' => IShare::TYPE_GROUP,
1025
+        ];
1026
+
1027
+        $file1GroupShareRecipient = Server::get(IManager::class)->newShare();
1028
+        $file1GroupShareRecipient->setShareType(IShare::TYPE_GROUP)
1029
+            ->setSharedWith('currentUserGroup')
1030
+            ->setSharedBy('initiator')
1031
+            ->setShareOwner('owner')
1032
+            ->setPermissions(Constants::PERMISSION_READ)
1033
+            ->setNode($file1)
1034
+            ->setId(42);
1035
+
1036
+        $file1GroupShareRecipientExpected = [
1037
+            'id' => 42,
1038
+            'share_type' => IShare::TYPE_GROUP,
1039
+        ];
1040
+
1041
+        $file1GroupShareOther = Server::get(IManager::class)->newShare();
1042
+        $file1GroupShareOther->setShareType(IShare::TYPE_GROUP)
1043
+            ->setSharedWith('recipient')
1044
+            ->setSharedBy('initiator')
1045
+            ->setShareOwner('owner')
1046
+            ->setPermissions(Constants::PERMISSION_READ)
1047
+            ->setNode($file1)
1048
+            ->setId(108);
1049
+
1050
+        $file1LinkShareOwner = Server::get(IManager::class)->newShare();
1051
+        $file1LinkShareOwner->setShareType(IShare::TYPE_LINK)
1052
+            ->setSharedWith('recipient')
1053
+            ->setSharedBy('initiator')
1054
+            ->setShareOwner('currentUser')
1055
+            ->setPermissions(Constants::PERMISSION_READ)
1056
+            ->setNode($file1)
1057
+            ->setId(415);
1058
+
1059
+        $file1LinkShareOwnerExpected = [
1060
+            'id' => 415,
1061
+            'share_type' => IShare::TYPE_LINK,
1062
+        ];
1063
+
1064
+        $file1EmailShareOwner = Server::get(IManager::class)->newShare();
1065
+        $file1EmailShareOwner->setShareType(IShare::TYPE_EMAIL)
1066
+            ->setSharedWith('recipient')
1067
+            ->setSharedBy('initiator')
1068
+            ->setShareOwner('currentUser')
1069
+            ->setPermissions(Constants::PERMISSION_READ)
1070
+            ->setNode($file1)
1071
+            ->setId(416);
1072
+
1073
+        $file1EmailShareOwnerExpected = [
1074
+            'id' => 416,
1075
+            'share_type' => IShare::TYPE_EMAIL,
1076
+        ];
1077
+
1078
+        $file1CircleShareOwner = Server::get(IManager::class)->newShare();
1079
+        $file1CircleShareOwner->setShareType(IShare::TYPE_CIRCLE)
1080
+            ->setSharedWith('recipient')
1081
+            ->setSharedBy('initiator')
1082
+            ->setShareOwner('currentUser')
1083
+            ->setPermissions(Constants::PERMISSION_READ)
1084
+            ->setNode($file1)
1085
+            ->setId(423);
1086
+
1087
+        $file1CircleShareOwnerExpected = [
1088
+            'id' => 423,
1089
+            'share_type' => IShare::TYPE_CIRCLE,
1090
+        ];
1091
+
1092
+        $file1RoomShareOwner = Server::get(IManager::class)->newShare();
1093
+        $file1RoomShareOwner->setShareType(IShare::TYPE_ROOM)
1094
+            ->setSharedWith('recipient')
1095
+            ->setSharedBy('initiator')
1096
+            ->setShareOwner('currentUser')
1097
+            ->setPermissions(Constants::PERMISSION_READ)
1098
+            ->setNode($file1)
1099
+            ->setId(442);
1100
+
1101
+        $file1RoomShareOwnerExpected = [
1102
+            'id' => 442,
1103
+            'share_type' => IShare::TYPE_ROOM,
1104
+        ];
1105
+
1106
+        $file1RemoteShareOwner = Server::get(IManager::class)->newShare();
1107
+        $file1RemoteShareOwner->setShareType(IShare::TYPE_REMOTE)
1108
+            ->setSharedWith('recipient')
1109
+            ->setSharedBy('initiator')
1110
+            ->setShareOwner('currentUser')
1111
+            ->setPermissions(Constants::PERMISSION_READ)
1112
+            ->setExpirationDate(new \DateTime('2000-01-01T01:02:03'))
1113
+            ->setNode($file1)
1114
+            ->setId(815);
1115
+
1116
+        $file1RemoteShareOwnerExpected = [
1117
+            'id' => 815,
1118
+            'share_type' => IShare::TYPE_REMOTE,
1119
+        ];
1120
+
1121
+        $file1RemoteGroupShareOwner = Server::get(IManager::class)->newShare();
1122
+        $file1RemoteGroupShareOwner->setShareType(IShare::TYPE_REMOTE_GROUP)
1123
+            ->setSharedWith('recipient')
1124
+            ->setSharedBy('initiator')
1125
+            ->setShareOwner('currentUser')
1126
+            ->setPermissions(Constants::PERMISSION_READ)
1127
+            ->setExpirationDate(new \DateTime('2000-01-02T01:02:03'))
1128
+            ->setNode($file1)
1129
+            ->setId(816);
1130
+
1131
+        $file1RemoteGroupShareOwnerExpected = [
1132
+            'id' => 816,
1133
+            'share_type' => IShare::TYPE_REMOTE_GROUP,
1134
+        ];
1135
+
1136
+        $file2UserShareOwner = Server::get(IManager::class)->newShare();
1137
+        $file2UserShareOwner->setShareType(IShare::TYPE_USER)
1138
+            ->setSharedWith('recipient')
1139
+            ->setSharedBy('initiator')
1140
+            ->setShareOwner('currentUser')
1141
+            ->setPermissions(Constants::PERMISSION_READ)
1142
+            ->setNode($file2)
1143
+            ->setId(823);
1144
+
1145
+        $file2UserShareOwnerExpected = [
1146
+            'id' => 823,
1147
+            'share_type' => IShare::TYPE_USER,
1148
+        ];
1149
+
1150
+        $data = [
1151
+            [
1152
+                [
1153
+                    'path' => $file1,
1154
+                ],
1155
+                [
1156
+                    'file1' => [
1157
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1158
+                    ],
1159
+                ],
1160
+                [
1161
+                ],
1162
+                [
1163
+                    $file1UserShareOwnerExpected
1164
+                ]
1165
+            ],
1166
+            [
1167
+                [
1168
+                    'path' => $file1,
1169
+                ],
1170
+                [
1171
+                    'file1' => [
1172
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1173
+                    ],
1174
+                ],
1175
+                [
1176
+                ],
1177
+                [
1178
+                    $file1UserShareOwnerExpected,
1179
+                ]
1180
+            ],
1181
+            [
1182
+                [
1183
+                    'path' => $file1,
1184
+                ],
1185
+                [
1186
+                    'file1' => [
1187
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1188
+                    ],
1189
+                ],
1190
+                [
1191
+                ],
1192
+                [
1193
+                    $file1UserShareOwnerExpected,
1194
+                    $file1UserShareInitiatorExpected,
1195
+                    $file1UserShareOtherExpected,
1196
+                ]
1197
+            ],
1198
+            [
1199
+                [
1200
+                    'path' => $file1,
1201
+                ],
1202
+                [
1203
+                    'file1' => [
1204
+                        IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1205
+                    ],
1206
+                ],
1207
+                [
1208
+                ],
1209
+                [
1210
+                    $file1UserShareInitiatorExpected,
1211
+                ]
1212
+            ],
1213
+            [
1214
+                [
1215
+                    'path' => $file1,
1216
+                ],
1217
+                [
1218
+                    'file1' => [
1219
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1220
+                        IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1221
+                    ],
1222
+                ],
1223
+                [
1224
+                ],
1225
+                [
1226
+                    $file1UserShareOwnerExpected,
1227
+                    $file1GroupShareRecipientExpected,
1228
+                ]
1229
+            ],
1230
+            [
1231
+                [
1232
+                    'path' => $file1,
1233
+                ],
1234
+                [
1235
+                    'file1' => [
1236
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1237
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1238
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1239
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1240
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1241
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1242
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1243
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1244
+                    ],
1245
+                ],
1246
+                [
1247
+                ],
1248
+                [
1249
+                    $file1UserShareOwnerExpected,
1250
+                    $file1GroupShareOwnerExpected,
1251
+                    $file1LinkShareOwnerExpected,
1252
+                    $file1EmailShareOwnerExpected,
1253
+                    $file1CircleShareOwnerExpected,
1254
+                    $file1RoomShareOwnerExpected,
1255
+                ]
1256
+            ],
1257
+            [
1258
+                [
1259
+                    'path' => $file1,
1260
+                ],
1261
+                [
1262
+                    'file1' => [
1263
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1264
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1265
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1266
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1267
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1268
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1269
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1270
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1271
+                    ],
1272
+                ],
1273
+                [
1274
+                    IShare::TYPE_REMOTE => true,
1275
+                    IShare::TYPE_REMOTE_GROUP => true,
1276
+                ],
1277
+                [
1278
+                    $file1UserShareOwnerExpected,
1279
+                    $file1GroupShareOwnerExpected,
1280
+                    $file1LinkShareOwnerExpected,
1281
+                    $file1EmailShareOwnerExpected,
1282
+                    $file1CircleShareOwnerExpected,
1283
+                    $file1RoomShareOwnerExpected,
1284
+                    $file1RemoteShareOwnerExpected,
1285
+                    $file1RemoteGroupShareOwnerExpected,
1286
+                ]
1287
+            ],
1288
+            [
1289
+                [
1290
+                    'path' => $folder,
1291
+                    'subfiles' => 'true',
1292
+                ],
1293
+                [
1294
+                    'file1' => [
1295
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1296
+                    ],
1297
+                    'file2' => [
1298
+                        IShare::TYPE_USER => [$file2UserShareOwner],
1299
+                    ],
1300
+                ],
1301
+                [
1302
+                ],
1303
+                [
1304
+                    $file1UserShareOwnerExpected,
1305
+                    $file2UserShareOwnerExpected,
1306
+                ]
1307
+            ],
1308
+            [
1309
+                [
1310
+                    'path' => $folder,
1311
+                    'subfiles' => 'true',
1312
+                ],
1313
+                [
1314
+                    'file1' => [
1315
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1316
+                    ],
1317
+                ],
1318
+                [
1319
+                ],
1320
+                [
1321
+                    $file1UserShareOwnerExpected,
1322
+                ]
1323
+            ],
1324
+            [
1325
+                [
1326
+                    'path' => $folder,
1327
+                    'subfiles' => 'true',
1328
+                ],
1329
+                [
1330
+                    'file1' => [
1331
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1332
+                    ],
1333
+                ],
1334
+                [
1335
+                ],
1336
+                [
1337
+                    $file1UserShareOwnerExpected
1338
+                ]
1339
+            ],
1340
+            [
1341
+                [
1342
+                    'path' => $folder,
1343
+                    'subfiles' => 'true',
1344
+                ],
1345
+                [
1346
+                    'file1' => [
1347
+                        IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1348
+                    ],
1349
+                    'file2' => [
1350
+                        IShare::TYPE_USER => [$file2UserShareOwner],
1351
+                    ],
1352
+                ],
1353
+                [
1354
+                ],
1355
+                [
1356
+                    $file1UserShareInitiatorExpected,
1357
+                    $file1UserShareOtherExpected,
1358
+                    $file2UserShareOwnerExpected,
1359
+                ]
1360
+            ],
1361
+            // This might not happen in a real environment, as the combination
1362
+            // of shares does not seem to be possible on a folder without
1363
+            // resharing rights; if the folder has resharing rights then the
1364
+            // share with others would be included too in the results.
1365
+            [
1366
+                [
1367
+                    'path' => $folder,
1368
+                    'subfiles' => 'true',
1369
+                ],
1370
+                [
1371
+                    'file1' => [
1372
+                        IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1373
+                    ],
1374
+                ],
1375
+                [
1376
+                ],
1377
+                [
1378
+                    $file1UserShareInitiatorExpected,
1379
+                ]
1380
+            ],
1381
+            [
1382
+                [
1383
+                    'path' => $folder,
1384
+                    'subfiles' => 'true',
1385
+                ],
1386
+                [
1387
+                    'file1' => [
1388
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1389
+                        IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1390
+                    ],
1391
+                ],
1392
+                [
1393
+                ],
1394
+                [
1395
+                    $file1UserShareOwnerExpected,
1396
+                    $file1GroupShareRecipientExpected,
1397
+                ]
1398
+            ],
1399
+            [
1400
+                [
1401
+                    'path' => $folder,
1402
+                    'subfiles' => 'true',
1403
+                ],
1404
+                [
1405
+                    'file1' => [
1406
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1407
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1408
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1409
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1410
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1411
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1412
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1413
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1414
+                    ],
1415
+                ],
1416
+                [
1417
+                ],
1418
+                [
1419
+                    $file1UserShareOwnerExpected,
1420
+                    $file1GroupShareOwnerExpected,
1421
+                    $file1LinkShareOwnerExpected,
1422
+                    $file1EmailShareOwnerExpected,
1423
+                    $file1CircleShareOwnerExpected,
1424
+                    $file1RoomShareOwnerExpected,
1425
+                ]
1426
+            ],
1427
+            [
1428
+                [
1429
+                    'path' => $folder,
1430
+                    'subfiles' => 'true',
1431
+                ],
1432
+                [
1433
+                    'file1' => [
1434
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1435
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1436
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1437
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1438
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1439
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1440
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1441
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1442
+                    ],
1443
+                ],
1444
+                [
1445
+                    IShare::TYPE_REMOTE => true,
1446
+                    IShare::TYPE_REMOTE_GROUP => true,
1447
+                ],
1448
+                [
1449
+                    $file1UserShareOwnerExpected,
1450
+                    $file1GroupShareOwnerExpected,
1451
+                    $file1LinkShareOwnerExpected,
1452
+                    $file1EmailShareOwnerExpected,
1453
+                    $file1CircleShareOwnerExpected,
1454
+                    $file1RoomShareOwnerExpected,
1455
+                    $file1RemoteShareOwnerExpected,
1456
+                    $file1RemoteGroupShareOwnerExpected,
1457
+                ]
1458
+            ],
1459
+        ];
1460
+
1461
+        return $data;
1462
+    }
1463
+
1464
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataGetShares')]
1465
+    public function testGetShares(array $getSharesParameters, array $shares, array $extraShareTypes, array $expected): void {
1466
+        /** @var ShareAPIController&MockObject $ocs */
1467
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
1468
+            ->setConstructorArgs([
1469
+                $this->appName,
1470
+                $this->request,
1471
+                $this->shareManager,
1472
+                $this->groupManager,
1473
+                $this->userManager,
1474
+                $this->rootFolder,
1475
+                $this->urlGenerator,
1476
+                $this->l,
1477
+                $this->config,
1478
+                $this->appConfig,
1479
+                $this->appManager,
1480
+                $this->serverContainer,
1481
+                $this->userStatusManager,
1482
+                $this->previewManager,
1483
+                $this->dateTimeZone,
1484
+                $this->logger,
1485
+                $this->factory,
1486
+                $this->mailer,
1487
+                $this->tagManager,
1488
+                $this->currentUser,
1489
+            ])
1490
+            ->onlyMethods(['formatShare'])
1491
+            ->getMock();
1492
+
1493
+        $ocs->method('formatShare')
1494
+            ->willReturnCallback(
1495
+                function ($share) {
1496
+                    return [
1497
+                        'id' => $share->getId(),
1498
+                        'share_type' => $share->getShareType()
1499
+                    ];
1500
+                }
1501
+            );
1502
+
1503
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1504
+        $userFolder->method('get')
1505
+            ->with('path')
1506
+            ->willReturn($getSharesParameters['path']);
1507
+
1508
+        $this->rootFolder->method('getUserFolder')
1509
+            ->with($this->currentUser)
1510
+            ->willReturn($userFolder);
1511
+
1512
+        $this->shareManager
1513
+            ->method('getSharesBy')
1514
+            ->willReturnCallback(
1515
+                function ($user, $shareType, $node) use ($shares) {
1516
+                    if (!isset($shares[$node->getName()]) || !isset($shares[$node->getName()][$shareType])) {
1517
+                        return [];
1518
+                    }
1519
+                    return $shares[$node->getName()][$shareType];
1520
+                }
1521
+            );
1522
+
1523
+        $this->shareManager
1524
+            ->method('outgoingServer2ServerSharesAllowed')
1525
+            ->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE] ?? false);
1526
+
1527
+        $this->shareManager
1528
+            ->method('outgoingServer2ServerGroupSharesAllowed')
1529
+            ->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE_GROUP] ?? false);
1530
+
1531
+        $this->groupManager
1532
+            ->method('isInGroup')
1533
+            ->willReturnCallback(
1534
+                function ($user, $group) {
1535
+                    return $group === 'currentUserGroup';
1536
+                }
1537
+            );
1538
+
1539
+        $result = $ocs->getShares(
1540
+            $getSharesParameters['sharedWithMe'] ?? 'false',
1541
+            $getSharesParameters['reshares'] ?? 'false',
1542
+            $getSharesParameters['subfiles'] ?? 'false',
1543
+            'path'
1544
+        );
1545
+
1546
+        $this->assertEquals($expected, $result->getData());
1547
+    }
1548
+
1549
+    public function testCanAccessShareAsOwner(): void {
1550
+        $share = $this->createMock(IShare::class);
1551
+        $share->method('getShareOwner')->willReturn($this->currentUser);
1552
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1553
+    }
1554
+
1555
+    public function testCanAccessShareAsSharer(): void {
1556
+        $share = $this->createMock(IShare::class);
1557
+        $share->method('getSharedBy')->willReturn($this->currentUser);
1558
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1559
+    }
1560
+
1561
+    public function testCanAccessShareAsSharee(): void {
1562
+        $share = $this->createMock(IShare::class);
1563
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
1564
+        $share->method('getSharedWith')->willReturn($this->currentUser);
1565
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1566
+    }
1567
+
1568
+    public function testCannotAccessLinkShare(): void {
1569
+        $share = $this->createMock(IShare::class);
1570
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
1571
+        $share->method('getNodeId')->willReturn(42);
1572
+
1573
+        $userFolder = $this->createMock(Folder::class);
1574
+        $this->rootFolder->method('getUserFolder')
1575
+            ->with($this->currentUser)
1576
+            ->willReturn($userFolder);
1577
+
1578
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1579
+    }
1580
+
1581
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataCanAccessShareWithPermissions')]
1582
+    public function testCanAccessShareWithPermissions(int $permissions, bool $expected): void {
1583
+        $share = $this->createMock(IShare::class);
1584
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
1585
+        $share->method('getSharedWith')->willReturn($this->createMock(IUser::class));
1586
+        $share->method('getNodeId')->willReturn(42);
1587
+
1588
+        $file = $this->createMock(File::class);
1589
+
1590
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1591
+        $userFolder->method('getFirstNodeById')
1592
+            ->with($share->getNodeId())
1593
+            ->willReturn($file);
1594
+        $userFolder->method('getById')
1595
+            ->with($share->getNodeId())
1596
+            ->willReturn([$file]);
1597
+        $this->rootFolder->method('getUserFolder')
1598
+            ->with($this->currentUser)
1599
+            ->willReturn($userFolder);
1600
+
1601
+        $file->method('getPermissions')
1602
+            ->willReturn($permissions);
1603
+
1604
+        if ($expected) {
1605
+            $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1606
+        } else {
1607
+            $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1608
+        }
1609
+    }
1610
+
1611
+    public static function dataCanAccessShareWithPermissions(): array {
1612
+        return [
1613
+            [Constants::PERMISSION_SHARE, true],
1614
+            [Constants::PERMISSION_READ, false],
1615
+            [Constants::PERMISSION_READ | Constants::PERMISSION_SHARE, true],
1616
+        ];
1617
+    }
1618
+
1619
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataCanAccessShareAsGroupMember')]
1620
+    public function testCanAccessShareAsGroupMember(string $group, bool $expected): void {
1621
+        $share = $this->createMock(IShare::class);
1622
+        $share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
1623
+        $share->method('getSharedWith')->willReturn($group);
1624
+        $share->method('getNodeId')->willReturn(42);
1625
+
1626
+        $file = $this->createMock(File::class);
1627
+
1628
+        $userFolder = $this->createMock(Folder::class);
1629
+        $userFolder->method('getFirstNodeById')
1630
+            ->with($share->getNodeId())
1631
+            ->willReturn($file);
1632
+        $userFolder->method('getById')
1633
+            ->with($share->getNodeId())
1634
+            ->willReturn([$file]);
1635
+        $this->rootFolder->method('getUserFolder')
1636
+            ->with($this->currentUser)
1637
+            ->willReturn($userFolder);
1638
+
1639
+        $user = $this->createMock(IUser::class);
1640
+        $this->userManager->method('get')
1641
+            ->with($this->currentUser)
1642
+            ->willReturn($user);
1643
+
1644
+        $group = $this->createMock(IGroup::class);
1645
+        $group->method('inGroup')->with($user)->willReturn(true);
1646
+        $group2 = $this->createMock(IGroup::class);
1647
+        $group2->method('inGroup')->with($user)->willReturn(false);
1648
+
1649
+        $this->groupManager->method('get')->willReturnMap([
1650
+            ['group', $group],
1651
+            ['group2', $group2],
1652
+            ['group-null', null],
1653
+        ]);
1654
+
1655
+        if ($expected) {
1656
+            $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1657
+        } else {
1658
+            $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1659
+        }
1660
+    }
1661
+
1662
+    public static function dataCanAccessShareAsGroupMember(): array {
1663
+        return [
1664
+            ['group', true],
1665
+            ['group2', false],
1666
+            ['group-null', false],
1667
+        ];
1668
+    }
1669
+
1670
+    public function dataCanAccessRoomShare() {
1671
+        $result = [];
1672
+
1673
+        $share = $this->createMock(IShare::class);
1674
+        $share->method('getShareType')->willReturn(IShare::TYPE_ROOM);
1675
+        $share->method('getSharedWith')->willReturn('recipientRoom');
1676
+
1677
+        $result[] = [
1678
+            false, $share, false, false
1679
+        ];
1680
+
1681
+        $result[] = [
1682
+            false, $share, false, true
1683
+        ];
1684
+
1685
+        $result[] = [
1686
+            true, $share, true, true
1687
+        ];
1688
+
1689
+        $result[] = [
1690
+            false, $share, true, false
1691
+        ];
1692
+
1693
+        return $result;
1694
+    }
1695
+
1696
+    /**
1697
+     *
1698
+     * @param bool $expects
1699
+     * @param IShare $share
1700
+     * @param bool helperAvailable
1701
+     * @param bool canAccessShareByHelper
1702
+     */
1703
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataCanAccessRoomShare')]
1704
+    public function testCanAccessRoomShare(bool $expected, IShare $share, bool $helperAvailable, bool $canAccessShareByHelper): void {
1705
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1706
+        $this->rootFolder->method('getUserFolder')
1707
+            ->with($this->currentUser)
1708
+            ->willReturn($userFolder);
1709
+
1710
+        $userFolder->method('getById')
1711
+            ->with($share->getNodeId())
1712
+            ->willReturn([$share->getNode()]);
1713
+
1714
+        if (!$helperAvailable) {
1715
+            $this->appManager->method('isEnabledForUser')
1716
+                ->with('spreed')
1717
+                ->willReturn(false);
1718
+        } else {
1719
+            $this->appManager->method('isEnabledForUser')
1720
+                ->with('spreed')
1721
+                ->willReturn(true);
1722
+
1723
+            // This is not possible anymore with PHPUnit 10+
1724
+            // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
1725
+            // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
1726
+            $helper = $this->getMockBuilder(\stdClass::class)
1727
+                ->addMethods(['canAccessShare'])
1728
+                ->getMock();
1729
+            $helper->method('canAccessShare')
1730
+                ->with($share, $this->currentUser)
1731
+                ->willReturn($canAccessShareByHelper);
1732
+
1733
+            $this->serverContainer->method('get')
1734
+                ->with('\OCA\Talk\Share\Helper\ShareAPIController')
1735
+                ->willReturn($helper);
1736
+        }
1737
+
1738
+        $this->assertEquals($expected, $this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1739
+    }
1740
+
1741
+
1742
+    public function testCreateShareNoPath(): void {
1743
+        $this->expectException(OCSNotFoundException::class);
1744
+        $this->expectExceptionMessage('Please specify a file or folder path');
1745
+
1746
+        $this->ocs->createShare();
1747
+    }
1748
+
1749
+
1750
+    public function testCreateShareInvalidPath(): void {
1751
+        $this->expectException(OCSNotFoundException::class);
1752
+        $this->expectExceptionMessage('Wrong path, file/folder does not exist');
1753
+
1754
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1755
+        $this->rootFolder->expects($this->once())
1756
+            ->method('getUserFolder')
1757
+            ->with('currentUser')
1758
+            ->willReturn($userFolder);
1759
+
1760
+        $userFolder->expects($this->once())
1761
+            ->method('get')
1762
+            ->with('invalid-path')
1763
+            ->willThrowException(new NotFoundException());
1764
+
1765
+        $this->ocs->createShare('invalid-path');
1766
+    }
1767
+
1768
+    public function testCreateShareInvalidShareType(): void {
1769
+        $this->expectException(OCSBadRequestException::class);
1770
+        $this->expectExceptionMessage('Unknown share type');
1771
+
1772
+        $share = $this->newShare();
1773
+        $this->shareManager->method('newShare')->willReturn($share);
1774
+
1775
+        [$userFolder, $file] = $this->getNonSharedUserFile();
1776
+        $this->rootFolder->expects($this->atLeastOnce())
1777
+            ->method('getUserFolder')
1778
+            ->with('currentUser')
1779
+            ->willReturn($userFolder);
1780
+
1781
+        $userFolder->expects($this->atLeastOnce())
1782
+            ->method('get')
1783
+            ->with('valid-path')
1784
+            ->willReturn($file);
1785
+        $userFolder->method('getById')
1786
+            ->willReturn([]);
1787
+
1788
+        $file->expects($this->once())
1789
+            ->method('lock')
1790
+            ->with(ILockingProvider::LOCK_SHARED);
1791
+
1792
+        $this->ocs->createShare('valid-path', 31);
1793
+    }
1794
+
1795
+    public function testCreateShareUserNoShareWith(): void {
1796
+        $this->expectException(OCSNotFoundException::class);
1797
+        $this->expectExceptionMessage('Please specify a valid account to share with');
1798
+
1799
+        $share = $this->newShare();
1800
+        $this->shareManager->method('newShare')->willReturn($share);
1801
+
1802
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1803
+        $this->rootFolder->method('getUserFolder')
1804
+            ->with('currentUser')
1805
+            ->willReturn($userFolder);
1806
+
1807
+        $userFolder->expects($this->once())
1808
+            ->method('get')
1809
+            ->with('valid-path')
1810
+            ->willReturn($path);
1811
+        $userFolder->method('getById')
1812
+            ->willReturn([]);
1813
+
1814
+        $path->expects($this->once())
1815
+            ->method('lock')
1816
+            ->with(ILockingProvider::LOCK_SHARED);
1817
+
1818
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER);
1819
+    }
1820
+
1821
+
1822
+    public function testCreateShareUserNoValidShareWith(): void {
1823
+        $this->expectException(OCSNotFoundException::class);
1824
+        $this->expectExceptionMessage('Please specify a valid account to share with');
1825
+
1826
+        $share = $this->newShare();
1827
+        $this->shareManager->method('newShare')->willReturn($share);
1828
+
1829
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1830
+        $this->rootFolder->method('getUserFolder')
1831
+            ->with('currentUser')
1832
+            ->willReturn($userFolder);
1833
+
1834
+        $userFolder->expects($this->once())
1835
+            ->method('get')
1836
+            ->with('valid-path')
1837
+            ->willReturn($path);
1838
+        $userFolder->method('getById')
1839
+            ->willReturn([]);
1840
+        $path->expects($this->once())
1841
+            ->method('lock')
1842
+            ->with(ILockingProvider::LOCK_SHARED);
1843
+        $this->userManager->method('userExists')
1844
+            ->with('invalidUser')
1845
+            ->willReturn(false);
1846
+
1847
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'invalidUser');
1848
+    }
1849
+
1850
+    public function testCreateShareUser(): void {
1851
+        $share = $this->newShare();
1852
+        $this->shareManager->method('newShare')->willReturn($share);
1853
+
1854
+        /** @var ShareAPIController $ocs */
1855
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
1856
+            ->setConstructorArgs([
1857
+                $this->appName,
1858
+                $this->request,
1859
+                $this->shareManager,
1860
+                $this->groupManager,
1861
+                $this->userManager,
1862
+                $this->rootFolder,
1863
+                $this->urlGenerator,
1864
+                $this->l,
1865
+                $this->config,
1866
+                $this->appConfig,
1867
+                $this->appManager,
1868
+                $this->serverContainer,
1869
+                $this->userStatusManager,
1870
+                $this->previewManager,
1871
+                $this->dateTimeZone,
1872
+                $this->logger,
1873
+                $this->factory,
1874
+                $this->mailer,
1875
+                $this->tagManager,
1876
+                $this->currentUser,
1877
+            ])->onlyMethods(['formatShare'])
1878
+            ->getMock();
1879
+
1880
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1881
+        $this->rootFolder->expects($this->exactly(2))
1882
+            ->method('getUserFolder')
1883
+            ->with('currentUser')
1884
+            ->willReturn($userFolder);
1885
+
1886
+        $userFolder->expects($this->once())
1887
+            ->method('get')
1888
+            ->with('valid-path')
1889
+            ->willReturn($path);
1890
+        $userFolder->method('getById')
1891
+            ->willReturn([]);
1892
+
1893
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
1894
+
1895
+        $path->expects($this->once())
1896
+            ->method('lock')
1897
+            ->with(ILockingProvider::LOCK_SHARED);
1898
+
1899
+        $this->shareManager->method('createShare')
1900
+            ->with($this->callback(function (IShare $share) use ($path) {
1901
+                return $share->getNode() === $path
1902
+                    && $share->getPermissions() === (
1903
+                        Constants::PERMISSION_ALL
1904
+                        & ~Constants::PERMISSION_DELETE
1905
+                        & ~Constants::PERMISSION_CREATE
1906
+                    )
1907
+                    && $share->getShareType() === IShare::TYPE_USER
1908
+                    && $share->getSharedWith() === 'validUser'
1909
+                    && $share->getSharedBy() === 'currentUser';
1910
+            }))
1911
+            ->willReturnArgument(0);
1912
+
1913
+        $expected = new DataResponse([]);
1914
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
1915
+
1916
+        $this->assertInstanceOf(get_class($expected), $result);
1917
+        $this->assertEquals($expected->getData(), $result->getData());
1918
+    }
1919
+
1920
+
1921
+    public function testCreateShareGroupNoValidShareWith(): void {
1922
+        $this->expectException(OCSNotFoundException::class);
1923
+        $this->expectExceptionMessage('Please specify a valid group');
1924
+
1925
+        $share = $this->newShare();
1926
+        $this->shareManager->method('newShare')->willReturn($share);
1927
+        $this->shareManager->method('createShare')->willReturnArgument(0);
1928
+        $this->shareManager->method('allowGroupSharing')->willReturn(true);
1929
+
1930
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1931
+        $this->rootFolder->method('getUserFolder')
1932
+            ->with('currentUser')
1933
+            ->willReturn($userFolder);
1934
+
1935
+        $userFolder->expects($this->once())
1936
+            ->method('get')
1937
+            ->with('valid-path')
1938
+            ->willReturn($path);
1939
+        $userFolder->method('getById')
1940
+            ->willReturn([]);
1941
+
1942
+        $path->expects($this->once())
1943
+            ->method('lock')
1944
+            ->with(ILockingProvider::LOCK_SHARED);
1945
+
1946
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
1947
+    }
1948
+
1949
+    public function testCreateShareGroup(): void {
1950
+        $share = $this->newShare();
1951
+        $this->shareManager->method('newShare')->willReturn($share);
1952
+
1953
+        /** @var ShareAPIController&MockObject $ocs */
1954
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
1955
+            ->setConstructorArgs([
1956
+                $this->appName,
1957
+                $this->request,
1958
+                $this->shareManager,
1959
+                $this->groupManager,
1960
+                $this->userManager,
1961
+                $this->rootFolder,
1962
+                $this->urlGenerator,
1963
+                $this->l,
1964
+                $this->config,
1965
+                $this->appConfig,
1966
+                $this->appManager,
1967
+                $this->serverContainer,
1968
+                $this->userStatusManager,
1969
+                $this->previewManager,
1970
+                $this->dateTimeZone,
1971
+                $this->logger,
1972
+                $this->factory,
1973
+                $this->mailer,
1974
+                $this->tagManager,
1975
+                $this->currentUser,
1976
+            ])->onlyMethods(['formatShare'])
1977
+            ->getMock();
1978
+
1979
+        $this->request
1980
+            ->method('getParam')
1981
+            ->willReturnMap([
1982
+                ['path', null, 'valid-path'],
1983
+                ['permissions', null, Constants::PERMISSION_ALL],
1984
+                ['shareType', '-1', IShare::TYPE_GROUP],
1985
+                ['shareWith', null, 'validGroup'],
1986
+            ]);
1987
+
1988
+        [$userFolder, $path] = $this->getNonSharedUserFolder();
1989
+        $this->rootFolder->expects($this->exactly(2))
1990
+            ->method('getUserFolder')
1991
+            ->with('currentUser')
1992
+            ->willReturn($userFolder);
1993
+
1994
+        $userFolder->expects($this->once())
1995
+            ->method('get')
1996
+            ->with('valid-path')
1997
+            ->willReturn($path);
1998
+        $userFolder->method('getById')
1999
+            ->willReturn([]);
2000
+
2001
+        $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2002
+
2003
+        $this->shareManager->expects($this->once())
2004
+            ->method('allowGroupSharing')
2005
+            ->willReturn(true);
2006
+
2007
+        $path->expects($this->once())
2008
+            ->method('lock')
2009
+            ->with(ILockingProvider::LOCK_SHARED);
2010
+
2011
+        $this->shareManager->method('createShare')
2012
+            ->with($this->callback(function (IShare $share) use ($path) {
2013
+                return $share->getNode() === $path
2014
+                && $share->getPermissions() === Constants::PERMISSION_ALL
2015
+                && $share->getShareType() === IShare::TYPE_GROUP
2016
+                && $share->getSharedWith() === 'validGroup'
2017
+                && $share->getSharedBy() === 'currentUser';
2018
+            }))
2019
+            ->willReturnArgument(0);
2020
+
2021
+        $expected = new DataResponse([]);
2022
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'validGroup');
2023
+
2024
+        $this->assertInstanceOf(get_class($expected), $result);
2025
+        $this->assertEquals($expected->getData(), $result->getData());
2026
+    }
2027
+
2028
+
2029
+    public function testCreateShareGroupNotAllowed(): void {
2030
+        $this->expectException(OCSNotFoundException::class);
2031
+        $this->expectExceptionMessage('Group sharing is disabled by the administrator');
2032
+
2033
+        $share = $this->newShare();
2034
+        $this->shareManager->method('newShare')->willReturn($share);
2035
+
2036
+        [$userFolder, $path] = $this->getNonSharedUserFolder();
2037
+        $this->rootFolder->method('getUserFolder')
2038
+            ->with('currentUser')
2039
+            ->willReturn($userFolder);
2040
+
2041
+        $userFolder->expects($this->once())
2042
+            ->method('get')
2043
+            ->with('valid-path')
2044
+            ->willReturn($path);
2045
+        $userFolder->method('getById')
2046
+            ->willReturn([]);
2047
+
2048
+        $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2049
+
2050
+        $this->shareManager->expects($this->once())
2051
+            ->method('allowGroupSharing')
2052
+            ->willReturn(false);
2053
+
2054
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
2055
+    }
2056
+
2057
+
2058
+    public function testCreateShareLinkNoLinksAllowed(): void {
2059
+        $this->expectException(OCSNotFoundException::class);
2060
+        $this->expectExceptionMessage('Public link sharing is disabled by the administrator');
2061
+
2062
+        $this->request
2063
+            ->method('getParam')
2064
+            ->willReturnMap([
2065
+                ['path', null, 'valid-path'],
2066
+                ['shareType', '-1', IShare::TYPE_LINK],
2067
+            ]);
2068
+
2069
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2070
+        $path->method('getId')->willReturn(42);
2071
+        $storage = $this->createMock(IStorage::class);
2072
+        $storage->method('instanceOfStorage')
2073
+            ->willReturnMap([
2074
+                ['OCA\Files_Sharing\External\Storage', false],
2075
+                ['OCA\Files_Sharing\SharedStorage', false],
2076
+            ]);
2077
+        $path->method('getStorage')->willReturn($storage);
2078
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2079
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2080
+        $this->rootFolder->method('getById')
2081
+            ->willReturn([]);
2082
+
2083
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2084
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2085
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(false);
2086
+
2087
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK);
2088
+    }
2089
+
2090
+
2091
+    public function testCreateShareLinkNoPublicUpload(): void {
2092
+        $this->expectException(OCSForbiddenException::class);
2093
+        $this->expectExceptionMessage('Public upload disabled by the administrator');
2094
+
2095
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2096
+        $path->method('getId')->willReturn(42);
2097
+        $storage = $this->createMock(IStorage::class);
2098
+        $storage->method('instanceOfStorage')
2099
+            ->willReturnMap([
2100
+                ['OCA\Files_Sharing\External\Storage', false],
2101
+                ['OCA\Files_Sharing\SharedStorage', false],
2102
+            ]);
2103
+        $path->method('getStorage')->willReturn($storage);
2104
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2105
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2106
+        $this->rootFolder->method('getById')
2107
+            ->willReturn([]);
2108
+
2109
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2110
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2111
+
2112
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2113
+    }
2114
+
2115
+
2116
+    public function testCreateShareLinkPublicUploadFile(): void {
2117
+        $this->expectException(OCSBadRequestException::class);
2118
+        $this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
2119
+
2120
+        $storage = $this->createMock(IStorage::class);
2121
+        $storage->method('instanceOfStorage')
2122
+            ->willReturnMap([
2123
+                ['OCA\Files_Sharing\External\Storage', false],
2124
+                ['OCA\Files_Sharing\SharedStorage', false],
2125
+            ]);
2126
+
2127
+        $file = $this->createMock(File::class);
2128
+        $file->method('getId')->willReturn(42);
2129
+        $file->method('getStorage')->willReturn($storage);
2130
+
2131
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2132
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($file);
2133
+        $this->rootFolder->method('getById')
2134
+            ->willReturn([]);
2135
+
2136
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2137
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2138
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2139
+
2140
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2141
+    }
2142
+
2143
+    public function testCreateShareLinkPublicUploadFolder(): void {
2144
+        $ocs = $this->mockFormatShare();
2145
+
2146
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2147
+        $path->method('getId')->willReturn(1);
2148
+        $storage = $this->createMock(IStorage::class);
2149
+        $storage->method('instanceOfStorage')
2150
+            ->willReturnMap([
2151
+                ['OCA\Files_Sharing\External\Storage', false],
2152
+                ['OCA\Files_Sharing\SharedStorage', false],
2153
+            ]);
2154
+        $path->method('getStorage')->willReturn($storage);
2155
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2156
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2157
+        $this->rootFolder->method('getById')
2158
+            ->willReturn([]);
2159
+
2160
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2161
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2162
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2163
+
2164
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2165
+            $this->callback(function (IShare $share) use ($path) {
2166
+                return $share->getNode() === $path
2167
+                    && $share->getShareType() === IShare::TYPE_LINK
2168
+                    && $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2169
+                    && $share->getSharedBy() === 'currentUser'
2170
+                    && $share->getPassword() === null
2171
+                    && $share->getExpirationDate() === null;
2172
+            })
2173
+        )->willReturnArgument(0);
2174
+
2175
+        $expected = new DataResponse([]);
2176
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', '', null, '');
2177
+
2178
+        $this->assertInstanceOf(get_class($expected), $result);
2179
+        $this->assertEquals($expected->getData(), $result->getData());
2180
+    }
2181
+
2182
+    public function testCreateShareLinkPassword(): void {
2183
+        $ocs = $this->mockFormatShare();
2184
+
2185
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2186
+        $path->method('getId')->willReturn(42);
2187
+        $storage = $this->createMock(IStorage::class);
2188
+        $storage->method('instanceOfStorage')
2189
+            ->willReturnMap([
2190
+                ['OCA\Files_Sharing\External\Storage', false],
2191
+                ['OCA\Files_Sharing\SharedStorage', false],
2192
+            ]);
2193
+        $path->method('getStorage')->willReturn($storage);
2194
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2195
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2196
+        $this->rootFolder->method('getById')
2197
+            ->willReturn([]);
2198
+
2199
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2200
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2201
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2202
+
2203
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2204
+            $this->callback(function (IShare $share) use ($path) {
2205
+                return $share->getNode() === $path
2206
+                && $share->getShareType() === IShare::TYPE_LINK
2207
+                && $share->getPermissions() === Constants::PERMISSION_READ // publicUpload was set to false
2208
+                && $share->getSharedBy() === 'currentUser'
2209
+                && $share->getPassword() === 'password'
2210
+                && $share->getExpirationDate() === null;
2211
+            })
2212
+        )->willReturnArgument(0);
2213
+
2214
+        $expected = new DataResponse([]);
2215
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_READ, IShare::TYPE_LINK, null, 'false', 'password', null, '');
2216
+
2217
+        $this->assertInstanceOf(get_class($expected), $result);
2218
+        $this->assertEquals($expected->getData(), $result->getData());
2219
+    }
2220
+
2221
+    public function testCreateShareLinkSendPasswordByTalk(): void {
2222
+        $ocs = $this->mockFormatShare();
2223
+
2224
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2225
+        $path->method('getId')->willReturn(42);
2226
+        $storage = $this->createMock(IStorage::class);
2227
+        $storage->method('instanceOfStorage')
2228
+            ->willReturnMap([
2229
+                ['OCA\Files_Sharing\External\Storage', false],
2230
+                ['OCA\Files_Sharing\SharedStorage', false],
2231
+            ]);
2232
+        $path->method('getStorage')->willReturn($storage);
2233
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2234
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2235
+        $this->rootFolder->method('getById')
2236
+            ->willReturn([]);
2237
+
2238
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2239
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2240
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2241
+
2242
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
2243
+
2244
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2245
+            $this->callback(function (IShare $share) use ($path) {
2246
+                return $share->getNode() === $path
2247
+                && $share->getShareType() === IShare::TYPE_LINK
2248
+                && $share->getPermissions() === (Constants::PERMISSION_ALL & ~(Constants::PERMISSION_SHARE))
2249
+                && $share->getSharedBy() === 'currentUser'
2250
+                && $share->getPassword() === 'password'
2251
+                && $share->getSendPasswordByTalk() === true
2252
+                && $share->getExpirationDate() === null;
2253
+            })
2254
+        )->willReturnArgument(0);
2255
+
2256
+        $expected = new DataResponse([]);
2257
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', 'password', 'true', '');
2258
+
2259
+        $this->assertInstanceOf(get_class($expected), $result);
2260
+        $this->assertEquals($expected->getData(), $result->getData());
2261
+    }
2262
+
2263
+
2264
+    public function testCreateShareLinkSendPasswordByTalkWithTalkDisabled(): void {
2265
+        $this->expectException(OCSForbiddenException::class);
2266
+        $this->expectExceptionMessage('Sharing valid-path sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled');
2267
+
2268
+        $ocs = $this->mockFormatShare();
2269
+
2270
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2271
+        $path->method('getId')->willReturn(42);
2272
+        $storage = $this->createMock(IStorage::class);
2273
+        $storage->method('instanceOfStorage')
2274
+            ->willReturnMap([
2275
+                ['OCA\Files_Sharing\External\Storage', false],
2276
+                ['OCA\Files_Sharing\SharedStorage', false],
2277
+            ]);
2278
+        $path->method('getStorage')->willReturn($storage);
2279
+        $path->method('getPath')->willReturn('valid-path');
2280
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2281
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2282
+        $this->rootFolder->method('getById')
2283
+            ->willReturn([]);
2284
+
2285
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2286
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2287
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2288
+
2289
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
2290
+
2291
+        $this->shareManager->expects($this->never())->method('createShare');
2292
+
2293
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', 'password', 'true', '');
2294
+    }
2295
+
2296
+    public function testCreateShareValidExpireDate(): void {
2297
+        $ocs = $this->mockFormatShare();
2298
+
2299
+        $this->request
2300
+            ->method('getParam')
2301
+            ->willReturnMap([
2302
+                ['path', null, 'valid-path'],
2303
+                ['shareType', '-1', IShare::TYPE_LINK],
2304
+                ['publicUpload', null, 'false'],
2305
+                ['expireDate', '', '2000-01-01'],
2306
+                ['password', '', ''],
2307
+            ]);
2308
+
2309
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2310
+        $path->method('getId')->willReturn(42);
2311
+        $storage = $this->createMock(IStorage::class);
2312
+        $storage->method('instanceOfStorage')
2313
+            ->willReturnMap([
2314
+                ['OCA\Files_Sharing\External\Storage', false],
2315
+                ['OCA\Files_Sharing\SharedStorage', false],
2316
+            ]);
2317
+        $path->method('getStorage')->willReturn($storage);
2318
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2319
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2320
+        $this->rootFolder->method('getById')
2321
+            ->willReturn([]);
2322
+
2323
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2324
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2325
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2326
+
2327
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2328
+            $this->callback(function (IShare $share) use ($path) {
2329
+                $date = new \DateTime('2000-01-01');
2330
+                $date->setTime(0, 0, 0);
2331
+
2332
+                return $share->getNode() === $path
2333
+                && $share->getShareType() === IShare::TYPE_LINK
2334
+                && $share->getPermissions() === Constants::PERMISSION_READ | Constants::PERMISSION_SHARE
2335
+                && $share->getSharedBy() === 'currentUser'
2336
+                && $share->getPassword() === null
2337
+                && $share->getExpirationDate() == $date;
2338
+            })
2339
+        )->willReturnArgument(0);
2340
+
2341
+        $expected = new DataResponse([]);
2342
+        $result = $ocs->createShare('valid-path', null, IShare::TYPE_LINK, null, 'false', '', null, '2000-01-01');
2343
+
2344
+        $this->assertInstanceOf(get_class($expected), $result);
2345
+        $this->assertEquals($expected->getData(), $result->getData());
2346
+    }
2347
+
2348
+
2349
+    public function testCreateShareInvalidExpireDate(): void {
2350
+        $this->expectException(OCSNotFoundException::class);
2351
+        $this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
2352
+
2353
+        $ocs = $this->mockFormatShare();
2354
+
2355
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2356
+        $path->method('getId')->willReturn(42);
2357
+        $storage = $this->createMock(IStorage::class);
2358
+        $storage->method('instanceOfStorage')
2359
+            ->willReturnMap([
2360
+                ['OCA\Files_Sharing\External\Storage', false],
2361
+                ['OCA\Files_Sharing\SharedStorage', false],
2362
+            ]);
2363
+        $path->method('getStorage')->willReturn($storage);
2364
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2365
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2366
+        $this->rootFolder->method('getById')
2367
+            ->willReturn([]);
2368
+
2369
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2370
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2371
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2372
+
2373
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, 'a1b2d3');
2374
+    }
2375
+
2376
+    public function testCreateShareRemote(): void {
2377
+        $share = $this->newShare();
2378
+        $this->shareManager->method('newShare')->willReturn($share);
2379
+
2380
+        /** @var ShareAPIController $ocs */
2381
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2382
+            ->setConstructorArgs([
2383
+                $this->appName,
2384
+                $this->request,
2385
+                $this->shareManager,
2386
+                $this->groupManager,
2387
+                $this->userManager,
2388
+                $this->rootFolder,
2389
+                $this->urlGenerator,
2390
+                $this->l,
2391
+                $this->config,
2392
+                $this->appConfig,
2393
+                $this->appManager,
2394
+                $this->serverContainer,
2395
+                $this->userStatusManager,
2396
+                $this->previewManager,
2397
+                $this->dateTimeZone,
2398
+                $this->logger,
2399
+                $this->factory,
2400
+                $this->mailer,
2401
+                $this->tagManager,
2402
+                $this->currentUser,
2403
+            ])->onlyMethods(['formatShare'])
2404
+            ->getMock();
2405
+
2406
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2407
+        $this->rootFolder->expects($this->exactly(2))
2408
+            ->method('getUserFolder')
2409
+            ->with('currentUser')
2410
+            ->willReturn($userFolder);
2411
+
2412
+        $userFolder->expects($this->once())
2413
+            ->method('get')
2414
+            ->with('valid-path')
2415
+            ->willReturn($path);
2416
+        $userFolder->method('getById')
2417
+            ->willReturn([]);
2418
+
2419
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2420
+
2421
+        $path->expects($this->once())
2422
+            ->method('lock')
2423
+            ->with(ILockingProvider::LOCK_SHARED);
2424
+
2425
+        $this->shareManager->method('createShare')
2426
+            ->with($this->callback(function (IShare $share) use ($path) {
2427
+                return $share->getNode() === $path
2428
+                    && $share->getPermissions() === (
2429
+                        Constants::PERMISSION_ALL
2430
+                        & ~Constants::PERMISSION_DELETE
2431
+                        & ~Constants::PERMISSION_CREATE
2432
+                    )
2433
+                    && $share->getShareType() === IShare::TYPE_REMOTE
2434
+                    && $share->getSharedWith() === '[email protected]'
2435
+                    && $share->getSharedBy() === 'currentUser';
2436
+            }))
2437
+            ->willReturnArgument(0);
2438
+
2439
+        $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
2440
+
2441
+        $expected = new DataResponse([]);
2442
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE, '[email protected]');
2443
+
2444
+        $this->assertInstanceOf(get_class($expected), $result);
2445
+        $this->assertEquals($expected->getData(), $result->getData());
2446
+    }
2447
+
2448
+    public function testCreateShareRemoteGroup(): void {
2449
+        $share = $this->newShare();
2450
+        $this->shareManager->method('newShare')->willReturn($share);
2451
+
2452
+        /** @var ShareAPIController $ocs */
2453
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2454
+            ->setConstructorArgs([
2455
+                $this->appName,
2456
+                $this->request,
2457
+                $this->shareManager,
2458
+                $this->groupManager,
2459
+                $this->userManager,
2460
+                $this->rootFolder,
2461
+                $this->urlGenerator,
2462
+                $this->l,
2463
+                $this->config,
2464
+                $this->appConfig,
2465
+                $this->appManager,
2466
+                $this->serverContainer,
2467
+                $this->userStatusManager,
2468
+                $this->previewManager,
2469
+                $this->dateTimeZone,
2470
+                $this->logger,
2471
+                $this->factory,
2472
+                $this->mailer,
2473
+                $this->tagManager,
2474
+                $this->currentUser,
2475
+            ])->onlyMethods(['formatShare'])
2476
+            ->getMock();
2477
+
2478
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2479
+        $this->rootFolder->expects($this->exactly(2))
2480
+            ->method('getUserFolder')
2481
+            ->with('currentUser')
2482
+            ->willReturn($userFolder);
2483
+
2484
+        $userFolder->expects($this->once())
2485
+            ->method('get')
2486
+            ->with('valid-path')
2487
+            ->willReturn($path);
2488
+        $userFolder->method('getById')
2489
+            ->willReturn([]);
2490
+
2491
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2492
+
2493
+        $path->expects($this->once())
2494
+            ->method('lock')
2495
+            ->with(ILockingProvider::LOCK_SHARED);
2496
+
2497
+        $this->shareManager->method('createShare')
2498
+            ->with($this->callback(function (IShare $share) use ($path) {
2499
+                return $share->getNode() === $path
2500
+                    && $share->getPermissions() === (
2501
+                        Constants::PERMISSION_ALL
2502
+                        & ~Constants::PERMISSION_DELETE
2503
+                        & ~Constants::PERMISSION_CREATE
2504
+                    )
2505
+                    && $share->getShareType() === IShare::TYPE_REMOTE_GROUP
2506
+                    && $share->getSharedWith() === '[email protected]'
2507
+                    && $share->getSharedBy() === 'currentUser';
2508
+            }))
2509
+            ->willReturnArgument(0);
2510
+
2511
+        $this->shareManager->method('outgoingServer2ServerGroupSharesAllowed')->willReturn(true);
2512
+
2513
+        $expected = new DataResponse([]);
2514
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE_GROUP, '[email protected]');
2515
+
2516
+        $this->assertInstanceOf(get_class($expected), $result);
2517
+        $this->assertEquals($expected->getData(), $result->getData());
2518
+    }
2519
+
2520
+    public function testCreateShareRoom(): void {
2521
+        $ocs = $this->mockFormatShare();
2522
+
2523
+        $share = $this->newShare();
2524
+        $this->shareManager->method('newShare')->willReturn($share);
2525
+
2526
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2527
+        $this->rootFolder->expects($this->exactly(2))
2528
+            ->method('getUserFolder')
2529
+            ->with('currentUser')
2530
+            ->willReturn($userFolder);
2531
+
2532
+        $userFolder->expects($this->once())
2533
+            ->method('get')
2534
+            ->with('valid-path')
2535
+            ->willReturn($path);
2536
+        $userFolder->method('getById')
2537
+            ->willReturn([]);
2538
+
2539
+        $path->expects($this->once())
2540
+            ->method('lock')
2541
+            ->with(ILockingProvider::LOCK_SHARED);
2542
+
2543
+        $this->appManager->method('isEnabledForUser')
2544
+            ->with('spreed')
2545
+            ->willReturn(true);
2546
+
2547
+        // This is not possible anymore with PHPUnit 10+
2548
+        // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2549
+        // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2550
+        $helper = $this->getMockBuilder(\stdClass::class)
2551
+            ->addMethods(['createShare'])
2552
+            ->getMock();
2553
+        $helper->method('createShare')
2554
+            ->with(
2555
+                $share,
2556
+                'recipientRoom',
2557
+                Constants::PERMISSION_ALL
2558
+                & ~Constants::PERMISSION_DELETE
2559
+                & ~Constants::PERMISSION_CREATE,
2560
+                ''
2561
+            )->willReturnCallback(
2562
+                function ($share): void {
2563
+                    $share->setSharedWith('recipientRoom');
2564
+                    $share->setPermissions(Constants::PERMISSION_ALL);
2565
+                }
2566
+            );
2567
+
2568
+        $this->serverContainer->method('get')
2569
+            ->with('\OCA\Talk\Share\Helper\ShareAPIController')
2570
+            ->willReturn($helper);
2571
+
2572
+        $this->shareManager->method('createShare')
2573
+            ->with($this->callback(function (IShare $share) use ($path) {
2574
+                return $share->getNode() === $path
2575
+                    && $share->getPermissions() === Constants::PERMISSION_ALL
2576
+                    && $share->getShareType() === IShare::TYPE_ROOM
2577
+                    && $share->getSharedWith() === 'recipientRoom'
2578
+                    && $share->getSharedBy() === 'currentUser';
2579
+            }))
2580
+            ->willReturnArgument(0);
2581
+
2582
+        $expected = new DataResponse([]);
2583
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2584
+
2585
+        $this->assertInstanceOf(get_class($expected), $result);
2586
+        $this->assertEquals($expected->getData(), $result->getData());
2587
+    }
2588
+
2589
+
2590
+    public function testCreateShareRoomHelperNotAvailable(): void {
2591
+        $this->expectException(OCSForbiddenException::class);
2592
+        $this->expectExceptionMessage('Sharing valid-path failed because the back end does not support room shares');
2593
+
2594
+        $ocs = $this->mockFormatShare();
2595
+
2596
+        $share = $this->newShare();
2597
+        $this->shareManager->method('newShare')->willReturn($share);
2598
+
2599
+        [$userFolder, $path] = $this->getNonSharedUserFolder();
2600
+        $this->rootFolder->method('getUserFolder')
2601
+            ->with('currentUser')
2602
+            ->willReturn($userFolder);
2603
+
2604
+        $path->method('getPath')->willReturn('valid-path');
2605
+        $userFolder->expects($this->once())
2606
+            ->method('get')
2607
+            ->with('valid-path')
2608
+            ->willReturn($path);
2609
+        $userFolder->method('getById')
2610
+            ->willReturn([]);
2611
+
2612
+        $path->expects($this->once())
2613
+            ->method('lock')
2614
+            ->with(ILockingProvider::LOCK_SHARED);
2615
+
2616
+        $this->appManager->method('isEnabledForUser')
2617
+            ->with('spreed')
2618
+            ->willReturn(false);
2619
+
2620
+        $this->shareManager->expects($this->never())->method('createShare');
2621
+
2622
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2623
+    }
2624
+
2625
+
2626
+    public function testCreateShareRoomHelperThrowException(): void {
2627
+        $this->expectException(OCSNotFoundException::class);
2628
+        $this->expectExceptionMessage('Exception thrown by the helper');
2629
+
2630
+        $ocs = $this->mockFormatShare();
2631
+
2632
+        $share = $this->newShare();
2633
+        $share->setSharedBy('currentUser');
2634
+        $this->shareManager->method('newShare')->willReturn($share);
2635
+
2636
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2637
+        $this->rootFolder->method('getUserFolder')
2638
+            ->with('currentUser')
2639
+            ->willReturn($userFolder);
2640
+
2641
+        $userFolder->expects($this->once())
2642
+            ->method('get')
2643
+            ->with('valid-path')
2644
+            ->willReturn($path);
2645
+        $userFolder->method('getById')
2646
+            ->willReturn([]);
2647
+
2648
+        $path->expects($this->once())
2649
+            ->method('lock')
2650
+            ->with(ILockingProvider::LOCK_SHARED);
2651
+
2652
+        $this->appManager->method('isEnabledForUser')
2653
+            ->with('spreed')
2654
+            ->willReturn(true);
2655
+
2656
+        // This is not possible anymore with PHPUnit 10+
2657
+        // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2658
+        // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2659
+        $helper = $this->getMockBuilder(\stdClass::class)
2660
+            ->addMethods(['createShare'])
2661
+            ->getMock();
2662
+        $helper->method('createShare')
2663
+            ->with(
2664
+                $share,
2665
+                'recipientRoom',
2666
+                Constants::PERMISSION_ALL & ~(Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE),
2667
+                ''
2668
+            )->willReturnCallback(
2669
+                function ($share): void {
2670
+                    throw new OCSNotFoundException('Exception thrown by the helper');
2671
+                }
2672
+            );
2673
+
2674
+        $this->serverContainer->method('get')
2675
+            ->with('\OCA\Talk\Share\Helper\ShareAPIController')
2676
+            ->willReturn($helper);
2677
+
2678
+        $this->shareManager->expects($this->never())->method('createShare');
2679
+
2680
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2681
+    }
2682
+
2683
+    /**
2684
+     * Test for https://github.com/owncloud/core/issues/22587
2685
+     * TODO: Remove once proper solution is in place
2686
+     */
2687
+    public function testCreateReshareOfFederatedMountNoDeletePermissions(): void {
2688
+        $share = Server::get(IManager::class)->newShare();
2689
+        $this->shareManager->method('newShare')->willReturn($share);
2690
+
2691
+        /** @var ShareAPIController&MockObject $ocs */
2692
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2693
+            ->setConstructorArgs([
2694
+                $this->appName,
2695
+                $this->request,
2696
+                $this->shareManager,
2697
+                $this->groupManager,
2698
+                $this->userManager,
2699
+                $this->rootFolder,
2700
+                $this->urlGenerator,
2701
+                $this->l,
2702
+                $this->config,
2703
+                $this->appConfig,
2704
+                $this->appManager,
2705
+                $this->serverContainer,
2706
+                $this->userStatusManager,
2707
+                $this->previewManager,
2708
+                $this->dateTimeZone,
2709
+                $this->logger,
2710
+                $this->factory,
2711
+                $this->mailer,
2712
+                $this->tagManager,
2713
+                $this->currentUser,
2714
+            ])->onlyMethods(['formatShare'])
2715
+            ->getMock();
2716
+
2717
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
2718
+        $this->rootFolder->expects($this->exactly(2))
2719
+            ->method('getUserFolder')
2720
+            ->with('currentUser')
2721
+            ->willReturn($userFolder);
2722
+
2723
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2724
+        $path->method('getId')->willReturn(42);
2725
+
2726
+        $storage = $this->createMock(IStorage::class);
2727
+        $storage->method('instanceOfStorage')
2728
+            ->willReturnMap([
2729
+                ['OCA\Files_Sharing\External\Storage', true],
2730
+                ['OCA\Files_Sharing\SharedStorage', false],
2731
+            ]);
2732
+        $userFolder->method('getStorage')->willReturn($storage);
2733
+        $path->method('getStorage')->willReturn($storage);
2734
+
2735
+        $path->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
2736
+        $userFolder->expects($this->once())
2737
+            ->method('get')
2738
+            ->with('valid-path')
2739
+            ->willReturn($path);
2740
+        $userFolder->method('getById')
2741
+            ->willReturn([]);
2742
+
2743
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2744
+
2745
+        $this->shareManager
2746
+            ->expects($this->once())
2747
+            ->method('createShare')
2748
+            ->with($this->callback(function (IShare $share) {
2749
+                return $share->getPermissions() === Constants::PERMISSION_READ;
2750
+            }))
2751
+            ->willReturnArgument(0);
2752
+
2753
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
2754
+    }
2755
+
2756
+
2757
+    public function testUpdateShareCantAccess(): void {
2758
+        $this->expectException(OCSNotFoundException::class);
2759
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
2760
+
2761
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
2762
+        $share = $this->newShare();
2763
+        $share->setNode($node);
2764
+
2765
+        $node->expects($this->once())
2766
+            ->method('lock')
2767
+            ->with(ILockingProvider::LOCK_SHARED);
2768
+
2769
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2770
+
2771
+        $this->rootFolder->method('getUserFolder')
2772
+            ->with($this->currentUser)
2773
+            ->willReturn($userFolder);
2774
+
2775
+        $userFolder->method('getById')
2776
+            ->with($share->getNodeId())
2777
+            ->willReturn([$share->getNode()]);
2778
+
2779
+        $this->ocs->updateShare(42);
2780
+    }
2781
+
2782
+
2783
+    public function testUpdateNoParametersLink(): void {
2784
+        $this->expectException(OCSBadRequestException::class);
2785
+        $this->expectExceptionMessage('Wrong or no update parameter given');
2786
+
2787
+        $node = $this->getMockBuilder(Folder::class)->getMock();
2788
+        $share = $this->newShare();
2789
+        $share->setPermissions(Constants::PERMISSION_ALL)
2790
+            ->setSharedBy($this->currentUser)
2791
+            ->setShareType(IShare::TYPE_LINK)
2792
+            ->setNode($node);
2793
+
2794
+        $node->expects($this->once())
2795
+            ->method('lock')
2796
+            ->with(ILockingProvider::LOCK_SHARED);
2797
+
2798
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2799
+
2800
+        $this->ocs->updateShare(42);
2801
+    }
2802
+
2803
+
2804
+    public function testUpdateNoParametersOther(): void {
2805
+        $this->expectException(OCSBadRequestException::class);
2806
+        $this->expectExceptionMessage('Wrong or no update parameter given');
2807
+
2808
+        $node = $this->getMockBuilder(Folder::class)->getMock();
2809
+        $share = $this->newShare();
2810
+        $share->setPermissions(Constants::PERMISSION_ALL)
2811
+            ->setSharedBy($this->currentUser)
2812
+            ->setShareType(IShare::TYPE_GROUP)
2813
+            ->setNode($node);
2814
+
2815
+        $node->expects($this->once())
2816
+            ->method('lock')
2817
+            ->with(ILockingProvider::LOCK_SHARED);
2818
+
2819
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2820
+
2821
+        $this->ocs->updateShare(42);
2822
+    }
2823
+
2824
+    public function testUpdateLinkShareClear(): void {
2825
+        $ocs = $this->mockFormatShare();
2826
+
2827
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
2828
+        $node->method('getId')
2829
+            ->willReturn(42);
2830
+        $share = $this->newShare();
2831
+        $share->setPermissions(Constants::PERMISSION_ALL)
2832
+            ->setSharedBy($this->currentUser)
2833
+            ->setShareType(IShare::TYPE_LINK)
2834
+            ->setPassword('password')
2835
+            ->setExpirationDate(new \DateTime())
2836
+            ->setNote('note')
2837
+            ->setLabel('label')
2838
+            ->setHideDownload(true)
2839
+            ->setPermissions(Constants::PERMISSION_ALL)
2840
+            ->setNode($node);
2841
+
2842
+        $node->expects($this->once())
2843
+            ->method('lock')
2844
+            ->with(ILockingProvider::LOCK_SHARED);
2845
+
2846
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2847
+
2848
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
2849
+            $this->callback(function (IShare $share) {
2850
+                return $share->getPermissions() === Constants::PERMISSION_READ
2851
+                && $share->getPassword() === null
2852
+                && $share->getExpirationDate() === null
2853
+                // Once set a note or a label are never back to null, only to an
2854
+                // empty string.
2855
+                && $share->getNote() === ''
2856
+                && $share->getLabel() === ''
2857
+                && $share->getHideDownload() === false;
2858
+            })
2859
+        )->willReturnArgument(0);
2860
+
2861
+        $this->shareManager->method('getSharedWith')
2862
+            ->willReturn([]);
2863
+
2864
+        $this->rootFolder->method('getUserFolder')
2865
+            ->with($this->currentUser)
2866
+            ->willReturn($userFolder);
2867
+
2868
+        $userFolder->method('getById')
2869
+            ->with(42)
2870
+            ->willReturn([$node]);
2871
+        $userFolder->method('getFirstNodeById')
2872
+            ->with(42)
2873
+            ->willReturn($node);
2874
+
2875
+        $mountPoint = $this->createMock(IMountPoint::class);
2876
+        $node->method('getMountPoint')
2877
+            ->willReturn($mountPoint);
2878
+        $mountPoint->method('getStorageRootId')
2879
+            ->willReturn(42);
2880
+
2881
+        $expected = new DataResponse([]);
2882
+        $result = $ocs->updateShare(42, null, '', null, 'false', '', '', '', 'false');
2883
+
2884
+        $this->assertInstanceOf(get_class($expected), $result);
2885
+        $this->assertEquals($expected->getData(), $result->getData());
2886
+    }
2887
+
2888
+    public function testUpdateLinkShareSet(): void {
2889
+        $ocs = $this->mockFormatShare();
2890
+
2891
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
2892
+        $folder->method('getId')
2893
+            ->willReturn(42);
2894
+
2895
+        $share = Server::get(IManager::class)->newShare();
2896
+        $share->setPermissions(Constants::PERMISSION_ALL)
2897
+            ->setSharedBy($this->currentUser)
2898
+            ->setShareType(IShare::TYPE_LINK)
2899
+            ->setNode($folder);
2900
+
2901
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2902
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2903
+
2904
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
2905
+            $this->callback(function (IShare $share) {
2906
+                $date = new \DateTime('2000-01-01');
2907
+                $date->setTime(0, 0, 0);
2908
+
2909
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2910
+                && $share->getPassword() === 'password'
2911
+                && $share->getExpirationDate() == $date
2912
+                && $share->getNote() === 'note'
2913
+                && $share->getLabel() === 'label'
2914
+                && $share->getHideDownload() === true;
2915
+            })
2916
+        )->willReturnArgument(0);
2917
+
2918
+        $this->shareManager->method('getSharedWith')
2919
+            ->willReturn([]);
2920
+
2921
+        $this->rootFolder->method('getUserFolder')
2922
+            ->with($this->currentUser)
2923
+            ->willReturn($userFolder);
2924
+
2925
+        $userFolder->method('getById')
2926
+            ->with(42)
2927
+            ->willReturn([$folder]);
2928
+
2929
+        $mountPoint = $this->createMock(IMountPoint::class);
2930
+        $folder->method('getMountPoint')
2931
+            ->willReturn($mountPoint);
2932
+        $mountPoint->method('getStorageRootId')
2933
+            ->willReturn(42);
2934
+
2935
+        $expected = new DataResponse([]);
2936
+        $result = $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-01', 'note', 'label', 'true');
2937
+
2938
+        $this->assertInstanceOf(get_class($expected), $result);
2939
+        $this->assertEquals($expected->getData(), $result->getData());
2940
+    }
2941
+
2942
+    #[\PHPUnit\Framework\Attributes\DataProvider('publicUploadParamsProvider')]
2943
+    public function testUpdateLinkShareEnablePublicUpload($permissions, $publicUpload, $expireDate, $password): void {
2944
+        $ocs = $this->mockFormatShare();
2945
+
2946
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
2947
+        $folder->method('getId')
2948
+            ->willReturn(42);
2949
+
2950
+        $share = Server::get(IManager::class)->newShare();
2951
+        $share->setPermissions(Constants::PERMISSION_ALL)
2952
+            ->setSharedBy($this->currentUser)
2953
+            ->setShareType(IShare::TYPE_LINK)
2954
+            ->setPassword('password')
2955
+            ->setNode($folder);
2956
+
2957
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2958
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2959
+        $this->shareManager->method('getSharedWith')->willReturn([]);
2960
+
2961
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
2962
+            $this->callback(function (IShare $share) {
2963
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2964
+                && $share->getPassword() === 'password'
2965
+                && $share->getExpirationDate() === null;
2966
+            })
2967
+        )->willReturnArgument(0);
2968
+
2969
+        $this->rootFolder->method('getUserFolder')
2970
+            ->with($this->currentUser)
2971
+            ->willReturn($userFolder);
2972
+
2973
+        $userFolder->method('getById')
2974
+            ->with(42)
2975
+            ->willReturn([$folder]);
2976
+
2977
+        $mountPoint = $this->createMock(IMountPoint::class);
2978
+        $folder->method('getMountPoint')
2979
+            ->willReturn($mountPoint);
2980
+        $mountPoint->method('getStorageRootId')
2981
+            ->willReturn(42);
2982
+
2983
+        $expected = new DataResponse([]);
2984
+        $result = $ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
2985
+
2986
+        $this->assertInstanceOf(get_class($expected), $result);
2987
+        $this->assertEquals($expected->getData(), $result->getData());
2988
+    }
2989
+
2990
+
2991
+    public static function publicLinkValidPermissionsProvider() {
2992
+        return [
2993
+            [Constants::PERMISSION_CREATE],
2994
+            [Constants::PERMISSION_READ],
2995
+            [Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE],
2996
+            [Constants::PERMISSION_READ | Constants::PERMISSION_DELETE],
2997
+            [Constants::PERMISSION_READ | Constants::PERMISSION_CREATE],
2998
+        ];
2999
+    }
3000
+
3001
+    #[\PHPUnit\Framework\Attributes\DataProvider('publicLinkValidPermissionsProvider')]
3002
+    public function testUpdateLinkShareSetCRUDPermissions($permissions): void {
3003
+        $ocs = $this->mockFormatShare();
3004
+
3005
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3006
+        $folder->method('getId')
3007
+            ->willReturn(42);
3008
+
3009
+        $share = Server::get(IManager::class)->newShare();
3010
+        $share->setPermissions(Constants::PERMISSION_ALL)
3011
+            ->setSharedBy($this->currentUser)
3012
+            ->setShareType(IShare::TYPE_LINK)
3013
+            ->setPassword('password')
3014
+            ->setNode($folder);
3015
+
3016
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3017
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3018
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3019
+
3020
+        $this->shareManager
3021
+            ->expects($this->any())
3022
+            ->method('updateShare')
3023
+            ->willReturnArgument(0);
3024
+
3025
+        $this->rootFolder->method('getUserFolder')
3026
+            ->with($this->currentUser)
3027
+            ->willReturn($userFolder);
3028
+
3029
+        $userFolder->method('getById')
3030
+            ->with(42)
3031
+            ->willReturn([$folder]);
3032
+
3033
+        $mountPoint = $this->createMock(IMountPoint::class);
3034
+        $folder->method('getMountPoint')
3035
+            ->willReturn($mountPoint);
3036
+        $mountPoint->method('getStorageRootId')
3037
+            ->willReturn(42);
3038
+
3039
+        $expected = new DataResponse([]);
3040
+        $result = $ocs->updateShare(42, $permissions, 'password', null, null, null);
3041
+
3042
+        $this->assertInstanceOf(get_class($expected), $result);
3043
+        $this->assertEquals($expected->getData(), $result->getData());
3044
+    }
3045
+
3046
+    public static function publicLinkInvalidPermissionsProvider1() {
3047
+        return [
3048
+            [Constants::PERMISSION_DELETE],
3049
+            [Constants::PERMISSION_UPDATE],
3050
+            [Constants::PERMISSION_SHARE],
3051
+        ];
3052
+    }
3053
+
3054
+    #[\PHPUnit\Framework\Attributes\DataProvider('publicLinkInvalidPermissionsProvider1')]
3055
+    public function testUpdateLinkShareSetInvalidCRUDPermissions1($permissions): void {
3056
+        $this->expectException(OCSBadRequestException::class);
3057
+        $this->expectExceptionMessage('Share must at least have READ or CREATE permissions');
3058
+
3059
+        $this->testUpdateLinkShareSetCRUDPermissions($permissions, null);
3060
+    }
3061
+
3062
+    public static function publicLinkInvalidPermissionsProvider2() {
3063
+        return [
3064
+            [Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE],
3065
+            [Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE],
3066
+        ];
3067
+    }
3068
+
3069
+    #[\PHPUnit\Framework\Attributes\DataProvider('publicLinkInvalidPermissionsProvider2')]
3070
+    public function testUpdateLinkShareSetInvalidCRUDPermissions2($permissions): void {
3071
+        $this->expectException(OCSBadRequestException::class);
3072
+        $this->expectExceptionMessage('Share must have READ permission if UPDATE or DELETE permission is set');
3073
+
3074
+        $this->testUpdateLinkShareSetCRUDPermissions($permissions);
3075
+    }
3076
+
3077
+    public function testUpdateLinkShareInvalidDate(): void {
3078
+        $this->expectException(OCSBadRequestException::class);
3079
+        $this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
3080
+
3081
+        $ocs = $this->mockFormatShare();
3082
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3083
+        $userFolder->method('getById')
3084
+            ->with(42)
3085
+            ->willReturn([$folder]);
3086
+        $this->rootFolder->method('getUserFolder')
3087
+            ->with($this->currentUser)
3088
+            ->willReturn($userFolder);
3089
+
3090
+        $folder->method('getId')
3091
+            ->willReturn(42);
3092
+
3093
+        $share = Server::get(IManager::class)->newShare();
3094
+        $share->setPermissions(Constants::PERMISSION_ALL)
3095
+            ->setSharedBy($this->currentUser)
3096
+            ->setShareType(IShare::TYPE_LINK)
3097
+            ->setNode($folder);
3098
+
3099
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3100
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3101
+
3102
+        $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-a');
3103
+    }
3104
+
3105
+    public static function publicUploadParamsProvider() {
3106
+        return [
3107
+            [null, 'true', null, 'password'],
3108
+            // legacy had no delete
3109
+            [
3110
+                Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE,
3111
+                'true', null, 'password'
3112
+            ],
3113
+            // correct
3114
+            [
3115
+                Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE,
3116
+                null, null, 'password'
3117
+            ],
3118
+        ];
3119
+    }
3120
+
3121
+    #[\PHPUnit\Framework\Attributes\DataProvider('publicUploadParamsProvider')]
3122
+    public function testUpdateLinkSharePublicUploadNotAllowed($permissions, $publicUpload, $expireDate, $password): void {
3123
+        $this->expectException(OCSForbiddenException::class);
3124
+        $this->expectExceptionMessage('Public upload disabled by the administrator');
3125
+
3126
+        $ocs = $this->mockFormatShare();
3127
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3128
+        $userFolder->method('getById')
3129
+            ->with(42)
3130
+            ->willReturn([$folder]);
3131
+        $this->rootFolder->method('getUserFolder')
3132
+            ->with($this->currentUser)
3133
+            ->willReturn($userFolder);
3134
+
3135
+        $folder->method('getId')->willReturn(42);
3136
+
3137
+        $share = Server::get(IManager::class)->newShare();
3138
+        $share->setPermissions(Constants::PERMISSION_ALL)
3139
+            ->setSharedBy($this->currentUser)
3140
+            ->setShareType(IShare::TYPE_LINK)
3141
+            ->setNode($folder);
3142
+
3143
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3144
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false);
3145
+
3146
+        $ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
3147
+    }
3148
+
3149
+
3150
+    public function testUpdateLinkSharePublicUploadOnFile(): void {
3151
+        $this->expectException(OCSBadRequestException::class);
3152
+        $this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
3153
+
3154
+        $ocs = $this->mockFormatShare();
3155
+
3156
+        $file = $this->getMockBuilder(File::class)->getMock();
3157
+        $file->method('getId')
3158
+            ->willReturn(42);
3159
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3160
+        $userFolder->method('getById')
3161
+            ->with(42)
3162
+            ->willReturn([$folder]);
3163
+        $this->rootFolder->method('getUserFolder')
3164
+            ->with($this->currentUser)
3165
+            ->willReturn($userFolder);
3166
+
3167
+        $share = Server::get(IManager::class)->newShare();
3168
+        $share->setPermissions(Constants::PERMISSION_ALL)
3169
+            ->setSharedBy($this->currentUser)
3170
+            ->setShareType(IShare::TYPE_LINK)
3171
+            ->setNode($file);
3172
+
3173
+        $this->shareManager
3174
+            ->method('getShareById')
3175
+            ->with('ocinternal:42')
3176
+            ->willReturn($share);
3177
+        $this->shareManager
3178
+            ->method('shareApiLinkAllowPublicUpload')
3179
+            ->willReturn(true);
3180
+        $this->shareManager
3181
+            ->method('updateShare')
3182
+            ->with($share)
3183
+            ->willThrowException(new \InvalidArgumentException('File shares cannot have create or delete permissions'));
3184
+
3185
+        $ocs->updateShare(42, null, 'password', null, 'true', '');
3186
+    }
3187
+
3188
+    public function testUpdateLinkSharePasswordDoesNotChangeOther(): void {
3189
+        $ocs = $this->mockFormatShare();
3190
+
3191
+        $date = new \DateTime('2000-01-01');
3192
+        $date->setTime(0, 0, 0);
3193
+
3194
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3195
+        $node->method('getId')->willReturn(42);
3196
+        $userFolder->method('getById')
3197
+            ->with(42)
3198
+            ->willReturn([$node]);
3199
+        $this->rootFolder->method('getUserFolder')
3200
+            ->with($this->currentUser)
3201
+            ->willReturn($userFolder);
3202
+        $share = $this->newShare();
3203
+        $share->setPermissions(Constants::PERMISSION_ALL)
3204
+            ->setSharedBy($this->currentUser)
3205
+            ->setShareType(IShare::TYPE_LINK)
3206
+            ->setPassword('password')
3207
+            ->setSendPasswordByTalk(true)
3208
+            ->setExpirationDate($date)
3209
+            ->setNote('note')
3210
+            ->setLabel('label')
3211
+            ->setHideDownload(true)
3212
+            ->setPermissions(Constants::PERMISSION_ALL)
3213
+            ->setNode($node);
3214
+
3215
+        $node->expects($this->once())
3216
+            ->method('lock')
3217
+            ->with(ILockingProvider::LOCK_SHARED);
3218
+
3219
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3220
+
3221
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3222
+            $this->callback(function (IShare $share) use ($date) {
3223
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3224
+                && $share->getPassword() === 'newpassword'
3225
+                && $share->getSendPasswordByTalk() === true
3226
+                && $share->getExpirationDate() === $date
3227
+                && $share->getNote() === 'note'
3228
+                && $share->getLabel() === 'label'
3229
+                && $share->getHideDownload() === true;
3230
+            })
3231
+        )->willReturnArgument(0);
3232
+
3233
+        $expected = new DataResponse([]);
3234
+        $result = $ocs->updateShare(42, null, 'newpassword', null, null, null, null, null, null);
3235
+
3236
+        $this->assertInstanceOf(get_class($expected), $result);
3237
+        $this->assertEquals($expected->getData(), $result->getData());
3238
+    }
3239
+
3240
+    public function testUpdateLinkShareSendPasswordByTalkDoesNotChangeOther(): void {
3241
+        $ocs = $this->mockFormatShare();
3242
+
3243
+        $date = new \DateTime('2000-01-01');
3244
+        $date->setTime(0, 0, 0);
3245
+
3246
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3247
+        $userFolder->method('getById')
3248
+            ->with(42)
3249
+            ->willReturn([$node]);
3250
+        $this->rootFolder->method('getUserFolder')
3251
+            ->with($this->currentUser)
3252
+            ->willReturn($userFolder);
3253
+        $node->method('getId')->willReturn(42);
3254
+        $share = $this->newShare();
3255
+        $share->setPermissions(Constants::PERMISSION_ALL)
3256
+            ->setSharedBy($this->currentUser)
3257
+            ->setShareType(IShare::TYPE_LINK)
3258
+            ->setPassword('password')
3259
+            ->setSendPasswordByTalk(false)
3260
+            ->setExpirationDate($date)
3261
+            ->setNote('note')
3262
+            ->setLabel('label')
3263
+            ->setHideDownload(true)
3264
+            ->setPermissions(Constants::PERMISSION_ALL)
3265
+            ->setNode($node);
3266
+
3267
+        $node->expects($this->once())
3268
+            ->method('lock')
3269
+            ->with(ILockingProvider::LOCK_SHARED);
3270
+
3271
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3272
+
3273
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3274
+
3275
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3276
+            $this->callback(function (IShare $share) use ($date) {
3277
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3278
+                && $share->getPassword() === 'password'
3279
+                && $share->getSendPasswordByTalk() === true
3280
+                && $share->getExpirationDate() === $date
3281
+                && $share->getNote() === 'note'
3282
+                && $share->getLabel() === 'label'
3283
+                && $share->getHideDownload() === true;
3284
+            })
3285
+        )->willReturnArgument(0);
3286
+
3287
+        $expected = new DataResponse([]);
3288
+        $result = $ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3289
+
3290
+        $this->assertInstanceOf(get_class($expected), $result);
3291
+        $this->assertEquals($expected->getData(), $result->getData());
3292
+    }
3293
+
3294
+
3295
+    public function testUpdateLinkShareSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3296
+        $this->expectException(OCSForbiddenException::class);
3297
+        $this->expectExceptionMessage('"Sending the password by Nextcloud Talk" for sharing a file or folder failed because Nextcloud Talk is not enabled.');
3298
+
3299
+        $ocs = $this->mockFormatShare();
3300
+
3301
+        $date = new \DateTime('2000-01-01');
3302
+        $date->setTime(0, 0, 0);
3303
+
3304
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3305
+        $userFolder->method('getById')
3306
+            ->with(42)
3307
+            ->willReturn([$node]);
3308
+        $this->rootFolder->method('getUserFolder')
3309
+            ->with($this->currentUser)
3310
+            ->willReturn($userFolder);
3311
+        $node->method('getId')->willReturn(42);
3312
+        $share = $this->newShare();
3313
+        $share->setPermissions(Constants::PERMISSION_ALL)
3314
+            ->setSharedBy($this->currentUser)
3315
+            ->setShareType(IShare::TYPE_LINK)
3316
+            ->setPassword('password')
3317
+            ->setSendPasswordByTalk(false)
3318
+            ->setExpirationDate($date)
3319
+            ->setNote('note')
3320
+            ->setLabel('label')
3321
+            ->setHideDownload(true)
3322
+            ->setPermissions(Constants::PERMISSION_ALL)
3323
+            ->setNode($node);
3324
+
3325
+        $node->expects($this->once())
3326
+            ->method('lock')
3327
+            ->with(ILockingProvider::LOCK_SHARED);
3328
+
3329
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3330
+
3331
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3332
+
3333
+        $this->shareManager->expects($this->never())->method('updateShare');
3334
+
3335
+        $ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3336
+    }
3337
+
3338
+    public function testUpdateLinkShareDoNotSendPasswordByTalkDoesNotChangeOther(): void {
3339
+        $ocs = $this->mockFormatShare();
3340
+
3341
+        $date = new \DateTime('2000-01-01');
3342
+        $date->setTime(0, 0, 0);
3343
+
3344
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3345
+        $userFolder->method('getById')
3346
+            ->with(42)
3347
+            ->willReturn([$node]);
3348
+        $this->rootFolder->method('getUserFolder')
3349
+            ->with($this->currentUser)
3350
+            ->willReturn($userFolder);
3351
+        $node->method('getId')->willReturn(42);
3352
+        $share = $this->newShare();
3353
+        $share->setPermissions(Constants::PERMISSION_ALL)
3354
+            ->setSharedBy($this->currentUser)
3355
+            ->setShareType(IShare::TYPE_LINK)
3356
+            ->setPassword('password')
3357
+            ->setSendPasswordByTalk(true)
3358
+            ->setExpirationDate($date)
3359
+            ->setNote('note')
3360
+            ->setLabel('label')
3361
+            ->setHideDownload(true)
3362
+            ->setPermissions(Constants::PERMISSION_ALL)
3363
+            ->setNode($node);
3364
+
3365
+        $node->expects($this->once())
3366
+            ->method('lock')
3367
+            ->with(ILockingProvider::LOCK_SHARED);
3368
+
3369
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3370
+
3371
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3372
+
3373
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3374
+            $this->callback(function (IShare $share) use ($date) {
3375
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3376
+                && $share->getPassword() === 'password'
3377
+                && $share->getSendPasswordByTalk() === false
3378
+                && $share->getExpirationDate() === $date
3379
+                && $share->getNote() === 'note'
3380
+                && $share->getLabel() === 'label'
3381
+                && $share->getHideDownload() === true;
3382
+            })
3383
+        )->willReturnArgument(0);
3384
+
3385
+        $expected = new DataResponse([]);
3386
+        $result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3387
+
3388
+        $this->assertInstanceOf(get_class($expected), $result);
3389
+        $this->assertEquals($expected->getData(), $result->getData());
3390
+    }
3391
+
3392
+    public function testUpdateLinkShareDoNotSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3393
+        $ocs = $this->mockFormatShare();
3394
+
3395
+        $date = new \DateTime('2000-01-01');
3396
+        $date->setTime(0, 0, 0);
3397
+
3398
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3399
+        $node->method('getId')
3400
+            ->willReturn(42);
3401
+
3402
+        $share = $this->newShare();
3403
+        $share->setPermissions(Constants::PERMISSION_ALL)
3404
+            ->setSharedBy($this->currentUser)
3405
+            ->setShareType(IShare::TYPE_LINK)
3406
+            ->setPassword('password')
3407
+            ->setSendPasswordByTalk(true)
3408
+            ->setExpirationDate($date)
3409
+            ->setNote('note')
3410
+            ->setLabel('label')
3411
+            ->setHideDownload(true)
3412
+            ->setPermissions(Constants::PERMISSION_ALL)
3413
+            ->setNode($node);
3414
+
3415
+        $node->expects($this->once())
3416
+            ->method('lock')
3417
+            ->with(ILockingProvider::LOCK_SHARED);
3418
+
3419
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3420
+
3421
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3422
+
3423
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3424
+            $this->callback(function (IShare $share) use ($date) {
3425
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3426
+                && $share->getPassword() === 'password'
3427
+                && $share->getSendPasswordByTalk() === false
3428
+                && $share->getExpirationDate() === $date
3429
+                && $share->getNote() === 'note'
3430
+                && $share->getLabel() === 'label'
3431
+                && $share->getHideDownload() === true;
3432
+            })
3433
+        )->willReturnArgument(0);
3434
+
3435
+        $this->rootFolder->method('getUserFolder')
3436
+            ->with($this->currentUser)
3437
+            ->willReturn($userFolder);
3438
+
3439
+        $userFolder->method('getById')
3440
+            ->with(42)
3441
+            ->willReturn([$node]);
3442
+
3443
+        $mountPoint = $this->createMock(IMountPoint::class);
3444
+        $node->method('getMountPoint')
3445
+            ->willReturn($mountPoint);
3446
+        $mountPoint->method('getStorageRootId')
3447
+            ->willReturn(42);
3448
+
3449
+        $mountPoint = $this->createMock(IMountPoint::class);
3450
+        $node->method('getMountPoint')
3451
+            ->willReturn($mountPoint);
3452
+        $mountPoint->method('getStorageRootId')
3453
+            ->willReturn(42);
3454
+
3455
+        $expected = new DataResponse([]);
3456
+        $result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3457
+
3458
+        $this->assertInstanceOf(get_class($expected), $result);
3459
+        $this->assertEquals($expected->getData(), $result->getData());
3460
+    }
3461
+
3462
+    public function testUpdateLinkShareExpireDateDoesNotChangeOther(): void {
3463
+        $ocs = $this->mockFormatShare();
3464
+
3465
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3466
+        $node->method('getId')
3467
+            ->willReturn(42);
3468
+
3469
+        $share = $this->newShare();
3470
+        $share->setPermissions(Constants::PERMISSION_ALL)
3471
+            ->setSharedBy($this->currentUser)
3472
+            ->setShareType(IShare::TYPE_LINK)
3473
+            ->setPassword('password')
3474
+            ->setSendPasswordByTalk(true)
3475
+            ->setExpirationDate(new \DateTime())
3476
+            ->setNote('note')
3477
+            ->setLabel('label')
3478
+            ->setHideDownload(true)
3479
+            ->setPermissions(Constants::PERMISSION_ALL)
3480
+            ->setNode($node);
3481
+
3482
+        $node->expects($this->once())
3483
+            ->method('lock')
3484
+            ->with(ILockingProvider::LOCK_SHARED);
3485
+
3486
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3487
+
3488
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3489
+            $this->callback(function (IShare $share) {
3490
+                $date = new \DateTime('2010-12-23');
3491
+                $date->setTime(0, 0, 0);
3492
+
3493
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3494
+                && $share->getPassword() === 'password'
3495
+                && $share->getSendPasswordByTalk() === true
3496
+                && $share->getExpirationDate() == $date
3497
+                && $share->getNote() === 'note'
3498
+                && $share->getLabel() === 'label'
3499
+                && $share->getHideDownload() === true;
3500
+            })
3501
+        )->willReturnArgument(0);
3502
+
3503
+        $this->rootFolder->method('getUserFolder')
3504
+            ->with($this->currentUser)
3505
+            ->willReturn($userFolder);
3506
+
3507
+        $userFolder->method('getById')
3508
+            ->with(42)
3509
+            ->willReturn([$node]);
3510
+
3511
+        $mountPoint = $this->createMock(IMountPoint::class);
3512
+        $node->method('getMountPoint')
3513
+            ->willReturn($mountPoint);
3514
+        $mountPoint->method('getStorageRootId')
3515
+            ->willReturn(42);
3516
+
3517
+        $expected = new DataResponse([]);
3518
+        $result = $ocs->updateShare(42, null, null, null, null, '2010-12-23', null, null, null);
3519
+
3520
+        $this->assertInstanceOf(get_class($expected), $result);
3521
+        $this->assertEquals($expected->getData(), $result->getData());
3522
+    }
3523
+
3524
+    public function testUpdateLinkSharePublicUploadDoesNotChangeOther(): void {
3525
+        $ocs = $this->mockFormatShare();
3526
+
3527
+        $date = new \DateTime('2000-01-01');
3528
+
3529
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3530
+        $folder->method('getId')
3531
+            ->willReturn(42);
3532
+
3533
+        $share = Server::get(IManager::class)->newShare();
3534
+        $share->setPermissions(Constants::PERMISSION_ALL)
3535
+            ->setSharedBy($this->currentUser)
3536
+            ->setShareType(IShare::TYPE_LINK)
3537
+            ->setPassword('password')
3538
+            ->setSendPasswordByTalk(true)
3539
+            ->setExpirationDate($date)
3540
+            ->setNote('note')
3541
+            ->setLabel('label')
3542
+            ->setHideDownload(true)
3543
+            ->setPermissions(Constants::PERMISSION_ALL)
3544
+            ->setNode($folder);
3545
+
3546
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3547
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3548
+
3549
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3550
+            $this->callback(function (IShare $share) use ($date) {
3551
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3552
+                && $share->getPassword() === 'password'
3553
+                && $share->getSendPasswordByTalk() === true
3554
+                && $share->getExpirationDate() === $date
3555
+                && $share->getNote() === 'note'
3556
+                && $share->getLabel() === 'label'
3557
+                && $share->getHideDownload() === true;
3558
+            })
3559
+        )->willReturnArgument(0);
3560
+
3561
+        $this->shareManager->method('getSharedWith')
3562
+            ->willReturn([]);
3563
+
3564
+        $this->rootFolder->method('getUserFolder')
3565
+            ->with($this->currentUser)
3566
+            ->willReturn($userFolder);
3567
+
3568
+        $userFolder->method('getById')
3569
+            ->with(42)
3570
+            ->willReturn([$folder]);
3571
+
3572
+        $mountPoint = $this->createMock(IMountPoint::class);
3573
+        $folder->method('getMountPoint')
3574
+            ->willReturn($mountPoint);
3575
+        $mountPoint->method('getStorageRootId')
3576
+            ->willReturn(42);
3577
+
3578
+        $expected = new DataResponse([]);
3579
+        $result = $ocs->updateShare(42, null, null, null, 'true', null, null, null, null);
3580
+
3581
+        $this->assertInstanceOf(get_class($expected), $result);
3582
+        $this->assertEquals($expected->getData(), $result->getData());
3583
+    }
3584
+
3585
+    public function testUpdateLinkSharePermissions(): void {
3586
+        $ocs = $this->mockFormatShare();
3587
+
3588
+        $date = new \DateTime('2000-01-01');
3589
+
3590
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3591
+        $folder->method('getId')
3592
+            ->willReturn(42);
3593
+
3594
+        $share = Server::get(IManager::class)->newShare();
3595
+        $share->setPermissions(Constants::PERMISSION_ALL)
3596
+            ->setSharedBy($this->currentUser)
3597
+            ->setShareType(IShare::TYPE_LINK)
3598
+            ->setPassword('password')
3599
+            ->setSendPasswordByTalk(true)
3600
+            ->setExpirationDate($date)
3601
+            ->setNote('note')
3602
+            ->setLabel('label')
3603
+            ->setHideDownload(true)
3604
+            ->setPermissions(Constants::PERMISSION_ALL)
3605
+            ->setNode($folder);
3606
+
3607
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3608
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3609
+
3610
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3611
+            $this->callback(function (IShare $share) use ($date): bool {
3612
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3613
+                && $share->getPassword() === 'password'
3614
+                && $share->getSendPasswordByTalk() === true
3615
+                && $share->getExpirationDate() === $date
3616
+                && $share->getNote() === 'note'
3617
+                && $share->getLabel() === 'label'
3618
+                && $share->getHideDownload() === true;
3619
+            })
3620
+        )->willReturnArgument(0);
3621
+
3622
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3623
+
3624
+        $this->rootFolder->method('getUserFolder')
3625
+            ->with($this->currentUser)
3626
+            ->willReturn($userFolder);
3627
+
3628
+        $userFolder->method('getById')
3629
+            ->with(42)
3630
+            ->willReturn([$folder]);
3631
+
3632
+        $mountPoint = $this->createMock(IMountPoint::class);
3633
+        $folder->method('getMountPoint')
3634
+            ->willReturn($mountPoint);
3635
+        $mountPoint->method('getStorageRootId')
3636
+            ->willReturn(42);
3637
+
3638
+        $expected = new DataResponse([]);
3639
+        $result = $ocs->updateShare(42, 7, null, null, 'true', null, null, null, null);
3640
+
3641
+        $this->assertInstanceOf(get_class($expected), $result);
3642
+        $this->assertEquals($expected->getData(), $result->getData());
3643
+    }
3644
+
3645
+    public function testUpdateLinkSharePermissionsShare(): void {
3646
+        $ocs = $this->mockFormatShare();
3647
+
3648
+        $date = new \DateTime('2000-01-01');
3649
+
3650
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3651
+        $folder->method('getId')
3652
+            ->willReturn(42);
3653
+
3654
+        $share = Server::get(IManager::class)->newShare();
3655
+        $share->setPermissions(Constants::PERMISSION_ALL)
3656
+            ->setSharedBy($this->currentUser)
3657
+            ->setShareType(IShare::TYPE_LINK)
3658
+            ->setPassword('password')
3659
+            ->setSendPasswordByTalk(true)
3660
+            ->setExpirationDate($date)
3661
+            ->setNote('note')
3662
+            ->setLabel('label')
3663
+            ->setHideDownload(true)
3664
+            ->setPermissions(Constants::PERMISSION_READ)
3665
+            ->setNode($folder);
3666
+
3667
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3668
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3669
+
3670
+        $this->shareManager->expects($this->once())
3671
+            ->method('updateShare')
3672
+            ->with(
3673
+                $this->callback(function (IShare $share) use ($date) {
3674
+                    return $share->getPermissions() === Constants::PERMISSION_ALL
3675
+                        && $share->getPassword() === 'password'
3676
+                        && $share->getSendPasswordByTalk() === true
3677
+                        && $share->getExpirationDate() === $date
3678
+                        && $share->getNote() === 'note'
3679
+                        && $share->getLabel() === 'label'
3680
+                        && $share->getHideDownload() === true;
3681
+                })
3682
+            )->willReturnArgument(0);
3683
+
3684
+        $this->rootFolder->method('getUserFolder')
3685
+            ->with($this->currentUser)
3686
+            ->willReturn($userFolder);
3687
+
3688
+        $userFolder->method('getById')
3689
+            ->with(42)
3690
+            ->willReturn([$folder]);
3691
+
3692
+        $mountPoint = $this->createMock(IMountPoint::class);
3693
+        $folder->method('getMountPoint')
3694
+            ->willReturn($mountPoint);
3695
+        $mountPoint->method('getStorageRootId')
3696
+            ->willReturn(42);
3697
+
3698
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3699
+
3700
+        $expected = new DataResponse([]);
3701
+        $result = $ocs->updateShare(42, Constants::PERMISSION_ALL, null, null, null, null, null, null, null);
3702
+
3703
+        $this->assertInstanceOf(get_class($expected), $result);
3704
+        $this->assertEquals($expected->getData(), $result->getData());
3705
+    }
3706
+
3707
+    public function testUpdateOtherPermissions(): void {
3708
+        $ocs = $this->mockFormatShare();
3709
+
3710
+        [$userFolder, $file] = $this->getNonSharedUserFolder();
3711
+        $file->method('getId')
3712
+            ->willReturn(42);
3713
+
3714
+        $share = Server::get(IManager::class)->newShare();
3715
+        $share->setPermissions(Constants::PERMISSION_ALL)
3716
+            ->setSharedBy($this->currentUser)
3717
+            ->setShareType(IShare::TYPE_USER)
3718
+            ->setNode($file);
3719
+
3720
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3721
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3722
+
3723
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3724
+            $this->callback(function (IShare $share) {
3725
+                return $share->getPermissions() === Constants::PERMISSION_ALL;
3726
+            })
3727
+        )->willReturnArgument(0);
3728
+
3729
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3730
+
3731
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3732
+        $this->rootFolder->method('getUserFolder')
3733
+            ->with($this->currentUser)
3734
+            ->willReturn($userFolder);
3735
+
3736
+        $userFolder->method('getById')
3737
+            ->with(42)
3738
+            ->willReturn([$file]);
3739
+
3740
+        $mountPoint = $this->createMock(IMountPoint::class);
3741
+        $file->method('getMountPoint')
3742
+            ->willReturn($mountPoint);
3743
+        $mountPoint->method('getStorageRootId')
3744
+            ->willReturn(42);
3745
+
3746
+        $expected = new DataResponse([]);
3747
+        $result = $ocs->updateShare(42, 31, null, null, null, null);
3748
+
3749
+        $this->assertInstanceOf(get_class($expected), $result);
3750
+        $this->assertEquals($expected->getData(), $result->getData());
3751
+    }
3752
+
3753
+    public function testUpdateShareCannotIncreasePermissions(): void {
3754
+        $ocs = $this->mockFormatShare();
3755
+
3756
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3757
+        $folder->method('getId')
3758
+            ->willReturn(42);
3759
+
3760
+        $share = Server::get(IManager::class)->newShare();
3761
+        $share
3762
+            ->setId(42)
3763
+            ->setSharedBy($this->currentUser)
3764
+            ->setShareOwner('anotheruser')
3765
+            ->setShareType(IShare::TYPE_GROUP)
3766
+            ->setSharedWith('group1')
3767
+            ->setPermissions(Constants::PERMISSION_READ)
3768
+            ->setNode($folder);
3769
+
3770
+        // note: updateShare will modify the received instance but getSharedWith will reread from the database,
3771
+        // so their values will be different
3772
+        $incomingShare = Server::get(IManager::class)->newShare();
3773
+        $incomingShare
3774
+            ->setId(42)
3775
+            ->setSharedBy($this->currentUser)
3776
+            ->setShareOwner('anotheruser')
3777
+            ->setShareType(IShare::TYPE_GROUP)
3778
+            ->setSharedWith('group1')
3779
+            ->setPermissions(Constants::PERMISSION_READ)
3780
+            ->setNode($folder);
3781
+
3782
+        $this->request
3783
+            ->method('getParam')
3784
+            ->willReturnMap([
3785
+                ['permissions', null, '31'],
3786
+            ]);
3787
+
3788
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3789
+
3790
+        $this->shareManager->expects($this->any())
3791
+            ->method('getSharedWith')
3792
+            ->willReturnMap([
3793
+                ['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3794
+                ['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]],
3795
+                ['currentUser', IShare::TYPE_ROOM, $share->getNode(), -1, 0, []]
3796
+            ]);
3797
+
3798
+        $this->rootFolder->method('getUserFolder')
3799
+            ->with($this->currentUser)
3800
+            ->willReturn($userFolder);
3801
+
3802
+        $userFolder->method('getById')
3803
+            ->with(42)
3804
+            ->willReturn([$folder]);
3805
+        $userFolder->method('getFirstNodeById')
3806
+            ->with(42)
3807
+            ->willReturn($folder);
3808
+
3809
+        $mountPoint = $this->createMock(IMountPoint::class);
3810
+        $folder->method('getMountPoint')
3811
+            ->willReturn($mountPoint);
3812
+        $mountPoint->method('getStorageRootId')
3813
+            ->willReturn(42);
3814
+
3815
+        $this->shareManager->expects($this->once())
3816
+            ->method('updateShare')
3817
+            ->with($share)
3818
+            ->willThrowException(new GenericShareException('Cannot increase permissions of path/file', 'Cannot increase permissions of path/file', 404));
3819
+
3820
+        try {
3821
+            $ocs->updateShare(42, 31);
3822
+            $this->fail();
3823
+        } catch (OCSException $e) {
3824
+            $this->assertEquals('Cannot increase permissions of path/file', $e->getMessage());
3825
+        }
3826
+    }
3827
+
3828
+    public function testUpdateShareCanIncreasePermissionsIfOwner(): void {
3829
+        $ocs = $this->mockFormatShare();
3830
+
3831
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3832
+        $folder->method('getId')
3833
+            ->willReturn(42);
3834
+
3835
+        $share = Server::get(IManager::class)->newShare();
3836
+        $share
3837
+            ->setId(42)
3838
+            ->setSharedBy($this->currentUser)
3839
+            ->setShareOwner($this->currentUser)
3840
+            ->setShareType(IShare::TYPE_GROUP)
3841
+            ->setSharedWith('group1')
3842
+            ->setPermissions(Constants::PERMISSION_READ)
3843
+            ->setNode($folder);
3844
+
3845
+        // note: updateShare will modify the received instance but getSharedWith will reread from the database,
3846
+        // so their values will be different
3847
+        $incomingShare = Server::get(IManager::class)->newShare();
3848
+        $incomingShare
3849
+            ->setId(42)
3850
+            ->setSharedBy($this->currentUser)
3851
+            ->setShareOwner($this->currentUser)
3852
+            ->setShareType(IShare::TYPE_GROUP)
3853
+            ->setSharedWith('group1')
3854
+            ->setPermissions(Constants::PERMISSION_READ)
3855
+            ->setNode($folder);
3856
+
3857
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3858
+
3859
+        $this->shareManager->expects($this->any())
3860
+            ->method('getSharedWith')
3861
+            ->willReturnMap([
3862
+                ['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3863
+                ['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]]
3864
+            ]);
3865
+
3866
+        $this->shareManager->expects($this->once())
3867
+            ->method('updateShare')
3868
+            ->with($share)
3869
+            ->willReturn($share);
3870
+
3871
+        $this->rootFolder->method('getUserFolder')
3872
+            ->with($this->currentUser)
3873
+            ->willReturn($userFolder);
3874
+
3875
+        $userFolder->method('getById')
3876
+            ->with(42)
3877
+            ->willReturn([$folder]);
3878
+
3879
+        $mountPoint = $this->createMock(IMountPoint::class);
3880
+        $folder->method('getMountPoint')
3881
+            ->willReturn($mountPoint);
3882
+        $mountPoint->method('getStorageRootId')
3883
+            ->willReturn(42);
3884
+
3885
+        $result = $ocs->updateShare(42, 31);
3886
+        $this->assertInstanceOf(DataResponse::class, $result);
3887
+    }
3888
+
3889
+    public function testUpdateShareOwnerless(): void {
3890
+        $ocs = $this->mockFormatShare();
3891
+
3892
+        $mount = $this->createMock(IShareOwnerlessMount::class);
3893
+
3894
+        $file = $this->createMock(File::class);
3895
+        $file
3896
+            ->expects($this->exactly(2))
3897
+            ->method('getPermissions')
3898
+            ->willReturn(Constants::PERMISSION_SHARE);
3899
+        $file
3900
+            ->expects($this->once())
3901
+            ->method('getMountPoint')
3902
+            ->willReturn($mount);
3903
+
3904
+        $userFolder = $this->createMock(Folder::class);
3905
+        $userFolder->method('getById')
3906
+            ->with(2)
3907
+            ->willReturn([$file]);
3908
+        $userFolder->method('getFirstNodeById')
3909
+            ->with(2)
3910
+            ->willReturn($file);
3911
+
3912
+        $this->rootFolder
3913
+            ->method('getUserFolder')
3914
+            ->with($this->currentUser)
3915
+            ->willReturn($userFolder);
3916
+
3917
+        $share = $this->createMock(IShare::class);
3918
+        $share
3919
+            ->expects($this->once())
3920
+            ->method('getNode')
3921
+            ->willReturn($file);
3922
+        $share
3923
+            ->expects($this->exactly(2))
3924
+            ->method('getNodeId')
3925
+            ->willReturn(2);
3926
+        $share
3927
+            ->expects($this->exactly(2))
3928
+            ->method('getPermissions')
3929
+            ->willReturn(Constants::PERMISSION_SHARE);
3930
+
3931
+        $this->shareManager
3932
+            ->expects($this->once())
3933
+            ->method('getShareById')
3934
+            ->with('ocinternal:1', $this->currentUser)
3935
+            ->willReturn($share);
3936
+
3937
+        $this->shareManager
3938
+            ->expects($this->once())
3939
+            ->method('updateShare')
3940
+            ->with($share)
3941
+            ->willReturn($share);
3942
+
3943
+        $result = $ocs->updateShare(1, Constants::PERMISSION_ALL);
3944
+        $this->assertInstanceOf(DataResponse::class, $result);
3945
+    }
3946
+
3947
+    public function dataFormatShare() {
3948
+        $file = $this->getMockBuilder(File::class)->getMock();
3949
+        $folder = $this->getMockBuilder(Folder::class)->getMock();
3950
+        $parent = $this->getMockBuilder(Folder::class)->getMock();
3951
+        $fileWithPreview = $this->getMockBuilder(File::class)->getMock();
3952
+
3953
+        $file->method('getMimeType')->willReturn('myMimeType');
3954
+        $folder->method('getMimeType')->willReturn('myFolderMimeType');
3955
+        $fileWithPreview->method('getMimeType')->willReturn('mimeWithPreview');
3956
+
3957
+        $mountPoint = $this->createMock(IMountPoint::class);
3958
+        $mountPoint->method('getMountType')->willReturn('');
3959
+        $file->method('getMountPoint')->willReturn($mountPoint);
3960
+        $folder->method('getMountPoint')->willReturn($mountPoint);
3961
+        $fileWithPreview->method('getMountPoint')->willReturn($mountPoint);
3962
+
3963
+        $file->method('getPath')->willReturn('file');
3964
+        $folder->method('getPath')->willReturn('folder');
3965
+        $fileWithPreview->method('getPath')->willReturn('fileWithPreview');
3966
+
3967
+        $parent->method('getId')->willReturn(1);
3968
+        $folder->method('getId')->willReturn(2);
3969
+        $file->method('getId')->willReturn(3);
3970
+        $fileWithPreview->method('getId')->willReturn(4);
3971
+
3972
+        $file->method('getParent')->willReturn($parent);
3973
+        $folder->method('getParent')->willReturn($parent);
3974
+        $fileWithPreview->method('getParent')->willReturn($parent);
3975
+
3976
+        $file->method('getSize')->willReturn(123456);
3977
+        $folder->method('getSize')->willReturn(123456);
3978
+        $fileWithPreview->method('getSize')->willReturn(123456);
3979
+        $file->method('getMTime')->willReturn(1234567890);
3980
+        $folder->method('getMTime')->willReturn(1234567890);
3981
+        $fileWithPreview->method('getMTime')->willReturn(1234567890);
3982
+
3983
+        $cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
3984
+        $cache->method('getNumericStorageId')->willReturn(100);
3985
+        $storage = $this->createMock(IStorage::class);
3986
+        $storage->method('getId')->willReturn('storageId');
3987
+        $storage->method('getCache')->willReturn($cache);
3988
+
3989
+        $file->method('getStorage')->willReturn($storage);
3990
+        $folder->method('getStorage')->willReturn($storage);
3991
+        $fileWithPreview->method('getStorage')->willReturn($storage);
3992
+
3993
+
3994
+        $mountPoint = $this->getMockBuilder(IMountPoint::class)->getMock();
3995
+        $mountPoint->method('getMountType')->willReturn('');
3996
+        $file->method('getMountPoint')->willReturn($mountPoint);
3997
+        $folder->method('getMountPoint')->willReturn($mountPoint);
3998
+
3999
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
4000
+        $owner->method('getDisplayName')->willReturn('ownerDN');
4001
+        $initiator = $this->getMockBuilder(IUser::class)->getMock();
4002
+        $initiator->method('getDisplayName')->willReturn('initiatorDN');
4003
+        $recipient = $this->getMockBuilder(IUser::class)->getMock();
4004
+        $recipient->method('getDisplayName')->willReturn('recipientDN');
4005
+        $recipient->method('getSystemEMailAddress')->willReturn('recipient');
4006
+        [$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
4007
+
4008
+        $result = [];
4009
+
4010
+        $share = Server::get(IManager::class)->newShare();
4011
+        $share->setShareType(IShare::TYPE_USER)
4012
+            ->setSharedWith('recipient')
4013
+            ->setSharedBy('initiator')
4014
+            ->setShareOwner('owner')
4015
+            ->setPermissions(Constants::PERMISSION_READ)
4016
+            ->setAttributes($shareAttributes)
4017
+            ->setNode($file)
4018
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4019
+            ->setTarget('myTarget')
4020
+            ->setNote('personal note')
4021
+            ->setId(42);
4022
+
4023
+        // User backend down
4024
+        $result[] = [
4025
+            [
4026
+                'id' => '42',
4027
+                'share_type' => IShare::TYPE_USER,
4028
+                'uid_owner' => 'initiator',
4029
+                'displayname_owner' => 'initiator',
4030
+                'permissions' => 1,
4031
+                'attributes' => $shareAttributesReturnJson,
4032
+                'stime' => 946684862,
4033
+                'parent' => null,
4034
+                'expiration' => null,
4035
+                'token' => null,
4036
+                'uid_file_owner' => 'owner',
4037
+                'displayname_file_owner' => 'owner',
4038
+                'path' => 'file',
4039
+                'item_type' => 'file',
4040
+                'storage_id' => 'storageId',
4041
+                'storage' => 100,
4042
+                'item_source' => 3,
4043
+                'file_source' => 3,
4044
+                'file_parent' => 1,
4045
+                'file_target' => 'myTarget',
4046
+                'share_with' => 'recipient',
4047
+                'share_with_displayname' => 'recipient',
4048
+                'share_with_displayname_unique' => 'recipient',
4049
+                'note' => 'personal note',
4050
+                'label' => '',
4051
+                'mail_send' => 0,
4052
+                'mimetype' => 'myMimeType',
4053
+                'has_preview' => false,
4054
+                'hide_download' => 0,
4055
+                'can_edit' => false,
4056
+                'can_delete' => false,
4057
+                'item_size' => 123456,
4058
+                'item_mtime' => 1234567890,
4059
+                'is-mount-root' => false,
4060
+                'mount-type' => '',
4061
+                'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4062
+                'item_permissions' => 1,
4063
+            ], $share, [], false
4064
+        ];
4065
+        // User backend up
4066
+        $result[] = [
4067
+            [
4068
+                'id' => '42',
4069
+                'share_type' => IShare::TYPE_USER,
4070
+                'uid_owner' => 'initiator',
4071
+                'displayname_owner' => 'initiatorDN',
4072
+                'permissions' => 1,
4073
+                'attributes' => $shareAttributesReturnJson,
4074
+                'stime' => 946684862,
4075
+                'parent' => null,
4076
+                'expiration' => null,
4077
+                'token' => null,
4078
+                'uid_file_owner' => 'owner',
4079
+                'displayname_file_owner' => 'ownerDN',
4080
+                'note' => 'personal note',
4081
+                'label' => '',
4082
+                'path' => 'file',
4083
+                'item_type' => 'file',
4084
+                'storage_id' => 'storageId',
4085
+                'storage' => 100,
4086
+                'item_source' => 3,
4087
+                'file_source' => 3,
4088
+                'file_parent' => 1,
4089
+                'file_target' => 'myTarget',
4090
+                'share_with' => 'recipient',
4091
+                'share_with_displayname' => 'recipientDN',
4092
+                'share_with_displayname_unique' => 'recipient',
4093
+                'mail_send' => 0,
4094
+                'mimetype' => 'myMimeType',
4095
+                'has_preview' => false,
4096
+                'hide_download' => 0,
4097
+                'can_edit' => false,
4098
+                'can_delete' => false,
4099
+                'item_size' => 123456,
4100
+                'item_mtime' => 1234567890,
4101
+                'is-mount-root' => false,
4102
+                'mount-type' => '',
4103
+                'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4104
+                'item_permissions' => 1,
4105
+            ], $share, [
4106
+                ['owner', $owner],
4107
+                ['initiator', $initiator],
4108
+                ['recipient', $recipient],
4109
+            ], false
4110
+        ];
4111
+
4112
+        $share = Server::get(IManager::class)->newShare();
4113
+        $share->setShareType(IShare::TYPE_USER)
4114
+            ->setSharedWith('recipient')
4115
+            ->setSharedBy('initiator')
4116
+            ->setShareOwner('owner')
4117
+            ->setPermissions(Constants::PERMISSION_READ)
4118
+            ->setNode($file)
4119
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4120
+            ->setTarget('myTarget')
4121
+            ->setNote('personal note')
4122
+            ->setId(42);
4123
+        // User backend down
4124
+        $result[] = [
4125
+            [
4126
+                'id' => '42',
4127
+                'share_type' => IShare::TYPE_USER,
4128
+                'uid_owner' => 'initiator',
4129
+                'displayname_owner' => 'initiator',
4130
+                'permissions' => 1,
4131
+                'attributes' => null,
4132
+                'stime' => 946684862,
4133
+                'parent' => null,
4134
+                'expiration' => null,
4135
+                'token' => null,
4136
+                'uid_file_owner' => 'owner',
4137
+                'displayname_file_owner' => 'owner',
4138
+                'note' => 'personal note',
4139
+                'label' => '',
4140
+                'path' => 'file',
4141
+                'item_type' => 'file',
4142
+                'storage_id' => 'storageId',
4143
+                'storage' => 100,
4144
+                'item_source' => 3,
4145
+                'file_source' => 3,
4146
+                'file_parent' => 1,
4147
+                'file_target' => 'myTarget',
4148
+                'share_with' => 'recipient',
4149
+                'share_with_displayname' => 'recipient',
4150
+                'share_with_displayname_unique' => 'recipient',
4151
+                'mail_send' => 0,
4152
+                'mimetype' => 'myMimeType',
4153
+                'has_preview' => false,
4154
+                'hide_download' => 0,
4155
+                'can_edit' => false,
4156
+                'can_delete' => false,
4157
+                'item_size' => 123456,
4158
+                'item_mtime' => 1234567890,
4159
+                'is-mount-root' => false,
4160
+                'mount-type' => '',
4161
+                'attributes' => null,
4162
+                'item_permissions' => 1,
4163
+            ], $share, [], false
4164
+        ];
4165
+
4166
+        $share = Server::get(IManager::class)->newShare();
4167
+        $share->setShareType(IShare::TYPE_USER)
4168
+            ->setSharedWith('recipient')
4169
+            ->setSharedBy('initiator')
4170
+            ->setShareOwner('currentUser')
4171
+            ->setPermissions(Constants::PERMISSION_READ)
4172
+            ->setNode($file)
4173
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4174
+            ->setTarget('myTarget')
4175
+            ->setNote('personal note')
4176
+            ->setId(42);
4177
+        // User backend down
4178
+        $result[] = [
4179
+            [
4180
+                'id' => '42',
4181
+                'share_type' => IShare::TYPE_USER,
4182
+                'uid_owner' => 'initiator',
4183
+                'displayname_owner' => 'initiator',
4184
+                'permissions' => 1,
4185
+                'attributes' => null,
4186
+                'stime' => 946684862,
4187
+                'parent' => null,
4188
+                'expiration' => null,
4189
+                'token' => null,
4190
+                'uid_file_owner' => 'currentUser',
4191
+                'displayname_file_owner' => 'currentUser',
4192
+                'note' => 'personal note',
4193
+                'label' => '',
4194
+                'path' => 'file',
4195
+                'item_type' => 'file',
4196
+                'storage_id' => 'storageId',
4197
+                'storage' => 100,
4198
+                'item_source' => 3,
4199
+                'file_source' => 3,
4200
+                'file_parent' => 1,
4201
+                'file_target' => 'myTarget',
4202
+                'share_with' => 'recipient',
4203
+                'share_with_displayname' => 'recipient',
4204
+                'share_with_displayname_unique' => 'recipient',
4205
+                'mail_send' => 0,
4206
+                'mimetype' => 'myMimeType',
4207
+                'has_preview' => false,
4208
+                'hide_download' => 0,
4209
+                'can_edit' => true,
4210
+                'can_delete' => true,
4211
+                'item_size' => 123456,
4212
+                'item_mtime' => 1234567890,
4213
+                'is-mount-root' => false,
4214
+                'mount-type' => '',
4215
+                'attributes' => null,
4216
+                'item_permissions' => 11,
4217
+            ], $share, [], false
4218
+        ];
4219
+
4220
+        // with existing group
4221
+
4222
+        $share = Server::get(IManager::class)->newShare();
4223
+        $share->setShareType(IShare::TYPE_GROUP)
4224
+            ->setSharedWith('recipientGroup')
4225
+            ->setSharedBy('initiator')
4226
+            ->setShareOwner('owner')
4227
+            ->setPermissions(Constants::PERMISSION_READ)
4228
+            ->setNode($file)
4229
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4230
+            ->setTarget('myTarget')
4231
+            ->setNote('personal note')
4232
+            ->setId(42);
4233
+
4234
+        $result[] = [
4235
+            [
4236
+                'id' => '42',
4237
+                'share_type' => IShare::TYPE_GROUP,
4238
+                'uid_owner' => 'initiator',
4239
+                'displayname_owner' => 'initiator',
4240
+                'permissions' => 1,
4241
+                'attributes' => null,
4242
+                'stime' => 946684862,
4243
+                'parent' => null,
4244
+                'expiration' => null,
4245
+                'token' => null,
4246
+                'uid_file_owner' => 'owner',
4247
+                'displayname_file_owner' => 'owner',
4248
+                'note' => 'personal note',
4249
+                'label' => '',
4250
+                'path' => 'file',
4251
+                'item_type' => 'file',
4252
+                'storage_id' => 'storageId',
4253
+                'storage' => 100,
4254
+                'item_source' => 3,
4255
+                'file_source' => 3,
4256
+                'file_parent' => 1,
4257
+                'file_target' => 'myTarget',
4258
+                'share_with' => 'recipientGroup',
4259
+                'share_with_displayname' => 'recipientGroupDisplayName',
4260
+                'mail_send' => 0,
4261
+                'mimetype' => 'myMimeType',
4262
+                'has_preview' => false,
4263
+                'hide_download' => 0,
4264
+                'can_edit' => false,
4265
+                'can_delete' => false,
4266
+                'item_size' => 123456,
4267
+                'item_mtime' => 1234567890,
4268
+                'is-mount-root' => false,
4269
+                'mount-type' => '',
4270
+                'attributes' => null,
4271
+                'item_permissions' => 1,
4272
+            ], $share, [], false
4273
+        ];
4274
+
4275
+        // with unknown group / no group backend
4276
+        $share = Server::get(IManager::class)->newShare();
4277
+        $share->setShareType(IShare::TYPE_GROUP)
4278
+            ->setSharedWith('recipientGroup2')
4279
+            ->setSharedBy('initiator')
4280
+            ->setShareOwner('owner')
4281
+            ->setPermissions(Constants::PERMISSION_READ)
4282
+            ->setNode($file)
4283
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4284
+            ->setTarget('myTarget')
4285
+            ->setNote('personal note')
4286
+            ->setId(42);
4287
+        $result[] = [
4288
+            [
4289
+                'id' => '42',
4290
+                'share_type' => IShare::TYPE_GROUP,
4291
+                'uid_owner' => 'initiator',
4292
+                'displayname_owner' => 'initiator',
4293
+                'permissions' => 1,
4294
+                'stime' => 946684862,
4295
+                'parent' => null,
4296
+                'expiration' => null,
4297
+                'token' => null,
4298
+                'uid_file_owner' => 'owner',
4299
+                'displayname_file_owner' => 'owner',
4300
+                'note' => 'personal note',
4301
+                'label' => '',
4302
+                'path' => 'file',
4303
+                'item_type' => 'file',
4304
+                'storage_id' => 'storageId',
4305
+                'storage' => 100,
4306
+                'item_source' => 3,
4307
+                'file_source' => 3,
4308
+                'file_parent' => 1,
4309
+                'file_target' => 'myTarget',
4310
+                'share_with' => 'recipientGroup2',
4311
+                'share_with_displayname' => 'recipientGroup2',
4312
+                'mail_send' => 0,
4313
+                'mimetype' => 'myMimeType',
4314
+                'has_preview' => false,
4315
+                'hide_download' => 0,
4316
+                'can_edit' => false,
4317
+                'can_delete' => false,
4318
+                'item_size' => 123456,
4319
+                'item_mtime' => 1234567890,
4320
+                'is-mount-root' => false,
4321
+                'mount-type' => '',
4322
+                'attributes' => null,
4323
+                'item_permissions' => 1,
4324
+            ], $share, [], false
4325
+        ];
4326
+
4327
+        $share = Server::get(IManager::class)->newShare();
4328
+        $share->setShareType(IShare::TYPE_LINK)
4329
+            ->setSharedBy('initiator')
4330
+            ->setShareOwner('owner')
4331
+            ->setPermissions(Constants::PERMISSION_READ)
4332
+            ->setNode($file)
4333
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4334
+            ->setTarget('myTarget')
4335
+            ->setPassword('mypassword')
4336
+            ->setExpirationDate(new \DateTime('2001-01-02T00:00:00'))
4337
+            ->setToken('myToken')
4338
+            ->setNote('personal note')
4339
+            ->setLabel('new link share')
4340
+            ->setId(42);
4341
+
4342
+        $result[] = [
4343
+            [
4344
+                'id' => '42',
4345
+                'share_type' => IShare::TYPE_LINK,
4346
+                'uid_owner' => 'initiator',
4347
+                'displayname_owner' => 'initiator',
4348
+                'permissions' => 1,
4349
+                'attributes' => null,
4350
+                'stime' => 946684862,
4351
+                'parent' => null,
4352
+                'expiration' => '2001-01-02 00:00:00',
4353
+                'token' => 'myToken',
4354
+                'uid_file_owner' => 'owner',
4355
+                'displayname_file_owner' => 'owner',
4356
+                'note' => 'personal note',
4357
+                'label' => 'new link share',
4358
+                'path' => 'file',
4359
+                'item_type' => 'file',
4360
+                'storage_id' => 'storageId',
4361
+                'storage' => 100,
4362
+                'item_source' => 3,
4363
+                'file_source' => 3,
4364
+                'file_parent' => 1,
4365
+                'file_target' => 'myTarget',
4366
+                'password' => 'mypassword',
4367
+                'share_with' => 'mypassword',
4368
+                'share_with_displayname' => '(Shared link)',
4369
+                'send_password_by_talk' => false,
4370
+                'mail_send' => 0,
4371
+                'url' => 'myLink',
4372
+                'mimetype' => 'myMimeType',
4373
+                'has_preview' => false,
4374
+                'hide_download' => 0,
4375
+                'can_edit' => false,
4376
+                'can_delete' => false,
4377
+                'item_size' => 123456,
4378
+                'item_mtime' => 1234567890,
4379
+                'is-mount-root' => false,
4380
+                'mount-type' => '',
4381
+                'attributes' => null,
4382
+                'item_permissions' => 1,
4383
+            ], $share, [], false
4384
+        ];
4385
+
4386
+        $share = Server::get(IManager::class)->newShare();
4387
+        $share->setShareType(IShare::TYPE_LINK)
4388
+            ->setSharedBy('initiator')
4389
+            ->setShareOwner('owner')
4390
+            ->setPermissions(Constants::PERMISSION_READ)
4391
+            ->setNode($file)
4392
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4393
+            ->setTarget('myTarget')
4394
+            ->setPassword('mypassword')
4395
+            ->setSendPasswordByTalk(true)
4396
+            ->setExpirationDate(new \DateTime('2001-01-02T00:00:00'))
4397
+            ->setToken('myToken')
4398
+            ->setNote('personal note')
4399
+            ->setLabel('new link share')
4400
+            ->setId(42);
4401
+
4402
+        $result[] = [
4403
+            [
4404
+                'id' => '42',
4405
+                'share_type' => IShare::TYPE_LINK,
4406
+                'uid_owner' => 'initiator',
4407
+                'displayname_owner' => 'initiator',
4408
+                'permissions' => 1,
4409
+                'stime' => 946684862,
4410
+                'parent' => null,
4411
+                'expiration' => '2001-01-02 00:00:00',
4412
+                'token' => 'myToken',
4413
+                'uid_file_owner' => 'owner',
4414
+                'displayname_file_owner' => 'owner',
4415
+                'note' => 'personal note',
4416
+                'label' => 'new link share',
4417
+                'path' => 'file',
4418
+                'item_type' => 'file',
4419
+                'storage_id' => 'storageId',
4420
+                'storage' => 100,
4421
+                'item_source' => 3,
4422
+                'file_source' => 3,
4423
+                'file_parent' => 1,
4424
+                'file_target' => 'myTarget',
4425
+                'password' => 'mypassword',
4426
+                'share_with' => 'mypassword',
4427
+                'share_with_displayname' => '(Shared link)',
4428
+                'send_password_by_talk' => true,
4429
+                'mail_send' => 0,
4430
+                'url' => 'myLink',
4431
+                'mimetype' => 'myMimeType',
4432
+                'has_preview' => false,
4433
+                'hide_download' => 0,
4434
+                'can_edit' => false,
4435
+                'can_delete' => false,
4436
+                'item_size' => 123456,
4437
+                'item_mtime' => 1234567890,
4438
+                'is-mount-root' => false,
4439
+                'mount-type' => '',
4440
+                'attributes' => null,
4441
+                'item_permissions' => 1,
4442
+            ], $share, [], false
4443
+        ];
4444
+
4445
+        $share = Server::get(IManager::class)->newShare();
4446
+        $share->setShareType(IShare::TYPE_REMOTE)
4447
+            ->setSharedBy('initiator')
4448
+            ->setSharedWith('[email protected]')
4449
+            ->setShareOwner('owner')
4450
+            ->setPermissions(Constants::PERMISSION_READ)
4451
+            ->setNode($folder)
4452
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4453
+            ->setExpirationDate(new \DateTime('2001-02-03T04:05:06'))
4454
+            ->setTarget('myTarget')
4455
+            ->setNote('personal note')
4456
+            ->setId(42);
4457
+
4458
+        $result[] = [
4459
+            [
4460
+                'id' => '42',
4461
+                'share_type' => IShare::TYPE_REMOTE,
4462
+                'uid_owner' => 'initiator',
4463
+                'displayname_owner' => 'initiator',
4464
+                'permissions' => 1,
4465
+                'stime' => 946684862,
4466
+                'parent' => null,
4467
+                'expiration' => '2001-02-03 00:00:00',
4468
+                'token' => null,
4469
+                'uid_file_owner' => 'owner',
4470
+                'displayname_file_owner' => 'owner',
4471
+                'note' => 'personal note',
4472
+                'label' => '',
4473
+                'path' => 'folder',
4474
+                'item_type' => 'folder',
4475
+                'storage_id' => 'storageId',
4476
+                'storage' => 100,
4477
+                'item_source' => 2,
4478
+                'file_source' => 2,
4479
+                'file_parent' => 1,
4480
+                'file_target' => 'myTarget',
4481
+                'share_with' => '[email protected]',
4482
+                'share_with_displayname' => 'foobar',
4483
+                'mail_send' => 0,
4484
+                'mimetype' => 'myFolderMimeType',
4485
+                'has_preview' => false,
4486
+                'hide_download' => 0,
4487
+                'can_edit' => false,
4488
+                'can_delete' => false,
4489
+                'item_size' => 123456,
4490
+                'item_mtime' => 1234567890,
4491
+                'is-mount-root' => false,
4492
+                'mount-type' => '',
4493
+                'attributes' => null,
4494
+                'item_permissions' => 1,
4495
+            ], $share, [], false
4496
+        ];
4497
+
4498
+        $share = Server::get(IManager::class)->newShare();
4499
+        $share->setShareType(IShare::TYPE_REMOTE_GROUP)
4500
+            ->setSharedBy('initiator')
4501
+            ->setSharedWith('[email protected]')
4502
+            ->setShareOwner('owner')
4503
+            ->setPermissions(Constants::PERMISSION_READ)
4504
+            ->setNode($folder)
4505
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4506
+            ->setExpirationDate(new \DateTime('2001-02-03T04:05:06'))
4507
+            ->setTarget('myTarget')
4508
+            ->setNote('personal note')
4509
+            ->setId(42);
4510
+
4511
+        $result[] = [
4512
+            [
4513
+                'id' => '42',
4514
+                'share_type' => IShare::TYPE_REMOTE_GROUP,
4515
+                'uid_owner' => 'initiator',
4516
+                'displayname_owner' => 'initiator',
4517
+                'permissions' => 1,
4518
+                'stime' => 946684862,
4519
+                'parent' => null,
4520
+                'expiration' => '2001-02-03 00:00:00',
4521
+                'token' => null,
4522
+                'uid_file_owner' => 'owner',
4523
+                'displayname_file_owner' => 'owner',
4524
+                'note' => 'personal note',
4525
+                'label' => '',
4526
+                'path' => 'folder',
4527
+                'item_type' => 'folder',
4528
+                'storage_id' => 'storageId',
4529
+                'storage' => 100,
4530
+                'item_source' => 2,
4531
+                'file_source' => 2,
4532
+                'file_parent' => 1,
4533
+                'file_target' => 'myTarget',
4534
+                'share_with' => '[email protected]',
4535
+                'share_with_displayname' => 'foobar',
4536
+                'mail_send' => 0,
4537
+                'mimetype' => 'myFolderMimeType',
4538
+                'has_preview' => false,
4539
+                'hide_download' => 0,
4540
+                'can_edit' => false,
4541
+                'can_delete' => false,
4542
+                'item_size' => 123456,
4543
+                'item_mtime' => 1234567890,
4544
+                'is-mount-root' => false,
4545
+                'mount-type' => '',
4546
+                'attributes' => null,
4547
+                'item_permissions' => 1,
4548
+            ], $share, [], false
4549
+        ];
4550
+
4551
+        // Circle with id, display name and avatar set by the Circles app
4552
+        $share = Server::get(IManager::class)->newShare();
4553
+        $share->setShareType(IShare::TYPE_CIRCLE)
4554
+            ->setSharedBy('initiator')
4555
+            ->setSharedWith('Circle (Public circle, circleOwner) [4815162342]')
4556
+            ->setSharedWithDisplayName('The display name')
4557
+            ->setSharedWithAvatar('path/to/the/avatar')
4558
+            ->setShareOwner('owner')
4559
+            ->setPermissions(Constants::PERMISSION_READ)
4560
+            ->setNode($folder)
4561
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4562
+            ->setTarget('myTarget')
4563
+            ->setId(42);
4564
+
4565
+        $result[] = [
4566
+            [
4567
+                'id' => '42',
4568
+                'share_type' => IShare::TYPE_CIRCLE,
4569
+                'uid_owner' => 'initiator',
4570
+                'displayname_owner' => 'initiator',
4571
+                'permissions' => 1,
4572
+                'attributes' => null,
4573
+                'stime' => 946684862,
4574
+                'parent' => null,
4575
+                'expiration' => null,
4576
+                'token' => null,
4577
+                'uid_file_owner' => 'owner',
4578
+                'displayname_file_owner' => 'owner',
4579
+                'note' => '',
4580
+                'label' => '',
4581
+                'path' => 'folder',
4582
+                'item_type' => 'folder',
4583
+                'storage_id' => 'storageId',
4584
+                'storage' => 100,
4585
+                'item_source' => 2,
4586
+                'file_source' => 2,
4587
+                'file_parent' => 1,
4588
+                'file_target' => 'myTarget',
4589
+                'share_with' => '4815162342',
4590
+                'share_with_displayname' => 'The display name',
4591
+                'share_with_avatar' => 'path/to/the/avatar',
4592
+                'mail_send' => 0,
4593
+                'mimetype' => 'myFolderMimeType',
4594
+                'has_preview' => false,
4595
+                'hide_download' => 0,
4596
+                'can_edit' => false,
4597
+                'can_delete' => false,
4598
+                'item_size' => 123456,
4599
+                'item_mtime' => 1234567890,
4600
+                'is-mount-root' => false,
4601
+                'mount-type' => '',
4602
+                'attributes' => null,
4603
+                'item_permissions' => 1,
4604
+            ], $share, [], false
4605
+        ];
4606
+
4607
+        // Circle with id set by the Circles app
4608
+        $share = Server::get(IManager::class)->newShare();
4609
+        $share->setShareType(IShare::TYPE_CIRCLE)
4610
+            ->setSharedBy('initiator')
4611
+            ->setSharedWith('Circle (Public circle, circleOwner) [4815162342]')
4612
+            ->setShareOwner('owner')
4613
+            ->setPermissions(Constants::PERMISSION_READ)
4614
+            ->setNode($folder)
4615
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4616
+            ->setTarget('myTarget')
4617
+            ->setId(42);
4618
+
4619
+        $result[] = [
4620
+            [
4621
+                'id' => '42',
4622
+                'share_type' => IShare::TYPE_CIRCLE,
4623
+                'uid_owner' => 'initiator',
4624
+                'displayname_owner' => 'initiator',
4625
+                'permissions' => 1,
4626
+                'stime' => 946684862,
4627
+                'parent' => null,
4628
+                'expiration' => null,
4629
+                'token' => null,
4630
+                'uid_file_owner' => 'owner',
4631
+                'displayname_file_owner' => 'owner',
4632
+                'note' => '',
4633
+                'label' => '',
4634
+                'path' => 'folder',
4635
+                'item_type' => 'folder',
4636
+                'storage_id' => 'storageId',
4637
+                'storage' => 100,
4638
+                'item_source' => 2,
4639
+                'file_source' => 2,
4640
+                'file_parent' => 1,
4641
+                'file_target' => 'myTarget',
4642
+                'share_with' => '4815162342',
4643
+                'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4644
+                'share_with_avatar' => '',
4645
+                'mail_send' => 0,
4646
+                'mimetype' => 'myFolderMimeType',
4647
+                'has_preview' => false,
4648
+                'hide_download' => 0,
4649
+                'can_edit' => false,
4650
+                'can_delete' => false,
4651
+                'item_size' => 123456,
4652
+                'item_mtime' => 1234567890,
4653
+                'is-mount-root' => false,
4654
+                'mount-type' => '',
4655
+                'attributes' => null,
4656
+                'item_permissions' => 1,
4657
+            ], $share, [], false
4658
+        ];
4659
+
4660
+        // Circle with id not set by the Circles app
4661
+        $share = Server::get(IManager::class)->newShare();
4662
+        $share->setShareType(IShare::TYPE_CIRCLE)
4663
+            ->setSharedBy('initiator')
4664
+            ->setSharedWith('Circle (Public circle, circleOwner)')
4665
+            ->setShareOwner('owner')
4666
+            ->setPermissions(Constants::PERMISSION_READ)
4667
+            ->setNode($folder)
4668
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4669
+            ->setTarget('myTarget')
4670
+            ->setId(42);
4671
+
4672
+        $result[] = [
4673
+            [
4674
+                'id' => '42',
4675
+                'share_type' => IShare::TYPE_CIRCLE,
4676
+                'uid_owner' => 'initiator',
4677
+                'displayname_owner' => 'initiator',
4678
+                'permissions' => 1,
4679
+                'stime' => 946684862,
4680
+                'parent' => null,
4681
+                'expiration' => null,
4682
+                'token' => null,
4683
+                'uid_file_owner' => 'owner',
4684
+                'displayname_file_owner' => 'owner',
4685
+                'note' => '',
4686
+                'label' => '',
4687
+                'path' => 'folder',
4688
+                'item_type' => 'folder',
4689
+                'storage_id' => 'storageId',
4690
+                'storage' => 100,
4691
+                'item_source' => 2,
4692
+                'file_source' => 2,
4693
+                'file_parent' => 1,
4694
+                'file_target' => 'myTarget',
4695
+                'share_with' => 'Circle',
4696
+                'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4697
+                'share_with_avatar' => '',
4698
+                'mail_send' => 0,
4699
+                'mimetype' => 'myFolderMimeType',
4700
+                'has_preview' => false,
4701
+                'hide_download' => 0,
4702
+                'can_edit' => false,
4703
+                'can_delete' => false,
4704
+                'item_size' => 123456,
4705
+                'item_mtime' => 1234567890,
4706
+                'is-mount-root' => false,
4707
+                'mount-type' => '',
4708
+                'attributes' => null,
4709
+                'item_permissions' => 1,
4710
+            ], $share, [], false
4711
+        ];
4712
+
4713
+        $share = Server::get(IManager::class)->newShare();
4714
+        $share->setShareType(IShare::TYPE_USER)
4715
+            ->setSharedBy('initiator')
4716
+            ->setSharedWith('recipient')
4717
+            ->setShareOwner('owner')
4718
+            ->setPermissions(Constants::PERMISSION_READ)
4719
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4720
+            ->setTarget('myTarget')
4721
+            ->setNote('personal note')
4722
+            ->setId(42);
4723
+
4724
+        $result[] = [
4725
+            [], $share, [], true
4726
+        ];
4727
+
4728
+        $share = Server::get(IManager::class)->newShare();
4729
+        $share->setShareType(IShare::TYPE_EMAIL)
4730
+            ->setSharedBy('initiator')
4731
+            ->setSharedWith('[email protected]')
4732
+            ->setShareOwner('owner')
4733
+            ->setPermissions(Constants::PERMISSION_READ)
4734
+            ->setNode($folder)
4735
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4736
+            ->setTarget('myTarget')
4737
+            ->setId(42)
4738
+            ->setPassword('password');
4739
+
4740
+        $result[] = [
4741
+            [
4742
+                'id' => '42',
4743
+                'share_type' => IShare::TYPE_EMAIL,
4744
+                'uid_owner' => 'initiator',
4745
+                'displayname_owner' => 'initiator',
4746
+                'permissions' => 1,
4747
+                'stime' => 946684862,
4748
+                'parent' => null,
4749
+                'expiration' => null,
4750
+                'token' => null,
4751
+                'uid_file_owner' => 'owner',
4752
+                'displayname_file_owner' => 'owner',
4753
+                'note' => '',
4754
+                'label' => '',
4755
+                'path' => 'folder',
4756
+                'item_type' => 'folder',
4757
+                'storage_id' => 'storageId',
4758
+                'storage' => 100,
4759
+                'item_source' => 2,
4760
+                'file_source' => 2,
4761
+                'file_parent' => 1,
4762
+                'file_target' => 'myTarget',
4763
+                'share_with' => '[email protected]',
4764
+                'share_with_displayname' => 'mail display name',
4765
+                'mail_send' => 0,
4766
+                'mimetype' => 'myFolderMimeType',
4767
+                'has_preview' => false,
4768
+                'password' => 'password',
4769
+                'send_password_by_talk' => false,
4770
+                'hide_download' => 0,
4771
+                'can_edit' => false,
4772
+                'can_delete' => false,
4773
+                'password_expiration_time' => null,
4774
+                'item_size' => 123456,
4775
+                'item_mtime' => 1234567890,
4776
+                'is-mount-root' => false,
4777
+                'mount-type' => '',
4778
+                'attributes' => null,
4779
+                'item_permissions' => 1,
4780
+            ], $share, [], false
4781
+        ];
4782
+
4783
+        $share = Server::get(IManager::class)->newShare();
4784
+        $share->setShareType(IShare::TYPE_EMAIL)
4785
+            ->setSharedBy('initiator')
4786
+            ->setSharedWith('[email protected]')
4787
+            ->setShareOwner('owner')
4788
+            ->setPermissions(Constants::PERMISSION_READ)
4789
+            ->setNode($folder)
4790
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4791
+            ->setTarget('myTarget')
4792
+            ->setId(42)
4793
+            ->setPassword('password')
4794
+            ->setSendPasswordByTalk(true);
4795
+
4796
+        $result[] = [
4797
+            [
4798
+                'id' => '42',
4799
+                'share_type' => IShare::TYPE_EMAIL,
4800
+                'uid_owner' => 'initiator',
4801
+                'displayname_owner' => 'initiator',
4802
+                'permissions' => 1,
4803
+                'stime' => 946684862,
4804
+                'parent' => null,
4805
+                'expiration' => null,
4806
+                'token' => null,
4807
+                'uid_file_owner' => 'owner',
4808
+                'displayname_file_owner' => 'owner',
4809
+                'note' => '',
4810
+                'label' => '',
4811
+                'path' => 'folder',
4812
+                'item_type' => 'folder',
4813
+                'storage_id' => 'storageId',
4814
+                'storage' => 100,
4815
+                'item_source' => 2,
4816
+                'file_source' => 2,
4817
+                'file_parent' => 1,
4818
+                'file_target' => 'myTarget',
4819
+                'share_with' => '[email protected]',
4820
+                'share_with_displayname' => 'mail display name',
4821
+                'mail_send' => 0,
4822
+                'mimetype' => 'myFolderMimeType',
4823
+                'has_preview' => false,
4824
+                'password' => 'password',
4825
+                'send_password_by_talk' => true,
4826
+                'hide_download' => 0,
4827
+                'can_edit' => false,
4828
+                'can_delete' => false,
4829
+                'password_expiration_time' => null,
4830
+                'item_size' => 123456,
4831
+                'item_mtime' => 1234567890,
4832
+                'is-mount-root' => false,
4833
+                'mount-type' => '',
4834
+                'attributes' => null,
4835
+                'item_permissions' => 1,
4836
+            ], $share, [], false
4837
+        ];
4838
+
4839
+        // Preview is available
4840
+        $share = Server::get(IManager::class)->newShare();
4841
+        $share->setShareType(IShare::TYPE_USER)
4842
+            ->setSharedWith('recipient')
4843
+            ->setSharedBy('initiator')
4844
+            ->setShareOwner('currentUser')
4845
+            ->setPermissions(Constants::PERMISSION_READ)
4846
+            ->setNode($fileWithPreview)
4847
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4848
+            ->setTarget('myTarget')
4849
+            ->setNote('personal note')
4850
+            ->setId(42);
4851
+
4852
+        $result[] = [
4853
+            [
4854
+                'id' => '42',
4855
+                'share_type' => IShare::TYPE_USER,
4856
+                'uid_owner' => 'initiator',
4857
+                'displayname_owner' => 'initiator',
4858
+                'permissions' => 1,
4859
+                'stime' => 946684862,
4860
+                'parent' => null,
4861
+                'expiration' => null,
4862
+                'token' => null,
4863
+                'uid_file_owner' => 'currentUser',
4864
+                'displayname_file_owner' => 'currentUser',
4865
+                'note' => 'personal note',
4866
+                'label' => '',
4867
+                'path' => 'fileWithPreview',
4868
+                'item_type' => 'file',
4869
+                'storage_id' => 'storageId',
4870
+                'storage' => 100,
4871
+                'item_source' => 4,
4872
+                'file_source' => 4,
4873
+                'file_parent' => 1,
4874
+                'file_target' => 'myTarget',
4875
+                'share_with' => 'recipient',
4876
+                'share_with_displayname' => 'recipient',
4877
+                'share_with_displayname_unique' => 'recipient',
4878
+                'mail_send' => 0,
4879
+                'mimetype' => 'mimeWithPreview',
4880
+                'has_preview' => true,
4881
+                'hide_download' => 0,
4882
+                'can_edit' => true,
4883
+                'can_delete' => true,
4884
+                'item_size' => 123456,
4885
+                'item_mtime' => 1234567890,
4886
+                'is-mount-root' => false,
4887
+                'mount-type' => '',
4888
+                'attributes' => null,
4889
+                'item_permissions' => 11,
4890
+            ], $share, [], false
4891
+        ];
4892
+
4893
+        return $result;
4894
+    }
4895
+
4896
+    /**
4897
+     *
4898
+     * @param array $expects
4899
+     * @param IShare $share
4900
+     * @param array $users
4901
+     * @param $exception
4902
+     */
4903
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataFormatShare')]
4904
+    public function testFormatShare(array $expects, IShare $share, array $users, $exception): void {
4905
+        $this->userManager->method('get')->willReturnMap($users);
4906
+
4907
+        $recipientGroup = $this->createMock(IGroup::class);
4908
+        $recipientGroup->method('getDisplayName')->willReturn('recipientGroupDisplayName');
4909
+        $this->groupManager->method('get')->willReturnMap([
4910
+            ['recipientGroup', $recipientGroup],
4911
+        ]);
4912
+
4913
+        $this->urlGenerator->method('linkToRouteAbsolute')
4914
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken'])
4915
+            ->willReturn('myLink');
4916
+
4917
+        $this->rootFolder->method('getUserFolder')
4918
+            ->with($this->currentUser)
4919
+            ->willReturnSelf();
4920
+        $this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
4921
+
4922
+        if (!$exception) {
4923
+            $this->rootFolder->method('getFirstNodeById')
4924
+                ->with($share->getNodeId())
4925
+                ->willReturn($share->getNode());
4926
+
4927
+            $this->rootFolder->method('getRelativePath')
4928
+                ->with($share->getNode()->getPath())
4929
+                ->willReturnArgument(0);
4930
+        }
4931
+
4932
+        $cm = $this->createMock(\OCP\Contacts\IManager::class);
4933
+        $this->overwriteService(\OCP\Contacts\IManager::class, $cm);
4934
+
4935
+        $cm->method('search')
4936
+            ->willReturnMap([
4937
+                ['[email protected]', ['CLOUD'], [
4938
+                    'limit' => 1,
4939
+                    'enumeration' => false,
4940
+                    'strict_search' => true,
4941
+                ],
4942
+                    [
4943
+                        [
4944
+                            'CLOUD' => [
4945
+                                '[email protected]',
4946
+                            ],
4947
+                            'FN' => 'foobar',
4948
+                        ],
4949
+                    ],
4950
+                ],
4951
+                ['[email protected]', ['EMAIL'], [
4952
+                    'limit' => 1,
4953
+                    'enumeration' => false,
4954
+                    'strict_search' => true,
4955
+                ],
4956
+                    [
4957
+                        [
4958
+                            'EMAIL' => [
4959
+                                '[email protected]',
4960
+                            ],
4961
+                            'FN' => 'mail display name',
4962
+                        ],
4963
+                    ],
4964
+                ],
4965
+            ]);
4966
+
4967
+        try {
4968
+            $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
4969
+            $this->assertFalse($exception);
4970
+            $this->assertEquals($expects, $result);
4971
+        } catch (NotFoundException $e) {
4972
+            $this->assertTrue($exception);
4973
+        }
4974
+    }
4975
+
4976
+    public function dataFormatRoomShare() {
4977
+        $file = $this->getMockBuilder(File::class)->getMock();
4978
+        $parent = $this->getMockBuilder(Folder::class)->getMock();
4979
+
4980
+        $file->method('getMimeType')->willReturn('myMimeType');
4981
+
4982
+        $file->method('getPath')->willReturn('file');
4983
+
4984
+        $parent->method('getId')->willReturn(1);
4985
+        $file->method('getId')->willReturn(3);
4986
+
4987
+        $file->method('getParent')->willReturn($parent);
4988
+
4989
+        $file->method('getSize')->willReturn(123456);
4990
+        $file->method('getMTime')->willReturn(1234567890);
4991
+
4992
+        $mountPoint = $this->getMockBuilder(IMountPoint::class)->getMock();
4993
+        $mountPoint->method('getMountType')->willReturn('');
4994
+        $file->method('getMountPoint')->willReturn($mountPoint);
4995
+
4996
+        $cache = $this->getMockBuilder('OCP\Files\Cache\ICache')->getMock();
4997
+        $cache->method('getNumericStorageId')->willReturn(100);
4998
+        $storage = $this->createMock(IStorage::class);
4999
+        $storage->method('getId')->willReturn('storageId');
5000
+        $storage->method('getCache')->willReturn($cache);
5001
+
5002
+        $file->method('getStorage')->willReturn($storage);
5003
+
5004
+        $result = [];
5005
+
5006
+        $share = Server::get(IManager::class)->newShare();
5007
+        $share->setShareType(IShare::TYPE_ROOM)
5008
+            ->setSharedWith('recipientRoom')
5009
+            ->setSharedBy('initiator')
5010
+            ->setShareOwner('owner')
5011
+            ->setPermissions(Constants::PERMISSION_READ)
5012
+            ->setNode($file)
5013
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
5014
+            ->setTarget('myTarget')
5015
+            ->setNote('personal note')
5016
+            ->setId(42);
5017
+
5018
+        $result[] = [
5019
+            [
5020
+                'id' => '42',
5021
+                'share_type' => IShare::TYPE_ROOM,
5022
+                'uid_owner' => 'initiator',
5023
+                'displayname_owner' => 'initiator',
5024
+                'permissions' => 1,
5025
+                'stime' => 946684862,
5026
+                'parent' => null,
5027
+                'expiration' => null,
5028
+                'token' => null,
5029
+                'uid_file_owner' => 'owner',
5030
+                'displayname_file_owner' => 'owner',
5031
+                'note' => 'personal note',
5032
+                'path' => 'file',
5033
+                'item_type' => 'file',
5034
+                'storage_id' => 'storageId',
5035
+                'storage' => 100,
5036
+                'item_source' => 3,
5037
+                'file_source' => 3,
5038
+                'file_parent' => 1,
5039
+                'file_target' => 'myTarget',
5040
+                'share_with' => 'recipientRoom',
5041
+                'share_with_displayname' => '',
5042
+                'mail_send' => 0,
5043
+                'mimetype' => 'myMimeType',
5044
+                'has_preview' => false,
5045
+                'hide_download' => 0,
5046
+                'label' => '',
5047
+                'can_edit' => false,
5048
+                'can_delete' => false,
5049
+                'item_size' => 123456,
5050
+                'item_mtime' => 1234567890,
5051
+                'is-mount-root' => false,
5052
+                'mount-type' => '',
5053
+                'attributes' => null,
5054
+                'item_permissions' => 1,
5055
+            ], $share, false, []
5056
+        ];
5057
+
5058
+        $share = Server::get(IManager::class)->newShare();
5059
+        $share->setShareType(IShare::TYPE_ROOM)
5060
+            ->setSharedWith('recipientRoom')
5061
+            ->setSharedBy('initiator')
5062
+            ->setShareOwner('owner')
5063
+            ->setPermissions(Constants::PERMISSION_READ)
5064
+            ->setNode($file)
5065
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
5066
+            ->setTarget('myTarget')
5067
+            ->setNote('personal note')
5068
+            ->setId(42);
5069
+
5070
+        $result[] = [
5071
+            [
5072
+                'id' => '42',
5073
+                'share_type' => IShare::TYPE_ROOM,
5074
+                'uid_owner' => 'initiator',
5075
+                'displayname_owner' => 'initiator',
5076
+                'permissions' => 1,
5077
+                'stime' => 946684862,
5078
+                'parent' => null,
5079
+                'expiration' => null,
5080
+                'token' => null,
5081
+                'uid_file_owner' => 'owner',
5082
+                'displayname_file_owner' => 'owner',
5083
+                'note' => 'personal note',
5084
+                'path' => 'file',
5085
+                'item_type' => 'file',
5086
+                'storage_id' => 'storageId',
5087
+                'storage' => 100,
5088
+                'item_source' => 3,
5089
+                'file_source' => 3,
5090
+                'file_parent' => 1,
5091
+                'file_target' => 'myTarget',
5092
+                'share_with' => 'recipientRoom',
5093
+                'share_with_displayname' => 'recipientRoomName',
5094
+                'mail_send' => 0,
5095
+                'mimetype' => 'myMimeType',
5096
+                'has_preview' => false,
5097
+                'hide_download' => 0,
5098
+                'label' => '',
5099
+                'can_edit' => false,
5100
+                'can_delete' => false,
5101
+                'item_size' => 123456,
5102
+                'item_mtime' => 1234567890,
5103
+                'is-mount-root' => false,
5104
+                'mount-type' => '',
5105
+                'attributes' => null,
5106
+                'item_permissions' => 9,
5107
+            ], $share, true, [
5108
+                'share_with_displayname' => 'recipientRoomName'
5109
+            ]
5110
+        ];
5111
+
5112
+        return $result;
5113
+    }
5114
+
5115
+    /**
5116
+     *
5117
+     * @param array $expects
5118
+     * @param IShare $share
5119
+     * @param bool $helperAvailable
5120
+     * @param array $formatShareByHelper
5121
+     */
5122
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataFormatRoomShare')]
5123
+    public function testFormatRoomShare(array $expects, IShare $share, bool $helperAvailable, array $formatShareByHelper): void {
5124
+        $this->rootFolder->method('getUserFolder')
5125
+            ->with($this->currentUser)
5126
+            ->willReturnSelf();
5127
+
5128
+        $this->rootFolder->method('getFirstNodeById')
5129
+            ->with($share->getNodeId())
5130
+            ->willReturn($share->getNode());
5131
+
5132
+        $this->rootFolder->method('getRelativePath')
5133
+            ->with($share->getNode()->getPath())
5134
+            ->willReturnArgument(0);
5135
+
5136
+        if (!$helperAvailable) {
5137
+            $this->appManager->method('isEnabledForUser')
5138
+                ->with('spreed')
5139
+                ->willReturn(false);
5140
+        } else {
5141
+            $this->appManager->method('isEnabledForUser')
5142
+                ->with('spreed')
5143
+                ->willReturn(true);
5144
+
5145
+            // This is not possible anymore with PHPUnit 10+
5146
+            // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
5147
+            // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
5148
+            $helper = $this->getMockBuilder(\stdClass::class)
5149
+                ->addMethods(['formatShare', 'canAccessShare'])
5150
+                ->getMock();
5151
+            $helper->method('formatShare')
5152
+                ->with($share)
5153
+                ->willReturn($formatShareByHelper);
5154
+            $helper->method('canAccessShare')
5155
+                ->with($share)
5156
+                ->willReturn(true);
5157
+
5158
+            $this->serverContainer->method('get')
5159
+                ->with('\OCA\Talk\Share\Helper\ShareAPIController')
5160
+                ->willReturn($helper);
5161
+        }
5162
+
5163
+        $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5164
+        $this->assertEquals($expects, $result);
5165
+    }
5166
+
5167
+    /**
5168
+     * @return list{Folder, Folder}
5169
+     */
5170
+    private function getNonSharedUserFolder(): array {
5171
+        $node = $this->getMockBuilder(Folder::class)->getMock();
5172
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
5173
+        $storage = $this->createMock(IStorage::class);
5174
+        $storage->method('instanceOfStorage')
5175
+            ->willReturnMap([
5176
+                ['OCA\Files_Sharing\External\Storage', false],
5177
+                ['OCA\Files_Sharing\SharedStorage', false],
5178
+            ]);
5179
+        $userFolder->method('getStorage')->willReturn($storage);
5180
+        $node->method('getStorage')->willReturn($storage);
5181
+        $node->method('getId')->willReturn(42);
5182
+        $user = $this->createMock(IUser::class);
5183
+        $user->method('getUID')->willReturn($this->currentUser);
5184
+        $node->method('getOwner')->willReturn($user);
5185
+        return [$userFolder, $node];
5186
+    }
5187
+
5188
+    /**
5189
+     * @return list{Folder, File}
5190
+     */
5191
+    private function getNonSharedUserFile(): array {
5192
+        $node = $this->getMockBuilder(File::class)->getMock();
5193
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
5194
+        $storage = $this->createMock(IStorage::class);
5195
+        $storage->method('instanceOfStorage')
5196
+            ->willReturnMap([
5197
+                ['OCA\Files_Sharing\External\Storage', false],
5198
+                ['OCA\Files_Sharing\SharedStorage', false],
5199
+            ]);
5200
+        $userFolder->method('getStorage')->willReturn($storage);
5201
+        $node->method('getStorage')->willReturn($storage);
5202
+        $node->method('getId')->willReturn(42);
5203
+        return [$userFolder, $node];
5204
+    }
5205
+
5206
+    public function testPopulateTags(): void {
5207
+        $tagger = $this->createMock(ITags::class);
5208
+        $this->tagManager->method('load')
5209
+            ->with('files')
5210
+            ->willReturn($tagger);
5211
+        $data = [
5212
+            ['file_source' => 10],
5213
+            ['file_source' => 22, 'foo' => 'bar'],
5214
+            ['file_source' => 42, 'x' => 'y'],
5215
+        ];
5216
+        $tags = [
5217
+            10 => ['tag3'],
5218
+            42 => ['tag1', 'tag2'],
5219
+        ];
5220
+        $tagger->method('getTagsForObjects')
5221
+            ->with([10, 22, 42])
5222
+            ->willReturn($tags);
5223
+
5224
+        $result = self::invokePrivate($this->ocs, 'populateTags', [$data]);
5225
+        $this->assertSame([
5226
+            ['file_source' => 10, 'tags' => ['tag3']],
5227
+            ['file_source' => 22, 'foo' => 'bar', 'tags' => []],
5228
+            ['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']],
5229
+        ], $result);
5230
+    }
5231 5231
 }
Please login to merge, or discard this patch.