Completed
Push — master ( 85ba4e...a17f4d )
by
unknown
40:29 queued 10s
created
tests/lib/Share20/ShareTest.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -21,45 +21,45 @@
 block discarded – undo
21 21
  * @package Test\Share20
22 22
  */
23 23
 class ShareTest extends \Test\TestCase {
24
-	protected IRootFolder&MockObject $rootFolder;
25
-	protected IUserManager&MockObject $userManager;
26
-	protected IShare $share;
24
+    protected IRootFolder&MockObject $rootFolder;
25
+    protected IUserManager&MockObject $userManager;
26
+    protected IShare $share;
27 27
 
28
-	protected function setUp(): void {
29
-		$this->rootFolder = $this->createMock(IRootFolder::class);
30
-		$this->userManager = $this->createMock(IUserManager::class);
31
-		$this->share = new Share($this->rootFolder, $this->userManager);
32
-	}
28
+    protected function setUp(): void {
29
+        $this->rootFolder = $this->createMock(IRootFolder::class);
30
+        $this->userManager = $this->createMock(IUserManager::class);
31
+        $this->share = new Share($this->rootFolder, $this->userManager);
32
+    }
33 33
 
34
-	public function testSetIdInt(): void {
35
-		$this->share->setId(42);
36
-		$this->assertEquals('42', $this->share->getId());
37
-	}
34
+    public function testSetIdInt(): void {
35
+        $this->share->setId(42);
36
+        $this->assertEquals('42', $this->share->getId());
37
+    }
38 38
 
39
-	public function testSetIdString(): void {
40
-		$this->share->setId('foo');
41
-		$this->assertEquals('foo', $this->share->getId());
42
-	}
39
+    public function testSetIdString(): void {
40
+        $this->share->setId('foo');
41
+        $this->assertEquals('foo', $this->share->getId());
42
+    }
43 43
 
44
-	public function testSetIdOnce(): void {
45
-		$this->expectException(IllegalIDChangeException::class);
46
-		$this->expectExceptionMessage('Not allowed to assign a new internal id to a share');
44
+    public function testSetIdOnce(): void {
45
+        $this->expectException(IllegalIDChangeException::class);
46
+        $this->expectExceptionMessage('Not allowed to assign a new internal id to a share');
47 47
 
48
-		$this->share->setId('foo');
49
-		$this->share->setId('bar');
50
-	}
48
+        $this->share->setId('foo');
49
+        $this->share->setId('bar');
50
+    }
51 51
 
52
-	public function testSetProviderIdString(): void {
53
-		$this->share->setProviderId('foo');
54
-		$this->share->setId('bar');
55
-		$this->assertEquals('foo:bar', $this->share->getFullId());
56
-	}
52
+    public function testSetProviderIdString(): void {
53
+        $this->share->setProviderId('foo');
54
+        $this->share->setId('bar');
55
+        $this->assertEquals('foo:bar', $this->share->getFullId());
56
+    }
57 57
 
58
-	public function testSetProviderIdOnce(): void {
59
-		$this->expectException(IllegalIDChangeException::class);
60
-		$this->expectExceptionMessage('Not allowed to assign a new provider id to a share');
58
+    public function testSetProviderIdOnce(): void {
59
+        $this->expectException(IllegalIDChangeException::class);
60
+        $this->expectExceptionMessage('Not allowed to assign a new provider id to a share');
61 61
 
62
-		$this->share->setProviderId('foo');
63
-		$this->share->setProviderId('bar');
64
-	}
62
+        $this->share->setProviderId('foo');
63
+        $this->share->setProviderId('bar');
64
+    }
65 65
 }
Please login to merge, or discard this patch.
tests/lib/Share20/DefaultShareProviderTest.php 2 patches
Indentation   +3063 added lines, -3063 removed lines patch added patch discarded remove patch
@@ -44,3071 +44,3071 @@
 block discarded – undo
44 44
  */
45 45
 #[\PHPUnit\Framework\Attributes\Group('DB')]
46 46
 class DefaultShareProviderTest extends \Test\TestCase {
47
-	/** @var IDBConnection */
48
-	protected $dbConn;
49
-
50
-	/** @var IUserManager | MockObject */
51
-	protected $userManager;
52
-
53
-	/** @var IGroupManager | MockObject */
54
-	protected $groupManager;
55
-
56
-	/** @var IRootFolder | MockObject */
57
-	protected $rootFolder;
58
-
59
-	/** @var DefaultShareProvider */
60
-	protected $provider;
61
-
62
-	/** @var MockObject|IMailer */
63
-	protected $mailer;
64
-
65
-	/** @var IFactory|MockObject */
66
-	protected $l10nFactory;
67
-
68
-	/** @var MockObject|IL10N */
69
-	protected $l10n;
70
-
71
-	/** @var MockObject|Defaults */
72
-	protected $defaults;
73
-
74
-	/** @var MockObject|IURLGenerator */
75
-	protected $urlGenerator;
76
-
77
-	/** @var ITimeFactory|MockObject */
78
-	protected $timeFactory;
79
-
80
-	/** @var LoggerInterface|MockObject */
81
-	protected $logger;
82
-
83
-	protected IConfig&MockObject $config;
84
-
85
-	protected IShareManager&MockObject $shareManager;
86
-
87
-	protected function setUp(): void {
88
-		$this->dbConn = Server::get(IDBConnection::class);
89
-		$this->userManager = $this->createMock(IUserManager::class);
90
-		$this->groupManager = $this->createMock(IGroupManager::class);
91
-		$this->rootFolder = $this->createMock(IRootFolder::class);
92
-		$this->mailer = $this->createMock(IMailer::class);
93
-		$this->l10nFactory = $this->createMock(IFactory::class);
94
-		$this->l10n = $this->createMock(IL10N::class);
95
-		$this->defaults = $this->getMockBuilder(Defaults::class)->disableOriginalConstructor()->getMock();
96
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
97
-		$this->timeFactory = $this->createMock(ITimeFactory::class);
98
-		$this->logger = $this->createMock(LoggerInterface::class);
99
-		$this->shareManager = $this->createMock(IShareManager::class);
100
-		$this->config = $this->createMock(IConfig::class);
101
-
102
-		$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
103
-		$this->timeFactory->expects($this->any())->method('now')->willReturn(new \DateTimeImmutable('2023-05-04 00:00 Europe/Berlin'));
104
-
105
-		//Empty share table
106
-		$this->dbConn->getQueryBuilder()->delete('share')->executeStatement();
107
-
108
-		$this->provider = new DefaultShareProvider(
109
-			$this->dbConn,
110
-			$this->userManager,
111
-			$this->groupManager,
112
-			$this->rootFolder,
113
-			$this->mailer,
114
-			$this->defaults,
115
-			$this->l10nFactory,
116
-			$this->urlGenerator,
117
-			$this->timeFactory,
118
-			$this->logger,
119
-			$this->shareManager,
120
-			$this->config,
121
-		);
122
-	}
123
-
124
-	protected function tearDown(): void {
125
-		$this->dbConn->getQueryBuilder()->delete('share')->executeStatement();
126
-		$this->dbConn->getQueryBuilder()->delete('filecache')->runAcrossAllShards()->executeStatement();
127
-		$this->dbConn->getQueryBuilder()->delete('storages')->executeStatement();
128
-	}
129
-
130
-	/**
131
-	 * @param int $shareType
132
-	 * @param string $sharedWith
133
-	 * @param string $sharedBy
134
-	 * @param string $shareOwner
135
-	 * @param string $itemType
136
-	 * @param int $fileSource
137
-	 * @param string $fileTarget
138
-	 * @param int $permissions
139
-	 * @param $token
140
-	 * @param $expiration
141
-	 * @return int
142
-	 */
143
-	private function addShareToDB($shareType, $sharedWith, $sharedBy, $shareOwner,
144
-		$itemType, $fileSource, $fileTarget, $permissions, $token, $expiration,
145
-		$parent = null) {
146
-		$qb = $this->dbConn->getQueryBuilder();
147
-		$qb->insert('share');
148
-
149
-		if ($shareType) {
150
-			$qb->setValue('share_type', $qb->expr()->literal($shareType));
151
-		}
152
-		if ($sharedWith) {
153
-			$qb->setValue('share_with', $qb->expr()->literal($sharedWith));
154
-		}
155
-		if ($sharedBy) {
156
-			$qb->setValue('uid_initiator', $qb->expr()->literal($sharedBy));
157
-		}
158
-		if ($shareOwner) {
159
-			$qb->setValue('uid_owner', $qb->expr()->literal($shareOwner));
160
-		}
161
-		if ($itemType) {
162
-			$qb->setValue('item_type', $qb->expr()->literal($itemType));
163
-		}
164
-		if ($fileSource) {
165
-			$qb->setValue('file_source', $qb->expr()->literal($fileSource));
166
-		}
167
-		if ($fileTarget) {
168
-			$qb->setValue('file_target', $qb->expr()->literal($fileTarget));
169
-		}
170
-		if ($permissions) {
171
-			$qb->setValue('permissions', $qb->expr()->literal($permissions));
172
-		}
173
-		if ($token) {
174
-			$qb->setValue('token', $qb->expr()->literal($token));
175
-		}
176
-		if ($expiration) {
177
-			$qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATETIME_MUTABLE));
178
-		}
179
-		if ($parent) {
180
-			$qb->setValue('parent', $qb->expr()->literal($parent));
181
-		}
182
-
183
-		$this->assertEquals(1, $qb->executeStatement());
184
-		return $qb->getLastInsertId();
185
-	}
186
-
187
-
188
-
189
-
190
-	public function testGetShareByIdNotExist(): void {
191
-		$this->expectException(ShareNotFound::class);
192
-
193
-		$this->provider->getShareById(1);
194
-	}
195
-
196
-	public function testGetShareByIdUserShare(): void {
197
-		$qb = $this->dbConn->getQueryBuilder();
198
-
199
-		$qb->insert('share')
200
-			->values([
201
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
202
-				'share_with' => $qb->expr()->literal('sharedWith'),
203
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
204
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
205
-				'item_type' => $qb->expr()->literal('file'),
206
-				'file_source' => $qb->expr()->literal(42),
207
-				'file_target' => $qb->expr()->literal('myTarget'),
208
-				'permissions' => $qb->expr()->literal(13),
209
-			]);
210
-		$qb->executeStatement();
211
-
212
-		$id = $qb->getLastInsertId();
213
-
214
-		$sharedBy = $this->createMock(IUser::class);
215
-		$sharedBy->method('getUID')->willReturn('sharedBy');
216
-		$shareOwner = $this->createMock(IUser::class);
217
-		$shareOwner->method('getUID')->willReturn('shareOwner');
218
-
219
-		$ownerPath = $this->createMock(File::class);
220
-		$shareOwnerFolder = $this->createMock(Folder::class);
221
-		$shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
222
-
223
-		$this->rootFolder
224
-			->method('getUserFolder')
225
-			->willReturnMap([
226
-				['shareOwner', $shareOwnerFolder],
227
-			]);
228
-
229
-		$share = $this->provider->getShareById($id);
230
-
231
-		$this->assertEquals($id, $share->getId());
232
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
233
-		$this->assertEquals('sharedWith', $share->getSharedWith());
234
-		$this->assertEquals('sharedBy', $share->getSharedBy());
235
-		$this->assertEquals('shareOwner', $share->getShareOwner());
236
-		$this->assertEquals($ownerPath, $share->getNode());
237
-		$this->assertEquals(13, $share->getPermissions());
238
-		$this->assertEquals(null, $share->getToken());
239
-		$this->assertEquals(null, $share->getExpirationDate());
240
-		$this->assertEquals('myTarget', $share->getTarget());
241
-	}
242
-
243
-	public function testGetShareByIdLazy(): void {
244
-		$qb = $this->dbConn->getQueryBuilder();
245
-
246
-		$qb->insert('share')
247
-			->values([
248
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
249
-				'share_with' => $qb->expr()->literal('sharedWith'),
250
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
251
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
252
-				'item_type' => $qb->expr()->literal('file'),
253
-				'file_source' => $qb->expr()->literal(42),
254
-				'file_target' => $qb->expr()->literal('myTarget'),
255
-				'permissions' => $qb->expr()->literal(13),
256
-			]);
257
-		$qb->executeStatement();
258
-
259
-		$id = $qb->getLastInsertId();
260
-
261
-		$this->rootFolder->expects($this->never())->method('getUserFolder');
262
-
263
-		$share = $this->provider->getShareById($id);
264
-
265
-		// We do not fetch the node so the rootfolder is never called.
266
-
267
-		$this->assertEquals($id, $share->getId());
268
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
269
-		$this->assertEquals('sharedWith', $share->getSharedWith());
270
-		$this->assertEquals('sharedBy', $share->getSharedBy());
271
-		$this->assertEquals('shareOwner', $share->getShareOwner());
272
-		$this->assertEquals(13, $share->getPermissions());
273
-		$this->assertEquals(null, $share->getToken());
274
-		$this->assertEquals(null, $share->getExpirationDate());
275
-		$this->assertEquals('myTarget', $share->getTarget());
276
-	}
277
-
278
-	public function testGetShareByIdLazy2(): void {
279
-		$qb = $this->dbConn->getQueryBuilder();
280
-
281
-		$qb->insert('share')
282
-			->values([
283
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
284
-				'share_with' => $qb->expr()->literal('sharedWith'),
285
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
286
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
287
-				'item_type' => $qb->expr()->literal('file'),
288
-				'file_source' => $qb->expr()->literal(42),
289
-				'file_target' => $qb->expr()->literal('myTarget'),
290
-				'permissions' => $qb->expr()->literal(13),
291
-			]);
292
-		$qb->executeStatement();
293
-
294
-		$id = $qb->getLastInsertId();
295
-
296
-		$ownerPath = $this->createMock(File::class);
297
-
298
-		$shareOwnerFolder = $this->createMock(Folder::class);
299
-		$shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
300
-
301
-		$this->rootFolder
302
-			->method('getUserFolder')
303
-			->with('shareOwner')
304
-			->willReturn($shareOwnerFolder);
305
-
306
-		$share = $this->provider->getShareById($id);
307
-
308
-		// We fetch the node so the root folder is eventually called
309
-
310
-		$this->assertEquals($id, $share->getId());
311
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
312
-		$this->assertEquals('sharedWith', $share->getSharedWith());
313
-		$this->assertEquals('sharedBy', $share->getSharedBy());
314
-		$this->assertEquals('shareOwner', $share->getShareOwner());
315
-		$this->assertEquals($ownerPath, $share->getNode());
316
-		$this->assertEquals(13, $share->getPermissions());
317
-		$this->assertEquals(null, $share->getToken());
318
-		$this->assertEquals(null, $share->getExpirationDate());
319
-		$this->assertEquals('myTarget', $share->getTarget());
320
-	}
321
-
322
-	public function testGetShareByIdGroupShare(): void {
323
-		$qb = $this->dbConn->getQueryBuilder();
324
-
325
-		$qb->insert('share')
326
-			->values([
327
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
328
-				'share_with' => $qb->expr()->literal('sharedWith'),
329
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
330
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
331
-				'item_type' => $qb->expr()->literal('file'),
332
-				'file_source' => $qb->expr()->literal(42),
333
-				'file_target' => $qb->expr()->literal('myTarget'),
334
-				'permissions' => $qb->expr()->literal(13),
335
-			]);
336
-		$this->assertEquals(1, $qb->executeStatement());
337
-
338
-		// Get the id
339
-		$id = $qb->getLastInsertId();
340
-
341
-		$ownerPath = $this->createMock(Folder::class);
342
-		$shareOwnerFolder = $this->createMock(Folder::class);
343
-		$shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
344
-
345
-		$this->rootFolder
346
-			->method('getUserFolder')
347
-			->willReturnMap([
348
-				['shareOwner', $shareOwnerFolder],
349
-			]);
350
-
351
-		$share = $this->provider->getShareById($id);
352
-
353
-		$this->assertEquals($id, $share->getId());
354
-		$this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
355
-		$this->assertEquals('sharedWith', $share->getSharedWith());
356
-		$this->assertEquals('sharedBy', $share->getSharedBy());
357
-		$this->assertEquals('shareOwner', $share->getShareOwner());
358
-		$this->assertEquals($ownerPath, $share->getNode());
359
-		$this->assertEquals(13, $share->getPermissions());
360
-		$this->assertEquals(null, $share->getToken());
361
-		$this->assertEquals(null, $share->getExpirationDate());
362
-		$this->assertEquals('myTarget', $share->getTarget());
363
-	}
364
-
365
-	public function testGetShareByIdUserGroupShare(): void {
366
-		$id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user0', 'user0', 'file', 42, 'myTarget', 31, null, null);
367
-		$this->addShareToDB(2, 'user1', 'user0', 'user0', 'file', 42, 'userTarget', 0, null, null, $id);
368
-
369
-		$user0 = $this->createMock(IUser::class);
370
-		$user0->method('getUID')->willReturn('user0');
371
-		$user1 = $this->createMock(IUser::class);
372
-		$user1->method('getUID')->willReturn('user1');
373
-
374
-		$group0 = $this->createMock(IGroup::class);
375
-		$group0->method('inGroup')->with($user1)->willReturn(true);
376
-		$group0->method('getDisplayName')->willReturn('g0-displayname');
377
-
378
-		$node = $this->createMock(Folder::class);
379
-		$node->method('getId')->willReturn(42);
380
-		$node->method('getName')->willReturn('myTarget');
381
-
382
-		$this->rootFolder->method('getUserFolder')->with('user0')->willReturnSelf();
383
-		$this->rootFolder->method('getFirstNodeById')->willReturn($node);
384
-
385
-		$this->userManager->method('get')->willReturnMap([
386
-			['user0', $user0],
387
-			['user1', $user1],
388
-		]);
389
-		$this->groupManager->method('get')->with('group0')->willReturn($group0);
390
-
391
-		$share = $this->provider->getShareById($id, 'user1');
392
-
393
-		$this->assertEquals($id, $share->getId());
394
-		$this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
395
-		$this->assertSame('group0', $share->getSharedWith());
396
-		$this->assertSame('user0', $share->getSharedBy());
397
-		$this->assertSame('user0', $share->getShareOwner());
398
-		$this->assertSame($node, $share->getNode());
399
-		$this->assertEquals(0, $share->getPermissions());
400
-		$this->assertEquals(null, $share->getToken());
401
-		$this->assertEquals(null, $share->getExpirationDate());
402
-		$this->assertEquals('userTarget', $share->getTarget());
403
-	}
404
-
405
-	public function testGetShareByIdLinkShare(): void {
406
-		$qb = $this->dbConn->getQueryBuilder();
407
-
408
-		$qb->insert('share')
409
-			->values([
410
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
411
-				'password' => $qb->expr()->literal('password'),
412
-				'password_by_talk' => $qb->expr()->literal(true),
413
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
414
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
415
-				'item_type' => $qb->expr()->literal('file'),
416
-				'file_source' => $qb->expr()->literal(42),
417
-				'file_target' => $qb->expr()->literal('myTarget'),
418
-				'permissions' => $qb->expr()->literal(13),
419
-				'token' => $qb->expr()->literal('token'),
420
-				'expiration' => $qb->expr()->literal('2000-01-02 00:00:00'),
421
-			]);
422
-		$this->assertEquals(1, $qb->executeStatement());
423
-
424
-		$id = $qb->getLastInsertId();
425
-
426
-		$ownerPath = $this->createMock(Folder::class);
427
-		$shareOwnerFolder = $this->createMock(Folder::class);
428
-		$shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
429
-
430
-		$this->rootFolder
431
-			->method('getUserFolder')
432
-			->willReturnMap([
433
-				['shareOwner', $shareOwnerFolder],
434
-			]);
435
-
436
-		$share = $this->provider->getShareById($id);
437
-
438
-		$this->assertEquals($id, $share->getId());
439
-		$this->assertEquals(IShare::TYPE_LINK, $share->getShareType());
440
-		$this->assertNull($share->getSharedWith());
441
-		$this->assertEquals('password', $share->getPassword());
442
-		$this->assertEquals(true, $share->getSendPasswordByTalk());
443
-		$this->assertEquals('sharedBy', $share->getSharedBy());
444
-		$this->assertEquals('shareOwner', $share->getShareOwner());
445
-		$this->assertEquals($ownerPath, $share->getNode());
446
-		$this->assertEquals(13, $share->getPermissions());
447
-		$this->assertEquals('token', $share->getToken());
448
-		$this->assertEquals(\DateTime::createFromFormat('Y-m-d H:i:s', '2000-01-02 00:00:00'), $share->getExpirationDate());
449
-		$this->assertEquals('myTarget', $share->getTarget());
450
-	}
451
-
452
-	public function testDeleteSingleShare(): void {
453
-		$qb = $this->dbConn->getQueryBuilder();
454
-		$qb->insert('share')
455
-			->values([
456
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
457
-				'share_with' => $qb->expr()->literal('sharedWith'),
458
-				'uid_owner' => $qb->expr()->literal('sharedBy'),
459
-				'item_type' => $qb->expr()->literal('file'),
460
-				'file_source' => $qb->expr()->literal(42),
461
-				'file_target' => $qb->expr()->literal('myTarget'),
462
-				'permissions' => $qb->expr()->literal(13),
463
-			]);
464
-		$this->assertEquals(1, $qb->executeStatement());
465
-
466
-		$id = (string)$qb->getLastInsertId();
467
-
468
-		$share = $this->createMock(IShare::class);
469
-		$share->method('getId')->willReturn($id);
470
-
471
-		/** @var DefaultShareProvider $provider */
472
-		$provider = $this->getMockBuilder(DefaultShareProvider::class)
473
-			->setConstructorArgs([
474
-				$this->dbConn,
475
-				$this->userManager,
476
-				$this->groupManager,
477
-				$this->rootFolder,
478
-				$this->mailer,
479
-				$this->defaults,
480
-				$this->l10nFactory,
481
-				$this->urlGenerator,
482
-				$this->timeFactory,
483
-				$this->logger,
484
-				$this->shareManager,
485
-				$this->config,
486
-			])
487
-			->onlyMethods(['getShareById'])
488
-			->getMock();
489
-
490
-		$provider->delete($share);
491
-
492
-		$qb = $this->dbConn->getQueryBuilder();
493
-		$qb->select('*')
494
-			->from('share');
495
-
496
-		$cursor = $qb->executeQuery();
497
-		$result = $cursor->fetchAllAssociative();
498
-		$cursor->closeCursor();
499
-
500
-		$this->assertEmpty($result);
501
-	}
502
-
503
-	public function testDeleteSingleShareLazy(): void {
504
-		$qb = $this->dbConn->getQueryBuilder();
505
-		$qb->insert('share')
506
-			->values([
507
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
508
-				'share_with' => $qb->expr()->literal('sharedWith'),
509
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
510
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
511
-				'item_type' => $qb->expr()->literal('file'),
512
-				'file_source' => $qb->expr()->literal(42),
513
-				'file_target' => $qb->expr()->literal('myTarget'),
514
-				'permissions' => $qb->expr()->literal(13),
515
-			]);
516
-		$this->assertEquals(1, $qb->executeStatement());
517
-
518
-		$id = $qb->getLastInsertId();
519
-
520
-		$this->rootFolder->expects($this->never())->method($this->anything());
521
-
522
-		$share = $this->provider->getShareById($id);
523
-		$this->provider->delete($share);
524
-
525
-		$qb = $this->dbConn->getQueryBuilder();
526
-		$qb->select('*')
527
-			->from('share');
528
-
529
-		$cursor = $qb->executeQuery();
530
-		$result = $cursor->fetchAllAssociative();
531
-		$cursor->closeCursor();
532
-
533
-		$this->assertEmpty($result);
534
-	}
535
-
536
-	public function testDeleteGroupShareWithUserGroupShares(): void {
537
-		$qb = $this->dbConn->getQueryBuilder();
538
-		$qb->insert('share')
539
-			->values([
540
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
541
-				'share_with' => $qb->expr()->literal('sharedWith'),
542
-				'uid_owner' => $qb->expr()->literal('sharedBy'),
543
-				'item_type' => $qb->expr()->literal('file'),
544
-				'file_source' => $qb->expr()->literal(42),
545
-				'file_target' => $qb->expr()->literal('myTarget'),
546
-				'permissions' => $qb->expr()->literal(13),
547
-			]);
548
-		$this->assertEquals(1, $qb->executeStatement());
549
-		$id = (string)$qb->getLastInsertId();
550
-
551
-		$qb = $this->dbConn->getQueryBuilder();
552
-		$qb->insert('share')
553
-			->values([
554
-				'share_type' => $qb->expr()->literal(2),
555
-				'share_with' => $qb->expr()->literal('sharedWithUser'),
556
-				'uid_owner' => $qb->expr()->literal('sharedBy'),
557
-				'item_type' => $qb->expr()->literal('file'),
558
-				'file_source' => $qb->expr()->literal(42),
559
-				'file_target' => $qb->expr()->literal('myTarget'),
560
-				'permissions' => $qb->expr()->literal(13),
561
-				'parent' => $qb->expr()->literal($id),
562
-			]);
563
-		$this->assertEquals(1, $qb->executeStatement());
564
-
565
-		$share = $this->createMock(IShare::class);
566
-		$share->method('getId')->willReturn($id);
567
-		$share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
568
-
569
-		/** @var DefaultShareProvider $provider */
570
-		$provider = $this->getMockBuilder(DefaultShareProvider::class)
571
-			->setConstructorArgs([
572
-				$this->dbConn,
573
-				$this->userManager,
574
-				$this->groupManager,
575
-				$this->rootFolder,
576
-				$this->mailer,
577
-				$this->defaults,
578
-				$this->l10nFactory,
579
-				$this->urlGenerator,
580
-				$this->timeFactory,
581
-				$this->logger,
582
-				$this->shareManager,
583
-				$this->config,
584
-			])
585
-			->onlyMethods(['getShareById'])
586
-			->getMock();
587
-
588
-		$provider->delete($share);
589
-
590
-		$qb = $this->dbConn->getQueryBuilder();
591
-		$qb->select('*')
592
-			->from('share');
593
-
594
-		$cursor = $qb->executeQuery();
595
-		$result = $cursor->fetchAllAssociative();
596
-		$cursor->closeCursor();
597
-
598
-		$this->assertEmpty($result);
599
-	}
600
-
601
-	public function testGetChildren(): void {
602
-		$qb = $this->dbConn->getQueryBuilder();
603
-		$qb->insert('share')
604
-			->values([
605
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
606
-				'share_with' => $qb->expr()->literal('sharedWith'),
607
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
608
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
609
-				'item_type' => $qb->expr()->literal('file'),
610
-				'file_source' => $qb->expr()->literal(42),
611
-				'file_target' => $qb->expr()->literal('myTarget'),
612
-				'permissions' => $qb->expr()->literal(13),
613
-			]);
614
-		$qb->executeStatement();
615
-
616
-		// Get the id
617
-		$id = (string)$qb->getLastInsertId();
618
-
619
-		$qb = $this->dbConn->getQueryBuilder();
620
-		$qb->insert('share')
621
-			->values([
622
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
623
-				'share_with' => $qb->expr()->literal('user1'),
624
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
625
-				'uid_initiator' => $qb->expr()->literal('user2'),
626
-				'item_type' => $qb->expr()->literal('file'),
627
-				'file_source' => $qb->expr()->literal(1),
628
-				'file_target' => $qb->expr()->literal('myTarget1'),
629
-				'permissions' => $qb->expr()->literal(2),
630
-				'parent' => $qb->expr()->literal($id),
631
-			]);
632
-		$qb->executeStatement();
633
-
634
-		$qb = $this->dbConn->getQueryBuilder();
635
-		$qb->insert('share')
636
-			->values([
637
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
638
-				'share_with' => $qb->expr()->literal('group1'),
639
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
640
-				'uid_initiator' => $qb->expr()->literal('user3'),
641
-				'item_type' => $qb->expr()->literal('folder'),
642
-				'file_source' => $qb->expr()->literal(3),
643
-				'file_target' => $qb->expr()->literal('myTarget2'),
644
-				'permissions' => $qb->expr()->literal(4),
645
-				'parent' => $qb->expr()->literal($id),
646
-			]);
647
-		$qb->executeStatement();
648
-
649
-		$ownerPath = $this->createMock(Folder::class);
650
-		$ownerFolder = $this->createMock(Folder::class);
651
-		$ownerFolder->method('getFirstNodeById')->willReturn($ownerPath);
652
-
653
-		$this->rootFolder
654
-			->method('getUserFolder')
655
-			->willReturnMap([
656
-				['shareOwner', $ownerFolder],
657
-			]);
658
-
659
-		$share = $this->createMock(IShare::class);
660
-		$share->method('getId')->willReturn($id);
661
-
662
-		$children = $this->provider->getChildren($share);
663
-
664
-		$this->assertCount(2, $children);
665
-
666
-		//Child1
667
-		$this->assertEquals(IShare::TYPE_USER, $children[0]->getShareType());
668
-		$this->assertEquals('user1', $children[0]->getSharedWith());
669
-		$this->assertEquals('user2', $children[0]->getSharedBy());
670
-		$this->assertEquals('shareOwner', $children[0]->getShareOwner());
671
-		$this->assertEquals($ownerPath, $children[0]->getNode());
672
-		$this->assertEquals(2, $children[0]->getPermissions());
673
-		$this->assertEquals(null, $children[0]->getToken());
674
-		$this->assertEquals(null, $children[0]->getExpirationDate());
675
-		$this->assertEquals('myTarget1', $children[0]->getTarget());
676
-
677
-		//Child2
678
-		$this->assertEquals(IShare::TYPE_GROUP, $children[1]->getShareType());
679
-		$this->assertEquals('group1', $children[1]->getSharedWith());
680
-		$this->assertEquals('user3', $children[1]->getSharedBy());
681
-		$this->assertEquals('shareOwner', $children[1]->getShareOwner());
682
-		$this->assertEquals($ownerPath, $children[1]->getNode());
683
-		$this->assertEquals(4, $children[1]->getPermissions());
684
-		$this->assertEquals(null, $children[1]->getToken());
685
-		$this->assertEquals(null, $children[1]->getExpirationDate());
686
-		$this->assertEquals('myTarget2', $children[1]->getTarget());
687
-	}
688
-
689
-	public function testCreateUserShare(): void {
690
-		$share = new Share($this->rootFolder, $this->userManager);
691
-
692
-		$shareOwner = $this->createMock(IUser::class);
693
-		$shareOwner->method('getUID')->willReturn('shareOwner');
694
-
695
-		$path = $this->createMock(File::class);
696
-		$path->method('getId')->willReturn(100);
697
-		$path->method('getOwner')->willReturn($shareOwner);
698
-
699
-		$ownerFolder = $this->createMock(Folder::class);
700
-		$userFolder = $this->createMock(Folder::class);
701
-		$this->rootFolder
702
-			->method('getUserFolder')
703
-			->willReturnMap([
704
-				['sharedBy', $userFolder],
705
-				['shareOwner', $ownerFolder],
706
-			]);
707
-
708
-		$userFolder->method('getFirstNodeById')
709
-			->with(100)
710
-			->willReturn($path);
711
-		$ownerFolder->method('getFirstNodeById')
712
-			->with(100)
713
-			->willReturn($path);
714
-
715
-		$share->setShareType(IShare::TYPE_USER);
716
-		$share->setSharedWith('sharedWith');
717
-		$share->setSharedBy('sharedBy');
718
-		$share->setShareOwner('shareOwner');
719
-		$share->setNode($path);
720
-		$share->setSharedWithDisplayName('Displayed Name');
721
-		$share->setSharedWithAvatar('/path/to/image.svg');
722
-		$share->setPermissions(1);
723
-
724
-		$attrs = new ShareAttributes();
725
-		$attrs->setAttribute('permissions', 'download', true);
726
-		$share->setAttributes($attrs);
727
-
728
-		$share->setTarget('/target');
729
-
730
-		$share2 = $this->provider->create($share);
731
-
732
-		$this->assertNotNull($share2->getId());
733
-		$this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
734
-		$this->assertSame(IShare::TYPE_USER, $share2->getShareType());
735
-		$this->assertSame('sharedWith', $share2->getSharedWith());
736
-		$this->assertSame('sharedBy', $share2->getSharedBy());
737
-		$this->assertSame('shareOwner', $share2->getShareOwner());
738
-		$this->assertSame(1, $share2->getPermissions());
739
-		$this->assertSame('/target', $share2->getTarget());
740
-		$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
741
-		$this->assertSame($path, $share2->getNode());
742
-
743
-		// Data is kept after creation
744
-		$this->assertSame('Displayed Name', $share->getSharedWithDisplayName());
745
-		$this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar());
746
-		$this->assertSame('Displayed Name', $share2->getSharedWithDisplayName());
747
-		$this->assertSame('/path/to/image.svg', $share2->getSharedWithAvatar());
748
-
749
-		$this->assertSame(
750
-			[
751
-				[
752
-					'scope' => 'permissions',
753
-					'key' => 'download',
754
-					'value' => true
755
-				]
756
-			],
757
-			$share->getAttributes()->toArray()
758
-		);
759
-	}
760
-
761
-	public function testCreateGroupShare(): void {
762
-		$share = new Share($this->rootFolder, $this->userManager);
763
-
764
-		$shareOwner = $this->createMock(IUser::class);
765
-		$shareOwner->method('getUID')->willReturn('shareOwner');
766
-
767
-		$path = $this->createMock(Folder::class);
768
-		$path->method('getId')->willReturn(100);
769
-		$path->method('getOwner')->willReturn($shareOwner);
770
-
771
-		$ownerFolder = $this->createMock(Folder::class);
772
-		$userFolder = $this->createMock(Folder::class);
773
-		$this->rootFolder
774
-			->method('getUserFolder')
775
-			->willReturnMap([
776
-				['sharedBy', $userFolder],
777
-				['shareOwner', $ownerFolder],
778
-			]);
779
-
780
-		$userFolder->method('getFirstNodeById')
781
-			->with(100)
782
-			->willReturn($path);
783
-		$ownerFolder->method('getFirstNodeById')
784
-			->with(100)
785
-			->willReturn($path);
786
-
787
-		$share->setShareType(IShare::TYPE_GROUP);
788
-		$share->setSharedWith('sharedWith');
789
-		$share->setSharedBy('sharedBy');
790
-		$share->setShareOwner('shareOwner');
791
-		$share->setNode($path);
792
-		$share->setPermissions(1);
793
-		$share->setSharedWithDisplayName('Displayed Name');
794
-		$share->setSharedWithAvatar('/path/to/image.svg');
795
-		$share->setTarget('/target');
796
-		$attrs = new ShareAttributes();
797
-		$attrs->setAttribute('permissions', 'download', true);
798
-		$share->setAttributes($attrs);
799
-
800
-		$share2 = $this->provider->create($share);
801
-
802
-		$this->assertNotNull($share2->getId());
803
-		$this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
804
-		$this->assertSame(IShare::TYPE_GROUP, $share2->getShareType());
805
-		$this->assertSame('sharedWith', $share2->getSharedWith());
806
-		$this->assertSame('sharedBy', $share2->getSharedBy());
807
-		$this->assertSame('shareOwner', $share2->getShareOwner());
808
-		$this->assertSame(1, $share2->getPermissions());
809
-		$this->assertSame('/target', $share2->getTarget());
810
-		$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
811
-		$this->assertSame($path, $share2->getNode());
812
-
813
-		// Data is kept after creation
814
-		$this->assertSame('Displayed Name', $share->getSharedWithDisplayName());
815
-		$this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar());
816
-		$this->assertSame('Displayed Name', $share2->getSharedWithDisplayName());
817
-		$this->assertSame('/path/to/image.svg', $share2->getSharedWithAvatar());
818
-
819
-		$this->assertSame(
820
-			[
821
-				[
822
-					'scope' => 'permissions',
823
-					'key' => 'download',
824
-					'value' => true
825
-				]
826
-			],
827
-			$share->getAttributes()->toArray()
828
-		);
829
-	}
830
-
831
-	public function testCreateLinkShare(): void {
832
-		$share = new Share($this->rootFolder, $this->userManager);
833
-
834
-		$shareOwner = $this->createMock(IUser::class);
835
-		$shareOwner->method('getUID')->willReturn('shareOwner');
836
-
837
-		$path = $this->createMock(Folder::class);
838
-		$path->method('getId')->willReturn(100);
839
-		$path->method('getOwner')->willReturn($shareOwner);
840
-
841
-		$ownerFolder = $this->createMock(Folder::class);
842
-		$userFolder = $this->createMock(Folder::class);
843
-		$this->rootFolder
844
-			->method('getUserFolder')
845
-			->willReturnMap([
846
-				['sharedBy', $userFolder],
847
-				['shareOwner', $ownerFolder],
848
-			]);
849
-
850
-		$userFolder->method('getFirstNodeById')
851
-			->with(100)
852
-			->willReturn($path);
853
-		$ownerFolder->method('getFirstNodeById')
854
-			->with(100)
855
-			->willReturn($path);
856
-
857
-		$share->setShareType(IShare::TYPE_LINK);
858
-		$share->setSharedBy('sharedBy');
859
-		$share->setShareOwner('shareOwner');
860
-		$share->setNode($path);
861
-		$share->setPermissions(1);
862
-		$share->setPassword('password');
863
-		$share->setSendPasswordByTalk(true);
864
-		$share->setToken('token');
865
-		$expireDate = new \DateTime();
866
-		$share->setExpirationDate($expireDate);
867
-		$share->setTarget('/target');
868
-
869
-		$share2 = $this->provider->create($share);
870
-
871
-		$this->assertNotNull($share2->getId());
872
-		$this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
873
-		$this->assertSame(IShare::TYPE_LINK, $share2->getShareType());
874
-		$this->assertSame('sharedBy', $share2->getSharedBy());
875
-		$this->assertSame('shareOwner', $share2->getShareOwner());
876
-		$this->assertSame(1, $share2->getPermissions());
877
-		$this->assertSame('/target', $share2->getTarget());
878
-		$this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
879
-		$this->assertSame($path, $share2->getNode());
880
-		$this->assertSame('password', $share2->getPassword());
881
-		$this->assertSame(true, $share2->getSendPasswordByTalk());
882
-		$this->assertSame('token', $share2->getToken());
883
-		$this->assertEquals($expireDate->getTimestamp(), $share2->getExpirationDate()->getTimestamp());
884
-	}
885
-
886
-	public function testGetShareByToken(): void {
887
-		$qb = $this->dbConn->getQueryBuilder();
888
-
889
-		$qb->insert('share')
890
-			->values([
891
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
892
-				'password' => $qb->expr()->literal('password'),
893
-				'password_by_talk' => $qb->expr()->literal(true),
894
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
895
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
896
-				'item_type' => $qb->expr()->literal('file'),
897
-				'file_source' => $qb->expr()->literal(42),
898
-				'file_target' => $qb->expr()->literal('myTarget'),
899
-				'permissions' => $qb->expr()->literal(13),
900
-				'token' => $qb->expr()->literal('secrettoken'),
901
-				'label' => $qb->expr()->literal('the label'),
902
-			]);
903
-		$qb->executeStatement();
904
-		$id = $qb->getLastInsertId();
905
-
906
-		$file = $this->createMock(File::class);
907
-
908
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
909
-		$this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
910
-
911
-		$share = $this->provider->getShareByToken('secrettoken');
912
-		$this->assertEquals($id, $share->getId());
913
-		$this->assertSame('shareOwner', $share->getShareOwner());
914
-		$this->assertSame('sharedBy', $share->getSharedBy());
915
-		$this->assertSame('secrettoken', $share->getToken());
916
-		$this->assertSame('password', $share->getPassword());
917
-		$this->assertSame('the label', $share->getLabel());
918
-		$this->assertSame(true, $share->getSendPasswordByTalk());
919
-		$this->assertSame(null, $share->getSharedWith());
920
-	}
921
-
922
-	/**
923
-	 * Assert that if no label is provided the label is correctly,
924
-	 * as types on IShare, a string and not null
925
-	 */
926
-	public function testGetShareByTokenNullLabel(): void {
927
-		$qb = $this->dbConn->getQueryBuilder();
928
-
929
-		$qb->insert('share')
930
-			->values([
931
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
932
-				'password' => $qb->expr()->literal('password'),
933
-				'password_by_talk' => $qb->expr()->literal(true),
934
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
935
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
936
-				'item_type' => $qb->expr()->literal('file'),
937
-				'file_source' => $qb->expr()->literal(42),
938
-				'file_target' => $qb->expr()->literal('myTarget'),
939
-				'permissions' => $qb->expr()->literal(13),
940
-				'token' => $qb->expr()->literal('secrettoken'),
941
-			]);
942
-		$qb->executeStatement();
943
-		$id = $qb->getLastInsertId();
944
-
945
-		$file = $this->createMock(File::class);
946
-
947
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
948
-		$this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
949
-
950
-		$share = $this->provider->getShareByToken('secrettoken');
951
-		$this->assertEquals($id, $share->getId());
952
-		$this->assertSame('', $share->getLabel());
953
-	}
954
-
955
-	public function testGetShareByTokenNotFound(): void {
956
-		$this->expectException(ShareNotFound::class);
957
-
958
-		$this->provider->getShareByToken('invalidtoken');
959
-	}
960
-
961
-	private function createTestStorageEntry($storageStringId) {
962
-		$qb = $this->dbConn->getQueryBuilder();
963
-		$qb->insert('storages')
964
-			->values([
965
-				'id' => $qb->expr()->literal($storageStringId),
966
-			]);
967
-		$this->assertEquals(1, $qb->executeStatement());
968
-		return $qb->getLastInsertId();
969
-	}
970
-
971
-	private function createTestFileEntry($path, $storage = 1) {
972
-		$qb = $this->dbConn->getQueryBuilder();
973
-		$qb->insert('filecache')
974
-			->values([
975
-				'storage' => $qb->createNamedParameter($storage, IQueryBuilder::PARAM_INT),
976
-				'path' => $qb->createNamedParameter($path),
977
-				'path_hash' => $qb->createNamedParameter(md5($path)),
978
-				'name' => $qb->createNamedParameter(basename($path)),
979
-			]);
980
-		$this->assertEquals(1, $qb->executeStatement());
981
-		return $qb->getLastInsertId();
982
-	}
983
-
984
-	public static function storageAndFileNameProvider(): array {
985
-		return [
986
-			// regular file on regular storage
987
-			['home::shareOwner', 'files/test.txt', 'files/test2.txt'],
988
-			// regular file on external storage
989
-			['smb::whatever', 'files/test.txt', 'files/test2.txt'],
990
-			// regular file on external storage in trashbin-like folder,
991
-			['smb::whatever', 'files_trashbin/files/test.txt', 'files_trashbin/files/test2.txt'],
992
-		];
993
-	}
994
-
995
-	#[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
996
-	public function testGetSharedWithUser($storageStringId, $fileName1, $fileName2): void {
997
-		$storageId = $this->createTestStorageEntry($storageStringId);
998
-		$fileId = $this->createTestFileEntry($fileName1, $storageId);
999
-		$fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1000
-		$qb = $this->dbConn->getQueryBuilder();
1001
-		$qb->insert('share')
1002
-			->values([
1003
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1004
-				'share_with' => $qb->expr()->literal('sharedWith'),
1005
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1006
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1007
-				'item_type' => $qb->expr()->literal('file'),
1008
-				'file_source' => $qb->expr()->literal($fileId),
1009
-				'file_target' => $qb->expr()->literal('myTarget'),
1010
-				'permissions' => $qb->expr()->literal(13),
1011
-			]);
1012
-		$this->assertEquals(1, $qb->executeStatement());
1013
-		$id = $qb->getLastInsertId();
1014
-
1015
-		$qb = $this->dbConn->getQueryBuilder();
1016
-		$qb->insert('share')
1017
-			->values([
1018
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1019
-				'share_with' => $qb->expr()->literal('sharedWith2'),
1020
-				'uid_owner' => $qb->expr()->literal('shareOwner2'),
1021
-				'uid_initiator' => $qb->expr()->literal('sharedBy2'),
1022
-				'item_type' => $qb->expr()->literal('file2'),
1023
-				'file_source' => $qb->expr()->literal($fileId2),
1024
-				'file_target' => $qb->expr()->literal('myTarget2'),
1025
-				'permissions' => $qb->expr()->literal(14),
1026
-			]);
1027
-		$this->assertEquals(1, $qb->executeStatement());
1028
-
1029
-		$file = $this->createMock(File::class);
1030
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1031
-		$this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file);
1032
-
1033
-		$share = $this->provider->getSharedWith('sharedWith', IShare::TYPE_USER, null, 1, 0);
1034
-		$this->assertCount(1, $share);
1035
-
1036
-		$share = $share[0];
1037
-		$this->assertEquals($id, $share->getId());
1038
-		$this->assertEquals('sharedWith', $share->getSharedWith());
1039
-		$this->assertEquals('shareOwner', $share->getShareOwner());
1040
-		$this->assertEquals('sharedBy', $share->getSharedBy());
1041
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1042
-	}
1043
-
1044
-	#[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1045
-	public function testGetSharedWithGroup($storageStringId, $fileName1, $fileName2): void {
1046
-		$storageId = $this->createTestStorageEntry($storageStringId);
1047
-		$fileId = $this->createTestFileEntry($fileName1, $storageId);
1048
-		$fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1049
-		$qb = $this->dbConn->getQueryBuilder();
1050
-		$qb->insert('share')
1051
-			->values([
1052
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1053
-				'share_with' => $qb->expr()->literal('sharedWith'),
1054
-				'uid_owner' => $qb->expr()->literal('shareOwner2'),
1055
-				'uid_initiator' => $qb->expr()->literal('sharedBy2'),
1056
-				'item_type' => $qb->expr()->literal('file'),
1057
-				'file_source' => $qb->expr()->literal($fileId2),
1058
-				'file_target' => $qb->expr()->literal('myTarget2'),
1059
-				'permissions' => $qb->expr()->literal(14),
1060
-			]);
1061
-		$this->assertEquals(1, $qb->executeStatement());
1062
-
1063
-		$qb = $this->dbConn->getQueryBuilder();
1064
-		$qb->insert('share')
1065
-			->values([
1066
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1067
-				'share_with' => $qb->expr()->literal('sharedWith'),
1068
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1069
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1070
-				'item_type' => $qb->expr()->literal('file'),
1071
-				'file_source' => $qb->expr()->literal($fileId),
1072
-				'file_target' => $qb->expr()->literal('myTarget'),
1073
-				'permissions' => $qb->expr()->literal(13),
1074
-			]);
1075
-		$this->assertEquals(1, $qb->executeStatement());
1076
-		$id = $qb->getLastInsertId();
1077
-
1078
-		$groups = [];
1079
-		foreach (range(0, 100) as $i) {
1080
-			$groups[] = 'group' . $i;
1081
-		}
1082
-
1083
-		$groups[] = 'sharedWith';
1084
-
1085
-		$user = $this->createMock(IUser::class);
1086
-		$user->method('getUID')->willReturn('sharedWith');
1087
-		$owner = $this->createMock(IUser::class);
1088
-		$owner->method('getUID')->willReturn('shareOwner');
1089
-		$initiator = $this->createMock(IUser::class);
1090
-		$initiator->method('getUID')->willReturn('sharedBy');
1091
-
1092
-		$this->userManager->method('get')->willReturnMap([
1093
-			['sharedWith', $user],
1094
-			['shareOwner', $owner],
1095
-			['sharedBy', $initiator],
1096
-		]);
1097
-		$this->groupManager
1098
-			->method('getUserGroupIds')
1099
-			->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'sharedWith' ? $groups : []));
1100
-
1101
-		$file = $this->createMock(File::class);
1102
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1103
-		$this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file);
1104
-
1105
-		$share = $this->provider->getSharedWith('sharedWith', IShare::TYPE_GROUP, null, 20, 1);
1106
-		$this->assertCount(1, $share);
1107
-
1108
-		$share = $share[0];
1109
-		$this->assertEquals($id, $share->getId());
1110
-		$this->assertEquals('sharedWith', $share->getSharedWith());
1111
-		$this->assertEquals('shareOwner', $share->getShareOwner());
1112
-		$this->assertEquals('sharedBy', $share->getSharedBy());
1113
-		$this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
1114
-	}
1115
-
1116
-	#[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1117
-	public function testGetSharedWithGroupUserModified($storageStringId, $fileName1, $fileName2): void {
1118
-		$storageId = $this->createTestStorageEntry($storageStringId);
1119
-		$fileId = $this->createTestFileEntry($fileName1, $storageId);
1120
-		$qb = $this->dbConn->getQueryBuilder();
1121
-		$qb->insert('share')
1122
-			->values([
1123
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1124
-				'share_with' => $qb->expr()->literal('sharedWith'),
1125
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1126
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1127
-				'item_type' => $qb->expr()->literal('file'),
1128
-				'file_source' => $qb->expr()->literal($fileId),
1129
-				'file_target' => $qb->expr()->literal('myTarget'),
1130
-				'permissions' => $qb->expr()->literal(13),
1131
-			]);
1132
-		$this->assertEquals(1, $qb->executeStatement());
1133
-		$id = $qb->getLastInsertId();
1134
-
1135
-		/*
47
+    /** @var IDBConnection */
48
+    protected $dbConn;
49
+
50
+    /** @var IUserManager | MockObject */
51
+    protected $userManager;
52
+
53
+    /** @var IGroupManager | MockObject */
54
+    protected $groupManager;
55
+
56
+    /** @var IRootFolder | MockObject */
57
+    protected $rootFolder;
58
+
59
+    /** @var DefaultShareProvider */
60
+    protected $provider;
61
+
62
+    /** @var MockObject|IMailer */
63
+    protected $mailer;
64
+
65
+    /** @var IFactory|MockObject */
66
+    protected $l10nFactory;
67
+
68
+    /** @var MockObject|IL10N */
69
+    protected $l10n;
70
+
71
+    /** @var MockObject|Defaults */
72
+    protected $defaults;
73
+
74
+    /** @var MockObject|IURLGenerator */
75
+    protected $urlGenerator;
76
+
77
+    /** @var ITimeFactory|MockObject */
78
+    protected $timeFactory;
79
+
80
+    /** @var LoggerInterface|MockObject */
81
+    protected $logger;
82
+
83
+    protected IConfig&MockObject $config;
84
+
85
+    protected IShareManager&MockObject $shareManager;
86
+
87
+    protected function setUp(): void {
88
+        $this->dbConn = Server::get(IDBConnection::class);
89
+        $this->userManager = $this->createMock(IUserManager::class);
90
+        $this->groupManager = $this->createMock(IGroupManager::class);
91
+        $this->rootFolder = $this->createMock(IRootFolder::class);
92
+        $this->mailer = $this->createMock(IMailer::class);
93
+        $this->l10nFactory = $this->createMock(IFactory::class);
94
+        $this->l10n = $this->createMock(IL10N::class);
95
+        $this->defaults = $this->getMockBuilder(Defaults::class)->disableOriginalConstructor()->getMock();
96
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
97
+        $this->timeFactory = $this->createMock(ITimeFactory::class);
98
+        $this->logger = $this->createMock(LoggerInterface::class);
99
+        $this->shareManager = $this->createMock(IShareManager::class);
100
+        $this->config = $this->createMock(IConfig::class);
101
+
102
+        $this->userManager->expects($this->any())->method('userExists')->willReturn(true);
103
+        $this->timeFactory->expects($this->any())->method('now')->willReturn(new \DateTimeImmutable('2023-05-04 00:00 Europe/Berlin'));
104
+
105
+        //Empty share table
106
+        $this->dbConn->getQueryBuilder()->delete('share')->executeStatement();
107
+
108
+        $this->provider = new DefaultShareProvider(
109
+            $this->dbConn,
110
+            $this->userManager,
111
+            $this->groupManager,
112
+            $this->rootFolder,
113
+            $this->mailer,
114
+            $this->defaults,
115
+            $this->l10nFactory,
116
+            $this->urlGenerator,
117
+            $this->timeFactory,
118
+            $this->logger,
119
+            $this->shareManager,
120
+            $this->config,
121
+        );
122
+    }
123
+
124
+    protected function tearDown(): void {
125
+        $this->dbConn->getQueryBuilder()->delete('share')->executeStatement();
126
+        $this->dbConn->getQueryBuilder()->delete('filecache')->runAcrossAllShards()->executeStatement();
127
+        $this->dbConn->getQueryBuilder()->delete('storages')->executeStatement();
128
+    }
129
+
130
+    /**
131
+     * @param int $shareType
132
+     * @param string $sharedWith
133
+     * @param string $sharedBy
134
+     * @param string $shareOwner
135
+     * @param string $itemType
136
+     * @param int $fileSource
137
+     * @param string $fileTarget
138
+     * @param int $permissions
139
+     * @param $token
140
+     * @param $expiration
141
+     * @return int
142
+     */
143
+    private function addShareToDB($shareType, $sharedWith, $sharedBy, $shareOwner,
144
+        $itemType, $fileSource, $fileTarget, $permissions, $token, $expiration,
145
+        $parent = null) {
146
+        $qb = $this->dbConn->getQueryBuilder();
147
+        $qb->insert('share');
148
+
149
+        if ($shareType) {
150
+            $qb->setValue('share_type', $qb->expr()->literal($shareType));
151
+        }
152
+        if ($sharedWith) {
153
+            $qb->setValue('share_with', $qb->expr()->literal($sharedWith));
154
+        }
155
+        if ($sharedBy) {
156
+            $qb->setValue('uid_initiator', $qb->expr()->literal($sharedBy));
157
+        }
158
+        if ($shareOwner) {
159
+            $qb->setValue('uid_owner', $qb->expr()->literal($shareOwner));
160
+        }
161
+        if ($itemType) {
162
+            $qb->setValue('item_type', $qb->expr()->literal($itemType));
163
+        }
164
+        if ($fileSource) {
165
+            $qb->setValue('file_source', $qb->expr()->literal($fileSource));
166
+        }
167
+        if ($fileTarget) {
168
+            $qb->setValue('file_target', $qb->expr()->literal($fileTarget));
169
+        }
170
+        if ($permissions) {
171
+            $qb->setValue('permissions', $qb->expr()->literal($permissions));
172
+        }
173
+        if ($token) {
174
+            $qb->setValue('token', $qb->expr()->literal($token));
175
+        }
176
+        if ($expiration) {
177
+            $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATETIME_MUTABLE));
178
+        }
179
+        if ($parent) {
180
+            $qb->setValue('parent', $qb->expr()->literal($parent));
181
+        }
182
+
183
+        $this->assertEquals(1, $qb->executeStatement());
184
+        return $qb->getLastInsertId();
185
+    }
186
+
187
+
188
+
189
+
190
+    public function testGetShareByIdNotExist(): void {
191
+        $this->expectException(ShareNotFound::class);
192
+
193
+        $this->provider->getShareById(1);
194
+    }
195
+
196
+    public function testGetShareByIdUserShare(): void {
197
+        $qb = $this->dbConn->getQueryBuilder();
198
+
199
+        $qb->insert('share')
200
+            ->values([
201
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
202
+                'share_with' => $qb->expr()->literal('sharedWith'),
203
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
204
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
205
+                'item_type' => $qb->expr()->literal('file'),
206
+                'file_source' => $qb->expr()->literal(42),
207
+                'file_target' => $qb->expr()->literal('myTarget'),
208
+                'permissions' => $qb->expr()->literal(13),
209
+            ]);
210
+        $qb->executeStatement();
211
+
212
+        $id = $qb->getLastInsertId();
213
+
214
+        $sharedBy = $this->createMock(IUser::class);
215
+        $sharedBy->method('getUID')->willReturn('sharedBy');
216
+        $shareOwner = $this->createMock(IUser::class);
217
+        $shareOwner->method('getUID')->willReturn('shareOwner');
218
+
219
+        $ownerPath = $this->createMock(File::class);
220
+        $shareOwnerFolder = $this->createMock(Folder::class);
221
+        $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
222
+
223
+        $this->rootFolder
224
+            ->method('getUserFolder')
225
+            ->willReturnMap([
226
+                ['shareOwner', $shareOwnerFolder],
227
+            ]);
228
+
229
+        $share = $this->provider->getShareById($id);
230
+
231
+        $this->assertEquals($id, $share->getId());
232
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
233
+        $this->assertEquals('sharedWith', $share->getSharedWith());
234
+        $this->assertEquals('sharedBy', $share->getSharedBy());
235
+        $this->assertEquals('shareOwner', $share->getShareOwner());
236
+        $this->assertEquals($ownerPath, $share->getNode());
237
+        $this->assertEquals(13, $share->getPermissions());
238
+        $this->assertEquals(null, $share->getToken());
239
+        $this->assertEquals(null, $share->getExpirationDate());
240
+        $this->assertEquals('myTarget', $share->getTarget());
241
+    }
242
+
243
+    public function testGetShareByIdLazy(): void {
244
+        $qb = $this->dbConn->getQueryBuilder();
245
+
246
+        $qb->insert('share')
247
+            ->values([
248
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
249
+                'share_with' => $qb->expr()->literal('sharedWith'),
250
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
251
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
252
+                'item_type' => $qb->expr()->literal('file'),
253
+                'file_source' => $qb->expr()->literal(42),
254
+                'file_target' => $qb->expr()->literal('myTarget'),
255
+                'permissions' => $qb->expr()->literal(13),
256
+            ]);
257
+        $qb->executeStatement();
258
+
259
+        $id = $qb->getLastInsertId();
260
+
261
+        $this->rootFolder->expects($this->never())->method('getUserFolder');
262
+
263
+        $share = $this->provider->getShareById($id);
264
+
265
+        // We do not fetch the node so the rootfolder is never called.
266
+
267
+        $this->assertEquals($id, $share->getId());
268
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
269
+        $this->assertEquals('sharedWith', $share->getSharedWith());
270
+        $this->assertEquals('sharedBy', $share->getSharedBy());
271
+        $this->assertEquals('shareOwner', $share->getShareOwner());
272
+        $this->assertEquals(13, $share->getPermissions());
273
+        $this->assertEquals(null, $share->getToken());
274
+        $this->assertEquals(null, $share->getExpirationDate());
275
+        $this->assertEquals('myTarget', $share->getTarget());
276
+    }
277
+
278
+    public function testGetShareByIdLazy2(): void {
279
+        $qb = $this->dbConn->getQueryBuilder();
280
+
281
+        $qb->insert('share')
282
+            ->values([
283
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
284
+                'share_with' => $qb->expr()->literal('sharedWith'),
285
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
286
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
287
+                'item_type' => $qb->expr()->literal('file'),
288
+                'file_source' => $qb->expr()->literal(42),
289
+                'file_target' => $qb->expr()->literal('myTarget'),
290
+                'permissions' => $qb->expr()->literal(13),
291
+            ]);
292
+        $qb->executeStatement();
293
+
294
+        $id = $qb->getLastInsertId();
295
+
296
+        $ownerPath = $this->createMock(File::class);
297
+
298
+        $shareOwnerFolder = $this->createMock(Folder::class);
299
+        $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
300
+
301
+        $this->rootFolder
302
+            ->method('getUserFolder')
303
+            ->with('shareOwner')
304
+            ->willReturn($shareOwnerFolder);
305
+
306
+        $share = $this->provider->getShareById($id);
307
+
308
+        // We fetch the node so the root folder is eventually called
309
+
310
+        $this->assertEquals($id, $share->getId());
311
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
312
+        $this->assertEquals('sharedWith', $share->getSharedWith());
313
+        $this->assertEquals('sharedBy', $share->getSharedBy());
314
+        $this->assertEquals('shareOwner', $share->getShareOwner());
315
+        $this->assertEquals($ownerPath, $share->getNode());
316
+        $this->assertEquals(13, $share->getPermissions());
317
+        $this->assertEquals(null, $share->getToken());
318
+        $this->assertEquals(null, $share->getExpirationDate());
319
+        $this->assertEquals('myTarget', $share->getTarget());
320
+    }
321
+
322
+    public function testGetShareByIdGroupShare(): void {
323
+        $qb = $this->dbConn->getQueryBuilder();
324
+
325
+        $qb->insert('share')
326
+            ->values([
327
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
328
+                'share_with' => $qb->expr()->literal('sharedWith'),
329
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
330
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
331
+                'item_type' => $qb->expr()->literal('file'),
332
+                'file_source' => $qb->expr()->literal(42),
333
+                'file_target' => $qb->expr()->literal('myTarget'),
334
+                'permissions' => $qb->expr()->literal(13),
335
+            ]);
336
+        $this->assertEquals(1, $qb->executeStatement());
337
+
338
+        // Get the id
339
+        $id = $qb->getLastInsertId();
340
+
341
+        $ownerPath = $this->createMock(Folder::class);
342
+        $shareOwnerFolder = $this->createMock(Folder::class);
343
+        $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
344
+
345
+        $this->rootFolder
346
+            ->method('getUserFolder')
347
+            ->willReturnMap([
348
+                ['shareOwner', $shareOwnerFolder],
349
+            ]);
350
+
351
+        $share = $this->provider->getShareById($id);
352
+
353
+        $this->assertEquals($id, $share->getId());
354
+        $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
355
+        $this->assertEquals('sharedWith', $share->getSharedWith());
356
+        $this->assertEquals('sharedBy', $share->getSharedBy());
357
+        $this->assertEquals('shareOwner', $share->getShareOwner());
358
+        $this->assertEquals($ownerPath, $share->getNode());
359
+        $this->assertEquals(13, $share->getPermissions());
360
+        $this->assertEquals(null, $share->getToken());
361
+        $this->assertEquals(null, $share->getExpirationDate());
362
+        $this->assertEquals('myTarget', $share->getTarget());
363
+    }
364
+
365
+    public function testGetShareByIdUserGroupShare(): void {
366
+        $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user0', 'user0', 'file', 42, 'myTarget', 31, null, null);
367
+        $this->addShareToDB(2, 'user1', 'user0', 'user0', 'file', 42, 'userTarget', 0, null, null, $id);
368
+
369
+        $user0 = $this->createMock(IUser::class);
370
+        $user0->method('getUID')->willReturn('user0');
371
+        $user1 = $this->createMock(IUser::class);
372
+        $user1->method('getUID')->willReturn('user1');
373
+
374
+        $group0 = $this->createMock(IGroup::class);
375
+        $group0->method('inGroup')->with($user1)->willReturn(true);
376
+        $group0->method('getDisplayName')->willReturn('g0-displayname');
377
+
378
+        $node = $this->createMock(Folder::class);
379
+        $node->method('getId')->willReturn(42);
380
+        $node->method('getName')->willReturn('myTarget');
381
+
382
+        $this->rootFolder->method('getUserFolder')->with('user0')->willReturnSelf();
383
+        $this->rootFolder->method('getFirstNodeById')->willReturn($node);
384
+
385
+        $this->userManager->method('get')->willReturnMap([
386
+            ['user0', $user0],
387
+            ['user1', $user1],
388
+        ]);
389
+        $this->groupManager->method('get')->with('group0')->willReturn($group0);
390
+
391
+        $share = $this->provider->getShareById($id, 'user1');
392
+
393
+        $this->assertEquals($id, $share->getId());
394
+        $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
395
+        $this->assertSame('group0', $share->getSharedWith());
396
+        $this->assertSame('user0', $share->getSharedBy());
397
+        $this->assertSame('user0', $share->getShareOwner());
398
+        $this->assertSame($node, $share->getNode());
399
+        $this->assertEquals(0, $share->getPermissions());
400
+        $this->assertEquals(null, $share->getToken());
401
+        $this->assertEquals(null, $share->getExpirationDate());
402
+        $this->assertEquals('userTarget', $share->getTarget());
403
+    }
404
+
405
+    public function testGetShareByIdLinkShare(): void {
406
+        $qb = $this->dbConn->getQueryBuilder();
407
+
408
+        $qb->insert('share')
409
+            ->values([
410
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
411
+                'password' => $qb->expr()->literal('password'),
412
+                'password_by_talk' => $qb->expr()->literal(true),
413
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
414
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
415
+                'item_type' => $qb->expr()->literal('file'),
416
+                'file_source' => $qb->expr()->literal(42),
417
+                'file_target' => $qb->expr()->literal('myTarget'),
418
+                'permissions' => $qb->expr()->literal(13),
419
+                'token' => $qb->expr()->literal('token'),
420
+                'expiration' => $qb->expr()->literal('2000-01-02 00:00:00'),
421
+            ]);
422
+        $this->assertEquals(1, $qb->executeStatement());
423
+
424
+        $id = $qb->getLastInsertId();
425
+
426
+        $ownerPath = $this->createMock(Folder::class);
427
+        $shareOwnerFolder = $this->createMock(Folder::class);
428
+        $shareOwnerFolder->method('getFirstNodeById')->with(42)->willReturn($ownerPath);
429
+
430
+        $this->rootFolder
431
+            ->method('getUserFolder')
432
+            ->willReturnMap([
433
+                ['shareOwner', $shareOwnerFolder],
434
+            ]);
435
+
436
+        $share = $this->provider->getShareById($id);
437
+
438
+        $this->assertEquals($id, $share->getId());
439
+        $this->assertEquals(IShare::TYPE_LINK, $share->getShareType());
440
+        $this->assertNull($share->getSharedWith());
441
+        $this->assertEquals('password', $share->getPassword());
442
+        $this->assertEquals(true, $share->getSendPasswordByTalk());
443
+        $this->assertEquals('sharedBy', $share->getSharedBy());
444
+        $this->assertEquals('shareOwner', $share->getShareOwner());
445
+        $this->assertEquals($ownerPath, $share->getNode());
446
+        $this->assertEquals(13, $share->getPermissions());
447
+        $this->assertEquals('token', $share->getToken());
448
+        $this->assertEquals(\DateTime::createFromFormat('Y-m-d H:i:s', '2000-01-02 00:00:00'), $share->getExpirationDate());
449
+        $this->assertEquals('myTarget', $share->getTarget());
450
+    }
451
+
452
+    public function testDeleteSingleShare(): void {
453
+        $qb = $this->dbConn->getQueryBuilder();
454
+        $qb->insert('share')
455
+            ->values([
456
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
457
+                'share_with' => $qb->expr()->literal('sharedWith'),
458
+                'uid_owner' => $qb->expr()->literal('sharedBy'),
459
+                'item_type' => $qb->expr()->literal('file'),
460
+                'file_source' => $qb->expr()->literal(42),
461
+                'file_target' => $qb->expr()->literal('myTarget'),
462
+                'permissions' => $qb->expr()->literal(13),
463
+            ]);
464
+        $this->assertEquals(1, $qb->executeStatement());
465
+
466
+        $id = (string)$qb->getLastInsertId();
467
+
468
+        $share = $this->createMock(IShare::class);
469
+        $share->method('getId')->willReturn($id);
470
+
471
+        /** @var DefaultShareProvider $provider */
472
+        $provider = $this->getMockBuilder(DefaultShareProvider::class)
473
+            ->setConstructorArgs([
474
+                $this->dbConn,
475
+                $this->userManager,
476
+                $this->groupManager,
477
+                $this->rootFolder,
478
+                $this->mailer,
479
+                $this->defaults,
480
+                $this->l10nFactory,
481
+                $this->urlGenerator,
482
+                $this->timeFactory,
483
+                $this->logger,
484
+                $this->shareManager,
485
+                $this->config,
486
+            ])
487
+            ->onlyMethods(['getShareById'])
488
+            ->getMock();
489
+
490
+        $provider->delete($share);
491
+
492
+        $qb = $this->dbConn->getQueryBuilder();
493
+        $qb->select('*')
494
+            ->from('share');
495
+
496
+        $cursor = $qb->executeQuery();
497
+        $result = $cursor->fetchAllAssociative();
498
+        $cursor->closeCursor();
499
+
500
+        $this->assertEmpty($result);
501
+    }
502
+
503
+    public function testDeleteSingleShareLazy(): void {
504
+        $qb = $this->dbConn->getQueryBuilder();
505
+        $qb->insert('share')
506
+            ->values([
507
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
508
+                'share_with' => $qb->expr()->literal('sharedWith'),
509
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
510
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
511
+                'item_type' => $qb->expr()->literal('file'),
512
+                'file_source' => $qb->expr()->literal(42),
513
+                'file_target' => $qb->expr()->literal('myTarget'),
514
+                'permissions' => $qb->expr()->literal(13),
515
+            ]);
516
+        $this->assertEquals(1, $qb->executeStatement());
517
+
518
+        $id = $qb->getLastInsertId();
519
+
520
+        $this->rootFolder->expects($this->never())->method($this->anything());
521
+
522
+        $share = $this->provider->getShareById($id);
523
+        $this->provider->delete($share);
524
+
525
+        $qb = $this->dbConn->getQueryBuilder();
526
+        $qb->select('*')
527
+            ->from('share');
528
+
529
+        $cursor = $qb->executeQuery();
530
+        $result = $cursor->fetchAllAssociative();
531
+        $cursor->closeCursor();
532
+
533
+        $this->assertEmpty($result);
534
+    }
535
+
536
+    public function testDeleteGroupShareWithUserGroupShares(): void {
537
+        $qb = $this->dbConn->getQueryBuilder();
538
+        $qb->insert('share')
539
+            ->values([
540
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
541
+                'share_with' => $qb->expr()->literal('sharedWith'),
542
+                'uid_owner' => $qb->expr()->literal('sharedBy'),
543
+                'item_type' => $qb->expr()->literal('file'),
544
+                'file_source' => $qb->expr()->literal(42),
545
+                'file_target' => $qb->expr()->literal('myTarget'),
546
+                'permissions' => $qb->expr()->literal(13),
547
+            ]);
548
+        $this->assertEquals(1, $qb->executeStatement());
549
+        $id = (string)$qb->getLastInsertId();
550
+
551
+        $qb = $this->dbConn->getQueryBuilder();
552
+        $qb->insert('share')
553
+            ->values([
554
+                'share_type' => $qb->expr()->literal(2),
555
+                'share_with' => $qb->expr()->literal('sharedWithUser'),
556
+                'uid_owner' => $qb->expr()->literal('sharedBy'),
557
+                'item_type' => $qb->expr()->literal('file'),
558
+                'file_source' => $qb->expr()->literal(42),
559
+                'file_target' => $qb->expr()->literal('myTarget'),
560
+                'permissions' => $qb->expr()->literal(13),
561
+                'parent' => $qb->expr()->literal($id),
562
+            ]);
563
+        $this->assertEquals(1, $qb->executeStatement());
564
+
565
+        $share = $this->createMock(IShare::class);
566
+        $share->method('getId')->willReturn($id);
567
+        $share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
568
+
569
+        /** @var DefaultShareProvider $provider */
570
+        $provider = $this->getMockBuilder(DefaultShareProvider::class)
571
+            ->setConstructorArgs([
572
+                $this->dbConn,
573
+                $this->userManager,
574
+                $this->groupManager,
575
+                $this->rootFolder,
576
+                $this->mailer,
577
+                $this->defaults,
578
+                $this->l10nFactory,
579
+                $this->urlGenerator,
580
+                $this->timeFactory,
581
+                $this->logger,
582
+                $this->shareManager,
583
+                $this->config,
584
+            ])
585
+            ->onlyMethods(['getShareById'])
586
+            ->getMock();
587
+
588
+        $provider->delete($share);
589
+
590
+        $qb = $this->dbConn->getQueryBuilder();
591
+        $qb->select('*')
592
+            ->from('share');
593
+
594
+        $cursor = $qb->executeQuery();
595
+        $result = $cursor->fetchAllAssociative();
596
+        $cursor->closeCursor();
597
+
598
+        $this->assertEmpty($result);
599
+    }
600
+
601
+    public function testGetChildren(): void {
602
+        $qb = $this->dbConn->getQueryBuilder();
603
+        $qb->insert('share')
604
+            ->values([
605
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
606
+                'share_with' => $qb->expr()->literal('sharedWith'),
607
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
608
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
609
+                'item_type' => $qb->expr()->literal('file'),
610
+                'file_source' => $qb->expr()->literal(42),
611
+                'file_target' => $qb->expr()->literal('myTarget'),
612
+                'permissions' => $qb->expr()->literal(13),
613
+            ]);
614
+        $qb->executeStatement();
615
+
616
+        // Get the id
617
+        $id = (string)$qb->getLastInsertId();
618
+
619
+        $qb = $this->dbConn->getQueryBuilder();
620
+        $qb->insert('share')
621
+            ->values([
622
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
623
+                'share_with' => $qb->expr()->literal('user1'),
624
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
625
+                'uid_initiator' => $qb->expr()->literal('user2'),
626
+                'item_type' => $qb->expr()->literal('file'),
627
+                'file_source' => $qb->expr()->literal(1),
628
+                'file_target' => $qb->expr()->literal('myTarget1'),
629
+                'permissions' => $qb->expr()->literal(2),
630
+                'parent' => $qb->expr()->literal($id),
631
+            ]);
632
+        $qb->executeStatement();
633
+
634
+        $qb = $this->dbConn->getQueryBuilder();
635
+        $qb->insert('share')
636
+            ->values([
637
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
638
+                'share_with' => $qb->expr()->literal('group1'),
639
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
640
+                'uid_initiator' => $qb->expr()->literal('user3'),
641
+                'item_type' => $qb->expr()->literal('folder'),
642
+                'file_source' => $qb->expr()->literal(3),
643
+                'file_target' => $qb->expr()->literal('myTarget2'),
644
+                'permissions' => $qb->expr()->literal(4),
645
+                'parent' => $qb->expr()->literal($id),
646
+            ]);
647
+        $qb->executeStatement();
648
+
649
+        $ownerPath = $this->createMock(Folder::class);
650
+        $ownerFolder = $this->createMock(Folder::class);
651
+        $ownerFolder->method('getFirstNodeById')->willReturn($ownerPath);
652
+
653
+        $this->rootFolder
654
+            ->method('getUserFolder')
655
+            ->willReturnMap([
656
+                ['shareOwner', $ownerFolder],
657
+            ]);
658
+
659
+        $share = $this->createMock(IShare::class);
660
+        $share->method('getId')->willReturn($id);
661
+
662
+        $children = $this->provider->getChildren($share);
663
+
664
+        $this->assertCount(2, $children);
665
+
666
+        //Child1
667
+        $this->assertEquals(IShare::TYPE_USER, $children[0]->getShareType());
668
+        $this->assertEquals('user1', $children[0]->getSharedWith());
669
+        $this->assertEquals('user2', $children[0]->getSharedBy());
670
+        $this->assertEquals('shareOwner', $children[0]->getShareOwner());
671
+        $this->assertEquals($ownerPath, $children[0]->getNode());
672
+        $this->assertEquals(2, $children[0]->getPermissions());
673
+        $this->assertEquals(null, $children[0]->getToken());
674
+        $this->assertEquals(null, $children[0]->getExpirationDate());
675
+        $this->assertEquals('myTarget1', $children[0]->getTarget());
676
+
677
+        //Child2
678
+        $this->assertEquals(IShare::TYPE_GROUP, $children[1]->getShareType());
679
+        $this->assertEquals('group1', $children[1]->getSharedWith());
680
+        $this->assertEquals('user3', $children[1]->getSharedBy());
681
+        $this->assertEquals('shareOwner', $children[1]->getShareOwner());
682
+        $this->assertEquals($ownerPath, $children[1]->getNode());
683
+        $this->assertEquals(4, $children[1]->getPermissions());
684
+        $this->assertEquals(null, $children[1]->getToken());
685
+        $this->assertEquals(null, $children[1]->getExpirationDate());
686
+        $this->assertEquals('myTarget2', $children[1]->getTarget());
687
+    }
688
+
689
+    public function testCreateUserShare(): void {
690
+        $share = new Share($this->rootFolder, $this->userManager);
691
+
692
+        $shareOwner = $this->createMock(IUser::class);
693
+        $shareOwner->method('getUID')->willReturn('shareOwner');
694
+
695
+        $path = $this->createMock(File::class);
696
+        $path->method('getId')->willReturn(100);
697
+        $path->method('getOwner')->willReturn($shareOwner);
698
+
699
+        $ownerFolder = $this->createMock(Folder::class);
700
+        $userFolder = $this->createMock(Folder::class);
701
+        $this->rootFolder
702
+            ->method('getUserFolder')
703
+            ->willReturnMap([
704
+                ['sharedBy', $userFolder],
705
+                ['shareOwner', $ownerFolder],
706
+            ]);
707
+
708
+        $userFolder->method('getFirstNodeById')
709
+            ->with(100)
710
+            ->willReturn($path);
711
+        $ownerFolder->method('getFirstNodeById')
712
+            ->with(100)
713
+            ->willReturn($path);
714
+
715
+        $share->setShareType(IShare::TYPE_USER);
716
+        $share->setSharedWith('sharedWith');
717
+        $share->setSharedBy('sharedBy');
718
+        $share->setShareOwner('shareOwner');
719
+        $share->setNode($path);
720
+        $share->setSharedWithDisplayName('Displayed Name');
721
+        $share->setSharedWithAvatar('/path/to/image.svg');
722
+        $share->setPermissions(1);
723
+
724
+        $attrs = new ShareAttributes();
725
+        $attrs->setAttribute('permissions', 'download', true);
726
+        $share->setAttributes($attrs);
727
+
728
+        $share->setTarget('/target');
729
+
730
+        $share2 = $this->provider->create($share);
731
+
732
+        $this->assertNotNull($share2->getId());
733
+        $this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
734
+        $this->assertSame(IShare::TYPE_USER, $share2->getShareType());
735
+        $this->assertSame('sharedWith', $share2->getSharedWith());
736
+        $this->assertSame('sharedBy', $share2->getSharedBy());
737
+        $this->assertSame('shareOwner', $share2->getShareOwner());
738
+        $this->assertSame(1, $share2->getPermissions());
739
+        $this->assertSame('/target', $share2->getTarget());
740
+        $this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
741
+        $this->assertSame($path, $share2->getNode());
742
+
743
+        // Data is kept after creation
744
+        $this->assertSame('Displayed Name', $share->getSharedWithDisplayName());
745
+        $this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar());
746
+        $this->assertSame('Displayed Name', $share2->getSharedWithDisplayName());
747
+        $this->assertSame('/path/to/image.svg', $share2->getSharedWithAvatar());
748
+
749
+        $this->assertSame(
750
+            [
751
+                [
752
+                    'scope' => 'permissions',
753
+                    'key' => 'download',
754
+                    'value' => true
755
+                ]
756
+            ],
757
+            $share->getAttributes()->toArray()
758
+        );
759
+    }
760
+
761
+    public function testCreateGroupShare(): void {
762
+        $share = new Share($this->rootFolder, $this->userManager);
763
+
764
+        $shareOwner = $this->createMock(IUser::class);
765
+        $shareOwner->method('getUID')->willReturn('shareOwner');
766
+
767
+        $path = $this->createMock(Folder::class);
768
+        $path->method('getId')->willReturn(100);
769
+        $path->method('getOwner')->willReturn($shareOwner);
770
+
771
+        $ownerFolder = $this->createMock(Folder::class);
772
+        $userFolder = $this->createMock(Folder::class);
773
+        $this->rootFolder
774
+            ->method('getUserFolder')
775
+            ->willReturnMap([
776
+                ['sharedBy', $userFolder],
777
+                ['shareOwner', $ownerFolder],
778
+            ]);
779
+
780
+        $userFolder->method('getFirstNodeById')
781
+            ->with(100)
782
+            ->willReturn($path);
783
+        $ownerFolder->method('getFirstNodeById')
784
+            ->with(100)
785
+            ->willReturn($path);
786
+
787
+        $share->setShareType(IShare::TYPE_GROUP);
788
+        $share->setSharedWith('sharedWith');
789
+        $share->setSharedBy('sharedBy');
790
+        $share->setShareOwner('shareOwner');
791
+        $share->setNode($path);
792
+        $share->setPermissions(1);
793
+        $share->setSharedWithDisplayName('Displayed Name');
794
+        $share->setSharedWithAvatar('/path/to/image.svg');
795
+        $share->setTarget('/target');
796
+        $attrs = new ShareAttributes();
797
+        $attrs->setAttribute('permissions', 'download', true);
798
+        $share->setAttributes($attrs);
799
+
800
+        $share2 = $this->provider->create($share);
801
+
802
+        $this->assertNotNull($share2->getId());
803
+        $this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
804
+        $this->assertSame(IShare::TYPE_GROUP, $share2->getShareType());
805
+        $this->assertSame('sharedWith', $share2->getSharedWith());
806
+        $this->assertSame('sharedBy', $share2->getSharedBy());
807
+        $this->assertSame('shareOwner', $share2->getShareOwner());
808
+        $this->assertSame(1, $share2->getPermissions());
809
+        $this->assertSame('/target', $share2->getTarget());
810
+        $this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
811
+        $this->assertSame($path, $share2->getNode());
812
+
813
+        // Data is kept after creation
814
+        $this->assertSame('Displayed Name', $share->getSharedWithDisplayName());
815
+        $this->assertSame('/path/to/image.svg', $share->getSharedWithAvatar());
816
+        $this->assertSame('Displayed Name', $share2->getSharedWithDisplayName());
817
+        $this->assertSame('/path/to/image.svg', $share2->getSharedWithAvatar());
818
+
819
+        $this->assertSame(
820
+            [
821
+                [
822
+                    'scope' => 'permissions',
823
+                    'key' => 'download',
824
+                    'value' => true
825
+                ]
826
+            ],
827
+            $share->getAttributes()->toArray()
828
+        );
829
+    }
830
+
831
+    public function testCreateLinkShare(): void {
832
+        $share = new Share($this->rootFolder, $this->userManager);
833
+
834
+        $shareOwner = $this->createMock(IUser::class);
835
+        $shareOwner->method('getUID')->willReturn('shareOwner');
836
+
837
+        $path = $this->createMock(Folder::class);
838
+        $path->method('getId')->willReturn(100);
839
+        $path->method('getOwner')->willReturn($shareOwner);
840
+
841
+        $ownerFolder = $this->createMock(Folder::class);
842
+        $userFolder = $this->createMock(Folder::class);
843
+        $this->rootFolder
844
+            ->method('getUserFolder')
845
+            ->willReturnMap([
846
+                ['sharedBy', $userFolder],
847
+                ['shareOwner', $ownerFolder],
848
+            ]);
849
+
850
+        $userFolder->method('getFirstNodeById')
851
+            ->with(100)
852
+            ->willReturn($path);
853
+        $ownerFolder->method('getFirstNodeById')
854
+            ->with(100)
855
+            ->willReturn($path);
856
+
857
+        $share->setShareType(IShare::TYPE_LINK);
858
+        $share->setSharedBy('sharedBy');
859
+        $share->setShareOwner('shareOwner');
860
+        $share->setNode($path);
861
+        $share->setPermissions(1);
862
+        $share->setPassword('password');
863
+        $share->setSendPasswordByTalk(true);
864
+        $share->setToken('token');
865
+        $expireDate = new \DateTime();
866
+        $share->setExpirationDate($expireDate);
867
+        $share->setTarget('/target');
868
+
869
+        $share2 = $this->provider->create($share);
870
+
871
+        $this->assertNotNull($share2->getId());
872
+        $this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
873
+        $this->assertSame(IShare::TYPE_LINK, $share2->getShareType());
874
+        $this->assertSame('sharedBy', $share2->getSharedBy());
875
+        $this->assertSame('shareOwner', $share2->getShareOwner());
876
+        $this->assertSame(1, $share2->getPermissions());
877
+        $this->assertSame('/target', $share2->getTarget());
878
+        $this->assertLessThanOrEqual(new \DateTime(), $share2->getShareTime());
879
+        $this->assertSame($path, $share2->getNode());
880
+        $this->assertSame('password', $share2->getPassword());
881
+        $this->assertSame(true, $share2->getSendPasswordByTalk());
882
+        $this->assertSame('token', $share2->getToken());
883
+        $this->assertEquals($expireDate->getTimestamp(), $share2->getExpirationDate()->getTimestamp());
884
+    }
885
+
886
+    public function testGetShareByToken(): void {
887
+        $qb = $this->dbConn->getQueryBuilder();
888
+
889
+        $qb->insert('share')
890
+            ->values([
891
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
892
+                'password' => $qb->expr()->literal('password'),
893
+                'password_by_talk' => $qb->expr()->literal(true),
894
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
895
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
896
+                'item_type' => $qb->expr()->literal('file'),
897
+                'file_source' => $qb->expr()->literal(42),
898
+                'file_target' => $qb->expr()->literal('myTarget'),
899
+                'permissions' => $qb->expr()->literal(13),
900
+                'token' => $qb->expr()->literal('secrettoken'),
901
+                'label' => $qb->expr()->literal('the label'),
902
+            ]);
903
+        $qb->executeStatement();
904
+        $id = $qb->getLastInsertId();
905
+
906
+        $file = $this->createMock(File::class);
907
+
908
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
909
+        $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
910
+
911
+        $share = $this->provider->getShareByToken('secrettoken');
912
+        $this->assertEquals($id, $share->getId());
913
+        $this->assertSame('shareOwner', $share->getShareOwner());
914
+        $this->assertSame('sharedBy', $share->getSharedBy());
915
+        $this->assertSame('secrettoken', $share->getToken());
916
+        $this->assertSame('password', $share->getPassword());
917
+        $this->assertSame('the label', $share->getLabel());
918
+        $this->assertSame(true, $share->getSendPasswordByTalk());
919
+        $this->assertSame(null, $share->getSharedWith());
920
+    }
921
+
922
+    /**
923
+     * Assert that if no label is provided the label is correctly,
924
+     * as types on IShare, a string and not null
925
+     */
926
+    public function testGetShareByTokenNullLabel(): void {
927
+        $qb = $this->dbConn->getQueryBuilder();
928
+
929
+        $qb->insert('share')
930
+            ->values([
931
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
932
+                'password' => $qb->expr()->literal('password'),
933
+                'password_by_talk' => $qb->expr()->literal(true),
934
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
935
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
936
+                'item_type' => $qb->expr()->literal('file'),
937
+                'file_source' => $qb->expr()->literal(42),
938
+                'file_target' => $qb->expr()->literal('myTarget'),
939
+                'permissions' => $qb->expr()->literal(13),
940
+                'token' => $qb->expr()->literal('secrettoken'),
941
+            ]);
942
+        $qb->executeStatement();
943
+        $id = $qb->getLastInsertId();
944
+
945
+        $file = $this->createMock(File::class);
946
+
947
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
948
+        $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
949
+
950
+        $share = $this->provider->getShareByToken('secrettoken');
951
+        $this->assertEquals($id, $share->getId());
952
+        $this->assertSame('', $share->getLabel());
953
+    }
954
+
955
+    public function testGetShareByTokenNotFound(): void {
956
+        $this->expectException(ShareNotFound::class);
957
+
958
+        $this->provider->getShareByToken('invalidtoken');
959
+    }
960
+
961
+    private function createTestStorageEntry($storageStringId) {
962
+        $qb = $this->dbConn->getQueryBuilder();
963
+        $qb->insert('storages')
964
+            ->values([
965
+                'id' => $qb->expr()->literal($storageStringId),
966
+            ]);
967
+        $this->assertEquals(1, $qb->executeStatement());
968
+        return $qb->getLastInsertId();
969
+    }
970
+
971
+    private function createTestFileEntry($path, $storage = 1) {
972
+        $qb = $this->dbConn->getQueryBuilder();
973
+        $qb->insert('filecache')
974
+            ->values([
975
+                'storage' => $qb->createNamedParameter($storage, IQueryBuilder::PARAM_INT),
976
+                'path' => $qb->createNamedParameter($path),
977
+                'path_hash' => $qb->createNamedParameter(md5($path)),
978
+                'name' => $qb->createNamedParameter(basename($path)),
979
+            ]);
980
+        $this->assertEquals(1, $qb->executeStatement());
981
+        return $qb->getLastInsertId();
982
+    }
983
+
984
+    public static function storageAndFileNameProvider(): array {
985
+        return [
986
+            // regular file on regular storage
987
+            ['home::shareOwner', 'files/test.txt', 'files/test2.txt'],
988
+            // regular file on external storage
989
+            ['smb::whatever', 'files/test.txt', 'files/test2.txt'],
990
+            // regular file on external storage in trashbin-like folder,
991
+            ['smb::whatever', 'files_trashbin/files/test.txt', 'files_trashbin/files/test2.txt'],
992
+        ];
993
+    }
994
+
995
+    #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
996
+    public function testGetSharedWithUser($storageStringId, $fileName1, $fileName2): void {
997
+        $storageId = $this->createTestStorageEntry($storageStringId);
998
+        $fileId = $this->createTestFileEntry($fileName1, $storageId);
999
+        $fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1000
+        $qb = $this->dbConn->getQueryBuilder();
1001
+        $qb->insert('share')
1002
+            ->values([
1003
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1004
+                'share_with' => $qb->expr()->literal('sharedWith'),
1005
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1006
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1007
+                'item_type' => $qb->expr()->literal('file'),
1008
+                'file_source' => $qb->expr()->literal($fileId),
1009
+                'file_target' => $qb->expr()->literal('myTarget'),
1010
+                'permissions' => $qb->expr()->literal(13),
1011
+            ]);
1012
+        $this->assertEquals(1, $qb->executeStatement());
1013
+        $id = $qb->getLastInsertId();
1014
+
1015
+        $qb = $this->dbConn->getQueryBuilder();
1016
+        $qb->insert('share')
1017
+            ->values([
1018
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1019
+                'share_with' => $qb->expr()->literal('sharedWith2'),
1020
+                'uid_owner' => $qb->expr()->literal('shareOwner2'),
1021
+                'uid_initiator' => $qb->expr()->literal('sharedBy2'),
1022
+                'item_type' => $qb->expr()->literal('file2'),
1023
+                'file_source' => $qb->expr()->literal($fileId2),
1024
+                'file_target' => $qb->expr()->literal('myTarget2'),
1025
+                'permissions' => $qb->expr()->literal(14),
1026
+            ]);
1027
+        $this->assertEquals(1, $qb->executeStatement());
1028
+
1029
+        $file = $this->createMock(File::class);
1030
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1031
+        $this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file);
1032
+
1033
+        $share = $this->provider->getSharedWith('sharedWith', IShare::TYPE_USER, null, 1, 0);
1034
+        $this->assertCount(1, $share);
1035
+
1036
+        $share = $share[0];
1037
+        $this->assertEquals($id, $share->getId());
1038
+        $this->assertEquals('sharedWith', $share->getSharedWith());
1039
+        $this->assertEquals('shareOwner', $share->getShareOwner());
1040
+        $this->assertEquals('sharedBy', $share->getSharedBy());
1041
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1042
+    }
1043
+
1044
+    #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1045
+    public function testGetSharedWithGroup($storageStringId, $fileName1, $fileName2): void {
1046
+        $storageId = $this->createTestStorageEntry($storageStringId);
1047
+        $fileId = $this->createTestFileEntry($fileName1, $storageId);
1048
+        $fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1049
+        $qb = $this->dbConn->getQueryBuilder();
1050
+        $qb->insert('share')
1051
+            ->values([
1052
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1053
+                'share_with' => $qb->expr()->literal('sharedWith'),
1054
+                'uid_owner' => $qb->expr()->literal('shareOwner2'),
1055
+                'uid_initiator' => $qb->expr()->literal('sharedBy2'),
1056
+                'item_type' => $qb->expr()->literal('file'),
1057
+                'file_source' => $qb->expr()->literal($fileId2),
1058
+                'file_target' => $qb->expr()->literal('myTarget2'),
1059
+                'permissions' => $qb->expr()->literal(14),
1060
+            ]);
1061
+        $this->assertEquals(1, $qb->executeStatement());
1062
+
1063
+        $qb = $this->dbConn->getQueryBuilder();
1064
+        $qb->insert('share')
1065
+            ->values([
1066
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1067
+                'share_with' => $qb->expr()->literal('sharedWith'),
1068
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1069
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1070
+                'item_type' => $qb->expr()->literal('file'),
1071
+                'file_source' => $qb->expr()->literal($fileId),
1072
+                'file_target' => $qb->expr()->literal('myTarget'),
1073
+                'permissions' => $qb->expr()->literal(13),
1074
+            ]);
1075
+        $this->assertEquals(1, $qb->executeStatement());
1076
+        $id = $qb->getLastInsertId();
1077
+
1078
+        $groups = [];
1079
+        foreach (range(0, 100) as $i) {
1080
+            $groups[] = 'group' . $i;
1081
+        }
1082
+
1083
+        $groups[] = 'sharedWith';
1084
+
1085
+        $user = $this->createMock(IUser::class);
1086
+        $user->method('getUID')->willReturn('sharedWith');
1087
+        $owner = $this->createMock(IUser::class);
1088
+        $owner->method('getUID')->willReturn('shareOwner');
1089
+        $initiator = $this->createMock(IUser::class);
1090
+        $initiator->method('getUID')->willReturn('sharedBy');
1091
+
1092
+        $this->userManager->method('get')->willReturnMap([
1093
+            ['sharedWith', $user],
1094
+            ['shareOwner', $owner],
1095
+            ['sharedBy', $initiator],
1096
+        ]);
1097
+        $this->groupManager
1098
+            ->method('getUserGroupIds')
1099
+            ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'sharedWith' ? $groups : []));
1100
+
1101
+        $file = $this->createMock(File::class);
1102
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1103
+        $this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file);
1104
+
1105
+        $share = $this->provider->getSharedWith('sharedWith', IShare::TYPE_GROUP, null, 20, 1);
1106
+        $this->assertCount(1, $share);
1107
+
1108
+        $share = $share[0];
1109
+        $this->assertEquals($id, $share->getId());
1110
+        $this->assertEquals('sharedWith', $share->getSharedWith());
1111
+        $this->assertEquals('shareOwner', $share->getShareOwner());
1112
+        $this->assertEquals('sharedBy', $share->getSharedBy());
1113
+        $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
1114
+    }
1115
+
1116
+    #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1117
+    public function testGetSharedWithGroupUserModified($storageStringId, $fileName1, $fileName2): void {
1118
+        $storageId = $this->createTestStorageEntry($storageStringId);
1119
+        $fileId = $this->createTestFileEntry($fileName1, $storageId);
1120
+        $qb = $this->dbConn->getQueryBuilder();
1121
+        $qb->insert('share')
1122
+            ->values([
1123
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1124
+                'share_with' => $qb->expr()->literal('sharedWith'),
1125
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1126
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1127
+                'item_type' => $qb->expr()->literal('file'),
1128
+                'file_source' => $qb->expr()->literal($fileId),
1129
+                'file_target' => $qb->expr()->literal('myTarget'),
1130
+                'permissions' => $qb->expr()->literal(13),
1131
+            ]);
1132
+        $this->assertEquals(1, $qb->executeStatement());
1133
+        $id = $qb->getLastInsertId();
1134
+
1135
+        /*
1136 1136
 		 * Wrong share. Should not be taken by code.
1137 1137
 		 */
1138
-		$qb = $this->dbConn->getQueryBuilder();
1139
-		$qb->insert('share')
1140
-			->values([
1141
-				'share_type' => $qb->expr()->literal(2),
1142
-				'share_with' => $qb->expr()->literal('user2'),
1143
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1144
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1145
-				'item_type' => $qb->expr()->literal('file'),
1146
-				'file_source' => $qb->expr()->literal($fileId),
1147
-				'file_target' => $qb->expr()->literal('wrongTarget'),
1148
-				'permissions' => $qb->expr()->literal(31),
1149
-				'parent' => $qb->expr()->literal($id),
1150
-			]);
1151
-		$this->assertEquals(1, $qb->executeStatement());
1152
-
1153
-		/*
1138
+        $qb = $this->dbConn->getQueryBuilder();
1139
+        $qb->insert('share')
1140
+            ->values([
1141
+                'share_type' => $qb->expr()->literal(2),
1142
+                'share_with' => $qb->expr()->literal('user2'),
1143
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1144
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1145
+                'item_type' => $qb->expr()->literal('file'),
1146
+                'file_source' => $qb->expr()->literal($fileId),
1147
+                'file_target' => $qb->expr()->literal('wrongTarget'),
1148
+                'permissions' => $qb->expr()->literal(31),
1149
+                'parent' => $qb->expr()->literal($id),
1150
+            ]);
1151
+        $this->assertEquals(1, $qb->executeStatement());
1152
+
1153
+        /*
1154 1154
 		 * Correct share. should be taken by code path.
1155 1155
 		 */
1156
-		$qb = $this->dbConn->getQueryBuilder();
1157
-		$qb->insert('share')
1158
-			->values([
1159
-				'share_type' => $qb->expr()->literal(2),
1160
-				'share_with' => $qb->expr()->literal('user'),
1161
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1162
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1163
-				'item_type' => $qb->expr()->literal('file'),
1164
-				'file_source' => $qb->expr()->literal($fileId),
1165
-				'file_target' => $qb->expr()->literal('userTarget'),
1166
-				'permissions' => $qb->expr()->literal(0),
1167
-				'parent' => $qb->expr()->literal($id),
1168
-			]);
1169
-		$this->assertEquals(1, $qb->executeStatement());
1170
-
1171
-		$groups = ['sharedWith'];
1172
-
1173
-		$user = $this->createMock(IUser::class);
1174
-		$user->method('getUID')->willReturn('user');
1175
-		$owner = $this->createMock(IUser::class);
1176
-		$owner->method('getUID')->willReturn('shareOwner');
1177
-		$initiator = $this->createMock(IUser::class);
1178
-		$initiator->method('getUID')->willReturn('sharedBy');
1179
-
1180
-		$this->userManager->method('get')->willReturnMap([
1181
-			['user', $user],
1182
-			['shareOwner', $owner],
1183
-			['sharedBy', $initiator],
1184
-		]);
1185
-		$this->groupManager
1186
-			->method('getUserGroupIds')
1187
-			->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'user' ? $groups : []));
1188
-
1189
-		$file = $this->createMock(File::class);
1190
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1191
-		$this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file);
1192
-
1193
-		$share = $this->provider->getSharedWith('user', IShare::TYPE_GROUP, null, -1, 0);
1194
-		$this->assertCount(1, $share);
1195
-
1196
-		$share = $share[0];
1197
-		$this->assertSame((string)$id, $share->getId());
1198
-		$this->assertSame('sharedWith', $share->getSharedWith());
1199
-		$this->assertSame('shareOwner', $share->getShareOwner());
1200
-		$this->assertSame('sharedBy', $share->getSharedBy());
1201
-		$this->assertSame(IShare::TYPE_GROUP, $share->getShareType());
1202
-		$this->assertSame(0, $share->getPermissions());
1203
-		$this->assertSame('userTarget', $share->getTarget());
1204
-	}
1205
-
1206
-	#[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1207
-	public function testGetSharedWithUserWithNode($storageStringId, $fileName1, $fileName2): void {
1208
-		$storageId = $this->createTestStorageEntry($storageStringId);
1209
-		$fileId = $this->createTestFileEntry($fileName1, $storageId);
1210
-		$fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1211
-		$this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1',
1212
-			'file', $fileId, 'myTarget', 31, null, null, null);
1213
-		$id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1',
1214
-			'file', $fileId2, 'myTarget', 31, null, null, null);
1215
-
1216
-		$user0 = $this->createMock(IUser::class);
1217
-		$user0->method('getUID')->willReturn('user0');
1218
-		$user0->method('getDisplayName')->willReturn('user0');
1219
-		$user1 = $this->createMock(IUser::class);
1220
-		$user1->method('getUID')->willReturn('user1');
1221
-		$user0->method('getDisplayName')->willReturn('user0');
1222
-
1223
-		$this->userManager->method('get')->willReturnMap([
1224
-			['user0', $user0],
1225
-			['user1', $user1],
1226
-		]);
1227
-
1228
-		$file = $this->createMock(File::class);
1229
-		$file->method('getId')->willReturn($fileId2);
1230
-
1231
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1232
-		$this->rootFolder->method('getFirstNodeById')->with($fileId2)->willReturn($file);
1233
-
1234
-		$share = $this->provider->getSharedWith('user0', IShare::TYPE_USER, $file, -1, 0);
1235
-		$this->assertCount(1, $share);
1236
-
1237
-		$share = $share[0];
1238
-		$this->assertEquals($id, $share->getId());
1239
-		$this->assertSame('user0', $share->getSharedWith());
1240
-		$this->assertSame('user1', $share->getShareOwner());
1241
-		$this->assertSame('user1', $share->getSharedBy());
1242
-		$this->assertSame($file, $share->getNode());
1243
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1244
-	}
1245
-
1246
-	#[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1247
-	public function testGetSharedWithGroupWithNode($storageStringId, $fileName1, $fileName2): void {
1248
-		$storageId = $this->createTestStorageEntry($storageStringId);
1249
-		$fileId = $this->createTestFileEntry($fileName1, $storageId);
1250
-		$fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1251
-		$this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1',
1252
-			'file', $fileId, 'myTarget', 31, null, null, null);
1253
-		$id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1',
1254
-			'file', $fileId2, 'myTarget', 31, null, null, null);
1255
-
1256
-		$user0 = $this->createMock(IUser::class);
1257
-		$user0->method('getUID')->willReturn('user0');
1258
-		$user1 = $this->createMock(IUser::class);
1259
-		$user1->method('getUID')->willReturn('user1');
1260
-
1261
-		$this->userManager->method('get')->willReturnMap([
1262
-			['user0', $user0],
1263
-			['user1', $user1],
1264
-		]);
1265
-
1266
-		$this->groupManager
1267
-			->method('getUserGroupIds')
1268
-			->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'user0' ? ['group0'] : []));
1269
-
1270
-		$node = $this->createMock(Folder::class);
1271
-		$node->method('getId')->willReturn($fileId2);
1272
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1273
-		$this->rootFolder->method('getFirstNodeById')->with($fileId2)->willReturn($node);
1274
-
1275
-		$share = $this->provider->getSharedWith('user0', IShare::TYPE_GROUP, $node, -1, 0);
1276
-		$this->assertCount(1, $share);
1277
-
1278
-		$share = $share[0];
1279
-		$this->assertEquals($id, $share->getId());
1280
-		$this->assertSame('group0', $share->getSharedWith());
1281
-		$this->assertSame('user1', $share->getShareOwner());
1282
-		$this->assertSame('user1', $share->getSharedBy());
1283
-		$this->assertSame($node, $share->getNode());
1284
-		$this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
1285
-	}
1286
-
1287
-	public static function shareTypesProvider(): array {
1288
-		return [
1289
-			[IShare::TYPE_USER, false],
1290
-			[IShare::TYPE_GROUP, false],
1291
-			[IShare::TYPE_USER, true],
1292
-			[IShare::TYPE_GROUP, true],
1293
-		];
1294
-	}
1295
-
1296
-	#[\PHPUnit\Framework\Attributes\DataProvider('shareTypesProvider')]
1297
-	public function testGetSharedWithWithDeletedFile($shareType, $trashed): void {
1298
-		if ($trashed) {
1299
-			// exists in database but is in trash
1300
-			$storageId = $this->createTestStorageEntry('home::shareOwner');
1301
-			$deletedFileId = $this->createTestFileEntry('files_trashbin/files/test.txt.d1465553223', $storageId);
1302
-		} else {
1303
-			// fileid that doesn't exist in the database
1304
-			$deletedFileId = 123;
1305
-		}
1306
-		$qb = $this->dbConn->getQueryBuilder();
1307
-		$qb->insert('share')
1308
-			->values([
1309
-				'share_type' => $qb->expr()->literal($shareType),
1310
-				'share_with' => $qb->expr()->literal('sharedWith'),
1311
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1312
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1313
-				'item_type' => $qb->expr()->literal('file'),
1314
-				'file_source' => $qb->expr()->literal($deletedFileId),
1315
-				'file_target' => $qb->expr()->literal('myTarget'),
1316
-				'permissions' => $qb->expr()->literal(13),
1317
-			]);
1318
-		$this->assertEquals(1, $qb->executeStatement());
1319
-
1320
-		$file = $this->createMock(File::class);
1321
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1322
-		$this->rootFolder->method('getFirstNodeById')->with($deletedFileId)->willReturn($file);
1323
-
1324
-		$groups = [];
1325
-		foreach (range(0, 100) as $i) {
1326
-			$groups[] = 'group' . $i;
1327
-		}
1328
-
1329
-		$groups[] = 'sharedWith';
1330
-
1331
-		$user = $this->createMock(IUser::class);
1332
-		$user->method('getUID')->willReturn('sharedWith');
1333
-		$owner = $this->createMock(IUser::class);
1334
-		$owner->method('getUID')->willReturn('shareOwner');
1335
-		$initiator = $this->createMock(IUser::class);
1336
-		$initiator->method('getUID')->willReturn('sharedBy');
1337
-
1338
-		$this->userManager->method('get')->willReturnMap([
1339
-			['sharedWith', $user],
1340
-			['shareOwner', $owner],
1341
-			['sharedBy', $initiator],
1342
-		]);
1343
-		$this->groupManager
1344
-			->method('getUserGroupIds')
1345
-			->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'sharedWith' ? $groups : []));
1346
-
1347
-		$share = $this->provider->getSharedWith('sharedWith', $shareType, null, 1, 0);
1348
-		$this->assertCount(0, $share);
1349
-	}
1350
-
1351
-	public function testGetSharesBy(): void {
1352
-		$qb = $this->dbConn->getQueryBuilder();
1353
-		$qb->insert('share')
1354
-			->values([
1355
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1356
-				'share_with' => $qb->expr()->literal('sharedWith'),
1357
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1358
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1359
-				'item_type' => $qb->expr()->literal('file'),
1360
-				'file_source' => $qb->expr()->literal(42),
1361
-				'file_target' => $qb->expr()->literal('myTarget'),
1362
-				'permissions' => $qb->expr()->literal(13),
1363
-			]);
1364
-		$this->assertEquals(1, $qb->executeStatement());
1365
-		$id = $qb->getLastInsertId();
1366
-
1367
-		$qb = $this->dbConn->getQueryBuilder();
1368
-		$qb->insert('share')
1369
-			->values([
1370
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1371
-				'share_with' => $qb->expr()->literal('sharedWith'),
1372
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1373
-				'uid_initiator' => $qb->expr()->literal('sharedBy2'),
1374
-				'item_type' => $qb->expr()->literal('file'),
1375
-				'file_source' => $qb->expr()->literal(42),
1376
-				'file_target' => $qb->expr()->literal('userTarget'),
1377
-				'permissions' => $qb->expr()->literal(0),
1378
-				'parent' => $qb->expr()->literal($id),
1379
-			]);
1380
-		$this->assertEquals(1, $qb->executeStatement());
1381
-
1382
-		$file = $this->createMock(File::class);
1383
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1384
-		$this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
1385
-
1386
-		$share = $this->provider->getSharesBy('sharedBy', IShare::TYPE_USER, null, false, 1, 0);
1387
-		$this->assertCount(1, $share);
1388
-
1389
-		/** @var IShare $share */
1390
-		$share = $share[0];
1391
-		$this->assertEquals($id, $share->getId());
1392
-		$this->assertEquals('sharedWith', $share->getSharedWith());
1393
-		$this->assertEquals('shareOwner', $share->getShareOwner());
1394
-		$this->assertEquals('sharedBy', $share->getSharedBy());
1395
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1396
-		$this->assertEquals(13, $share->getPermissions());
1397
-		$this->assertEquals('myTarget', $share->getTarget());
1398
-	}
1399
-
1400
-	public function testGetSharesNode(): void {
1401
-		$qb = $this->dbConn->getQueryBuilder();
1402
-		$qb->insert('share')
1403
-			->values([
1404
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1405
-				'share_with' => $qb->expr()->literal('sharedWith'),
1406
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1407
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1408
-				'item_type' => $qb->expr()->literal('file'),
1409
-				'file_source' => $qb->expr()->literal(42),
1410
-				'file_target' => $qb->expr()->literal('myTarget'),
1411
-				'permissions' => $qb->expr()->literal(13),
1412
-			]);
1413
-		$this->assertEquals(1, $qb->executeStatement());
1414
-		$id = $qb->getLastInsertId();
1415
-
1416
-		$qb = $this->dbConn->getQueryBuilder();
1417
-		$qb->insert('share')
1418
-			->values([
1419
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1420
-				'share_with' => $qb->expr()->literal('sharedWith'),
1421
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1422
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1423
-				'item_type' => $qb->expr()->literal('file'),
1424
-				'file_source' => $qb->expr()->literal(43),
1425
-				'file_target' => $qb->expr()->literal('userTarget'),
1426
-				'permissions' => $qb->expr()->literal(0),
1427
-				'parent' => $qb->expr()->literal($id),
1428
-			]);
1429
-		$this->assertEquals(1, $qb->executeStatement());
1430
-
1431
-		$file = $this->createMock(File::class);
1432
-		$file->method('getId')->willReturn(42);
1433
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1434
-		$this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
1435
-
1436
-		$share = $this->provider->getSharesBy('sharedBy', IShare::TYPE_USER, $file, false, 1, 0);
1437
-		$this->assertCount(1, $share);
1438
-
1439
-		/** @var IShare $share */
1440
-		$share = $share[0];
1441
-		$this->assertEquals($id, $share->getId());
1442
-		$this->assertEquals('sharedWith', $share->getSharedWith());
1443
-		$this->assertEquals('shareOwner', $share->getShareOwner());
1444
-		$this->assertEquals('sharedBy', $share->getSharedBy());
1445
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1446
-		$this->assertEquals(13, $share->getPermissions());
1447
-		$this->assertEquals('myTarget', $share->getTarget());
1448
-	}
1449
-
1450
-	public function testGetSharesReshare(): void {
1451
-		$qb = $this->dbConn->getQueryBuilder();
1452
-		$qb->insert('share')
1453
-			->values([
1454
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1455
-				'share_with' => $qb->expr()->literal('sharedWith'),
1456
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1457
-				'uid_initiator' => $qb->expr()->literal('shareOwner'),
1458
-				'item_type' => $qb->expr()->literal('file'),
1459
-				'file_source' => $qb->expr()->literal(42),
1460
-				'file_target' => $qb->expr()->literal('myTarget'),
1461
-				'permissions' => $qb->expr()->literal(13),
1462
-			]);
1463
-		$this->assertEquals(1, $qb->executeStatement());
1464
-		$id1 = $qb->getLastInsertId();
1465
-
1466
-		$qb = $this->dbConn->getQueryBuilder();
1467
-		$qb->insert('share')
1468
-			->values([
1469
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1470
-				'share_with' => $qb->expr()->literal('sharedWith'),
1471
-				'uid_owner' => $qb->expr()->literal('shareOwner'),
1472
-				'uid_initiator' => $qb->expr()->literal('sharedBy'),
1473
-				'item_type' => $qb->expr()->literal('file'),
1474
-				'file_source' => $qb->expr()->literal(42),
1475
-				'file_target' => $qb->expr()->literal('userTarget'),
1476
-				'permissions' => $qb->expr()->literal(0),
1477
-			]);
1478
-		$this->assertEquals(1, $qb->executeStatement());
1479
-		$id2 = $qb->getLastInsertId();
1480
-
1481
-		$file = $this->createMock(File::class);
1482
-		$file->method('getId')->willReturn(42);
1483
-		$this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1484
-		$this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
1485
-
1486
-		$shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_USER, null, true, -1, 0);
1487
-		$this->assertCount(2, $shares);
1488
-
1489
-		/** @var IShare $share */
1490
-		$share = $shares[0];
1491
-		$this->assertEquals($id1, $share->getId());
1492
-		$this->assertSame('sharedWith', $share->getSharedWith());
1493
-		$this->assertSame('shareOwner', $share->getShareOwner());
1494
-		$this->assertSame('shareOwner', $share->getSharedBy());
1495
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1496
-		$this->assertEquals(13, $share->getPermissions());
1497
-		$this->assertEquals('myTarget', $share->getTarget());
1498
-
1499
-		$share = $shares[1];
1500
-		$this->assertEquals($id2, $share->getId());
1501
-		$this->assertSame('sharedWith', $share->getSharedWith());
1502
-		$this->assertSame('shareOwner', $share->getShareOwner());
1503
-		$this->assertSame('sharedBy', $share->getSharedBy());
1504
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1505
-		$this->assertEquals(0, $share->getPermissions());
1506
-		$this->assertEquals('userTarget', $share->getTarget());
1507
-	}
1508
-
1509
-	public function testDeleteFromSelfGroupNoCustomShare(): void {
1510
-		$qb = $this->dbConn->getQueryBuilder();
1511
-		$stmt = $qb->insert('share')
1512
-			->values([
1513
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1514
-				'share_with' => $qb->expr()->literal('group'),
1515
-				'uid_owner' => $qb->expr()->literal('user1'),
1516
-				'uid_initiator' => $qb->expr()->literal('user1'),
1517
-				'item_type' => $qb->expr()->literal('file'),
1518
-				'file_source' => $qb->expr()->literal(1),
1519
-				'file_target' => $qb->expr()->literal('myTarget1'),
1520
-				'permissions' => $qb->expr()->literal(2)
1521
-			])->executeStatement();
1522
-		$this->assertEquals(1, $stmt);
1523
-		$id = $qb->getLastInsertId();
1524
-
1525
-		$user1 = $this->createMock(IUser::class);
1526
-		$user1->method('getUID')->willReturn('user1');
1527
-		$user2 = $this->createMock(IUser::class);
1528
-		$user2->method('getUID')->willReturn('user2');
1529
-		$this->userManager->method('get')->willReturnMap([
1530
-			['user1', $user1],
1531
-			['user2', $user2],
1532
-		]);
1533
-
1534
-		$group = $this->createMock(IGroup::class);
1535
-		$group->method('getGID')->willReturn('group');
1536
-		$group->method('inGroup')->with($user2)->willReturn(true);
1537
-		$group->method('getDisplayName')->willReturn('group-displayname');
1538
-		$this->groupManager->method('get')->with('group')->willReturn($group);
1539
-
1540
-		$file = $this->createMock(File::class);
1541
-		$file->method('getId')->willReturn(1);
1542
-
1543
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1544
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1545
-
1546
-		$share = $this->provider->getShareById($id);
1547
-
1548
-		$this->provider->deleteFromSelf($share, 'user2');
1549
-
1550
-		$qb = $this->dbConn->getQueryBuilder();
1551
-		$stmt = $qb->select('*')
1552
-			->from('share')
1553
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(2)))
1554
-			->executeQuery();
1555
-
1556
-		$shares = $stmt->fetchAllAssociative();
1557
-		$stmt->closeCursor();
1558
-
1559
-		$this->assertCount(1, $shares);
1560
-		$share2 = $shares[0];
1561
-		$this->assertEquals($id, $share2['parent']);
1562
-		$this->assertEquals(0, $share2['permissions']);
1563
-		$this->assertEquals('user2', $share2['share_with']);
1564
-	}
1565
-
1566
-	public function testDeleteFromSelfGroupAlreadyCustomShare(): void {
1567
-		$qb = $this->dbConn->getQueryBuilder();
1568
-		$stmt = $qb->insert('share')
1569
-			->values([
1570
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1571
-				'share_with' => $qb->expr()->literal('group'),
1572
-				'uid_owner' => $qb->expr()->literal('user1'),
1573
-				'uid_initiator' => $qb->expr()->literal('user1'),
1574
-				'item_type' => $qb->expr()->literal('file'),
1575
-				'file_source' => $qb->expr()->literal(1),
1576
-				'file_target' => $qb->expr()->literal('myTarget1'),
1577
-				'permissions' => $qb->expr()->literal(2)
1578
-			])->executeStatement();
1579
-		$this->assertEquals(1, $stmt);
1580
-		$id = $qb->getLastInsertId();
1581
-
1582
-		$qb = $this->dbConn->getQueryBuilder();
1583
-		$stmt = $qb->insert('share')
1584
-			->values([
1585
-				'share_type' => $qb->expr()->literal(2),
1586
-				'share_with' => $qb->expr()->literal('user2'),
1587
-				'uid_owner' => $qb->expr()->literal('user1'),
1588
-				'uid_initiator' => $qb->expr()->literal('user1'),
1589
-				'item_type' => $qb->expr()->literal('file'),
1590
-				'file_source' => $qb->expr()->literal(1),
1591
-				'file_target' => $qb->expr()->literal('myTarget1'),
1592
-				'permissions' => $qb->expr()->literal(2),
1593
-				'parent' => $qb->expr()->literal($id),
1594
-			])->executeStatement();
1595
-		$this->assertEquals(1, $stmt);
1596
-
1597
-		$user1 = $this->createMock(IUser::class);
1598
-		$user1->method('getUID')->willReturn('user1');
1599
-		$user2 = $this->createMock(IUser::class);
1600
-		$user2->method('getUID')->willReturn('user2');
1601
-		$this->userManager->method('get')->willReturnMap([
1602
-			['user1', $user1],
1603
-			['user2', $user2],
1604
-		]);
1605
-
1606
-		$group = $this->createMock(IGroup::class);
1607
-		$group->method('getGID')->willReturn('group');
1608
-		$group->method('inGroup')->with($user2)->willReturn(true);
1609
-		$group->method('getDisplayName')->willReturn('group-displayname');
1610
-		$this->groupManager->method('get')->with('group')->willReturn($group);
1611
-
1612
-		$file = $this->createMock(File::class);
1613
-		$file->method('getId')->willReturn(1);
1614
-
1615
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1616
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1617
-
1618
-		$share = $this->provider->getShareById($id);
1619
-
1620
-		$this->provider->deleteFromSelf($share, 'user2');
1621
-
1622
-		$qb = $this->dbConn->getQueryBuilder();
1623
-		$stmt = $qb->select('*')
1624
-			->from('share')
1625
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(2)))
1626
-			->executeQuery();
1627
-
1628
-		$shares = $stmt->fetchAllAssociative();
1629
-		$stmt->closeCursor();
1630
-
1631
-		$this->assertCount(1, $shares);
1632
-		$share2 = $shares[0];
1633
-		$this->assertEquals($id, $share2['parent']);
1634
-		$this->assertEquals(0, $share2['permissions']);
1635
-		$this->assertEquals('user2', $share2['share_with']);
1636
-	}
1637
-
1638
-
1639
-	public function testDeleteFromSelfGroupUserNotInGroup(): void {
1640
-		$qb = $this->dbConn->getQueryBuilder();
1641
-		$stmt = $qb->insert('share')
1642
-			->values([
1643
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1644
-				'share_with' => $qb->expr()->literal('group'),
1645
-				'uid_owner' => $qb->expr()->literal('user1'),
1646
-				'uid_initiator' => $qb->expr()->literal('user1'),
1647
-				'item_type' => $qb->expr()->literal('file'),
1648
-				'file_source' => $qb->expr()->literal(1),
1649
-				'file_target' => $qb->expr()->literal('myTarget1'),
1650
-				'permissions' => $qb->expr()->literal(2)
1651
-			])->executeStatement();
1652
-		$this->assertEquals(1, $stmt);
1653
-		$id = $qb->getLastInsertId();
1654
-
1655
-		$user1 = $this->createMock(IUser::class);
1656
-		$user1->method('getUID')->willReturn('user1');
1657
-		$user2 = $this->createMock(IUser::class);
1658
-		$user2->method('getUID')->willReturn('user2');
1659
-		$this->userManager->method('get')->willReturnMap([
1660
-			['user1', $user1],
1661
-			['user2', $user2],
1662
-		]);
1663
-
1664
-		$group = $this->createMock(IGroup::class);
1665
-		$group->method('getGID')->willReturn('group');
1666
-		$group->method('inGroup')->with($user2)->willReturn(false);
1667
-		$group->method('getDisplayName')->willReturn('group-displayname');
1668
-		$this->groupManager->method('get')->with('group')->willReturn($group);
1669
-
1670
-		$file = $this->createMock(File::class);
1671
-		$file->method('getId')->willReturn(1);
1672
-
1673
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1674
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1675
-
1676
-		$share = $this->provider->getShareById($id);
1677
-
1678
-		$this->provider->deleteFromSelf($share, 'user2');
1679
-	}
1680
-
1681
-
1682
-	public function testDeleteFromSelfGroupDoesNotExist(): void {
1683
-		$this->expectException(ProviderException::class);
1684
-		$this->expectExceptionMessage('Group "group" does not exist');
1685
-
1686
-		$qb = $this->dbConn->getQueryBuilder();
1687
-		$stmt = $qb->insert('share')
1688
-			->values([
1689
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1690
-				'share_with' => $qb->expr()->literal('group'),
1691
-				'uid_owner' => $qb->expr()->literal('user1'),
1692
-				'uid_initiator' => $qb->expr()->literal('user1'),
1693
-				'item_type' => $qb->expr()->literal('file'),
1694
-				'file_source' => $qb->expr()->literal(1),
1695
-				'file_target' => $qb->expr()->literal('myTarget1'),
1696
-				'permissions' => $qb->expr()->literal(2)
1697
-			])->executeStatement();
1698
-		$this->assertEquals(1, $stmt);
1699
-		$id = $qb->getLastInsertId();
1700
-
1701
-		$user1 = $this->createMock(IUser::class);
1702
-		$user1->method('getUID')->willReturn('user1');
1703
-		$user2 = $this->createMock(IUser::class);
1704
-		$user2->method('getUID')->willReturn('user2');
1705
-		$this->userManager->method('get')->willReturnMap([
1706
-			['user1', $user1],
1707
-			['user2', $user2],
1708
-		]);
1709
-
1710
-		$this->groupManager->method('get')->with('group')->willReturn(null);
1711
-
1712
-		$file = $this->createMock(File::class);
1713
-		$file->method('getId')->willReturn(1);
1714
-
1715
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1716
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1717
-
1718
-		$share = $this->provider->getShareById($id);
1719
-
1720
-		$this->provider->deleteFromSelf($share, 'user2');
1721
-	}
1722
-
1723
-	public function testDeleteFromSelfUser(): void {
1724
-		$qb = $this->dbConn->getQueryBuilder();
1725
-		$stmt = $qb->insert('share')
1726
-			->values([
1727
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1728
-				'share_with' => $qb->expr()->literal('user2'),
1729
-				'uid_owner' => $qb->expr()->literal('user1'),
1730
-				'uid_initiator' => $qb->expr()->literal('user1'),
1731
-				'item_type' => $qb->expr()->literal('file'),
1732
-				'file_source' => $qb->expr()->literal(1),
1733
-				'file_target' => $qb->expr()->literal('myTarget1'),
1734
-				'permissions' => $qb->expr()->literal(2)
1735
-			])->executeStatement();
1736
-		$this->assertEquals(1, $stmt);
1737
-		$id = $qb->getLastInsertId();
1738
-
1739
-		$user1 = $this->createMock(IUser::class);
1740
-		$user1->method('getUID')->willReturn('user1');
1741
-		$user1->method('getDisplayName')->willReturn('user1');
1742
-		$user2 = $this->createMock(IUser::class);
1743
-		$user2->method('getUID')->willReturn('user2');
1744
-		$user2->method('getDisplayName')->willReturn('user2');
1745
-		$this->userManager->method('get')->willReturnMap([
1746
-			['user1', $user1],
1747
-			['user2', $user2],
1748
-		]);
1749
-
1750
-		$file = $this->createMock(File::class);
1751
-		$file->method('getId')->willReturn(1);
1752
-
1753
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1754
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1755
-
1756
-		$share = $this->provider->getShareById($id);
1757
-
1758
-		$this->provider->deleteFromSelf($share, 'user2');
1759
-
1760
-		$qb = $this->dbConn->getQueryBuilder();
1761
-		$stmt = $qb->select('*')
1762
-			->from('share')
1763
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
1764
-			->executeQuery();
1765
-
1766
-		$shares = $stmt->fetchAllAssociative();
1767
-		$stmt->closeCursor();
1768
-
1769
-		$this->assertCount(0, $shares);
1770
-	}
1771
-
1772
-
1773
-	public function testDeleteFromSelfUserNotRecipient(): void {
1774
-		$this->expectException(ProviderException::class);
1775
-		$this->expectExceptionMessage('Recipient does not match');
1776
-
1777
-		$qb = $this->dbConn->getQueryBuilder();
1778
-		$stmt = $qb->insert('share')
1779
-			->values([
1780
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1781
-				'share_with' => $qb->expr()->literal('user2'),
1782
-				'uid_owner' => $qb->expr()->literal('user1'),
1783
-				'uid_initiator' => $qb->expr()->literal('user1'),
1784
-				'item_type' => $qb->expr()->literal('file'),
1785
-				'file_source' => $qb->expr()->literal(1),
1786
-				'file_target' => $qb->expr()->literal('myTarget1'),
1787
-				'permissions' => $qb->expr()->literal(2)
1788
-			])->executeStatement();
1789
-		$this->assertEquals(1, $stmt);
1790
-		$id = $qb->getLastInsertId();
1791
-
1792
-		$user1 = $this->createMock(IUser::class);
1793
-		$user1->method('getUID')->willReturn('user1');
1794
-		$user1->method('getDisplayName')->willReturn('user1');
1795
-		$user2 = $this->createMock(IUser::class);
1796
-		$user2->method('getUID')->willReturn('user2');
1797
-		$user2->method('getDisplayName')->willReturn('user2');
1798
-		$user3 = $this->createMock(IUser::class);
1799
-		$this->userManager->method('get')->willReturnMap([
1800
-			['user1', $user1],
1801
-			['user2', $user2],
1802
-		]);
1803
-
1804
-		$file = $this->createMock(File::class);
1805
-		$file->method('getId')->willReturn(1);
1806
-
1807
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1808
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1809
-
1810
-		$share = $this->provider->getShareById($id);
1811
-
1812
-		$this->provider->deleteFromSelf($share, $user3);
1813
-	}
1814
-
1815
-
1816
-	public function testDeleteFromSelfLink(): void {
1817
-		$this->expectException(ProviderException::class);
1818
-		$this->expectExceptionMessage('Invalid shareType');
1819
-
1820
-		$qb = $this->dbConn->getQueryBuilder();
1821
-		$stmt = $qb->insert('share')
1822
-			->values([
1823
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
1824
-				'uid_owner' => $qb->expr()->literal('user1'),
1825
-				'uid_initiator' => $qb->expr()->literal('user1'),
1826
-				'item_type' => $qb->expr()->literal('file'),
1827
-				'file_source' => $qb->expr()->literal(1),
1828
-				'file_target' => $qb->expr()->literal('myTarget1'),
1829
-				'permissions' => $qb->expr()->literal(2),
1830
-				'token' => $qb->expr()->literal('token'),
1831
-			])->executeStatement();
1832
-		$this->assertEquals(1, $stmt);
1833
-		$id = $qb->getLastInsertId();
1834
-
1835
-		$user1 = $this->createMock(IUser::class);
1836
-		$user1->method('getUID')->willReturn('user1');
1837
-		$this->userManager->method('get')->willReturnMap([
1838
-			['user1', $user1],
1839
-		]);
1840
-
1841
-		$file = $this->createMock(File::class);
1842
-		$file->method('getId')->willReturn(1);
1843
-
1844
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1845
-		$this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1846
-
1847
-		$share = $this->provider->getShareById($id);
1848
-
1849
-		$this->provider->deleteFromSelf($share, $user1);
1850
-	}
1851
-
1852
-	public function testUpdateUser(): void {
1853
-		$id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user2',
1854
-			'file', 42, 'target', 31, null, null);
1855
-
1856
-		$users = [];
1857
-		for ($i = 0; $i < 6; $i++) {
1858
-			$user = $this->createMock(IUser::class);
1859
-			$user->method('getUID')->willReturn('user' . $i);
1860
-			$user->method('getDisplayName')->willReturn('user' . $i);
1861
-			$users['user' . $i] = $user;
1862
-		}
1863
-
1864
-		$this->userManager->method('get')->willReturnCallback(
1865
-			function ($userId) use ($users) {
1866
-				return $users[$userId];
1867
-			}
1868
-		);
1869
-
1870
-		$file1 = $this->createMock(File::class);
1871
-		$file1->method('getId')->willReturn(42);
1872
-		$file2 = $this->createMock(File::class);
1873
-		$file2->method('getId')->willReturn(43);
1874
-
1875
-		$folder1 = $this->createMock(Folder::class);
1876
-		$folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
1877
-		$folder2 = $this->createMock(Folder::class);
1878
-		$folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
1879
-
1880
-		$this->rootFolder->method('getUserFolder')->willReturnMap([
1881
-			['user2', $folder1],
1882
-			['user5', $folder2],
1883
-		]);
1884
-
1885
-		$share = $this->provider->getShareById($id);
1886
-
1887
-		$share->setSharedWith('user3');
1888
-		$share->setSharedBy('user4');
1889
-		$share->setShareOwner('user5');
1890
-		$share->setNode($file2);
1891
-		$share->setPermissions(1);
1892
-
1893
-		$share2 = $this->provider->update($share);
1894
-
1895
-		$this->assertEquals($id, $share2->getId());
1896
-		$this->assertSame('user3', $share2->getSharedWith());
1897
-		$this->assertSame('user4', $share2->getSharedBy());
1898
-		$this->assertSame('user5', $share2->getShareOwner());
1899
-		$this->assertSame(1, $share2->getPermissions());
1900
-
1901
-		$share2 = $this->provider->getShareById($id);
1902
-
1903
-		$this->assertEquals($id, $share2->getId());
1904
-		$this->assertSame('user3', $share2->getSharedWith());
1905
-		$this->assertSame('user4', $share2->getSharedBy());
1906
-		$this->assertSame('user5', $share2->getShareOwner());
1907
-		$this->assertSame(1, $share2->getPermissions());
1908
-	}
1909
-
1910
-	public function testUpdateLink(): void {
1911
-		$id = $this->addShareToDB(IShare::TYPE_LINK, null, 'user1', 'user2',
1912
-			'file', 42, 'target', 31, null, null);
1913
-
1914
-		$users = [];
1915
-		for ($i = 0; $i < 6; $i++) {
1916
-			$user = $this->createMock(IUser::class);
1917
-			$user->method('getUID')->willReturn('user' . $i);
1918
-			$users['user' . $i] = $user;
1919
-		}
1920
-
1921
-		$this->userManager->method('get')->willReturnCallback(
1922
-			function ($userId) use ($users) {
1923
-				return $users[$userId];
1924
-			}
1925
-		);
1926
-
1927
-		$file1 = $this->createMock(File::class);
1928
-		$file1->method('getId')->willReturn(42);
1929
-		$file2 = $this->createMock(File::class);
1930
-		$file2->method('getId')->willReturn(43);
1931
-
1932
-		$folder1 = $this->createMock(Folder::class);
1933
-		$folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
1934
-		$folder2 = $this->createMock(Folder::class);
1935
-		$folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
1936
-
1937
-		$this->rootFolder->method('getUserFolder')->willReturnMap([
1938
-			['user2', $folder1],
1939
-			['user5', $folder2],
1940
-		]);
1941
-
1942
-		$share = $this->provider->getShareById($id);
1943
-
1944
-		$share->setPassword('password');
1945
-		$share->setSendPasswordByTalk(true);
1946
-		$share->setSharedBy('user4');
1947
-		$share->setShareOwner('user5');
1948
-		$share->setNode($file2);
1949
-		$share->setPermissions(1);
1950
-
1951
-		$share2 = $this->provider->update($share);
1952
-
1953
-		$this->assertEquals($id, $share2->getId());
1954
-		$this->assertEquals('password', $share2->getPassword());
1955
-		$this->assertSame(true, $share2->getSendPasswordByTalk());
1956
-		$this->assertSame('user4', $share2->getSharedBy());
1957
-		$this->assertSame('user5', $share2->getShareOwner());
1958
-		$this->assertSame(1, $share2->getPermissions());
1959
-
1960
-		$share2 = $this->provider->getShareById($id);
1961
-
1962
-		$this->assertEquals($id, $share2->getId());
1963
-		$this->assertEquals('password', $share2->getPassword());
1964
-		$this->assertSame(true, $share2->getSendPasswordByTalk());
1965
-		$this->assertSame('user4', $share2->getSharedBy());
1966
-		$this->assertSame('user5', $share2->getShareOwner());
1967
-		$this->assertSame(1, $share2->getPermissions());
1968
-	}
1969
-
1970
-	public function testUpdateLinkRemovePassword(): void {
1971
-		$id = $this->addShareToDB(IShare::TYPE_LINK, 'foo', 'user1', 'user2',
1972
-			'file', 42, 'target', 31, null, null);
1973
-
1974
-		$qb = $this->dbConn->getQueryBuilder();
1975
-		$qb->update('share');
1976
-		$qb->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1977
-		$qb->set('password', $qb->createNamedParameter('password'));
1978
-		$this->assertEquals(1, $qb->executeStatement());
1979
-
1980
-		$users = [];
1981
-		for ($i = 0; $i < 6; $i++) {
1982
-			$user = $this->createMock(IUser::class);
1983
-			$user->method('getUID')->willReturn('user' . $i);
1984
-			$users['user' . $i] = $user;
1985
-		}
1986
-
1987
-		$this->userManager->method('get')->willReturnCallback(
1988
-			function ($userId) use ($users) {
1989
-				return $users[$userId];
1990
-			}
1991
-		);
1992
-
1993
-		$file1 = $this->createMock(File::class);
1994
-		$file1->method('getId')->willReturn(42);
1995
-		$file2 = $this->createMock(File::class);
1996
-		$file2->method('getId')->willReturn(43);
1997
-
1998
-		$folder1 = $this->createMock(Folder::class);
1999
-		$folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
2000
-		$folder2 = $this->createMock(Folder::class);
2001
-		$folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
2002
-
2003
-		$this->rootFolder->method('getUserFolder')->willReturnMap([
2004
-			['user2', $folder1],
2005
-			['user5', $folder2],
2006
-		]);
2007
-
2008
-		$share = $this->provider->getShareById($id);
2009
-
2010
-		$share->setPassword(null);
2011
-		$share->setSharedBy('user4');
2012
-		$share->setShareOwner('user5');
2013
-		$share->setNode($file2);
2014
-		$share->setPermissions(1);
2015
-
2016
-		$share2 = $this->provider->update($share);
2017
-
2018
-		$this->assertEquals($id, $share2->getId());
2019
-		$this->assertEquals(null, $share2->getPassword());
2020
-		$this->assertSame('user4', $share2->getSharedBy());
2021
-		$this->assertSame('user5', $share2->getShareOwner());
2022
-		$this->assertSame(1, $share2->getPermissions());
2023
-
2024
-		$share2 = $this->provider->getShareById($id);
2025
-
2026
-		$this->assertEquals($id, $share2->getId());
2027
-		$this->assertEquals(null, $share2->getPassword());
2028
-		$this->assertSame('user4', $share2->getSharedBy());
2029
-		$this->assertSame('user5', $share2->getShareOwner());
2030
-		$this->assertSame(1, $share2->getPermissions());
2031
-	}
2032
-
2033
-	public function testUpdateGroupNoSub(): void {
2034
-		$id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user2',
2035
-			'file', 42, 'target', 31, null, null);
2036
-
2037
-		$users = [];
2038
-		for ($i = 0; $i < 6; $i++) {
2039
-			$user = $this->createMock(IUser::class);
2040
-			$user->method('getUID')->willReturn('user' . $i);
2041
-			$users['user' . $i] = $user;
2042
-		}
2043
-
2044
-		$this->userManager->method('get')->willReturnCallback(
2045
-			function ($userId) use ($users) {
2046
-				return $users[$userId];
2047
-			}
2048
-		);
2049
-
2050
-		$groups = [];
2051
-		for ($i = 0; $i < 2; $i++) {
2052
-			$group = $this->createMock(IGroup::class);
2053
-			$group->method('getGID')->willReturn('group' . $i);
2054
-			$group->method('getDisplayName')->willReturn('group-displayname' . $i);
2055
-			$groups['group' . $i] = $group;
2056
-		}
2057
-
2058
-		$this->groupManager->method('get')->willReturnCallback(
2059
-			function ($groupId) use ($groups) {
2060
-				return $groups[$groupId];
2061
-			}
2062
-		);
2063
-
2064
-		$file1 = $this->createMock(File::class);
2065
-		$file1->method('getId')->willReturn(42);
2066
-		$file2 = $this->createMock(File::class);
2067
-		$file2->method('getId')->willReturn(43);
2068
-
2069
-		$folder1 = $this->createMock(Folder::class);
2070
-		$folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
2071
-		$folder2 = $this->createMock(Folder::class);
2072
-		$folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
2073
-
2074
-		$this->rootFolder->method('getUserFolder')->willReturnMap([
2075
-			['user2', $folder1],
2076
-			['user5', $folder2],
2077
-		]);
2078
-
2079
-		$share = $this->provider->getShareById($id);
2080
-
2081
-		$share->setSharedWith('group0');
2082
-		$share->setSharedBy('user4');
2083
-		$share->setShareOwner('user5');
2084
-		$share->setNode($file2);
2085
-		$share->setPermissions(1);
2086
-
2087
-		$share2 = $this->provider->update($share);
2088
-
2089
-		$this->assertEquals($id, $share2->getId());
2090
-		// Group shares do not allow updating the recipient
2091
-		$this->assertSame('group0', $share2->getSharedWith());
2092
-		$this->assertSame('user4', $share2->getSharedBy());
2093
-		$this->assertSame('user5', $share2->getShareOwner());
2094
-		$this->assertSame(1, $share2->getPermissions());
2095
-
2096
-		$share2 = $this->provider->getShareById($id);
2097
-
2098
-		$this->assertEquals($id, $share2->getId());
2099
-		// Group shares do not allow updating the recipient
2100
-		$this->assertSame('group0', $share2->getSharedWith());
2101
-		$this->assertSame('user4', $share2->getSharedBy());
2102
-		$this->assertSame('user5', $share2->getShareOwner());
2103
-		$this->assertSame(1, $share2->getPermissions());
2104
-	}
2105
-
2106
-	public function testUpdateGroupSubShares(): void {
2107
-		$id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user2',
2108
-			'file', 42, 'target', 31, null, null);
2109
-
2110
-		$id2 = $this->addShareToDB(2, 'user0', 'user1', 'user2',
2111
-			'file', 42, 'mytarget', 31, null, null, $id);
2112
-
2113
-		$id3 = $this->addShareToDB(2, 'user3', 'user1', 'user2',
2114
-			'file', 42, 'mytarget2', 0, null, null, $id);
2115
-
2116
-		$users = [];
2117
-		for ($i = 0; $i < 6; $i++) {
2118
-			$user = $this->createMock(IUser::class);
2119
-			$user->method('getUID')->willReturn('user' . $i);
2120
-			$users['user' . $i] = $user;
2121
-		}
2122
-
2123
-		$this->userManager->method('get')->willReturnCallback(
2124
-			function ($userId) use ($users) {
2125
-				return $users[$userId];
2126
-			}
2127
-		);
2128
-
2129
-		$groups = [];
2130
-		for ($i = 0; $i < 2; $i++) {
2131
-			$group = $this->createMock(IGroup::class);
2132
-			$group->method('getGID')->willReturn('group' . $i);
2133
-			$group->method('getDisplayName')->willReturn('group-displayname' . $i);
2134
-			$groups['group' . $i] = $group;
2135
-		}
2136
-
2137
-		$this->groupManager->method('get')->willReturnCallback(
2138
-			function ($groupId) use ($groups) {
2139
-				return $groups[$groupId];
2140
-			}
2141
-		);
2142
-
2143
-		$file1 = $this->createMock(File::class);
2144
-		$file1->method('getId')->willReturn(42);
2145
-		$file2 = $this->createMock(File::class);
2146
-		$file2->method('getId')->willReturn(43);
2147
-
2148
-		$folder1 = $this->createMock(Folder::class);
2149
-		$folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
2150
-		$folder2 = $this->createMock(Folder::class);
2151
-		$folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
2152
-
2153
-		$this->rootFolder->method('getUserFolder')->willReturnMap([
2154
-			['user2', $folder1],
2155
-			['user5', $folder2],
2156
-		]);
2157
-
2158
-		$share = $this->provider->getShareById($id);
2159
-
2160
-		$share->setSharedWith('group0');
2161
-		$share->setSharedBy('user4');
2162
-		$share->setShareOwner('user5');
2163
-		$share->setNode($file2);
2164
-		$share->setPermissions(1);
2165
-
2166
-		$share2 = $this->provider->update($share);
2167
-
2168
-		$this->assertEquals($id, $share2->getId());
2169
-		// Group shares do not allow updating the recipient
2170
-		$this->assertSame('group0', $share2->getSharedWith());
2171
-		$this->assertSame('user4', $share2->getSharedBy());
2172
-		$this->assertSame('user5', $share2->getShareOwner());
2173
-		$this->assertSame(1, $share2->getPermissions());
2174
-
2175
-		$share2 = $this->provider->getShareById($id);
2176
-
2177
-		$this->assertEquals($id, $share2->getId());
2178
-		// Group shares do not allow updating the recipient
2179
-		$this->assertSame('group0', $share2->getSharedWith());
2180
-		$this->assertSame('user4', $share2->getSharedBy());
2181
-		$this->assertSame('user5', $share2->getShareOwner());
2182
-		$this->assertSame(1, $share2->getPermissions());
2183
-
2184
-		$qb = $this->dbConn->getQueryBuilder();
2185
-		$stmt = $qb->select('*')
2186
-			->from('share')
2187
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($id)))
2188
-			->orderBy('id')
2189
-			->executeQuery();
2190
-
2191
-		$shares = $stmt->fetchAllAssociative();
2192
-
2193
-		$this->assertSame('user0', $shares[0]['share_with']);
2194
-		$this->assertSame('user4', $shares[0]['uid_initiator']);
2195
-		$this->assertSame('user5', $shares[0]['uid_owner']);
2196
-		$this->assertSame(1, (int)$shares[0]['permissions']);
2197
-
2198
-		$this->assertSame('user3', $shares[1]['share_with']);
2199
-		$this->assertSame('user4', $shares[1]['uid_initiator']);
2200
-		$this->assertSame('user5', $shares[1]['uid_owner']);
2201
-		$this->assertSame(0, (int)$shares[1]['permissions']);
2202
-
2203
-
2204
-		$stmt->closeCursor();
2205
-	}
2206
-
2207
-	public function testMoveUserShare(): void {
2208
-		$id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1', 'file',
2209
-			42, 'mytaret', 31, null, null);
2210
-
2211
-		$user0 = $this->createMock(IUser::class);
2212
-		$user0->method('getUID')->willReturn('user0');
2213
-		$user0->method('getDisplayName')->willReturn('user0');
2214
-		$user1 = $this->createMock(IUser::class);
2215
-		$user1->method('getUID')->willReturn('user1');
2216
-		$user1->method('getDisplayName')->willReturn('user1');
2217
-
2218
-		$this->userManager->method('get')->willReturnMap([
2219
-			['user0', $user0],
2220
-			['user1', $user1],
2221
-		]);
2222
-
2223
-		$file = $this->createMock(File::class);
2224
-		$file->method('getId')->willReturn(42);
2225
-
2226
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
2227
-		$this->rootFolder->method('getFirstNodeById')->willReturn($file);
2228
-
2229
-		$share = $this->provider->getShareById($id, null);
2230
-
2231
-		$share->setTarget('/newTarget');
2232
-		$this->provider->move($share, $user0);
2233
-
2234
-		$share = $this->provider->getShareById($id, null);
2235
-		$this->assertSame('/newTarget', $share->getTarget());
2236
-	}
2237
-
2238
-	public function testMoveGroupShare(): void {
2239
-		$id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1', 'file',
2240
-			42, 'mytaret', 31, null, null);
2241
-
2242
-		$user0 = $this->createMock(IUser::class);
2243
-		$user0->method('getUID')->willReturn('user0');
2244
-		$user1 = $this->createMock(IUser::class);
2245
-		$user1->method('getUID')->willReturn('user1');
2246
-
2247
-		$group0 = $this->createMock(IGroup::class);
2248
-		$group0->method('getGID')->willReturn('group0');
2249
-		$group0->method('inGroup')->with($user0)->willReturn(true);
2250
-		$group0->method('getDisplayName')->willReturn('group0-displayname');
2251
-
2252
-		$this->groupManager->method('get')->with('group0')->willReturn($group0);
2253
-
2254
-		$this->userManager->method('get')->willReturnMap([
2255
-			['user0', $user0],
2256
-			['user1', $user1],
2257
-		]);
2258
-
2259
-		$folder = $this->createMock(Folder::class);
2260
-		$folder->method('getId')->willReturn(42);
2261
-
2262
-		$this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
2263
-		$this->rootFolder->method('getFirstNodeById')->willReturn($folder);
2264
-
2265
-		$share = $this->provider->getShareById($id, 'user0');
2266
-
2267
-		$share->setTarget('/newTarget');
2268
-		$this->provider->move($share, 'user0');
2269
-
2270
-		$share = $this->provider->getShareById($id, 'user0');
2271
-		$this->assertSame('/newTarget', $share->getTarget());
2272
-
2273
-		$share->setTarget('/ultraNewTarget');
2274
-		$this->provider->move($share, 'user0');
2275
-
2276
-		$share = $this->provider->getShareById($id, 'user0');
2277
-		$this->assertSame('/ultraNewTarget', $share->getTarget());
2278
-	}
2279
-
2280
-	public static function dataDeleteUser(): array {
2281
-		return [
2282
-			[IShare::TYPE_USER, 'a', 'b', 'c', 'a', true],
2283
-			[IShare::TYPE_USER, 'a', 'b', 'c', 'b', false],
2284
-			[IShare::TYPE_USER, 'a', 'b', 'c', 'c', true],
2285
-			[IShare::TYPE_USER, 'a', 'b', 'c', 'd', false],
2286
-			[IShare::TYPE_GROUP, 'a', 'b', 'c', 'a', true],
2287
-			[IShare::TYPE_GROUP, 'a', 'b', 'c', 'b', false],
2288
-			// The group c is still valid but user c is deleted so group share stays
2289
-			[IShare::TYPE_GROUP, 'a', 'b', 'c', 'c', false],
2290
-			[IShare::TYPE_GROUP, 'a', 'b', 'c', 'd', false],
2291
-			[IShare::TYPE_LINK, 'a', 'b', 'c', 'a', true],
2292
-			// To avoid invisible link shares delete initiated link shares as well (see #22327)
2293
-			[IShare::TYPE_LINK, 'a', 'b', 'c', 'b', true],
2294
-			[IShare::TYPE_LINK, 'a', 'b', 'c', 'c', false],
2295
-			[IShare::TYPE_LINK, 'a', 'b', 'c', 'd', false],
2296
-		];
2297
-	}
2298
-
2299
-	/**
2300
-	 *
2301
-	 * @param int $type The shareType (user/group/link)
2302
-	 * @param string $owner The owner of the share (uid)
2303
-	 * @param string $initiator The initiator of the share (uid)
2304
-	 * @param string $recipient The recipient of the share (uid/gid/pass)
2305
-	 * @param string $deletedUser The user that is deleted
2306
-	 * @param bool $rowDeleted Is the row deleted in this setup
2307
-	 */
2308
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUser')]
2309
-	public function testDeleteUser($type, $owner, $initiator, $recipient, $deletedUser, $rowDeleted): void {
2310
-		$qb = $this->dbConn->getQueryBuilder();
2311
-		$qb->insert('share')
2312
-			->setValue('share_type', $qb->createNamedParameter($type))
2313
-			->setValue('uid_owner', $qb->createNamedParameter($owner))
2314
-			->setValue('uid_initiator', $qb->createNamedParameter($initiator))
2315
-			->setValue('share_with', $qb->createNamedParameter($recipient))
2316
-			->setValue('item_type', $qb->createNamedParameter('file'))
2317
-			->setValue('item_source', $qb->createNamedParameter(42))
2318
-			->setValue('file_source', $qb->createNamedParameter(42))
2319
-			->executeStatement();
2320
-
2321
-		$id = $qb->getLastInsertId();
2322
-
2323
-		$this->provider->userDeleted($deletedUser, $type);
2324
-
2325
-		$qb = $this->dbConn->getQueryBuilder();
2326
-		$qb->select('*')
2327
-			->from('share')
2328
-			->where(
2329
-				$qb->expr()->eq('id', $qb->createNamedParameter($id))
2330
-			);
2331
-		$cursor = $qb->executeQuery();
2332
-		$data = $cursor->fetchAllAssociative();
2333
-		$cursor->closeCursor();
2334
-
2335
-		$this->assertCount($rowDeleted ? 0 : 1, $data);
2336
-	}
2337
-
2338
-	public static function dataDeleteUserGroup(): array {
2339
-		return [
2340
-			['a', 'b', 'c', 'a', true, true],
2341
-			['a', 'b', 'c', 'b', false, false],
2342
-			['a', 'b', 'c', 'c', false, true],
2343
-			['a', 'b', 'c', 'd', false, false],
2344
-		];
2345
-	}
2346
-
2347
-	/**
2348
-	 *
2349
-	 * @param string $owner The owner of the share (uid)
2350
-	 * @param string $initiator The initiator of the share (uid)
2351
-	 * @param string $recipient The recipient of the usergroup share (uid)
2352
-	 * @param string $deletedUser The user that is deleted
2353
-	 * @param bool $groupShareDeleted
2354
-	 * @param bool $userGroupShareDeleted
2355
-	 */
2356
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUserGroup')]
2357
-	public function testDeleteUserGroup($owner, $initiator, $recipient, $deletedUser, $groupShareDeleted, $userGroupShareDeleted): void {
2358
-		$qb = $this->dbConn->getQueryBuilder();
2359
-		$qb->insert('share')
2360
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
2361
-			->setValue('uid_owner', $qb->createNamedParameter($owner))
2362
-			->setValue('uid_initiator', $qb->createNamedParameter($initiator))
2363
-			->setValue('share_with', $qb->createNamedParameter('group'))
2364
-			->setValue('item_type', $qb->createNamedParameter('file'))
2365
-			->setValue('item_source', $qb->createNamedParameter(42))
2366
-			->setValue('file_source', $qb->createNamedParameter(42))
2367
-			->executeStatement();
2368
-		$groupId = $qb->getLastInsertId();
2369
-
2370
-		$qb = $this->dbConn->getQueryBuilder();
2371
-		$qb->insert('share')
2372
-			->setValue('share_type', $qb->createNamedParameter(2))
2373
-			->setValue('uid_owner', $qb->createNamedParameter($owner))
2374
-			->setValue('uid_initiator', $qb->createNamedParameter($initiator))
2375
-			->setValue('share_with', $qb->createNamedParameter($recipient))
2376
-			->setValue('item_type', $qb->createNamedParameter('file'))
2377
-			->setValue('item_source', $qb->createNamedParameter(42))
2378
-			->setValue('file_source', $qb->createNamedParameter(42))
2379
-			->executeStatement();
2380
-		$userGroupId = $qb->getLastInsertId();
2381
-
2382
-		$this->provider->userDeleted($deletedUser, IShare::TYPE_GROUP);
2383
-
2384
-		$qb = $this->dbConn->getQueryBuilder();
2385
-		$qb->select('*')
2386
-			->from('share')
2387
-			->where(
2388
-				$qb->expr()->eq('id', $qb->createNamedParameter($userGroupId))
2389
-			);
2390
-		$cursor = $qb->executeQuery();
2391
-		$data = $cursor->fetchAllAssociative();
2392
-		$cursor->closeCursor();
2393
-		$this->assertCount($userGroupShareDeleted ? 0 : 1, $data);
2394
-
2395
-		$qb = $this->dbConn->getQueryBuilder();
2396
-		$qb->select('*')
2397
-			->from('share')
2398
-			->where(
2399
-				$qb->expr()->eq('id', $qb->createNamedParameter($groupId))
2400
-			);
2401
-		$cursor = $qb->executeQuery();
2402
-		$data = $cursor->fetchAllAssociative();
2403
-		$cursor->closeCursor();
2404
-		$this->assertCount($groupShareDeleted ? 0 : 1, $data);
2405
-	}
2406
-
2407
-	public static function dataGroupDeleted(): array {
2408
-		return [
2409
-			[
2410
-				[
2411
-					'type' => IShare::TYPE_USER,
2412
-					'recipient' => 'user',
2413
-					'children' => []
2414
-				], 'group', false
2415
-			],
2416
-			[
2417
-				[
2418
-					'type' => IShare::TYPE_USER,
2419
-					'recipient' => 'user',
2420
-					'children' => []
2421
-				], 'user', false
2422
-			],
2423
-			[
2424
-				[
2425
-					'type' => IShare::TYPE_LINK,
2426
-					'recipient' => 'user',
2427
-					'children' => []
2428
-				], 'group', false
2429
-			],
2430
-			[
2431
-				[
2432
-					'type' => IShare::TYPE_GROUP,
2433
-					'recipient' => 'group1',
2434
-					'children' => [
2435
-						'foo',
2436
-						'bar'
2437
-					]
2438
-				], 'group2', false
2439
-			],
2440
-			[
2441
-				[
2442
-					'type' => IShare::TYPE_GROUP,
2443
-					'recipient' => 'group1',
2444
-					'children' => [
2445
-						'foo',
2446
-						'bar'
2447
-					]
2448
-				], 'group1', true
2449
-			],
2450
-		];
2451
-	}
2452
-
2453
-	/**
2454
-	 *
2455
-	 * @param $shares
2456
-	 * @param $groupToDelete
2457
-	 * @param $shouldBeDeleted
2458
-	 */
2459
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataGroupDeleted')]
2460
-	public function testGroupDeleted($shares, $groupToDelete, $shouldBeDeleted): void {
2461
-		$qb = $this->dbConn->getQueryBuilder();
2462
-		$qb->insert('share')
2463
-			->setValue('share_type', $qb->createNamedParameter($shares['type']))
2464
-			->setValue('uid_owner', $qb->createNamedParameter('owner'))
2465
-			->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2466
-			->setValue('share_with', $qb->createNamedParameter($shares['recipient']))
2467
-			->setValue('item_type', $qb->createNamedParameter('file'))
2468
-			->setValue('item_source', $qb->createNamedParameter(42))
2469
-			->setValue('file_source', $qb->createNamedParameter(42))
2470
-			->executeStatement();
2471
-		$ids = [$qb->getLastInsertId()];
2472
-
2473
-		foreach ($shares['children'] as $child) {
2474
-			$qb = $this->dbConn->getQueryBuilder();
2475
-			$qb->insert('share')
2476
-				->setValue('share_type', $qb->createNamedParameter(2))
2477
-				->setValue('uid_owner', $qb->createNamedParameter('owner'))
2478
-				->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2479
-				->setValue('share_with', $qb->createNamedParameter($child))
2480
-				->setValue('item_type', $qb->createNamedParameter('file'))
2481
-				->setValue('item_source', $qb->createNamedParameter(42))
2482
-				->setValue('file_source', $qb->createNamedParameter(42))
2483
-				->setValue('parent', $qb->createNamedParameter($ids[0]))
2484
-				->executeStatement();
2485
-			$ids[] = $qb->getLastInsertId();
2486
-		}
2487
-
2488
-		$this->provider->groupDeleted($groupToDelete);
2489
-
2490
-		$qb = $this->dbConn->getQueryBuilder();
2491
-		$cursor = $qb->select('*')
2492
-			->from('share')
2493
-			->where($qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
2494
-			->executeQuery();
2495
-		$data = $cursor->fetchAllAssociative();
2496
-		$cursor->closeCursor();
2497
-
2498
-		$this->assertCount($shouldBeDeleted ? 0 : count($ids), $data);
2499
-	}
2500
-
2501
-	public static function dataUserDeletedFromGroup(): array {
2502
-		return [
2503
-			['group1', 'user1', true],
2504
-			['group1', 'user2', false],
2505
-			['group2', 'user1', false],
2506
-		];
2507
-	}
2508
-
2509
-	/**
2510
-	 * Given a group share with 'group1'
2511
-	 * And a user specific group share with 'user1'.
2512
-	 * User $user is deleted from group $gid.
2513
-	 *
2514
-	 *
2515
-	 * @param string $group
2516
-	 * @param string $user
2517
-	 * @param bool $toDelete
2518
-	 */
2519
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataUserDeletedFromGroup')]
2520
-	public function testUserDeletedFromGroup($group, $user, $toDelete): void {
2521
-		$qb = $this->dbConn->getQueryBuilder();
2522
-		$qb->insert('share')
2523
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
2524
-			->setValue('uid_owner', $qb->createNamedParameter('owner'))
2525
-			->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2526
-			->setValue('share_with', $qb->createNamedParameter('group1'))
2527
-			->setValue('item_type', $qb->createNamedParameter('file'))
2528
-			->setValue('item_source', $qb->createNamedParameter(42))
2529
-			->setValue('file_source', $qb->createNamedParameter(42));
2530
-		$qb->executeStatement();
2531
-		$id1 = $qb->getLastInsertId();
2532
-
2533
-		$qb = $this->dbConn->getQueryBuilder();
2534
-		$qb->insert('share')
2535
-			->setValue('share_type', $qb->createNamedParameter(2))
2536
-			->setValue('uid_owner', $qb->createNamedParameter('owner'))
2537
-			->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2538
-			->setValue('share_with', $qb->createNamedParameter('user1'))
2539
-			->setValue('item_type', $qb->createNamedParameter('file'))
2540
-			->setValue('item_source', $qb->createNamedParameter(42))
2541
-			->setValue('file_source', $qb->createNamedParameter(42))
2542
-			->setValue('parent', $qb->createNamedParameter($id1));
2543
-		$qb->executeStatement();
2544
-		$id2 = $qb->getLastInsertId();
2545
-
2546
-		$this->provider->userDeletedFromGroup($user, $group);
2547
-
2548
-		$qb = $this->dbConn->getQueryBuilder();
2549
-		$qb->select('*')
2550
-			->from('share')
2551
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id2)));
2552
-		$cursor = $qb->executeQuery();
2553
-		$data = $cursor->fetchAllAssociative();
2554
-		$cursor->closeCursor();
2555
-
2556
-		$this->assertCount($toDelete ? 0 : 1, $data);
2557
-	}
2558
-
2559
-	public function testGetSharesInFolder(): void {
2560
-		$userManager = Server::get(IUserManager::class);
2561
-		$groupManager = Server::get(IGroupManager::class);
2562
-		$rootFolder = Server::get(IRootFolder::class);
2563
-
2564
-		$provider = new DefaultShareProvider(
2565
-			$this->dbConn,
2566
-			$userManager,
2567
-			$groupManager,
2568
-			$rootFolder,
2569
-			$this->mailer,
2570
-			$this->defaults,
2571
-			$this->l10nFactory,
2572
-			$this->urlGenerator,
2573
-			$this->timeFactory,
2574
-			$this->logger,
2575
-			$this->shareManager,
2576
-			$this->config,
2577
-		);
2578
-
2579
-		$password = md5(time());
2580
-
2581
-		$u1 = $userManager->createUser('testShare1', $password);
2582
-		$u2 = $userManager->createUser('testShare2', $password);
2583
-		$u3 = $userManager->createUser('testShare3', $password);
2584
-
2585
-		$g1 = $groupManager->createGroup('group1');
2586
-
2587
-		$u1Folder = $rootFolder->getUserFolder($u1->getUID());
2588
-		$folder1 = $u1Folder->newFolder('foo');
2589
-		$file1 = $folder1->newFile('bar');
2590
-		$folder2 = $folder1->newFolder('baz');
2591
-
2592
-		$shareManager = Server::get(IShareManager::class);
2593
-		$share1 = $shareManager->newShare();
2594
-		$share1->setNode($folder1)
2595
-			->setSharedBy($u1->getUID())
2596
-			->setSharedWith($u2->getUID())
2597
-			->setShareOwner($u1->getUID())
2598
-			->setShareType(IShare::TYPE_USER)
2599
-			->setPermissions(Constants::PERMISSION_ALL);
2600
-		$share1 = $this->provider->create($share1);
2601
-
2602
-		$share2 = $shareManager->newShare();
2603
-		$share2->setNode($file1)
2604
-			->setSharedBy($u2->getUID())
2605
-			->setSharedWith($u3->getUID())
2606
-			->setShareOwner($u1->getUID())
2607
-			->setShareType(IShare::TYPE_USER)
2608
-			->setPermissions(Constants::PERMISSION_READ);
2609
-		$share2 = $this->provider->create($share2);
2610
-
2611
-		$share3 = $shareManager->newShare();
2612
-		$share3->setNode($folder2)
2613
-			->setSharedBy($u2->getUID())
2614
-			->setShareOwner($u1->getUID())
2615
-			->setShareType(IShare::TYPE_LINK)
2616
-			->setPermissions(Constants::PERMISSION_READ);
2617
-		$share3 = $this->provider->create($share3);
2618
-
2619
-		$share4 = $shareManager->newShare();
2620
-		$share4->setNode($folder2)
2621
-			->setSharedBy($u1->getUID())
2622
-			->setSharedWith($g1->getGID())
2623
-			->setShareOwner($u1->getUID())
2624
-			->setShareType(IShare::TYPE_GROUP)
2625
-			->setPermissions(Constants::PERMISSION_READ);
2626
-		$share4 = $this->provider->create($share4);
2627
-
2628
-		$result = $provider->getSharesInFolder($u1->getUID(), $folder1, false);
2629
-		$this->assertCount(1, $result);
2630
-		$shares = array_pop($result);
2631
-		$this->assertCount(1, $shares);
2632
-		$this->assertSame($folder2->getId(), $shares[0]->getNodeId());
2633
-
2634
-		$result = $provider->getSharesInFolder($u1->getUID(), $folder1, true);
2635
-		$this->assertCount(2, $result);
2636
-
2637
-		$file_shares = $result[$file1->getId()];
2638
-		$this->assertCount(1, $file_shares);
2639
-		$this->assertSame($file1->getId(), $file_shares[0]->getNodeId());
2640
-		$this->assertSame(IShare::TYPE_USER, $file_shares[0]->getShareType());
2641
-
2642
-		$folder_shares = $result[$folder2->getId()];
2643
-		$this->assertCount(2, $folder_shares);
2644
-		$this->assertSame($folder2->getId(), $folder_shares[0]->getNodeId());
2645
-		$this->assertSame($folder2->getId(), $folder_shares[1]->getNodeId());
2646
-		$this->assertSame(IShare::TYPE_LINK, $folder_shares[0]->getShareType());
2647
-		$this->assertSame(IShare::TYPE_GROUP, $folder_shares[1]->getShareType());
2648
-
2649
-		$provider->delete($share1);
2650
-		$provider->delete($share2);
2651
-		$provider->delete($share3);
2652
-		$provider->delete($share4);
2653
-
2654
-		$u1->delete();
2655
-		$u2->delete();
2656
-		$u3->delete();
2657
-		$g1->delete();
2658
-	}
2659
-
2660
-	public function testGetAccessListNoCurrentAccessRequired(): void {
2661
-		$userManager = Server::get(IUserManager::class);
2662
-		$groupManager = Server::get(IGroupManager::class);
2663
-		$rootFolder = Server::get(IRootFolder::class);
2664
-
2665
-		$provider = new DefaultShareProvider(
2666
-			$this->dbConn,
2667
-			$userManager,
2668
-			$groupManager,
2669
-			$rootFolder,
2670
-			$this->mailer,
2671
-			$this->defaults,
2672
-			$this->l10nFactory,
2673
-			$this->urlGenerator,
2674
-			$this->timeFactory,
2675
-			$this->logger,
2676
-			$this->shareManager,
2677
-			$this->config,
2678
-		);
2679
-
2680
-		$u1 = $userManager->createUser('testShare1', 'test');
2681
-		$u2 = $userManager->createUser('testShare2', 'test');
2682
-		$u3 = $userManager->createUser('testShare3', 'test');
2683
-		$u4 = $userManager->createUser('testShare4', 'test');
2684
-		$u5 = $userManager->createUser('testShare5', 'test');
2685
-
2686
-		$g1 = $groupManager->createGroup('group1');
2687
-		$g1->addUser($u3);
2688
-		$g1->addUser($u4);
2689
-
2690
-		$u1Folder = $rootFolder->getUserFolder($u1->getUID());
2691
-		$folder1 = $u1Folder->newFolder('foo');
2692
-		$folder2 = $folder1->newFolder('baz');
2693
-		$file1 = $folder2->newFile('bar');
2694
-
2695
-		$result = $provider->getAccessList([$folder1, $folder2, $file1], false);
2696
-		$this->assertCount(0, $result['users']);
2697
-		$this->assertFalse($result['public']);
2698
-
2699
-		$shareManager = Server::get(IShareManager::class);
2700
-		$share1 = $shareManager->newShare();
2701
-		$share1->setNode($folder1)
2702
-			->setSharedBy($u1->getUID())
2703
-			->setSharedWith($u2->getUID())
2704
-			->setShareOwner($u1->getUID())
2705
-			->setShareType(IShare::TYPE_USER)
2706
-			->setPermissions(Constants::PERMISSION_ALL);
2707
-		$share1 = $this->provider->create($share1);
2708
-		$share1 = $provider->acceptShare($share1, $u2->getUid());
2709
-
2710
-		$share2 = $shareManager->newShare();
2711
-		$share2->setNode($folder2)
2712
-			->setSharedBy($u2->getUID())
2713
-			->setSharedWith($g1->getGID())
2714
-			->setShareOwner($u1->getUID())
2715
-			->setShareType(IShare::TYPE_GROUP)
2716
-			->setPermissions(Constants::PERMISSION_ALL);
2717
-		$share2 = $this->provider->create($share2);
2718
-
2719
-		$shareManager->deleteFromSelf($share2, $u4->getUID());
2720
-
2721
-		$share2 = $provider->acceptShare($share2, $u3->getUid());
2722
-		$share2 = $provider->acceptShare($share2, $u4->getUid());
2723
-
2724
-		$share3 = $shareManager->newShare();
2725
-		$share3->setNode($file1)
2726
-			->setSharedBy($u3->getUID())
2727
-			->setShareOwner($u1->getUID())
2728
-			->setShareType(IShare::TYPE_LINK)
2729
-			->setPermissions(Constants::PERMISSION_READ);
2730
-		$share3 = $this->provider->create($share3);
2731
-
2732
-		$share4 = $shareManager->newShare();
2733
-		$share4->setNode($file1)
2734
-			->setSharedBy($u3->getUID())
2735
-			->setSharedWith($u5->getUID())
2736
-			->setShareOwner($u1->getUID())
2737
-			->setShareType(IShare::TYPE_USER)
2738
-			->setPermissions(Constants::PERMISSION_READ);
2739
-		$share4 = $this->provider->create($share4);
2740
-		$share4 = $provider->acceptShare($share4, $u5->getUid());
2741
-
2742
-		$result = $provider->getAccessList([$folder1, $folder2, $file1], false);
2743
-
2744
-		$this->assertCount(4, $result['users']);
2745
-		$this->assertContains('testShare2', $result['users']);
2746
-		$this->assertContains('testShare3', $result['users']);
2747
-		$this->assertContains('testShare4', $result['users']);
2748
-		$this->assertContains('testShare5', $result['users']);
2749
-		$this->assertTrue($result['public']);
2750
-
2751
-		$provider->delete($share1);
2752
-		$provider->delete($share2);
2753
-		$provider->delete($share3);
2754
-		$provider->delete($share4);
2755
-
2756
-		$u1->delete();
2757
-		$u2->delete();
2758
-		$u3->delete();
2759
-		$u4->delete();
2760
-		$u5->delete();
2761
-		$g1->delete();
2762
-	}
2763
-
2764
-	public function testGetAccessListCurrentAccessRequired(): void {
2765
-		$userManager = Server::get(IUserManager::class);
2766
-		$groupManager = Server::get(IGroupManager::class);
2767
-		$rootFolder = Server::get(IRootFolder::class);
2768
-
2769
-		$provider = new DefaultShareProvider(
2770
-			$this->dbConn,
2771
-			$userManager,
2772
-			$groupManager,
2773
-			$rootFolder,
2774
-			$this->mailer,
2775
-			$this->defaults,
2776
-			$this->l10nFactory,
2777
-			$this->urlGenerator,
2778
-			$this->timeFactory,
2779
-			$this->logger,
2780
-			$this->shareManager,
2781
-			$this->config,
2782
-		);
2783
-
2784
-		$u1 = $userManager->createUser('testShare1', 'test');
2785
-		$u2 = $userManager->createUser('testShare2', 'test');
2786
-		$u3 = $userManager->createUser('testShare3', 'test');
2787
-		$u4 = $userManager->createUser('testShare4', 'test');
2788
-		$u5 = $userManager->createUser('testShare5', 'test');
2789
-
2790
-		$g1 = $groupManager->createGroup('group1');
2791
-		$g1->addUser($u3);
2792
-		$g1->addUser($u4);
2793
-
2794
-		$u1Folder = $rootFolder->getUserFolder($u1->getUID());
2795
-		$folder1 = $u1Folder->newFolder('foo');
2796
-		$folder2 = $folder1->newFolder('baz');
2797
-		$file1 = $folder2->newFile('bar');
2798
-
2799
-		$result = $provider->getAccessList([$folder1, $folder2, $file1], false);
2800
-		$this->assertCount(0, $result['users']);
2801
-		$this->assertFalse($result['public']);
2802
-
2803
-		$shareManager = Server::get(IShareManager::class);
2804
-		$share1 = $shareManager->newShare();
2805
-		$share1->setNode($folder1)
2806
-			->setSharedBy($u1->getUID())
2807
-			->setSharedWith($u2->getUID())
2808
-			->setShareOwner($u1->getUID())
2809
-			->setShareType(IShare::TYPE_USER)
2810
-			->setPermissions(Constants::PERMISSION_ALL);
2811
-		$share1 = $this->provider->create($share1);
2812
-		$share1 = $provider->acceptShare($share1, $u2->getUid());
2813
-
2814
-		$share2 = $shareManager->newShare();
2815
-		$share2->setNode($folder2)
2816
-			->setSharedBy($u2->getUID())
2817
-			->setSharedWith($g1->getGID())
2818
-			->setShareOwner($u1->getUID())
2819
-			->setShareType(IShare::TYPE_GROUP)
2820
-			->setPermissions(Constants::PERMISSION_ALL);
2821
-		$share2 = $this->provider->create($share2);
2822
-		$share2 = $provider->acceptShare($share2, $u3->getUid());
2823
-		$share2 = $provider->acceptShare($share2, $u4->getUid());
2824
-
2825
-		$shareManager->deleteFromSelf($share2, $u4->getUID());
2826
-
2827
-		$share3 = $shareManager->newShare();
2828
-		$share3->setNode($file1)
2829
-			->setSharedBy($u3->getUID())
2830
-			->setShareOwner($u1->getUID())
2831
-			->setShareType(IShare::TYPE_LINK)
2832
-			->setPermissions(Constants::PERMISSION_READ);
2833
-		$share3 = $this->provider->create($share3);
2834
-
2835
-		$share4 = $shareManager->newShare();
2836
-		$share4->setNode($file1)
2837
-			->setSharedBy($u3->getUID())
2838
-			->setSharedWith($u5->getUID())
2839
-			->setShareOwner($u1->getUID())
2840
-			->setShareType(IShare::TYPE_USER)
2841
-			->setPermissions(Constants::PERMISSION_READ);
2842
-		$share4 = $this->provider->create($share4);
2843
-		$share4 = $provider->acceptShare($share4, $u5->getUid());
2844
-
2845
-		$result = $provider->getAccessList([$folder1, $folder2, $file1], true);
2846
-
2847
-		$this->assertCount(3, $result['users']);
2848
-		$this->assertArrayHasKey('testShare2', $result['users']);
2849
-		$this->assertArrayHasKey('testShare3', $result['users']);
2850
-		$this->assertArrayHasKey('testShare5', $result['users']);
2851
-		$this->assertTrue($result['public']);
2852
-
2853
-		$provider->delete($share1);
2854
-		$provider->delete($share2);
2855
-		$provider->delete($share3);
2856
-		$provider->delete($share4);
2857
-
2858
-		$u1->delete();
2859
-		$u2->delete();
2860
-		$u3->delete();
2861
-		$u4->delete();
2862
-		$u5->delete();
2863
-		$g1->delete();
2864
-	}
2865
-
2866
-	public function testGetAllShares(): void {
2867
-		$qb = $this->dbConn->getQueryBuilder();
2868
-
2869
-		$qb->insert('share')
2870
-			->values([
2871
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
2872
-				'share_with' => $qb->expr()->literal('sharedWith1'),
2873
-				'uid_owner' => $qb->expr()->literal('shareOwner1'),
2874
-				'uid_initiator' => $qb->expr()->literal('sharedBy1'),
2875
-				'item_type' => $qb->expr()->literal('file'),
2876
-				'file_source' => $qb->expr()->literal(42),
2877
-				'file_target' => $qb->expr()->literal('myTarget1'),
2878
-				'permissions' => $qb->expr()->literal(13),
2879
-			]);
2880
-		$qb->executeStatement();
2881
-
2882
-		$id1 = $qb->getLastInsertId();
2883
-
2884
-		$qb->insert('share')
2885
-			->values([
2886
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
2887
-				'share_with' => $qb->expr()->literal('sharedWith2'),
2888
-				'uid_owner' => $qb->expr()->literal('shareOwner2'),
2889
-				'uid_initiator' => $qb->expr()->literal('sharedBy2'),
2890
-				'item_type' => $qb->expr()->literal('file'),
2891
-				'file_source' => $qb->expr()->literal(43),
2892
-				'file_target' => $qb->expr()->literal('myTarget2'),
2893
-				'permissions' => $qb->expr()->literal(14),
2894
-			]);
2895
-		$qb->executeStatement();
2896
-
2897
-		$id2 = $qb->getLastInsertId();
2898
-
2899
-		$qb->insert('share')
2900
-			->values([
2901
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
2902
-				'token' => $qb->expr()->literal('token3'),
2903
-				'uid_owner' => $qb->expr()->literal('shareOwner3'),
2904
-				'uid_initiator' => $qb->expr()->literal('sharedBy3'),
2905
-				'item_type' => $qb->expr()->literal('file'),
2906
-				'file_source' => $qb->expr()->literal(44),
2907
-				'file_target' => $qb->expr()->literal('myTarget3'),
2908
-				'permissions' => $qb->expr()->literal(15),
2909
-			]);
2910
-		$qb->executeStatement();
2911
-
2912
-		$id3 = $qb->getLastInsertId();
2913
-
2914
-		$qb->insert('share')
2915
-			->values([
2916
-				'share_type' => $qb->expr()->literal(IShare::TYPE_EMAIL),
2917
-				'share_with' => $qb->expr()->literal('shareOwner4'),
2918
-				'token' => $qb->expr()->literal('token4'),
2919
-				'uid_owner' => $qb->expr()->literal('shareOwner4'),
2920
-				'uid_initiator' => $qb->expr()->literal('sharedBy4'),
2921
-				'item_type' => $qb->expr()->literal('file'),
2922
-				'file_source' => $qb->expr()->literal(45),
2923
-				'file_target' => $qb->expr()->literal('myTarget4'),
2924
-				'permissions' => $qb->expr()->literal(16),
2925
-			]);
2926
-		$qb->executeStatement();
2927
-
2928
-		$id4 = $qb->getLastInsertId();
2929
-
2930
-		$qb->insert('share')
2931
-			->values([
2932
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
2933
-				'token' => $qb->expr()->literal('token5'),
2934
-				'uid_owner' => $qb->expr()->literal('shareOwner5'),
2935
-				'uid_initiator' => $qb->expr()->literal('sharedBy5'),
2936
-				'item_type' => $qb->expr()->literal('file'),
2937
-				'file_source' => $qb->expr()->literal(46),
2938
-				'file_target' => $qb->expr()->literal('myTarget5'),
2939
-				'permissions' => $qb->expr()->literal(17),
2940
-			]);
2941
-		$qb->executeStatement();
2942
-
2943
-		$id5 = $qb->getLastInsertId();
2944
-
2945
-		$ownerPath1 = $this->createMock(File::class);
2946
-		$shareOwner1Folder = $this->createMock(Folder::class);
2947
-		$shareOwner1Folder->method('getFirstNodeById')->willReturn($ownerPath1);
2948
-
2949
-		$ownerPath2 = $this->createMock(File::class);
2950
-		$shareOwner2Folder = $this->createMock(Folder::class);
2951
-		$shareOwner2Folder->method('getFirstNodeById')->willReturn($ownerPath2);
2952
-
2953
-		$ownerPath3 = $this->createMock(File::class);
2954
-		$shareOwner3Folder = $this->createMock(Folder::class);
2955
-		$shareOwner3Folder->method('getFirstNodeById')->willReturn($ownerPath3);
2956
-
2957
-		$ownerPath4 = $this->createMock(File::class);
2958
-		$shareOwner4Folder = $this->createMock(Folder::class);
2959
-		$shareOwner4Folder->method('getFirstNodeById')->willReturn($ownerPath4);
2960
-
2961
-		$ownerPath5 = $this->createMock(File::class);
2962
-		$shareOwner5Folder = $this->createMock(Folder::class);
2963
-		$shareOwner5Folder->method('getFirstNodeById')->willReturn($ownerPath5);
2964
-
2965
-		$this->rootFolder
2966
-			->method('getUserFolder')
2967
-			->willReturnMap(
2968
-				[
2969
-					['shareOwner1', $shareOwner1Folder],
2970
-					['shareOwner2', $shareOwner2Folder],
2971
-					['shareOwner3', $shareOwner3Folder],
2972
-					['shareOwner4', $shareOwner4Folder],
2973
-					['shareOwner5', $shareOwner5Folder],
2974
-				]
2975
-			);
2976
-
2977
-		$shares = iterator_to_array($this->provider->getAllShares());
2978
-		$this->assertEquals(4, count($shares));
2979
-
2980
-		$share = $shares[0];
2981
-
2982
-		// We fetch the node so the root folder is eventually called
2983
-
2984
-		$this->assertEquals($id1, $share->getId());
2985
-		$this->assertEquals(IShare::TYPE_USER, $share->getShareType());
2986
-		$this->assertEquals('sharedWith1', $share->getSharedWith());
2987
-		$this->assertEquals('sharedBy1', $share->getSharedBy());
2988
-		$this->assertEquals('shareOwner1', $share->getShareOwner());
2989
-		$this->assertEquals($ownerPath1, $share->getNode());
2990
-		$this->assertEquals(13, $share->getPermissions());
2991
-		$this->assertEquals(null, $share->getToken());
2992
-		$this->assertEquals('myTarget1', $share->getTarget());
2993
-
2994
-		$share = $shares[1];
2995
-
2996
-		$this->assertEquals($id2, $share->getId());
2997
-		$this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
2998
-		$this->assertEquals('sharedWith2', $share->getSharedWith());
2999
-		$this->assertEquals('sharedBy2', $share->getSharedBy());
3000
-		$this->assertEquals('shareOwner2', $share->getShareOwner());
3001
-		$this->assertEquals($ownerPath2, $share->getNode());
3002
-		$this->assertEquals(14, $share->getPermissions());
3003
-		$this->assertEquals(null, $share->getToken());
3004
-		$this->assertEquals('myTarget2', $share->getTarget());
3005
-
3006
-		$share = $shares[2];
3007
-
3008
-		$this->assertEquals($id3, $share->getId());
3009
-		$this->assertEquals(IShare::TYPE_LINK, $share->getShareType());
3010
-		$this->assertEquals(null, $share->getSharedWith());
3011
-		$this->assertEquals('sharedBy3', $share->getSharedBy());
3012
-		$this->assertEquals('shareOwner3', $share->getShareOwner());
3013
-		$this->assertEquals($ownerPath3, $share->getNode());
3014
-		$this->assertEquals(15, $share->getPermissions());
3015
-		$this->assertEquals('token3', $share->getToken());
3016
-		$this->assertEquals('myTarget3', $share->getTarget());
3017
-
3018
-		$share = $shares[3];
3019
-
3020
-		$this->assertEquals($id5, $share->getId());
3021
-		$this->assertEquals(IShare::TYPE_LINK, $share->getShareType());
3022
-		$this->assertEquals(null, $share->getSharedWith());
3023
-		$this->assertEquals('sharedBy5', $share->getSharedBy());
3024
-		$this->assertEquals('shareOwner5', $share->getShareOwner());
3025
-		$this->assertEquals($ownerPath5, $share->getNode());
3026
-		$this->assertEquals(17, $share->getPermissions());
3027
-		$this->assertEquals('token5', $share->getToken());
3028
-		$this->assertEquals('myTarget5', $share->getTarget());
3029
-	}
3030
-
3031
-
3032
-	public function testGetSharesByPath(): void {
3033
-		$qb = $this->dbConn->getQueryBuilder();
3034
-
3035
-		$qb->insert('share')
3036
-			->values([
3037
-				'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
3038
-				'uid_owner' => $qb->expr()->literal('user1'),
3039
-				'uid_initiator' => $qb->expr()->literal('user1'),
3040
-				'share_with' => $qb->expr()->literal('user2'),
3041
-				'item_type' => $qb->expr()->literal('file'),
3042
-				'file_source' => $qb->expr()->literal(1),
3043
-			]);
3044
-		$qb->executeStatement();
3045
-
3046
-		$id1 = $qb->getLastInsertId();
3047
-
3048
-		$qb->insert('share')
3049
-			->values([
3050
-				'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
3051
-				'uid_owner' => $qb->expr()->literal('user1'),
3052
-				'uid_initiator' => $qb->expr()->literal('user1'),
3053
-				'share_with' => $qb->expr()->literal('user2'),
3054
-				'item_type' => $qb->expr()->literal('file'),
3055
-				'file_source' => $qb->expr()->literal(1),
3056
-			]);
3057
-		$qb->executeStatement();
3058
-
3059
-		$id2 = $qb->getLastInsertId();
3060
-
3061
-		$qb->insert('share')
3062
-			->values([
3063
-				'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
3064
-				'uid_owner' => $qb->expr()->literal('user1'),
3065
-				'uid_initiator' => $qb->expr()->literal('user1'),
3066
-				'share_with' => $qb->expr()->literal('user2'),
3067
-				'item_type' => $qb->expr()->literal('file'),
3068
-				'file_source' => $qb->expr()->literal(1),
3069
-			]);
3070
-		$qb->executeStatement();
3071
-
3072
-		$id3 = $qb->getLastInsertId();
3073
-
3074
-		$ownerPath1 = $this->createMock(File::class);
3075
-		$shareOwner1Folder = $this->createMock(Folder::class);
3076
-		$shareOwner1Folder->method('getFirstNodeById')->willReturn($ownerPath1);
3077
-
3078
-		$ownerPath2 = $this->createMock(File::class);
3079
-		$shareOwner2Folder = $this->createMock(Folder::class);
3080
-		$shareOwner2Folder->method('getFirstNodeById')->willReturn($ownerPath2);
3081
-
3082
-		$ownerPath3 = $this->createMock(File::class);
3083
-		$shareOwner3Folder = $this->createMock(Folder::class);
3084
-		$shareOwner3Folder->method('getFirstNodeById')->willReturn($ownerPath3);
3085
-
3086
-		$this->rootFolder
3087
-			->method('getUserFolder')
3088
-			->willReturnMap(
3089
-				[
3090
-					['shareOwner1', $shareOwner1Folder],
3091
-					['shareOwner2', $shareOwner2Folder],
3092
-					['shareOwner3', $shareOwner3Folder],
3093
-				]
3094
-			);
3095
-
3096
-		$node = $this->createMock(Node::class);
3097
-		$node
3098
-			->expects($this->once())
3099
-			->method('getId')
3100
-			->willReturn(1);
3101
-
3102
-		$shares = $this->provider->getSharesByPath($node);
3103
-		$this->assertCount(3, $shares);
3104
-
3105
-		$this->assertEquals($id1, $shares[0]->getId());
3106
-		$this->assertEquals(IShare::TYPE_USER, $shares[0]->getShareType());
3107
-
3108
-		$this->assertEquals($id2, $shares[1]->getId());
3109
-		$this->assertEquals(IShare::TYPE_GROUP, $shares[1]->getShareType());
3110
-
3111
-		$this->assertEquals($id3, $shares[2]->getId());
3112
-		$this->assertEquals(IShare::TYPE_LINK, $shares[2]->getShareType());
3113
-	}
1156
+        $qb = $this->dbConn->getQueryBuilder();
1157
+        $qb->insert('share')
1158
+            ->values([
1159
+                'share_type' => $qb->expr()->literal(2),
1160
+                'share_with' => $qb->expr()->literal('user'),
1161
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1162
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1163
+                'item_type' => $qb->expr()->literal('file'),
1164
+                'file_source' => $qb->expr()->literal($fileId),
1165
+                'file_target' => $qb->expr()->literal('userTarget'),
1166
+                'permissions' => $qb->expr()->literal(0),
1167
+                'parent' => $qb->expr()->literal($id),
1168
+            ]);
1169
+        $this->assertEquals(1, $qb->executeStatement());
1170
+
1171
+        $groups = ['sharedWith'];
1172
+
1173
+        $user = $this->createMock(IUser::class);
1174
+        $user->method('getUID')->willReturn('user');
1175
+        $owner = $this->createMock(IUser::class);
1176
+        $owner->method('getUID')->willReturn('shareOwner');
1177
+        $initiator = $this->createMock(IUser::class);
1178
+        $initiator->method('getUID')->willReturn('sharedBy');
1179
+
1180
+        $this->userManager->method('get')->willReturnMap([
1181
+            ['user', $user],
1182
+            ['shareOwner', $owner],
1183
+            ['sharedBy', $initiator],
1184
+        ]);
1185
+        $this->groupManager
1186
+            ->method('getUserGroupIds')
1187
+            ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'user' ? $groups : []));
1188
+
1189
+        $file = $this->createMock(File::class);
1190
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1191
+        $this->rootFolder->method('getFirstNodeById')->with($fileId)->willReturn($file);
1192
+
1193
+        $share = $this->provider->getSharedWith('user', IShare::TYPE_GROUP, null, -1, 0);
1194
+        $this->assertCount(1, $share);
1195
+
1196
+        $share = $share[0];
1197
+        $this->assertSame((string)$id, $share->getId());
1198
+        $this->assertSame('sharedWith', $share->getSharedWith());
1199
+        $this->assertSame('shareOwner', $share->getShareOwner());
1200
+        $this->assertSame('sharedBy', $share->getSharedBy());
1201
+        $this->assertSame(IShare::TYPE_GROUP, $share->getShareType());
1202
+        $this->assertSame(0, $share->getPermissions());
1203
+        $this->assertSame('userTarget', $share->getTarget());
1204
+    }
1205
+
1206
+    #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1207
+    public function testGetSharedWithUserWithNode($storageStringId, $fileName1, $fileName2): void {
1208
+        $storageId = $this->createTestStorageEntry($storageStringId);
1209
+        $fileId = $this->createTestFileEntry($fileName1, $storageId);
1210
+        $fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1211
+        $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1',
1212
+            'file', $fileId, 'myTarget', 31, null, null, null);
1213
+        $id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1',
1214
+            'file', $fileId2, 'myTarget', 31, null, null, null);
1215
+
1216
+        $user0 = $this->createMock(IUser::class);
1217
+        $user0->method('getUID')->willReturn('user0');
1218
+        $user0->method('getDisplayName')->willReturn('user0');
1219
+        $user1 = $this->createMock(IUser::class);
1220
+        $user1->method('getUID')->willReturn('user1');
1221
+        $user0->method('getDisplayName')->willReturn('user0');
1222
+
1223
+        $this->userManager->method('get')->willReturnMap([
1224
+            ['user0', $user0],
1225
+            ['user1', $user1],
1226
+        ]);
1227
+
1228
+        $file = $this->createMock(File::class);
1229
+        $file->method('getId')->willReturn($fileId2);
1230
+
1231
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1232
+        $this->rootFolder->method('getFirstNodeById')->with($fileId2)->willReturn($file);
1233
+
1234
+        $share = $this->provider->getSharedWith('user0', IShare::TYPE_USER, $file, -1, 0);
1235
+        $this->assertCount(1, $share);
1236
+
1237
+        $share = $share[0];
1238
+        $this->assertEquals($id, $share->getId());
1239
+        $this->assertSame('user0', $share->getSharedWith());
1240
+        $this->assertSame('user1', $share->getShareOwner());
1241
+        $this->assertSame('user1', $share->getSharedBy());
1242
+        $this->assertSame($file, $share->getNode());
1243
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1244
+    }
1245
+
1246
+    #[\PHPUnit\Framework\Attributes\DataProvider('storageAndFileNameProvider')]
1247
+    public function testGetSharedWithGroupWithNode($storageStringId, $fileName1, $fileName2): void {
1248
+        $storageId = $this->createTestStorageEntry($storageStringId);
1249
+        $fileId = $this->createTestFileEntry($fileName1, $storageId);
1250
+        $fileId2 = $this->createTestFileEntry($fileName2, $storageId);
1251
+        $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1',
1252
+            'file', $fileId, 'myTarget', 31, null, null, null);
1253
+        $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1',
1254
+            'file', $fileId2, 'myTarget', 31, null, null, null);
1255
+
1256
+        $user0 = $this->createMock(IUser::class);
1257
+        $user0->method('getUID')->willReturn('user0');
1258
+        $user1 = $this->createMock(IUser::class);
1259
+        $user1->method('getUID')->willReturn('user1');
1260
+
1261
+        $this->userManager->method('get')->willReturnMap([
1262
+            ['user0', $user0],
1263
+            ['user1', $user1],
1264
+        ]);
1265
+
1266
+        $this->groupManager
1267
+            ->method('getUserGroupIds')
1268
+            ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'user0' ? ['group0'] : []));
1269
+
1270
+        $node = $this->createMock(Folder::class);
1271
+        $node->method('getId')->willReturn($fileId2);
1272
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1273
+        $this->rootFolder->method('getFirstNodeById')->with($fileId2)->willReturn($node);
1274
+
1275
+        $share = $this->provider->getSharedWith('user0', IShare::TYPE_GROUP, $node, -1, 0);
1276
+        $this->assertCount(1, $share);
1277
+
1278
+        $share = $share[0];
1279
+        $this->assertEquals($id, $share->getId());
1280
+        $this->assertSame('group0', $share->getSharedWith());
1281
+        $this->assertSame('user1', $share->getShareOwner());
1282
+        $this->assertSame('user1', $share->getSharedBy());
1283
+        $this->assertSame($node, $share->getNode());
1284
+        $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
1285
+    }
1286
+
1287
+    public static function shareTypesProvider(): array {
1288
+        return [
1289
+            [IShare::TYPE_USER, false],
1290
+            [IShare::TYPE_GROUP, false],
1291
+            [IShare::TYPE_USER, true],
1292
+            [IShare::TYPE_GROUP, true],
1293
+        ];
1294
+    }
1295
+
1296
+    #[\PHPUnit\Framework\Attributes\DataProvider('shareTypesProvider')]
1297
+    public function testGetSharedWithWithDeletedFile($shareType, $trashed): void {
1298
+        if ($trashed) {
1299
+            // exists in database but is in trash
1300
+            $storageId = $this->createTestStorageEntry('home::shareOwner');
1301
+            $deletedFileId = $this->createTestFileEntry('files_trashbin/files/test.txt.d1465553223', $storageId);
1302
+        } else {
1303
+            // fileid that doesn't exist in the database
1304
+            $deletedFileId = 123;
1305
+        }
1306
+        $qb = $this->dbConn->getQueryBuilder();
1307
+        $qb->insert('share')
1308
+            ->values([
1309
+                'share_type' => $qb->expr()->literal($shareType),
1310
+                'share_with' => $qb->expr()->literal('sharedWith'),
1311
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1312
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1313
+                'item_type' => $qb->expr()->literal('file'),
1314
+                'file_source' => $qb->expr()->literal($deletedFileId),
1315
+                'file_target' => $qb->expr()->literal('myTarget'),
1316
+                'permissions' => $qb->expr()->literal(13),
1317
+            ]);
1318
+        $this->assertEquals(1, $qb->executeStatement());
1319
+
1320
+        $file = $this->createMock(File::class);
1321
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1322
+        $this->rootFolder->method('getFirstNodeById')->with($deletedFileId)->willReturn($file);
1323
+
1324
+        $groups = [];
1325
+        foreach (range(0, 100) as $i) {
1326
+            $groups[] = 'group' . $i;
1327
+        }
1328
+
1329
+        $groups[] = 'sharedWith';
1330
+
1331
+        $user = $this->createMock(IUser::class);
1332
+        $user->method('getUID')->willReturn('sharedWith');
1333
+        $owner = $this->createMock(IUser::class);
1334
+        $owner->method('getUID')->willReturn('shareOwner');
1335
+        $initiator = $this->createMock(IUser::class);
1336
+        $initiator->method('getUID')->willReturn('sharedBy');
1337
+
1338
+        $this->userManager->method('get')->willReturnMap([
1339
+            ['sharedWith', $user],
1340
+            ['shareOwner', $owner],
1341
+            ['sharedBy', $initiator],
1342
+        ]);
1343
+        $this->groupManager
1344
+            ->method('getUserGroupIds')
1345
+            ->willReturnCallback(fn (IUser $user) => ($user->getUID() === 'sharedWith' ? $groups : []));
1346
+
1347
+        $share = $this->provider->getSharedWith('sharedWith', $shareType, null, 1, 0);
1348
+        $this->assertCount(0, $share);
1349
+    }
1350
+
1351
+    public function testGetSharesBy(): void {
1352
+        $qb = $this->dbConn->getQueryBuilder();
1353
+        $qb->insert('share')
1354
+            ->values([
1355
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1356
+                'share_with' => $qb->expr()->literal('sharedWith'),
1357
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1358
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1359
+                'item_type' => $qb->expr()->literal('file'),
1360
+                'file_source' => $qb->expr()->literal(42),
1361
+                'file_target' => $qb->expr()->literal('myTarget'),
1362
+                'permissions' => $qb->expr()->literal(13),
1363
+            ]);
1364
+        $this->assertEquals(1, $qb->executeStatement());
1365
+        $id = $qb->getLastInsertId();
1366
+
1367
+        $qb = $this->dbConn->getQueryBuilder();
1368
+        $qb->insert('share')
1369
+            ->values([
1370
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1371
+                'share_with' => $qb->expr()->literal('sharedWith'),
1372
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1373
+                'uid_initiator' => $qb->expr()->literal('sharedBy2'),
1374
+                'item_type' => $qb->expr()->literal('file'),
1375
+                'file_source' => $qb->expr()->literal(42),
1376
+                'file_target' => $qb->expr()->literal('userTarget'),
1377
+                'permissions' => $qb->expr()->literal(0),
1378
+                'parent' => $qb->expr()->literal($id),
1379
+            ]);
1380
+        $this->assertEquals(1, $qb->executeStatement());
1381
+
1382
+        $file = $this->createMock(File::class);
1383
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1384
+        $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
1385
+
1386
+        $share = $this->provider->getSharesBy('sharedBy', IShare::TYPE_USER, null, false, 1, 0);
1387
+        $this->assertCount(1, $share);
1388
+
1389
+        /** @var IShare $share */
1390
+        $share = $share[0];
1391
+        $this->assertEquals($id, $share->getId());
1392
+        $this->assertEquals('sharedWith', $share->getSharedWith());
1393
+        $this->assertEquals('shareOwner', $share->getShareOwner());
1394
+        $this->assertEquals('sharedBy', $share->getSharedBy());
1395
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1396
+        $this->assertEquals(13, $share->getPermissions());
1397
+        $this->assertEquals('myTarget', $share->getTarget());
1398
+    }
1399
+
1400
+    public function testGetSharesNode(): void {
1401
+        $qb = $this->dbConn->getQueryBuilder();
1402
+        $qb->insert('share')
1403
+            ->values([
1404
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1405
+                'share_with' => $qb->expr()->literal('sharedWith'),
1406
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1407
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1408
+                'item_type' => $qb->expr()->literal('file'),
1409
+                'file_source' => $qb->expr()->literal(42),
1410
+                'file_target' => $qb->expr()->literal('myTarget'),
1411
+                'permissions' => $qb->expr()->literal(13),
1412
+            ]);
1413
+        $this->assertEquals(1, $qb->executeStatement());
1414
+        $id = $qb->getLastInsertId();
1415
+
1416
+        $qb = $this->dbConn->getQueryBuilder();
1417
+        $qb->insert('share')
1418
+            ->values([
1419
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1420
+                'share_with' => $qb->expr()->literal('sharedWith'),
1421
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1422
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1423
+                'item_type' => $qb->expr()->literal('file'),
1424
+                'file_source' => $qb->expr()->literal(43),
1425
+                'file_target' => $qb->expr()->literal('userTarget'),
1426
+                'permissions' => $qb->expr()->literal(0),
1427
+                'parent' => $qb->expr()->literal($id),
1428
+            ]);
1429
+        $this->assertEquals(1, $qb->executeStatement());
1430
+
1431
+        $file = $this->createMock(File::class);
1432
+        $file->method('getId')->willReturn(42);
1433
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1434
+        $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
1435
+
1436
+        $share = $this->provider->getSharesBy('sharedBy', IShare::TYPE_USER, $file, false, 1, 0);
1437
+        $this->assertCount(1, $share);
1438
+
1439
+        /** @var IShare $share */
1440
+        $share = $share[0];
1441
+        $this->assertEquals($id, $share->getId());
1442
+        $this->assertEquals('sharedWith', $share->getSharedWith());
1443
+        $this->assertEquals('shareOwner', $share->getShareOwner());
1444
+        $this->assertEquals('sharedBy', $share->getSharedBy());
1445
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1446
+        $this->assertEquals(13, $share->getPermissions());
1447
+        $this->assertEquals('myTarget', $share->getTarget());
1448
+    }
1449
+
1450
+    public function testGetSharesReshare(): void {
1451
+        $qb = $this->dbConn->getQueryBuilder();
1452
+        $qb->insert('share')
1453
+            ->values([
1454
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1455
+                'share_with' => $qb->expr()->literal('sharedWith'),
1456
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1457
+                'uid_initiator' => $qb->expr()->literal('shareOwner'),
1458
+                'item_type' => $qb->expr()->literal('file'),
1459
+                'file_source' => $qb->expr()->literal(42),
1460
+                'file_target' => $qb->expr()->literal('myTarget'),
1461
+                'permissions' => $qb->expr()->literal(13),
1462
+            ]);
1463
+        $this->assertEquals(1, $qb->executeStatement());
1464
+        $id1 = $qb->getLastInsertId();
1465
+
1466
+        $qb = $this->dbConn->getQueryBuilder();
1467
+        $qb->insert('share')
1468
+            ->values([
1469
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1470
+                'share_with' => $qb->expr()->literal('sharedWith'),
1471
+                'uid_owner' => $qb->expr()->literal('shareOwner'),
1472
+                'uid_initiator' => $qb->expr()->literal('sharedBy'),
1473
+                'item_type' => $qb->expr()->literal('file'),
1474
+                'file_source' => $qb->expr()->literal(42),
1475
+                'file_target' => $qb->expr()->literal('userTarget'),
1476
+                'permissions' => $qb->expr()->literal(0),
1477
+            ]);
1478
+        $this->assertEquals(1, $qb->executeStatement());
1479
+        $id2 = $qb->getLastInsertId();
1480
+
1481
+        $file = $this->createMock(File::class);
1482
+        $file->method('getId')->willReturn(42);
1483
+        $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
1484
+        $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
1485
+
1486
+        $shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_USER, null, true, -1, 0);
1487
+        $this->assertCount(2, $shares);
1488
+
1489
+        /** @var IShare $share */
1490
+        $share = $shares[0];
1491
+        $this->assertEquals($id1, $share->getId());
1492
+        $this->assertSame('sharedWith', $share->getSharedWith());
1493
+        $this->assertSame('shareOwner', $share->getShareOwner());
1494
+        $this->assertSame('shareOwner', $share->getSharedBy());
1495
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1496
+        $this->assertEquals(13, $share->getPermissions());
1497
+        $this->assertEquals('myTarget', $share->getTarget());
1498
+
1499
+        $share = $shares[1];
1500
+        $this->assertEquals($id2, $share->getId());
1501
+        $this->assertSame('sharedWith', $share->getSharedWith());
1502
+        $this->assertSame('shareOwner', $share->getShareOwner());
1503
+        $this->assertSame('sharedBy', $share->getSharedBy());
1504
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
1505
+        $this->assertEquals(0, $share->getPermissions());
1506
+        $this->assertEquals('userTarget', $share->getTarget());
1507
+    }
1508
+
1509
+    public function testDeleteFromSelfGroupNoCustomShare(): void {
1510
+        $qb = $this->dbConn->getQueryBuilder();
1511
+        $stmt = $qb->insert('share')
1512
+            ->values([
1513
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1514
+                'share_with' => $qb->expr()->literal('group'),
1515
+                'uid_owner' => $qb->expr()->literal('user1'),
1516
+                'uid_initiator' => $qb->expr()->literal('user1'),
1517
+                'item_type' => $qb->expr()->literal('file'),
1518
+                'file_source' => $qb->expr()->literal(1),
1519
+                'file_target' => $qb->expr()->literal('myTarget1'),
1520
+                'permissions' => $qb->expr()->literal(2)
1521
+            ])->executeStatement();
1522
+        $this->assertEquals(1, $stmt);
1523
+        $id = $qb->getLastInsertId();
1524
+
1525
+        $user1 = $this->createMock(IUser::class);
1526
+        $user1->method('getUID')->willReturn('user1');
1527
+        $user2 = $this->createMock(IUser::class);
1528
+        $user2->method('getUID')->willReturn('user2');
1529
+        $this->userManager->method('get')->willReturnMap([
1530
+            ['user1', $user1],
1531
+            ['user2', $user2],
1532
+        ]);
1533
+
1534
+        $group = $this->createMock(IGroup::class);
1535
+        $group->method('getGID')->willReturn('group');
1536
+        $group->method('inGroup')->with($user2)->willReturn(true);
1537
+        $group->method('getDisplayName')->willReturn('group-displayname');
1538
+        $this->groupManager->method('get')->with('group')->willReturn($group);
1539
+
1540
+        $file = $this->createMock(File::class);
1541
+        $file->method('getId')->willReturn(1);
1542
+
1543
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1544
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1545
+
1546
+        $share = $this->provider->getShareById($id);
1547
+
1548
+        $this->provider->deleteFromSelf($share, 'user2');
1549
+
1550
+        $qb = $this->dbConn->getQueryBuilder();
1551
+        $stmt = $qb->select('*')
1552
+            ->from('share')
1553
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(2)))
1554
+            ->executeQuery();
1555
+
1556
+        $shares = $stmt->fetchAllAssociative();
1557
+        $stmt->closeCursor();
1558
+
1559
+        $this->assertCount(1, $shares);
1560
+        $share2 = $shares[0];
1561
+        $this->assertEquals($id, $share2['parent']);
1562
+        $this->assertEquals(0, $share2['permissions']);
1563
+        $this->assertEquals('user2', $share2['share_with']);
1564
+    }
1565
+
1566
+    public function testDeleteFromSelfGroupAlreadyCustomShare(): void {
1567
+        $qb = $this->dbConn->getQueryBuilder();
1568
+        $stmt = $qb->insert('share')
1569
+            ->values([
1570
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1571
+                'share_with' => $qb->expr()->literal('group'),
1572
+                'uid_owner' => $qb->expr()->literal('user1'),
1573
+                'uid_initiator' => $qb->expr()->literal('user1'),
1574
+                'item_type' => $qb->expr()->literal('file'),
1575
+                'file_source' => $qb->expr()->literal(1),
1576
+                'file_target' => $qb->expr()->literal('myTarget1'),
1577
+                'permissions' => $qb->expr()->literal(2)
1578
+            ])->executeStatement();
1579
+        $this->assertEquals(1, $stmt);
1580
+        $id = $qb->getLastInsertId();
1581
+
1582
+        $qb = $this->dbConn->getQueryBuilder();
1583
+        $stmt = $qb->insert('share')
1584
+            ->values([
1585
+                'share_type' => $qb->expr()->literal(2),
1586
+                'share_with' => $qb->expr()->literal('user2'),
1587
+                'uid_owner' => $qb->expr()->literal('user1'),
1588
+                'uid_initiator' => $qb->expr()->literal('user1'),
1589
+                'item_type' => $qb->expr()->literal('file'),
1590
+                'file_source' => $qb->expr()->literal(1),
1591
+                'file_target' => $qb->expr()->literal('myTarget1'),
1592
+                'permissions' => $qb->expr()->literal(2),
1593
+                'parent' => $qb->expr()->literal($id),
1594
+            ])->executeStatement();
1595
+        $this->assertEquals(1, $stmt);
1596
+
1597
+        $user1 = $this->createMock(IUser::class);
1598
+        $user1->method('getUID')->willReturn('user1');
1599
+        $user2 = $this->createMock(IUser::class);
1600
+        $user2->method('getUID')->willReturn('user2');
1601
+        $this->userManager->method('get')->willReturnMap([
1602
+            ['user1', $user1],
1603
+            ['user2', $user2],
1604
+        ]);
1605
+
1606
+        $group = $this->createMock(IGroup::class);
1607
+        $group->method('getGID')->willReturn('group');
1608
+        $group->method('inGroup')->with($user2)->willReturn(true);
1609
+        $group->method('getDisplayName')->willReturn('group-displayname');
1610
+        $this->groupManager->method('get')->with('group')->willReturn($group);
1611
+
1612
+        $file = $this->createMock(File::class);
1613
+        $file->method('getId')->willReturn(1);
1614
+
1615
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1616
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1617
+
1618
+        $share = $this->provider->getShareById($id);
1619
+
1620
+        $this->provider->deleteFromSelf($share, 'user2');
1621
+
1622
+        $qb = $this->dbConn->getQueryBuilder();
1623
+        $stmt = $qb->select('*')
1624
+            ->from('share')
1625
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(2)))
1626
+            ->executeQuery();
1627
+
1628
+        $shares = $stmt->fetchAllAssociative();
1629
+        $stmt->closeCursor();
1630
+
1631
+        $this->assertCount(1, $shares);
1632
+        $share2 = $shares[0];
1633
+        $this->assertEquals($id, $share2['parent']);
1634
+        $this->assertEquals(0, $share2['permissions']);
1635
+        $this->assertEquals('user2', $share2['share_with']);
1636
+    }
1637
+
1638
+
1639
+    public function testDeleteFromSelfGroupUserNotInGroup(): void {
1640
+        $qb = $this->dbConn->getQueryBuilder();
1641
+        $stmt = $qb->insert('share')
1642
+            ->values([
1643
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1644
+                'share_with' => $qb->expr()->literal('group'),
1645
+                'uid_owner' => $qb->expr()->literal('user1'),
1646
+                'uid_initiator' => $qb->expr()->literal('user1'),
1647
+                'item_type' => $qb->expr()->literal('file'),
1648
+                'file_source' => $qb->expr()->literal(1),
1649
+                'file_target' => $qb->expr()->literal('myTarget1'),
1650
+                'permissions' => $qb->expr()->literal(2)
1651
+            ])->executeStatement();
1652
+        $this->assertEquals(1, $stmt);
1653
+        $id = $qb->getLastInsertId();
1654
+
1655
+        $user1 = $this->createMock(IUser::class);
1656
+        $user1->method('getUID')->willReturn('user1');
1657
+        $user2 = $this->createMock(IUser::class);
1658
+        $user2->method('getUID')->willReturn('user2');
1659
+        $this->userManager->method('get')->willReturnMap([
1660
+            ['user1', $user1],
1661
+            ['user2', $user2],
1662
+        ]);
1663
+
1664
+        $group = $this->createMock(IGroup::class);
1665
+        $group->method('getGID')->willReturn('group');
1666
+        $group->method('inGroup')->with($user2)->willReturn(false);
1667
+        $group->method('getDisplayName')->willReturn('group-displayname');
1668
+        $this->groupManager->method('get')->with('group')->willReturn($group);
1669
+
1670
+        $file = $this->createMock(File::class);
1671
+        $file->method('getId')->willReturn(1);
1672
+
1673
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1674
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1675
+
1676
+        $share = $this->provider->getShareById($id);
1677
+
1678
+        $this->provider->deleteFromSelf($share, 'user2');
1679
+    }
1680
+
1681
+
1682
+    public function testDeleteFromSelfGroupDoesNotExist(): void {
1683
+        $this->expectException(ProviderException::class);
1684
+        $this->expectExceptionMessage('Group "group" does not exist');
1685
+
1686
+        $qb = $this->dbConn->getQueryBuilder();
1687
+        $stmt = $qb->insert('share')
1688
+            ->values([
1689
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
1690
+                'share_with' => $qb->expr()->literal('group'),
1691
+                'uid_owner' => $qb->expr()->literal('user1'),
1692
+                'uid_initiator' => $qb->expr()->literal('user1'),
1693
+                'item_type' => $qb->expr()->literal('file'),
1694
+                'file_source' => $qb->expr()->literal(1),
1695
+                'file_target' => $qb->expr()->literal('myTarget1'),
1696
+                'permissions' => $qb->expr()->literal(2)
1697
+            ])->executeStatement();
1698
+        $this->assertEquals(1, $stmt);
1699
+        $id = $qb->getLastInsertId();
1700
+
1701
+        $user1 = $this->createMock(IUser::class);
1702
+        $user1->method('getUID')->willReturn('user1');
1703
+        $user2 = $this->createMock(IUser::class);
1704
+        $user2->method('getUID')->willReturn('user2');
1705
+        $this->userManager->method('get')->willReturnMap([
1706
+            ['user1', $user1],
1707
+            ['user2', $user2],
1708
+        ]);
1709
+
1710
+        $this->groupManager->method('get')->with('group')->willReturn(null);
1711
+
1712
+        $file = $this->createMock(File::class);
1713
+        $file->method('getId')->willReturn(1);
1714
+
1715
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1716
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1717
+
1718
+        $share = $this->provider->getShareById($id);
1719
+
1720
+        $this->provider->deleteFromSelf($share, 'user2');
1721
+    }
1722
+
1723
+    public function testDeleteFromSelfUser(): void {
1724
+        $qb = $this->dbConn->getQueryBuilder();
1725
+        $stmt = $qb->insert('share')
1726
+            ->values([
1727
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1728
+                'share_with' => $qb->expr()->literal('user2'),
1729
+                'uid_owner' => $qb->expr()->literal('user1'),
1730
+                'uid_initiator' => $qb->expr()->literal('user1'),
1731
+                'item_type' => $qb->expr()->literal('file'),
1732
+                'file_source' => $qb->expr()->literal(1),
1733
+                'file_target' => $qb->expr()->literal('myTarget1'),
1734
+                'permissions' => $qb->expr()->literal(2)
1735
+            ])->executeStatement();
1736
+        $this->assertEquals(1, $stmt);
1737
+        $id = $qb->getLastInsertId();
1738
+
1739
+        $user1 = $this->createMock(IUser::class);
1740
+        $user1->method('getUID')->willReturn('user1');
1741
+        $user1->method('getDisplayName')->willReturn('user1');
1742
+        $user2 = $this->createMock(IUser::class);
1743
+        $user2->method('getUID')->willReturn('user2');
1744
+        $user2->method('getDisplayName')->willReturn('user2');
1745
+        $this->userManager->method('get')->willReturnMap([
1746
+            ['user1', $user1],
1747
+            ['user2', $user2],
1748
+        ]);
1749
+
1750
+        $file = $this->createMock(File::class);
1751
+        $file->method('getId')->willReturn(1);
1752
+
1753
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1754
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1755
+
1756
+        $share = $this->provider->getShareById($id);
1757
+
1758
+        $this->provider->deleteFromSelf($share, 'user2');
1759
+
1760
+        $qb = $this->dbConn->getQueryBuilder();
1761
+        $stmt = $qb->select('*')
1762
+            ->from('share')
1763
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
1764
+            ->executeQuery();
1765
+
1766
+        $shares = $stmt->fetchAllAssociative();
1767
+        $stmt->closeCursor();
1768
+
1769
+        $this->assertCount(0, $shares);
1770
+    }
1771
+
1772
+
1773
+    public function testDeleteFromSelfUserNotRecipient(): void {
1774
+        $this->expectException(ProviderException::class);
1775
+        $this->expectExceptionMessage('Recipient does not match');
1776
+
1777
+        $qb = $this->dbConn->getQueryBuilder();
1778
+        $stmt = $qb->insert('share')
1779
+            ->values([
1780
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
1781
+                'share_with' => $qb->expr()->literal('user2'),
1782
+                'uid_owner' => $qb->expr()->literal('user1'),
1783
+                'uid_initiator' => $qb->expr()->literal('user1'),
1784
+                'item_type' => $qb->expr()->literal('file'),
1785
+                'file_source' => $qb->expr()->literal(1),
1786
+                'file_target' => $qb->expr()->literal('myTarget1'),
1787
+                'permissions' => $qb->expr()->literal(2)
1788
+            ])->executeStatement();
1789
+        $this->assertEquals(1, $stmt);
1790
+        $id = $qb->getLastInsertId();
1791
+
1792
+        $user1 = $this->createMock(IUser::class);
1793
+        $user1->method('getUID')->willReturn('user1');
1794
+        $user1->method('getDisplayName')->willReturn('user1');
1795
+        $user2 = $this->createMock(IUser::class);
1796
+        $user2->method('getUID')->willReturn('user2');
1797
+        $user2->method('getDisplayName')->willReturn('user2');
1798
+        $user3 = $this->createMock(IUser::class);
1799
+        $this->userManager->method('get')->willReturnMap([
1800
+            ['user1', $user1],
1801
+            ['user2', $user2],
1802
+        ]);
1803
+
1804
+        $file = $this->createMock(File::class);
1805
+        $file->method('getId')->willReturn(1);
1806
+
1807
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1808
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1809
+
1810
+        $share = $this->provider->getShareById($id);
1811
+
1812
+        $this->provider->deleteFromSelf($share, $user3);
1813
+    }
1814
+
1815
+
1816
+    public function testDeleteFromSelfLink(): void {
1817
+        $this->expectException(ProviderException::class);
1818
+        $this->expectExceptionMessage('Invalid shareType');
1819
+
1820
+        $qb = $this->dbConn->getQueryBuilder();
1821
+        $stmt = $qb->insert('share')
1822
+            ->values([
1823
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
1824
+                'uid_owner' => $qb->expr()->literal('user1'),
1825
+                'uid_initiator' => $qb->expr()->literal('user1'),
1826
+                'item_type' => $qb->expr()->literal('file'),
1827
+                'file_source' => $qb->expr()->literal(1),
1828
+                'file_target' => $qb->expr()->literal('myTarget1'),
1829
+                'permissions' => $qb->expr()->literal(2),
1830
+                'token' => $qb->expr()->literal('token'),
1831
+            ])->executeStatement();
1832
+        $this->assertEquals(1, $stmt);
1833
+        $id = $qb->getLastInsertId();
1834
+
1835
+        $user1 = $this->createMock(IUser::class);
1836
+        $user1->method('getUID')->willReturn('user1');
1837
+        $this->userManager->method('get')->willReturnMap([
1838
+            ['user1', $user1],
1839
+        ]);
1840
+
1841
+        $file = $this->createMock(File::class);
1842
+        $file->method('getId')->willReturn(1);
1843
+
1844
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
1845
+        $this->rootFolder->method('getFirstNodeById')->with(1)->willReturn($file);
1846
+
1847
+        $share = $this->provider->getShareById($id);
1848
+
1849
+        $this->provider->deleteFromSelf($share, $user1);
1850
+    }
1851
+
1852
+    public function testUpdateUser(): void {
1853
+        $id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user2',
1854
+            'file', 42, 'target', 31, null, null);
1855
+
1856
+        $users = [];
1857
+        for ($i = 0; $i < 6; $i++) {
1858
+            $user = $this->createMock(IUser::class);
1859
+            $user->method('getUID')->willReturn('user' . $i);
1860
+            $user->method('getDisplayName')->willReturn('user' . $i);
1861
+            $users['user' . $i] = $user;
1862
+        }
1863
+
1864
+        $this->userManager->method('get')->willReturnCallback(
1865
+            function ($userId) use ($users) {
1866
+                return $users[$userId];
1867
+            }
1868
+        );
1869
+
1870
+        $file1 = $this->createMock(File::class);
1871
+        $file1->method('getId')->willReturn(42);
1872
+        $file2 = $this->createMock(File::class);
1873
+        $file2->method('getId')->willReturn(43);
1874
+
1875
+        $folder1 = $this->createMock(Folder::class);
1876
+        $folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
1877
+        $folder2 = $this->createMock(Folder::class);
1878
+        $folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
1879
+
1880
+        $this->rootFolder->method('getUserFolder')->willReturnMap([
1881
+            ['user2', $folder1],
1882
+            ['user5', $folder2],
1883
+        ]);
1884
+
1885
+        $share = $this->provider->getShareById($id);
1886
+
1887
+        $share->setSharedWith('user3');
1888
+        $share->setSharedBy('user4');
1889
+        $share->setShareOwner('user5');
1890
+        $share->setNode($file2);
1891
+        $share->setPermissions(1);
1892
+
1893
+        $share2 = $this->provider->update($share);
1894
+
1895
+        $this->assertEquals($id, $share2->getId());
1896
+        $this->assertSame('user3', $share2->getSharedWith());
1897
+        $this->assertSame('user4', $share2->getSharedBy());
1898
+        $this->assertSame('user5', $share2->getShareOwner());
1899
+        $this->assertSame(1, $share2->getPermissions());
1900
+
1901
+        $share2 = $this->provider->getShareById($id);
1902
+
1903
+        $this->assertEquals($id, $share2->getId());
1904
+        $this->assertSame('user3', $share2->getSharedWith());
1905
+        $this->assertSame('user4', $share2->getSharedBy());
1906
+        $this->assertSame('user5', $share2->getShareOwner());
1907
+        $this->assertSame(1, $share2->getPermissions());
1908
+    }
1909
+
1910
+    public function testUpdateLink(): void {
1911
+        $id = $this->addShareToDB(IShare::TYPE_LINK, null, 'user1', 'user2',
1912
+            'file', 42, 'target', 31, null, null);
1913
+
1914
+        $users = [];
1915
+        for ($i = 0; $i < 6; $i++) {
1916
+            $user = $this->createMock(IUser::class);
1917
+            $user->method('getUID')->willReturn('user' . $i);
1918
+            $users['user' . $i] = $user;
1919
+        }
1920
+
1921
+        $this->userManager->method('get')->willReturnCallback(
1922
+            function ($userId) use ($users) {
1923
+                return $users[$userId];
1924
+            }
1925
+        );
1926
+
1927
+        $file1 = $this->createMock(File::class);
1928
+        $file1->method('getId')->willReturn(42);
1929
+        $file2 = $this->createMock(File::class);
1930
+        $file2->method('getId')->willReturn(43);
1931
+
1932
+        $folder1 = $this->createMock(Folder::class);
1933
+        $folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
1934
+        $folder2 = $this->createMock(Folder::class);
1935
+        $folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
1936
+
1937
+        $this->rootFolder->method('getUserFolder')->willReturnMap([
1938
+            ['user2', $folder1],
1939
+            ['user5', $folder2],
1940
+        ]);
1941
+
1942
+        $share = $this->provider->getShareById($id);
1943
+
1944
+        $share->setPassword('password');
1945
+        $share->setSendPasswordByTalk(true);
1946
+        $share->setSharedBy('user4');
1947
+        $share->setShareOwner('user5');
1948
+        $share->setNode($file2);
1949
+        $share->setPermissions(1);
1950
+
1951
+        $share2 = $this->provider->update($share);
1952
+
1953
+        $this->assertEquals($id, $share2->getId());
1954
+        $this->assertEquals('password', $share2->getPassword());
1955
+        $this->assertSame(true, $share2->getSendPasswordByTalk());
1956
+        $this->assertSame('user4', $share2->getSharedBy());
1957
+        $this->assertSame('user5', $share2->getShareOwner());
1958
+        $this->assertSame(1, $share2->getPermissions());
1959
+
1960
+        $share2 = $this->provider->getShareById($id);
1961
+
1962
+        $this->assertEquals($id, $share2->getId());
1963
+        $this->assertEquals('password', $share2->getPassword());
1964
+        $this->assertSame(true, $share2->getSendPasswordByTalk());
1965
+        $this->assertSame('user4', $share2->getSharedBy());
1966
+        $this->assertSame('user5', $share2->getShareOwner());
1967
+        $this->assertSame(1, $share2->getPermissions());
1968
+    }
1969
+
1970
+    public function testUpdateLinkRemovePassword(): void {
1971
+        $id = $this->addShareToDB(IShare::TYPE_LINK, 'foo', 'user1', 'user2',
1972
+            'file', 42, 'target', 31, null, null);
1973
+
1974
+        $qb = $this->dbConn->getQueryBuilder();
1975
+        $qb->update('share');
1976
+        $qb->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1977
+        $qb->set('password', $qb->createNamedParameter('password'));
1978
+        $this->assertEquals(1, $qb->executeStatement());
1979
+
1980
+        $users = [];
1981
+        for ($i = 0; $i < 6; $i++) {
1982
+            $user = $this->createMock(IUser::class);
1983
+            $user->method('getUID')->willReturn('user' . $i);
1984
+            $users['user' . $i] = $user;
1985
+        }
1986
+
1987
+        $this->userManager->method('get')->willReturnCallback(
1988
+            function ($userId) use ($users) {
1989
+                return $users[$userId];
1990
+            }
1991
+        );
1992
+
1993
+        $file1 = $this->createMock(File::class);
1994
+        $file1->method('getId')->willReturn(42);
1995
+        $file2 = $this->createMock(File::class);
1996
+        $file2->method('getId')->willReturn(43);
1997
+
1998
+        $folder1 = $this->createMock(Folder::class);
1999
+        $folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
2000
+        $folder2 = $this->createMock(Folder::class);
2001
+        $folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
2002
+
2003
+        $this->rootFolder->method('getUserFolder')->willReturnMap([
2004
+            ['user2', $folder1],
2005
+            ['user5', $folder2],
2006
+        ]);
2007
+
2008
+        $share = $this->provider->getShareById($id);
2009
+
2010
+        $share->setPassword(null);
2011
+        $share->setSharedBy('user4');
2012
+        $share->setShareOwner('user5');
2013
+        $share->setNode($file2);
2014
+        $share->setPermissions(1);
2015
+
2016
+        $share2 = $this->provider->update($share);
2017
+
2018
+        $this->assertEquals($id, $share2->getId());
2019
+        $this->assertEquals(null, $share2->getPassword());
2020
+        $this->assertSame('user4', $share2->getSharedBy());
2021
+        $this->assertSame('user5', $share2->getShareOwner());
2022
+        $this->assertSame(1, $share2->getPermissions());
2023
+
2024
+        $share2 = $this->provider->getShareById($id);
2025
+
2026
+        $this->assertEquals($id, $share2->getId());
2027
+        $this->assertEquals(null, $share2->getPassword());
2028
+        $this->assertSame('user4', $share2->getSharedBy());
2029
+        $this->assertSame('user5', $share2->getShareOwner());
2030
+        $this->assertSame(1, $share2->getPermissions());
2031
+    }
2032
+
2033
+    public function testUpdateGroupNoSub(): void {
2034
+        $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user2',
2035
+            'file', 42, 'target', 31, null, null);
2036
+
2037
+        $users = [];
2038
+        for ($i = 0; $i < 6; $i++) {
2039
+            $user = $this->createMock(IUser::class);
2040
+            $user->method('getUID')->willReturn('user' . $i);
2041
+            $users['user' . $i] = $user;
2042
+        }
2043
+
2044
+        $this->userManager->method('get')->willReturnCallback(
2045
+            function ($userId) use ($users) {
2046
+                return $users[$userId];
2047
+            }
2048
+        );
2049
+
2050
+        $groups = [];
2051
+        for ($i = 0; $i < 2; $i++) {
2052
+            $group = $this->createMock(IGroup::class);
2053
+            $group->method('getGID')->willReturn('group' . $i);
2054
+            $group->method('getDisplayName')->willReturn('group-displayname' . $i);
2055
+            $groups['group' . $i] = $group;
2056
+        }
2057
+
2058
+        $this->groupManager->method('get')->willReturnCallback(
2059
+            function ($groupId) use ($groups) {
2060
+                return $groups[$groupId];
2061
+            }
2062
+        );
2063
+
2064
+        $file1 = $this->createMock(File::class);
2065
+        $file1->method('getId')->willReturn(42);
2066
+        $file2 = $this->createMock(File::class);
2067
+        $file2->method('getId')->willReturn(43);
2068
+
2069
+        $folder1 = $this->createMock(Folder::class);
2070
+        $folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
2071
+        $folder2 = $this->createMock(Folder::class);
2072
+        $folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
2073
+
2074
+        $this->rootFolder->method('getUserFolder')->willReturnMap([
2075
+            ['user2', $folder1],
2076
+            ['user5', $folder2],
2077
+        ]);
2078
+
2079
+        $share = $this->provider->getShareById($id);
2080
+
2081
+        $share->setSharedWith('group0');
2082
+        $share->setSharedBy('user4');
2083
+        $share->setShareOwner('user5');
2084
+        $share->setNode($file2);
2085
+        $share->setPermissions(1);
2086
+
2087
+        $share2 = $this->provider->update($share);
2088
+
2089
+        $this->assertEquals($id, $share2->getId());
2090
+        // Group shares do not allow updating the recipient
2091
+        $this->assertSame('group0', $share2->getSharedWith());
2092
+        $this->assertSame('user4', $share2->getSharedBy());
2093
+        $this->assertSame('user5', $share2->getShareOwner());
2094
+        $this->assertSame(1, $share2->getPermissions());
2095
+
2096
+        $share2 = $this->provider->getShareById($id);
2097
+
2098
+        $this->assertEquals($id, $share2->getId());
2099
+        // Group shares do not allow updating the recipient
2100
+        $this->assertSame('group0', $share2->getSharedWith());
2101
+        $this->assertSame('user4', $share2->getSharedBy());
2102
+        $this->assertSame('user5', $share2->getShareOwner());
2103
+        $this->assertSame(1, $share2->getPermissions());
2104
+    }
2105
+
2106
+    public function testUpdateGroupSubShares(): void {
2107
+        $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user2',
2108
+            'file', 42, 'target', 31, null, null);
2109
+
2110
+        $id2 = $this->addShareToDB(2, 'user0', 'user1', 'user2',
2111
+            'file', 42, 'mytarget', 31, null, null, $id);
2112
+
2113
+        $id3 = $this->addShareToDB(2, 'user3', 'user1', 'user2',
2114
+            'file', 42, 'mytarget2', 0, null, null, $id);
2115
+
2116
+        $users = [];
2117
+        for ($i = 0; $i < 6; $i++) {
2118
+            $user = $this->createMock(IUser::class);
2119
+            $user->method('getUID')->willReturn('user' . $i);
2120
+            $users['user' . $i] = $user;
2121
+        }
2122
+
2123
+        $this->userManager->method('get')->willReturnCallback(
2124
+            function ($userId) use ($users) {
2125
+                return $users[$userId];
2126
+            }
2127
+        );
2128
+
2129
+        $groups = [];
2130
+        for ($i = 0; $i < 2; $i++) {
2131
+            $group = $this->createMock(IGroup::class);
2132
+            $group->method('getGID')->willReturn('group' . $i);
2133
+            $group->method('getDisplayName')->willReturn('group-displayname' . $i);
2134
+            $groups['group' . $i] = $group;
2135
+        }
2136
+
2137
+        $this->groupManager->method('get')->willReturnCallback(
2138
+            function ($groupId) use ($groups) {
2139
+                return $groups[$groupId];
2140
+            }
2141
+        );
2142
+
2143
+        $file1 = $this->createMock(File::class);
2144
+        $file1->method('getId')->willReturn(42);
2145
+        $file2 = $this->createMock(File::class);
2146
+        $file2->method('getId')->willReturn(43);
2147
+
2148
+        $folder1 = $this->createMock(Folder::class);
2149
+        $folder1->method('getFirstNodeById')->with(42)->willReturn($file1);
2150
+        $folder2 = $this->createMock(Folder::class);
2151
+        $folder2->method('getFirstNodeById')->with(43)->willReturn($file2);
2152
+
2153
+        $this->rootFolder->method('getUserFolder')->willReturnMap([
2154
+            ['user2', $folder1],
2155
+            ['user5', $folder2],
2156
+        ]);
2157
+
2158
+        $share = $this->provider->getShareById($id);
2159
+
2160
+        $share->setSharedWith('group0');
2161
+        $share->setSharedBy('user4');
2162
+        $share->setShareOwner('user5');
2163
+        $share->setNode($file2);
2164
+        $share->setPermissions(1);
2165
+
2166
+        $share2 = $this->provider->update($share);
2167
+
2168
+        $this->assertEquals($id, $share2->getId());
2169
+        // Group shares do not allow updating the recipient
2170
+        $this->assertSame('group0', $share2->getSharedWith());
2171
+        $this->assertSame('user4', $share2->getSharedBy());
2172
+        $this->assertSame('user5', $share2->getShareOwner());
2173
+        $this->assertSame(1, $share2->getPermissions());
2174
+
2175
+        $share2 = $this->provider->getShareById($id);
2176
+
2177
+        $this->assertEquals($id, $share2->getId());
2178
+        // Group shares do not allow updating the recipient
2179
+        $this->assertSame('group0', $share2->getSharedWith());
2180
+        $this->assertSame('user4', $share2->getSharedBy());
2181
+        $this->assertSame('user5', $share2->getShareOwner());
2182
+        $this->assertSame(1, $share2->getPermissions());
2183
+
2184
+        $qb = $this->dbConn->getQueryBuilder();
2185
+        $stmt = $qb->select('*')
2186
+            ->from('share')
2187
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($id)))
2188
+            ->orderBy('id')
2189
+            ->executeQuery();
2190
+
2191
+        $shares = $stmt->fetchAllAssociative();
2192
+
2193
+        $this->assertSame('user0', $shares[0]['share_with']);
2194
+        $this->assertSame('user4', $shares[0]['uid_initiator']);
2195
+        $this->assertSame('user5', $shares[0]['uid_owner']);
2196
+        $this->assertSame(1, (int)$shares[0]['permissions']);
2197
+
2198
+        $this->assertSame('user3', $shares[1]['share_with']);
2199
+        $this->assertSame('user4', $shares[1]['uid_initiator']);
2200
+        $this->assertSame('user5', $shares[1]['uid_owner']);
2201
+        $this->assertSame(0, (int)$shares[1]['permissions']);
2202
+
2203
+
2204
+        $stmt->closeCursor();
2205
+    }
2206
+
2207
+    public function testMoveUserShare(): void {
2208
+        $id = $this->addShareToDB(IShare::TYPE_USER, 'user0', 'user1', 'user1', 'file',
2209
+            42, 'mytaret', 31, null, null);
2210
+
2211
+        $user0 = $this->createMock(IUser::class);
2212
+        $user0->method('getUID')->willReturn('user0');
2213
+        $user0->method('getDisplayName')->willReturn('user0');
2214
+        $user1 = $this->createMock(IUser::class);
2215
+        $user1->method('getUID')->willReturn('user1');
2216
+        $user1->method('getDisplayName')->willReturn('user1');
2217
+
2218
+        $this->userManager->method('get')->willReturnMap([
2219
+            ['user0', $user0],
2220
+            ['user1', $user1],
2221
+        ]);
2222
+
2223
+        $file = $this->createMock(File::class);
2224
+        $file->method('getId')->willReturn(42);
2225
+
2226
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
2227
+        $this->rootFolder->method('getFirstNodeById')->willReturn($file);
2228
+
2229
+        $share = $this->provider->getShareById($id, null);
2230
+
2231
+        $share->setTarget('/newTarget');
2232
+        $this->provider->move($share, $user0);
2233
+
2234
+        $share = $this->provider->getShareById($id, null);
2235
+        $this->assertSame('/newTarget', $share->getTarget());
2236
+    }
2237
+
2238
+    public function testMoveGroupShare(): void {
2239
+        $id = $this->addShareToDB(IShare::TYPE_GROUP, 'group0', 'user1', 'user1', 'file',
2240
+            42, 'mytaret', 31, null, null);
2241
+
2242
+        $user0 = $this->createMock(IUser::class);
2243
+        $user0->method('getUID')->willReturn('user0');
2244
+        $user1 = $this->createMock(IUser::class);
2245
+        $user1->method('getUID')->willReturn('user1');
2246
+
2247
+        $group0 = $this->createMock(IGroup::class);
2248
+        $group0->method('getGID')->willReturn('group0');
2249
+        $group0->method('inGroup')->with($user0)->willReturn(true);
2250
+        $group0->method('getDisplayName')->willReturn('group0-displayname');
2251
+
2252
+        $this->groupManager->method('get')->with('group0')->willReturn($group0);
2253
+
2254
+        $this->userManager->method('get')->willReturnMap([
2255
+            ['user0', $user0],
2256
+            ['user1', $user1],
2257
+        ]);
2258
+
2259
+        $folder = $this->createMock(Folder::class);
2260
+        $folder->method('getId')->willReturn(42);
2261
+
2262
+        $this->rootFolder->method('getUserFolder')->with('user1')->willReturnSelf();
2263
+        $this->rootFolder->method('getFirstNodeById')->willReturn($folder);
2264
+
2265
+        $share = $this->provider->getShareById($id, 'user0');
2266
+
2267
+        $share->setTarget('/newTarget');
2268
+        $this->provider->move($share, 'user0');
2269
+
2270
+        $share = $this->provider->getShareById($id, 'user0');
2271
+        $this->assertSame('/newTarget', $share->getTarget());
2272
+
2273
+        $share->setTarget('/ultraNewTarget');
2274
+        $this->provider->move($share, 'user0');
2275
+
2276
+        $share = $this->provider->getShareById($id, 'user0');
2277
+        $this->assertSame('/ultraNewTarget', $share->getTarget());
2278
+    }
2279
+
2280
+    public static function dataDeleteUser(): array {
2281
+        return [
2282
+            [IShare::TYPE_USER, 'a', 'b', 'c', 'a', true],
2283
+            [IShare::TYPE_USER, 'a', 'b', 'c', 'b', false],
2284
+            [IShare::TYPE_USER, 'a', 'b', 'c', 'c', true],
2285
+            [IShare::TYPE_USER, 'a', 'b', 'c', 'd', false],
2286
+            [IShare::TYPE_GROUP, 'a', 'b', 'c', 'a', true],
2287
+            [IShare::TYPE_GROUP, 'a', 'b', 'c', 'b', false],
2288
+            // The group c is still valid but user c is deleted so group share stays
2289
+            [IShare::TYPE_GROUP, 'a', 'b', 'c', 'c', false],
2290
+            [IShare::TYPE_GROUP, 'a', 'b', 'c', 'd', false],
2291
+            [IShare::TYPE_LINK, 'a', 'b', 'c', 'a', true],
2292
+            // To avoid invisible link shares delete initiated link shares as well (see #22327)
2293
+            [IShare::TYPE_LINK, 'a', 'b', 'c', 'b', true],
2294
+            [IShare::TYPE_LINK, 'a', 'b', 'c', 'c', false],
2295
+            [IShare::TYPE_LINK, 'a', 'b', 'c', 'd', false],
2296
+        ];
2297
+    }
2298
+
2299
+    /**
2300
+     *
2301
+     * @param int $type The shareType (user/group/link)
2302
+     * @param string $owner The owner of the share (uid)
2303
+     * @param string $initiator The initiator of the share (uid)
2304
+     * @param string $recipient The recipient of the share (uid/gid/pass)
2305
+     * @param string $deletedUser The user that is deleted
2306
+     * @param bool $rowDeleted Is the row deleted in this setup
2307
+     */
2308
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUser')]
2309
+    public function testDeleteUser($type, $owner, $initiator, $recipient, $deletedUser, $rowDeleted): void {
2310
+        $qb = $this->dbConn->getQueryBuilder();
2311
+        $qb->insert('share')
2312
+            ->setValue('share_type', $qb->createNamedParameter($type))
2313
+            ->setValue('uid_owner', $qb->createNamedParameter($owner))
2314
+            ->setValue('uid_initiator', $qb->createNamedParameter($initiator))
2315
+            ->setValue('share_with', $qb->createNamedParameter($recipient))
2316
+            ->setValue('item_type', $qb->createNamedParameter('file'))
2317
+            ->setValue('item_source', $qb->createNamedParameter(42))
2318
+            ->setValue('file_source', $qb->createNamedParameter(42))
2319
+            ->executeStatement();
2320
+
2321
+        $id = $qb->getLastInsertId();
2322
+
2323
+        $this->provider->userDeleted($deletedUser, $type);
2324
+
2325
+        $qb = $this->dbConn->getQueryBuilder();
2326
+        $qb->select('*')
2327
+            ->from('share')
2328
+            ->where(
2329
+                $qb->expr()->eq('id', $qb->createNamedParameter($id))
2330
+            );
2331
+        $cursor = $qb->executeQuery();
2332
+        $data = $cursor->fetchAllAssociative();
2333
+        $cursor->closeCursor();
2334
+
2335
+        $this->assertCount($rowDeleted ? 0 : 1, $data);
2336
+    }
2337
+
2338
+    public static function dataDeleteUserGroup(): array {
2339
+        return [
2340
+            ['a', 'b', 'c', 'a', true, true],
2341
+            ['a', 'b', 'c', 'b', false, false],
2342
+            ['a', 'b', 'c', 'c', false, true],
2343
+            ['a', 'b', 'c', 'd', false, false],
2344
+        ];
2345
+    }
2346
+
2347
+    /**
2348
+     *
2349
+     * @param string $owner The owner of the share (uid)
2350
+     * @param string $initiator The initiator of the share (uid)
2351
+     * @param string $recipient The recipient of the usergroup share (uid)
2352
+     * @param string $deletedUser The user that is deleted
2353
+     * @param bool $groupShareDeleted
2354
+     * @param bool $userGroupShareDeleted
2355
+     */
2356
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataDeleteUserGroup')]
2357
+    public function testDeleteUserGroup($owner, $initiator, $recipient, $deletedUser, $groupShareDeleted, $userGroupShareDeleted): void {
2358
+        $qb = $this->dbConn->getQueryBuilder();
2359
+        $qb->insert('share')
2360
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
2361
+            ->setValue('uid_owner', $qb->createNamedParameter($owner))
2362
+            ->setValue('uid_initiator', $qb->createNamedParameter($initiator))
2363
+            ->setValue('share_with', $qb->createNamedParameter('group'))
2364
+            ->setValue('item_type', $qb->createNamedParameter('file'))
2365
+            ->setValue('item_source', $qb->createNamedParameter(42))
2366
+            ->setValue('file_source', $qb->createNamedParameter(42))
2367
+            ->executeStatement();
2368
+        $groupId = $qb->getLastInsertId();
2369
+
2370
+        $qb = $this->dbConn->getQueryBuilder();
2371
+        $qb->insert('share')
2372
+            ->setValue('share_type', $qb->createNamedParameter(2))
2373
+            ->setValue('uid_owner', $qb->createNamedParameter($owner))
2374
+            ->setValue('uid_initiator', $qb->createNamedParameter($initiator))
2375
+            ->setValue('share_with', $qb->createNamedParameter($recipient))
2376
+            ->setValue('item_type', $qb->createNamedParameter('file'))
2377
+            ->setValue('item_source', $qb->createNamedParameter(42))
2378
+            ->setValue('file_source', $qb->createNamedParameter(42))
2379
+            ->executeStatement();
2380
+        $userGroupId = $qb->getLastInsertId();
2381
+
2382
+        $this->provider->userDeleted($deletedUser, IShare::TYPE_GROUP);
2383
+
2384
+        $qb = $this->dbConn->getQueryBuilder();
2385
+        $qb->select('*')
2386
+            ->from('share')
2387
+            ->where(
2388
+                $qb->expr()->eq('id', $qb->createNamedParameter($userGroupId))
2389
+            );
2390
+        $cursor = $qb->executeQuery();
2391
+        $data = $cursor->fetchAllAssociative();
2392
+        $cursor->closeCursor();
2393
+        $this->assertCount($userGroupShareDeleted ? 0 : 1, $data);
2394
+
2395
+        $qb = $this->dbConn->getQueryBuilder();
2396
+        $qb->select('*')
2397
+            ->from('share')
2398
+            ->where(
2399
+                $qb->expr()->eq('id', $qb->createNamedParameter($groupId))
2400
+            );
2401
+        $cursor = $qb->executeQuery();
2402
+        $data = $cursor->fetchAllAssociative();
2403
+        $cursor->closeCursor();
2404
+        $this->assertCount($groupShareDeleted ? 0 : 1, $data);
2405
+    }
2406
+
2407
+    public static function dataGroupDeleted(): array {
2408
+        return [
2409
+            [
2410
+                [
2411
+                    'type' => IShare::TYPE_USER,
2412
+                    'recipient' => 'user',
2413
+                    'children' => []
2414
+                ], 'group', false
2415
+            ],
2416
+            [
2417
+                [
2418
+                    'type' => IShare::TYPE_USER,
2419
+                    'recipient' => 'user',
2420
+                    'children' => []
2421
+                ], 'user', false
2422
+            ],
2423
+            [
2424
+                [
2425
+                    'type' => IShare::TYPE_LINK,
2426
+                    'recipient' => 'user',
2427
+                    'children' => []
2428
+                ], 'group', false
2429
+            ],
2430
+            [
2431
+                [
2432
+                    'type' => IShare::TYPE_GROUP,
2433
+                    'recipient' => 'group1',
2434
+                    'children' => [
2435
+                        'foo',
2436
+                        'bar'
2437
+                    ]
2438
+                ], 'group2', false
2439
+            ],
2440
+            [
2441
+                [
2442
+                    'type' => IShare::TYPE_GROUP,
2443
+                    'recipient' => 'group1',
2444
+                    'children' => [
2445
+                        'foo',
2446
+                        'bar'
2447
+                    ]
2448
+                ], 'group1', true
2449
+            ],
2450
+        ];
2451
+    }
2452
+
2453
+    /**
2454
+     *
2455
+     * @param $shares
2456
+     * @param $groupToDelete
2457
+     * @param $shouldBeDeleted
2458
+     */
2459
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataGroupDeleted')]
2460
+    public function testGroupDeleted($shares, $groupToDelete, $shouldBeDeleted): void {
2461
+        $qb = $this->dbConn->getQueryBuilder();
2462
+        $qb->insert('share')
2463
+            ->setValue('share_type', $qb->createNamedParameter($shares['type']))
2464
+            ->setValue('uid_owner', $qb->createNamedParameter('owner'))
2465
+            ->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2466
+            ->setValue('share_with', $qb->createNamedParameter($shares['recipient']))
2467
+            ->setValue('item_type', $qb->createNamedParameter('file'))
2468
+            ->setValue('item_source', $qb->createNamedParameter(42))
2469
+            ->setValue('file_source', $qb->createNamedParameter(42))
2470
+            ->executeStatement();
2471
+        $ids = [$qb->getLastInsertId()];
2472
+
2473
+        foreach ($shares['children'] as $child) {
2474
+            $qb = $this->dbConn->getQueryBuilder();
2475
+            $qb->insert('share')
2476
+                ->setValue('share_type', $qb->createNamedParameter(2))
2477
+                ->setValue('uid_owner', $qb->createNamedParameter('owner'))
2478
+                ->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2479
+                ->setValue('share_with', $qb->createNamedParameter($child))
2480
+                ->setValue('item_type', $qb->createNamedParameter('file'))
2481
+                ->setValue('item_source', $qb->createNamedParameter(42))
2482
+                ->setValue('file_source', $qb->createNamedParameter(42))
2483
+                ->setValue('parent', $qb->createNamedParameter($ids[0]))
2484
+                ->executeStatement();
2485
+            $ids[] = $qb->getLastInsertId();
2486
+        }
2487
+
2488
+        $this->provider->groupDeleted($groupToDelete);
2489
+
2490
+        $qb = $this->dbConn->getQueryBuilder();
2491
+        $cursor = $qb->select('*')
2492
+            ->from('share')
2493
+            ->where($qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
2494
+            ->executeQuery();
2495
+        $data = $cursor->fetchAllAssociative();
2496
+        $cursor->closeCursor();
2497
+
2498
+        $this->assertCount($shouldBeDeleted ? 0 : count($ids), $data);
2499
+    }
2500
+
2501
+    public static function dataUserDeletedFromGroup(): array {
2502
+        return [
2503
+            ['group1', 'user1', true],
2504
+            ['group1', 'user2', false],
2505
+            ['group2', 'user1', false],
2506
+        ];
2507
+    }
2508
+
2509
+    /**
2510
+     * Given a group share with 'group1'
2511
+     * And a user specific group share with 'user1'.
2512
+     * User $user is deleted from group $gid.
2513
+     *
2514
+     *
2515
+     * @param string $group
2516
+     * @param string $user
2517
+     * @param bool $toDelete
2518
+     */
2519
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataUserDeletedFromGroup')]
2520
+    public function testUserDeletedFromGroup($group, $user, $toDelete): void {
2521
+        $qb = $this->dbConn->getQueryBuilder();
2522
+        $qb->insert('share')
2523
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
2524
+            ->setValue('uid_owner', $qb->createNamedParameter('owner'))
2525
+            ->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2526
+            ->setValue('share_with', $qb->createNamedParameter('group1'))
2527
+            ->setValue('item_type', $qb->createNamedParameter('file'))
2528
+            ->setValue('item_source', $qb->createNamedParameter(42))
2529
+            ->setValue('file_source', $qb->createNamedParameter(42));
2530
+        $qb->executeStatement();
2531
+        $id1 = $qb->getLastInsertId();
2532
+
2533
+        $qb = $this->dbConn->getQueryBuilder();
2534
+        $qb->insert('share')
2535
+            ->setValue('share_type', $qb->createNamedParameter(2))
2536
+            ->setValue('uid_owner', $qb->createNamedParameter('owner'))
2537
+            ->setValue('uid_initiator', $qb->createNamedParameter('initiator'))
2538
+            ->setValue('share_with', $qb->createNamedParameter('user1'))
2539
+            ->setValue('item_type', $qb->createNamedParameter('file'))
2540
+            ->setValue('item_source', $qb->createNamedParameter(42))
2541
+            ->setValue('file_source', $qb->createNamedParameter(42))
2542
+            ->setValue('parent', $qb->createNamedParameter($id1));
2543
+        $qb->executeStatement();
2544
+        $id2 = $qb->getLastInsertId();
2545
+
2546
+        $this->provider->userDeletedFromGroup($user, $group);
2547
+
2548
+        $qb = $this->dbConn->getQueryBuilder();
2549
+        $qb->select('*')
2550
+            ->from('share')
2551
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id2)));
2552
+        $cursor = $qb->executeQuery();
2553
+        $data = $cursor->fetchAllAssociative();
2554
+        $cursor->closeCursor();
2555
+
2556
+        $this->assertCount($toDelete ? 0 : 1, $data);
2557
+    }
2558
+
2559
+    public function testGetSharesInFolder(): void {
2560
+        $userManager = Server::get(IUserManager::class);
2561
+        $groupManager = Server::get(IGroupManager::class);
2562
+        $rootFolder = Server::get(IRootFolder::class);
2563
+
2564
+        $provider = new DefaultShareProvider(
2565
+            $this->dbConn,
2566
+            $userManager,
2567
+            $groupManager,
2568
+            $rootFolder,
2569
+            $this->mailer,
2570
+            $this->defaults,
2571
+            $this->l10nFactory,
2572
+            $this->urlGenerator,
2573
+            $this->timeFactory,
2574
+            $this->logger,
2575
+            $this->shareManager,
2576
+            $this->config,
2577
+        );
2578
+
2579
+        $password = md5(time());
2580
+
2581
+        $u1 = $userManager->createUser('testShare1', $password);
2582
+        $u2 = $userManager->createUser('testShare2', $password);
2583
+        $u3 = $userManager->createUser('testShare3', $password);
2584
+
2585
+        $g1 = $groupManager->createGroup('group1');
2586
+
2587
+        $u1Folder = $rootFolder->getUserFolder($u1->getUID());
2588
+        $folder1 = $u1Folder->newFolder('foo');
2589
+        $file1 = $folder1->newFile('bar');
2590
+        $folder2 = $folder1->newFolder('baz');
2591
+
2592
+        $shareManager = Server::get(IShareManager::class);
2593
+        $share1 = $shareManager->newShare();
2594
+        $share1->setNode($folder1)
2595
+            ->setSharedBy($u1->getUID())
2596
+            ->setSharedWith($u2->getUID())
2597
+            ->setShareOwner($u1->getUID())
2598
+            ->setShareType(IShare::TYPE_USER)
2599
+            ->setPermissions(Constants::PERMISSION_ALL);
2600
+        $share1 = $this->provider->create($share1);
2601
+
2602
+        $share2 = $shareManager->newShare();
2603
+        $share2->setNode($file1)
2604
+            ->setSharedBy($u2->getUID())
2605
+            ->setSharedWith($u3->getUID())
2606
+            ->setShareOwner($u1->getUID())
2607
+            ->setShareType(IShare::TYPE_USER)
2608
+            ->setPermissions(Constants::PERMISSION_READ);
2609
+        $share2 = $this->provider->create($share2);
2610
+
2611
+        $share3 = $shareManager->newShare();
2612
+        $share3->setNode($folder2)
2613
+            ->setSharedBy($u2->getUID())
2614
+            ->setShareOwner($u1->getUID())
2615
+            ->setShareType(IShare::TYPE_LINK)
2616
+            ->setPermissions(Constants::PERMISSION_READ);
2617
+        $share3 = $this->provider->create($share3);
2618
+
2619
+        $share4 = $shareManager->newShare();
2620
+        $share4->setNode($folder2)
2621
+            ->setSharedBy($u1->getUID())
2622
+            ->setSharedWith($g1->getGID())
2623
+            ->setShareOwner($u1->getUID())
2624
+            ->setShareType(IShare::TYPE_GROUP)
2625
+            ->setPermissions(Constants::PERMISSION_READ);
2626
+        $share4 = $this->provider->create($share4);
2627
+
2628
+        $result = $provider->getSharesInFolder($u1->getUID(), $folder1, false);
2629
+        $this->assertCount(1, $result);
2630
+        $shares = array_pop($result);
2631
+        $this->assertCount(1, $shares);
2632
+        $this->assertSame($folder2->getId(), $shares[0]->getNodeId());
2633
+
2634
+        $result = $provider->getSharesInFolder($u1->getUID(), $folder1, true);
2635
+        $this->assertCount(2, $result);
2636
+
2637
+        $file_shares = $result[$file1->getId()];
2638
+        $this->assertCount(1, $file_shares);
2639
+        $this->assertSame($file1->getId(), $file_shares[0]->getNodeId());
2640
+        $this->assertSame(IShare::TYPE_USER, $file_shares[0]->getShareType());
2641
+
2642
+        $folder_shares = $result[$folder2->getId()];
2643
+        $this->assertCount(2, $folder_shares);
2644
+        $this->assertSame($folder2->getId(), $folder_shares[0]->getNodeId());
2645
+        $this->assertSame($folder2->getId(), $folder_shares[1]->getNodeId());
2646
+        $this->assertSame(IShare::TYPE_LINK, $folder_shares[0]->getShareType());
2647
+        $this->assertSame(IShare::TYPE_GROUP, $folder_shares[1]->getShareType());
2648
+
2649
+        $provider->delete($share1);
2650
+        $provider->delete($share2);
2651
+        $provider->delete($share3);
2652
+        $provider->delete($share4);
2653
+
2654
+        $u1->delete();
2655
+        $u2->delete();
2656
+        $u3->delete();
2657
+        $g1->delete();
2658
+    }
2659
+
2660
+    public function testGetAccessListNoCurrentAccessRequired(): void {
2661
+        $userManager = Server::get(IUserManager::class);
2662
+        $groupManager = Server::get(IGroupManager::class);
2663
+        $rootFolder = Server::get(IRootFolder::class);
2664
+
2665
+        $provider = new DefaultShareProvider(
2666
+            $this->dbConn,
2667
+            $userManager,
2668
+            $groupManager,
2669
+            $rootFolder,
2670
+            $this->mailer,
2671
+            $this->defaults,
2672
+            $this->l10nFactory,
2673
+            $this->urlGenerator,
2674
+            $this->timeFactory,
2675
+            $this->logger,
2676
+            $this->shareManager,
2677
+            $this->config,
2678
+        );
2679
+
2680
+        $u1 = $userManager->createUser('testShare1', 'test');
2681
+        $u2 = $userManager->createUser('testShare2', 'test');
2682
+        $u3 = $userManager->createUser('testShare3', 'test');
2683
+        $u4 = $userManager->createUser('testShare4', 'test');
2684
+        $u5 = $userManager->createUser('testShare5', 'test');
2685
+
2686
+        $g1 = $groupManager->createGroup('group1');
2687
+        $g1->addUser($u3);
2688
+        $g1->addUser($u4);
2689
+
2690
+        $u1Folder = $rootFolder->getUserFolder($u1->getUID());
2691
+        $folder1 = $u1Folder->newFolder('foo');
2692
+        $folder2 = $folder1->newFolder('baz');
2693
+        $file1 = $folder2->newFile('bar');
2694
+
2695
+        $result = $provider->getAccessList([$folder1, $folder2, $file1], false);
2696
+        $this->assertCount(0, $result['users']);
2697
+        $this->assertFalse($result['public']);
2698
+
2699
+        $shareManager = Server::get(IShareManager::class);
2700
+        $share1 = $shareManager->newShare();
2701
+        $share1->setNode($folder1)
2702
+            ->setSharedBy($u1->getUID())
2703
+            ->setSharedWith($u2->getUID())
2704
+            ->setShareOwner($u1->getUID())
2705
+            ->setShareType(IShare::TYPE_USER)
2706
+            ->setPermissions(Constants::PERMISSION_ALL);
2707
+        $share1 = $this->provider->create($share1);
2708
+        $share1 = $provider->acceptShare($share1, $u2->getUid());
2709
+
2710
+        $share2 = $shareManager->newShare();
2711
+        $share2->setNode($folder2)
2712
+            ->setSharedBy($u2->getUID())
2713
+            ->setSharedWith($g1->getGID())
2714
+            ->setShareOwner($u1->getUID())
2715
+            ->setShareType(IShare::TYPE_GROUP)
2716
+            ->setPermissions(Constants::PERMISSION_ALL);
2717
+        $share2 = $this->provider->create($share2);
2718
+
2719
+        $shareManager->deleteFromSelf($share2, $u4->getUID());
2720
+
2721
+        $share2 = $provider->acceptShare($share2, $u3->getUid());
2722
+        $share2 = $provider->acceptShare($share2, $u4->getUid());
2723
+
2724
+        $share3 = $shareManager->newShare();
2725
+        $share3->setNode($file1)
2726
+            ->setSharedBy($u3->getUID())
2727
+            ->setShareOwner($u1->getUID())
2728
+            ->setShareType(IShare::TYPE_LINK)
2729
+            ->setPermissions(Constants::PERMISSION_READ);
2730
+        $share3 = $this->provider->create($share3);
2731
+
2732
+        $share4 = $shareManager->newShare();
2733
+        $share4->setNode($file1)
2734
+            ->setSharedBy($u3->getUID())
2735
+            ->setSharedWith($u5->getUID())
2736
+            ->setShareOwner($u1->getUID())
2737
+            ->setShareType(IShare::TYPE_USER)
2738
+            ->setPermissions(Constants::PERMISSION_READ);
2739
+        $share4 = $this->provider->create($share4);
2740
+        $share4 = $provider->acceptShare($share4, $u5->getUid());
2741
+
2742
+        $result = $provider->getAccessList([$folder1, $folder2, $file1], false);
2743
+
2744
+        $this->assertCount(4, $result['users']);
2745
+        $this->assertContains('testShare2', $result['users']);
2746
+        $this->assertContains('testShare3', $result['users']);
2747
+        $this->assertContains('testShare4', $result['users']);
2748
+        $this->assertContains('testShare5', $result['users']);
2749
+        $this->assertTrue($result['public']);
2750
+
2751
+        $provider->delete($share1);
2752
+        $provider->delete($share2);
2753
+        $provider->delete($share3);
2754
+        $provider->delete($share4);
2755
+
2756
+        $u1->delete();
2757
+        $u2->delete();
2758
+        $u3->delete();
2759
+        $u4->delete();
2760
+        $u5->delete();
2761
+        $g1->delete();
2762
+    }
2763
+
2764
+    public function testGetAccessListCurrentAccessRequired(): void {
2765
+        $userManager = Server::get(IUserManager::class);
2766
+        $groupManager = Server::get(IGroupManager::class);
2767
+        $rootFolder = Server::get(IRootFolder::class);
2768
+
2769
+        $provider = new DefaultShareProvider(
2770
+            $this->dbConn,
2771
+            $userManager,
2772
+            $groupManager,
2773
+            $rootFolder,
2774
+            $this->mailer,
2775
+            $this->defaults,
2776
+            $this->l10nFactory,
2777
+            $this->urlGenerator,
2778
+            $this->timeFactory,
2779
+            $this->logger,
2780
+            $this->shareManager,
2781
+            $this->config,
2782
+        );
2783
+
2784
+        $u1 = $userManager->createUser('testShare1', 'test');
2785
+        $u2 = $userManager->createUser('testShare2', 'test');
2786
+        $u3 = $userManager->createUser('testShare3', 'test');
2787
+        $u4 = $userManager->createUser('testShare4', 'test');
2788
+        $u5 = $userManager->createUser('testShare5', 'test');
2789
+
2790
+        $g1 = $groupManager->createGroup('group1');
2791
+        $g1->addUser($u3);
2792
+        $g1->addUser($u4);
2793
+
2794
+        $u1Folder = $rootFolder->getUserFolder($u1->getUID());
2795
+        $folder1 = $u1Folder->newFolder('foo');
2796
+        $folder2 = $folder1->newFolder('baz');
2797
+        $file1 = $folder2->newFile('bar');
2798
+
2799
+        $result = $provider->getAccessList([$folder1, $folder2, $file1], false);
2800
+        $this->assertCount(0, $result['users']);
2801
+        $this->assertFalse($result['public']);
2802
+
2803
+        $shareManager = Server::get(IShareManager::class);
2804
+        $share1 = $shareManager->newShare();
2805
+        $share1->setNode($folder1)
2806
+            ->setSharedBy($u1->getUID())
2807
+            ->setSharedWith($u2->getUID())
2808
+            ->setShareOwner($u1->getUID())
2809
+            ->setShareType(IShare::TYPE_USER)
2810
+            ->setPermissions(Constants::PERMISSION_ALL);
2811
+        $share1 = $this->provider->create($share1);
2812
+        $share1 = $provider->acceptShare($share1, $u2->getUid());
2813
+
2814
+        $share2 = $shareManager->newShare();
2815
+        $share2->setNode($folder2)
2816
+            ->setSharedBy($u2->getUID())
2817
+            ->setSharedWith($g1->getGID())
2818
+            ->setShareOwner($u1->getUID())
2819
+            ->setShareType(IShare::TYPE_GROUP)
2820
+            ->setPermissions(Constants::PERMISSION_ALL);
2821
+        $share2 = $this->provider->create($share2);
2822
+        $share2 = $provider->acceptShare($share2, $u3->getUid());
2823
+        $share2 = $provider->acceptShare($share2, $u4->getUid());
2824
+
2825
+        $shareManager->deleteFromSelf($share2, $u4->getUID());
2826
+
2827
+        $share3 = $shareManager->newShare();
2828
+        $share3->setNode($file1)
2829
+            ->setSharedBy($u3->getUID())
2830
+            ->setShareOwner($u1->getUID())
2831
+            ->setShareType(IShare::TYPE_LINK)
2832
+            ->setPermissions(Constants::PERMISSION_READ);
2833
+        $share3 = $this->provider->create($share3);
2834
+
2835
+        $share4 = $shareManager->newShare();
2836
+        $share4->setNode($file1)
2837
+            ->setSharedBy($u3->getUID())
2838
+            ->setSharedWith($u5->getUID())
2839
+            ->setShareOwner($u1->getUID())
2840
+            ->setShareType(IShare::TYPE_USER)
2841
+            ->setPermissions(Constants::PERMISSION_READ);
2842
+        $share4 = $this->provider->create($share4);
2843
+        $share4 = $provider->acceptShare($share4, $u5->getUid());
2844
+
2845
+        $result = $provider->getAccessList([$folder1, $folder2, $file1], true);
2846
+
2847
+        $this->assertCount(3, $result['users']);
2848
+        $this->assertArrayHasKey('testShare2', $result['users']);
2849
+        $this->assertArrayHasKey('testShare3', $result['users']);
2850
+        $this->assertArrayHasKey('testShare5', $result['users']);
2851
+        $this->assertTrue($result['public']);
2852
+
2853
+        $provider->delete($share1);
2854
+        $provider->delete($share2);
2855
+        $provider->delete($share3);
2856
+        $provider->delete($share4);
2857
+
2858
+        $u1->delete();
2859
+        $u2->delete();
2860
+        $u3->delete();
2861
+        $u4->delete();
2862
+        $u5->delete();
2863
+        $g1->delete();
2864
+    }
2865
+
2866
+    public function testGetAllShares(): void {
2867
+        $qb = $this->dbConn->getQueryBuilder();
2868
+
2869
+        $qb->insert('share')
2870
+            ->values([
2871
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
2872
+                'share_with' => $qb->expr()->literal('sharedWith1'),
2873
+                'uid_owner' => $qb->expr()->literal('shareOwner1'),
2874
+                'uid_initiator' => $qb->expr()->literal('sharedBy1'),
2875
+                'item_type' => $qb->expr()->literal('file'),
2876
+                'file_source' => $qb->expr()->literal(42),
2877
+                'file_target' => $qb->expr()->literal('myTarget1'),
2878
+                'permissions' => $qb->expr()->literal(13),
2879
+            ]);
2880
+        $qb->executeStatement();
2881
+
2882
+        $id1 = $qb->getLastInsertId();
2883
+
2884
+        $qb->insert('share')
2885
+            ->values([
2886
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
2887
+                'share_with' => $qb->expr()->literal('sharedWith2'),
2888
+                'uid_owner' => $qb->expr()->literal('shareOwner2'),
2889
+                'uid_initiator' => $qb->expr()->literal('sharedBy2'),
2890
+                'item_type' => $qb->expr()->literal('file'),
2891
+                'file_source' => $qb->expr()->literal(43),
2892
+                'file_target' => $qb->expr()->literal('myTarget2'),
2893
+                'permissions' => $qb->expr()->literal(14),
2894
+            ]);
2895
+        $qb->executeStatement();
2896
+
2897
+        $id2 = $qb->getLastInsertId();
2898
+
2899
+        $qb->insert('share')
2900
+            ->values([
2901
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
2902
+                'token' => $qb->expr()->literal('token3'),
2903
+                'uid_owner' => $qb->expr()->literal('shareOwner3'),
2904
+                'uid_initiator' => $qb->expr()->literal('sharedBy3'),
2905
+                'item_type' => $qb->expr()->literal('file'),
2906
+                'file_source' => $qb->expr()->literal(44),
2907
+                'file_target' => $qb->expr()->literal('myTarget3'),
2908
+                'permissions' => $qb->expr()->literal(15),
2909
+            ]);
2910
+        $qb->executeStatement();
2911
+
2912
+        $id3 = $qb->getLastInsertId();
2913
+
2914
+        $qb->insert('share')
2915
+            ->values([
2916
+                'share_type' => $qb->expr()->literal(IShare::TYPE_EMAIL),
2917
+                'share_with' => $qb->expr()->literal('shareOwner4'),
2918
+                'token' => $qb->expr()->literal('token4'),
2919
+                'uid_owner' => $qb->expr()->literal('shareOwner4'),
2920
+                'uid_initiator' => $qb->expr()->literal('sharedBy4'),
2921
+                'item_type' => $qb->expr()->literal('file'),
2922
+                'file_source' => $qb->expr()->literal(45),
2923
+                'file_target' => $qb->expr()->literal('myTarget4'),
2924
+                'permissions' => $qb->expr()->literal(16),
2925
+            ]);
2926
+        $qb->executeStatement();
2927
+
2928
+        $id4 = $qb->getLastInsertId();
2929
+
2930
+        $qb->insert('share')
2931
+            ->values([
2932
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
2933
+                'token' => $qb->expr()->literal('token5'),
2934
+                'uid_owner' => $qb->expr()->literal('shareOwner5'),
2935
+                'uid_initiator' => $qb->expr()->literal('sharedBy5'),
2936
+                'item_type' => $qb->expr()->literal('file'),
2937
+                'file_source' => $qb->expr()->literal(46),
2938
+                'file_target' => $qb->expr()->literal('myTarget5'),
2939
+                'permissions' => $qb->expr()->literal(17),
2940
+            ]);
2941
+        $qb->executeStatement();
2942
+
2943
+        $id5 = $qb->getLastInsertId();
2944
+
2945
+        $ownerPath1 = $this->createMock(File::class);
2946
+        $shareOwner1Folder = $this->createMock(Folder::class);
2947
+        $shareOwner1Folder->method('getFirstNodeById')->willReturn($ownerPath1);
2948
+
2949
+        $ownerPath2 = $this->createMock(File::class);
2950
+        $shareOwner2Folder = $this->createMock(Folder::class);
2951
+        $shareOwner2Folder->method('getFirstNodeById')->willReturn($ownerPath2);
2952
+
2953
+        $ownerPath3 = $this->createMock(File::class);
2954
+        $shareOwner3Folder = $this->createMock(Folder::class);
2955
+        $shareOwner3Folder->method('getFirstNodeById')->willReturn($ownerPath3);
2956
+
2957
+        $ownerPath4 = $this->createMock(File::class);
2958
+        $shareOwner4Folder = $this->createMock(Folder::class);
2959
+        $shareOwner4Folder->method('getFirstNodeById')->willReturn($ownerPath4);
2960
+
2961
+        $ownerPath5 = $this->createMock(File::class);
2962
+        $shareOwner5Folder = $this->createMock(Folder::class);
2963
+        $shareOwner5Folder->method('getFirstNodeById')->willReturn($ownerPath5);
2964
+
2965
+        $this->rootFolder
2966
+            ->method('getUserFolder')
2967
+            ->willReturnMap(
2968
+                [
2969
+                    ['shareOwner1', $shareOwner1Folder],
2970
+                    ['shareOwner2', $shareOwner2Folder],
2971
+                    ['shareOwner3', $shareOwner3Folder],
2972
+                    ['shareOwner4', $shareOwner4Folder],
2973
+                    ['shareOwner5', $shareOwner5Folder],
2974
+                ]
2975
+            );
2976
+
2977
+        $shares = iterator_to_array($this->provider->getAllShares());
2978
+        $this->assertEquals(4, count($shares));
2979
+
2980
+        $share = $shares[0];
2981
+
2982
+        // We fetch the node so the root folder is eventually called
2983
+
2984
+        $this->assertEquals($id1, $share->getId());
2985
+        $this->assertEquals(IShare::TYPE_USER, $share->getShareType());
2986
+        $this->assertEquals('sharedWith1', $share->getSharedWith());
2987
+        $this->assertEquals('sharedBy1', $share->getSharedBy());
2988
+        $this->assertEquals('shareOwner1', $share->getShareOwner());
2989
+        $this->assertEquals($ownerPath1, $share->getNode());
2990
+        $this->assertEquals(13, $share->getPermissions());
2991
+        $this->assertEquals(null, $share->getToken());
2992
+        $this->assertEquals('myTarget1', $share->getTarget());
2993
+
2994
+        $share = $shares[1];
2995
+
2996
+        $this->assertEquals($id2, $share->getId());
2997
+        $this->assertEquals(IShare::TYPE_GROUP, $share->getShareType());
2998
+        $this->assertEquals('sharedWith2', $share->getSharedWith());
2999
+        $this->assertEquals('sharedBy2', $share->getSharedBy());
3000
+        $this->assertEquals('shareOwner2', $share->getShareOwner());
3001
+        $this->assertEquals($ownerPath2, $share->getNode());
3002
+        $this->assertEquals(14, $share->getPermissions());
3003
+        $this->assertEquals(null, $share->getToken());
3004
+        $this->assertEquals('myTarget2', $share->getTarget());
3005
+
3006
+        $share = $shares[2];
3007
+
3008
+        $this->assertEquals($id3, $share->getId());
3009
+        $this->assertEquals(IShare::TYPE_LINK, $share->getShareType());
3010
+        $this->assertEquals(null, $share->getSharedWith());
3011
+        $this->assertEquals('sharedBy3', $share->getSharedBy());
3012
+        $this->assertEquals('shareOwner3', $share->getShareOwner());
3013
+        $this->assertEquals($ownerPath3, $share->getNode());
3014
+        $this->assertEquals(15, $share->getPermissions());
3015
+        $this->assertEquals('token3', $share->getToken());
3016
+        $this->assertEquals('myTarget3', $share->getTarget());
3017
+
3018
+        $share = $shares[3];
3019
+
3020
+        $this->assertEquals($id5, $share->getId());
3021
+        $this->assertEquals(IShare::TYPE_LINK, $share->getShareType());
3022
+        $this->assertEquals(null, $share->getSharedWith());
3023
+        $this->assertEquals('sharedBy5', $share->getSharedBy());
3024
+        $this->assertEquals('shareOwner5', $share->getShareOwner());
3025
+        $this->assertEquals($ownerPath5, $share->getNode());
3026
+        $this->assertEquals(17, $share->getPermissions());
3027
+        $this->assertEquals('token5', $share->getToken());
3028
+        $this->assertEquals('myTarget5', $share->getTarget());
3029
+    }
3030
+
3031
+
3032
+    public function testGetSharesByPath(): void {
3033
+        $qb = $this->dbConn->getQueryBuilder();
3034
+
3035
+        $qb->insert('share')
3036
+            ->values([
3037
+                'share_type' => $qb->expr()->literal(IShare::TYPE_USER),
3038
+                'uid_owner' => $qb->expr()->literal('user1'),
3039
+                'uid_initiator' => $qb->expr()->literal('user1'),
3040
+                'share_with' => $qb->expr()->literal('user2'),
3041
+                'item_type' => $qb->expr()->literal('file'),
3042
+                'file_source' => $qb->expr()->literal(1),
3043
+            ]);
3044
+        $qb->executeStatement();
3045
+
3046
+        $id1 = $qb->getLastInsertId();
3047
+
3048
+        $qb->insert('share')
3049
+            ->values([
3050
+                'share_type' => $qb->expr()->literal(IShare::TYPE_GROUP),
3051
+                'uid_owner' => $qb->expr()->literal('user1'),
3052
+                'uid_initiator' => $qb->expr()->literal('user1'),
3053
+                'share_with' => $qb->expr()->literal('user2'),
3054
+                'item_type' => $qb->expr()->literal('file'),
3055
+                'file_source' => $qb->expr()->literal(1),
3056
+            ]);
3057
+        $qb->executeStatement();
3058
+
3059
+        $id2 = $qb->getLastInsertId();
3060
+
3061
+        $qb->insert('share')
3062
+            ->values([
3063
+                'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
3064
+                'uid_owner' => $qb->expr()->literal('user1'),
3065
+                'uid_initiator' => $qb->expr()->literal('user1'),
3066
+                'share_with' => $qb->expr()->literal('user2'),
3067
+                'item_type' => $qb->expr()->literal('file'),
3068
+                'file_source' => $qb->expr()->literal(1),
3069
+            ]);
3070
+        $qb->executeStatement();
3071
+
3072
+        $id3 = $qb->getLastInsertId();
3073
+
3074
+        $ownerPath1 = $this->createMock(File::class);
3075
+        $shareOwner1Folder = $this->createMock(Folder::class);
3076
+        $shareOwner1Folder->method('getFirstNodeById')->willReturn($ownerPath1);
3077
+
3078
+        $ownerPath2 = $this->createMock(File::class);
3079
+        $shareOwner2Folder = $this->createMock(Folder::class);
3080
+        $shareOwner2Folder->method('getFirstNodeById')->willReturn($ownerPath2);
3081
+
3082
+        $ownerPath3 = $this->createMock(File::class);
3083
+        $shareOwner3Folder = $this->createMock(Folder::class);
3084
+        $shareOwner3Folder->method('getFirstNodeById')->willReturn($ownerPath3);
3085
+
3086
+        $this->rootFolder
3087
+            ->method('getUserFolder')
3088
+            ->willReturnMap(
3089
+                [
3090
+                    ['shareOwner1', $shareOwner1Folder],
3091
+                    ['shareOwner2', $shareOwner2Folder],
3092
+                    ['shareOwner3', $shareOwner3Folder],
3093
+                ]
3094
+            );
3095
+
3096
+        $node = $this->createMock(Node::class);
3097
+        $node
3098
+            ->expects($this->once())
3099
+            ->method('getId')
3100
+            ->willReturn(1);
3101
+
3102
+        $shares = $this->provider->getSharesByPath($node);
3103
+        $this->assertCount(3, $shares);
3104
+
3105
+        $this->assertEquals($id1, $shares[0]->getId());
3106
+        $this->assertEquals(IShare::TYPE_USER, $shares[0]->getShareType());
3107
+
3108
+        $this->assertEquals($id2, $shares[1]->getId());
3109
+        $this->assertEquals(IShare::TYPE_GROUP, $shares[1]->getShareType());
3110
+
3111
+        $this->assertEquals($id3, $shares[2]->getId());
3112
+        $this->assertEquals(IShare::TYPE_LINK, $shares[2]->getShareType());
3113
+    }
3114 3114
 }
Please login to merge, or discard this patch.
Spacing   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -463,7 +463,7 @@  discard block
 block discarded – undo
463 463
 			]);
464 464
 		$this->assertEquals(1, $qb->executeStatement());
465 465
 
466
-		$id = (string)$qb->getLastInsertId();
466
+		$id = (string) $qb->getLastInsertId();
467 467
 
468 468
 		$share = $this->createMock(IShare::class);
469 469
 		$share->method('getId')->willReturn($id);
@@ -546,7 +546,7 @@  discard block
 block discarded – undo
546 546
 				'permissions' => $qb->expr()->literal(13),
547 547
 			]);
548 548
 		$this->assertEquals(1, $qb->executeStatement());
549
-		$id = (string)$qb->getLastInsertId();
549
+		$id = (string) $qb->getLastInsertId();
550 550
 
551 551
 		$qb = $this->dbConn->getQueryBuilder();
552 552
 		$qb->insert('share')
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
 		$qb->executeStatement();
615 615
 
616 616
 		// Get the id
617
-		$id = (string)$qb->getLastInsertId();
617
+		$id = (string) $qb->getLastInsertId();
618 618
 
619 619
 		$qb = $this->dbConn->getQueryBuilder();
620 620
 		$qb->insert('share')
@@ -730,7 +730,7 @@  discard block
 block discarded – undo
730 730
 		$share2 = $this->provider->create($share);
731 731
 
732 732
 		$this->assertNotNull($share2->getId());
733
-		$this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
733
+		$this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId());
734 734
 		$this->assertSame(IShare::TYPE_USER, $share2->getShareType());
735 735
 		$this->assertSame('sharedWith', $share2->getSharedWith());
736 736
 		$this->assertSame('sharedBy', $share2->getSharedBy());
@@ -800,7 +800,7 @@  discard block
 block discarded – undo
800 800
 		$share2 = $this->provider->create($share);
801 801
 
802 802
 		$this->assertNotNull($share2->getId());
803
-		$this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
803
+		$this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId());
804 804
 		$this->assertSame(IShare::TYPE_GROUP, $share2->getShareType());
805 805
 		$this->assertSame('sharedWith', $share2->getSharedWith());
806 806
 		$this->assertSame('sharedBy', $share2->getSharedBy());
@@ -869,7 +869,7 @@  discard block
 block discarded – undo
869 869
 		$share2 = $this->provider->create($share);
870 870
 
871 871
 		$this->assertNotNull($share2->getId());
872
-		$this->assertSame('ocinternal:' . $share2->getId(), $share2->getFullId());
872
+		$this->assertSame('ocinternal:'.$share2->getId(), $share2->getFullId());
873 873
 		$this->assertSame(IShare::TYPE_LINK, $share2->getShareType());
874 874
 		$this->assertSame('sharedBy', $share2->getSharedBy());
875 875
 		$this->assertSame('shareOwner', $share2->getShareOwner());
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
 
1078 1078
 		$groups = [];
1079 1079
 		foreach (range(0, 100) as $i) {
1080
-			$groups[] = 'group' . $i;
1080
+			$groups[] = 'group'.$i;
1081 1081
 		}
1082 1082
 
1083 1083
 		$groups[] = 'sharedWith';
@@ -1194,7 +1194,7 @@  discard block
 block discarded – undo
1194 1194
 		$this->assertCount(1, $share);
1195 1195
 
1196 1196
 		$share = $share[0];
1197
-		$this->assertSame((string)$id, $share->getId());
1197
+		$this->assertSame((string) $id, $share->getId());
1198 1198
 		$this->assertSame('sharedWith', $share->getSharedWith());
1199 1199
 		$this->assertSame('shareOwner', $share->getShareOwner());
1200 1200
 		$this->assertSame('sharedBy', $share->getSharedBy());
@@ -1323,7 +1323,7 @@  discard block
 block discarded – undo
1323 1323
 
1324 1324
 		$groups = [];
1325 1325
 		foreach (range(0, 100) as $i) {
1326
-			$groups[] = 'group' . $i;
1326
+			$groups[] = 'group'.$i;
1327 1327
 		}
1328 1328
 
1329 1329
 		$groups[] = 'sharedWith';
@@ -1856,13 +1856,13 @@  discard block
 block discarded – undo
1856 1856
 		$users = [];
1857 1857
 		for ($i = 0; $i < 6; $i++) {
1858 1858
 			$user = $this->createMock(IUser::class);
1859
-			$user->method('getUID')->willReturn('user' . $i);
1860
-			$user->method('getDisplayName')->willReturn('user' . $i);
1861
-			$users['user' . $i] = $user;
1859
+			$user->method('getUID')->willReturn('user'.$i);
1860
+			$user->method('getDisplayName')->willReturn('user'.$i);
1861
+			$users['user'.$i] = $user;
1862 1862
 		}
1863 1863
 
1864 1864
 		$this->userManager->method('get')->willReturnCallback(
1865
-			function ($userId) use ($users) {
1865
+			function($userId) use ($users) {
1866 1866
 				return $users[$userId];
1867 1867
 			}
1868 1868
 		);
@@ -1914,12 +1914,12 @@  discard block
 block discarded – undo
1914 1914
 		$users = [];
1915 1915
 		for ($i = 0; $i < 6; $i++) {
1916 1916
 			$user = $this->createMock(IUser::class);
1917
-			$user->method('getUID')->willReturn('user' . $i);
1918
-			$users['user' . $i] = $user;
1917
+			$user->method('getUID')->willReturn('user'.$i);
1918
+			$users['user'.$i] = $user;
1919 1919
 		}
1920 1920
 
1921 1921
 		$this->userManager->method('get')->willReturnCallback(
1922
-			function ($userId) use ($users) {
1922
+			function($userId) use ($users) {
1923 1923
 				return $users[$userId];
1924 1924
 			}
1925 1925
 		);
@@ -1980,12 +1980,12 @@  discard block
 block discarded – undo
1980 1980
 		$users = [];
1981 1981
 		for ($i = 0; $i < 6; $i++) {
1982 1982
 			$user = $this->createMock(IUser::class);
1983
-			$user->method('getUID')->willReturn('user' . $i);
1984
-			$users['user' . $i] = $user;
1983
+			$user->method('getUID')->willReturn('user'.$i);
1984
+			$users['user'.$i] = $user;
1985 1985
 		}
1986 1986
 
1987 1987
 		$this->userManager->method('get')->willReturnCallback(
1988
-			function ($userId) use ($users) {
1988
+			function($userId) use ($users) {
1989 1989
 				return $users[$userId];
1990 1990
 			}
1991 1991
 		);
@@ -2037,12 +2037,12 @@  discard block
 block discarded – undo
2037 2037
 		$users = [];
2038 2038
 		for ($i = 0; $i < 6; $i++) {
2039 2039
 			$user = $this->createMock(IUser::class);
2040
-			$user->method('getUID')->willReturn('user' . $i);
2041
-			$users['user' . $i] = $user;
2040
+			$user->method('getUID')->willReturn('user'.$i);
2041
+			$users['user'.$i] = $user;
2042 2042
 		}
2043 2043
 
2044 2044
 		$this->userManager->method('get')->willReturnCallback(
2045
-			function ($userId) use ($users) {
2045
+			function($userId) use ($users) {
2046 2046
 				return $users[$userId];
2047 2047
 			}
2048 2048
 		);
@@ -2050,13 +2050,13 @@  discard block
 block discarded – undo
2050 2050
 		$groups = [];
2051 2051
 		for ($i = 0; $i < 2; $i++) {
2052 2052
 			$group = $this->createMock(IGroup::class);
2053
-			$group->method('getGID')->willReturn('group' . $i);
2054
-			$group->method('getDisplayName')->willReturn('group-displayname' . $i);
2055
-			$groups['group' . $i] = $group;
2053
+			$group->method('getGID')->willReturn('group'.$i);
2054
+			$group->method('getDisplayName')->willReturn('group-displayname'.$i);
2055
+			$groups['group'.$i] = $group;
2056 2056
 		}
2057 2057
 
2058 2058
 		$this->groupManager->method('get')->willReturnCallback(
2059
-			function ($groupId) use ($groups) {
2059
+			function($groupId) use ($groups) {
2060 2060
 				return $groups[$groupId];
2061 2061
 			}
2062 2062
 		);
@@ -2116,12 +2116,12 @@  discard block
 block discarded – undo
2116 2116
 		$users = [];
2117 2117
 		for ($i = 0; $i < 6; $i++) {
2118 2118
 			$user = $this->createMock(IUser::class);
2119
-			$user->method('getUID')->willReturn('user' . $i);
2120
-			$users['user' . $i] = $user;
2119
+			$user->method('getUID')->willReturn('user'.$i);
2120
+			$users['user'.$i] = $user;
2121 2121
 		}
2122 2122
 
2123 2123
 		$this->userManager->method('get')->willReturnCallback(
2124
-			function ($userId) use ($users) {
2124
+			function($userId) use ($users) {
2125 2125
 				return $users[$userId];
2126 2126
 			}
2127 2127
 		);
@@ -2129,13 +2129,13 @@  discard block
 block discarded – undo
2129 2129
 		$groups = [];
2130 2130
 		for ($i = 0; $i < 2; $i++) {
2131 2131
 			$group = $this->createMock(IGroup::class);
2132
-			$group->method('getGID')->willReturn('group' . $i);
2133
-			$group->method('getDisplayName')->willReturn('group-displayname' . $i);
2134
-			$groups['group' . $i] = $group;
2132
+			$group->method('getGID')->willReturn('group'.$i);
2133
+			$group->method('getDisplayName')->willReturn('group-displayname'.$i);
2134
+			$groups['group'.$i] = $group;
2135 2135
 		}
2136 2136
 
2137 2137
 		$this->groupManager->method('get')->willReturnCallback(
2138
-			function ($groupId) use ($groups) {
2138
+			function($groupId) use ($groups) {
2139 2139
 				return $groups[$groupId];
2140 2140
 			}
2141 2141
 		);
@@ -2193,12 +2193,12 @@  discard block
 block discarded – undo
2193 2193
 		$this->assertSame('user0', $shares[0]['share_with']);
2194 2194
 		$this->assertSame('user4', $shares[0]['uid_initiator']);
2195 2195
 		$this->assertSame('user5', $shares[0]['uid_owner']);
2196
-		$this->assertSame(1, (int)$shares[0]['permissions']);
2196
+		$this->assertSame(1, (int) $shares[0]['permissions']);
2197 2197
 
2198 2198
 		$this->assertSame('user3', $shares[1]['share_with']);
2199 2199
 		$this->assertSame('user4', $shares[1]['uid_initiator']);
2200 2200
 		$this->assertSame('user5', $shares[1]['uid_owner']);
2201
-		$this->assertSame(0, (int)$shares[1]['permissions']);
2201
+		$this->assertSame(0, (int) $shares[1]['permissions']);
2202 2202
 
2203 2203
 
2204 2204
 		$stmt->closeCursor();
Please login to merge, or discard this patch.
tests/lib/Share20/ManagerTest.php 2 patches
Indentation   +4822 added lines, -4822 removed lines patch added patch discarded remove patch
@@ -64,10 +64,10 @@  discard block
 block discarded – undo
64 64
 use Psr\Log\LoggerInterface;
65 65
 
66 66
 class DummyShareManagerListener {
67
-	public function post() {
68
-	}
69
-	public function listener() {
70
-	}
67
+    public function post() {
68
+    }
69
+    public function listener() {
70
+    }
71 71
 }
72 72
 
73 73
 /**
@@ -77,5010 +77,5010 @@  discard block
 block discarded – undo
77 77
  */
78 78
 #[\PHPUnit\Framework\Attributes\Group('DB')]
79 79
 class ManagerTest extends \Test\TestCase {
80
-	protected Manager $manager;
81
-	protected LoggerInterface&MockObject $logger;
82
-	protected IConfig&MockObject $config;
83
-	protected ISecureRandom&MockObject $secureRandom;
84
-	protected IHasher&MockObject $hasher;
85
-	protected IShareProvider&MockObject $defaultProvider;
86
-	protected IMountManager&MockObject $mountManager;
87
-	protected IGroupManager&MockObject $groupManager;
88
-	protected IL10N&MockObject $l;
89
-	protected IFactory&MockObject $l10nFactory;
90
-	protected DummyFactory $factory;
91
-	protected IUserManager&MockObject $userManager;
92
-	protected IRootFolder&MockObject $rootFolder;
93
-	protected IEventDispatcher&MockObject $dispatcher;
94
-	protected IUserSession&MockObject $userSession;
95
-	protected KnownUserService&MockObject $knownUserService;
96
-	protected ShareDisableChecker $shareDisabledChecker;
97
-	private DateTimeZone $timezone;
98
-	protected IDateTimeZone&MockObject $dateTimeZone;
99
-	protected IAppConfig&MockObject $appConfig;
100
-
101
-	protected function setUp(): void {
102
-		$this->logger = $this->createMock(LoggerInterface::class);
103
-		$this->config = $this->createMock(IConfig::class);
104
-		$this->secureRandom = $this->createMock(ISecureRandom::class);
105
-		$this->hasher = $this->createMock(IHasher::class);
106
-		$this->mountManager = $this->createMock(IMountManager::class);
107
-		$this->groupManager = $this->createMock(IGroupManager::class);
108
-		$this->userManager = $this->createMock(IUserManager::class);
109
-		$this->rootFolder = $this->createMock(IRootFolder::class);
110
-		$this->dispatcher = $this->createMock(IEventDispatcher::class);
111
-		$this->userSession = $this->createMock(IUserSession::class);
112
-		$this->knownUserService = $this->createMock(KnownUserService::class);
113
-
114
-		$this->shareDisabledChecker = new ShareDisableChecker($this->config, $this->userManager, $this->groupManager);
115
-		$this->dateTimeZone = $this->createMock(IDateTimeZone::class);
116
-		$this->timezone = new \DateTimeZone('Pacific/Auckland');
117
-		$this->dateTimeZone->method('getTimeZone')->willReturnCallback(fn () => $this->timezone);
118
-
119
-		$this->appConfig = $this->createMock(IAppConfig::class);
120
-
121
-		$this->l10nFactory = $this->createMock(IFactory::class);
122
-		$this->l = $this->createMock(IL10N::class);
123
-		$this->l->method('t')
124
-			->willReturnCallback(function ($text, $parameters = []) {
125
-				return vsprintf($text, $parameters);
126
-			});
127
-		$this->l->method('n')
128
-			->willReturnCallback(function ($singular, $plural, $count, $parameters = []) {
129
-				return vsprintf(str_replace('%n', $count, ($count === 1) ? $singular : $plural), $parameters);
130
-			});
131
-		$this->l10nFactory->method('get')->willReturn($this->l);
132
-
133
-		$this->factory = new DummyFactory(\OC::$server);
134
-
135
-		$this->manager = $this->createManager($this->factory);
136
-
137
-		$this->defaultProvider = $this->createMock(DefaultShareProvider::class);
138
-		$this->defaultProvider->method('identifier')->willReturn('default');
139
-		$this->factory->setProvider($this->defaultProvider);
140
-	}
141
-
142
-	private function createManager(IProviderFactory $factory): Manager {
143
-		return new Manager(
144
-			$this->logger,
145
-			$this->config,
146
-			$this->secureRandom,
147
-			$this->hasher,
148
-			$this->mountManager,
149
-			$this->groupManager,
150
-			$this->l10nFactory,
151
-			$factory,
152
-			$this->userManager,
153
-			$this->rootFolder,
154
-			$this->dispatcher,
155
-			$this->userSession,
156
-			$this->knownUserService,
157
-			$this->shareDisabledChecker,
158
-			$this->dateTimeZone,
159
-			$this->appConfig,
160
-		);
161
-	}
162
-
163
-	/**
164
-	 * @return MockBuilder<Manager>
165
-	 */
166
-	private function createManagerMock(): MockBuilder {
167
-		return $this->getMockBuilder(Manager::class)
168
-			->setConstructorArgs([
169
-				$this->logger,
170
-				$this->config,
171
-				$this->secureRandom,
172
-				$this->hasher,
173
-				$this->mountManager,
174
-				$this->groupManager,
175
-				$this->l10nFactory,
176
-				$this->factory,
177
-				$this->userManager,
178
-				$this->rootFolder,
179
-				$this->dispatcher,
180
-				$this->userSession,
181
-				$this->knownUserService,
182
-				$this->shareDisabledChecker,
183
-				$this->dateTimeZone,
184
-				$this->appConfig,
185
-			]);
186
-	}
187
-
188
-	private function createFolderMock(string $folderPath): MockObject&Folder {
189
-		$folder = $this->createMock(Folder::class);
190
-		$folder->method('getPath')->willReturn($folderPath);
191
-		$folder->method('getRelativePath')->willReturnCallback(
192
-			fn (string $path): ?string => PathHelper::getRelativePath($folderPath, $path)
193
-		);
194
-		return $folder;
195
-	}
196
-
197
-	public function testDeleteNoShareId(): void {
198
-		$this->expectException(\InvalidArgumentException::class);
199
-
200
-		$share = $this->manager->newShare();
201
-
202
-		$this->manager->deleteShare($share);
203
-	}
204
-
205
-	public static function dataTestDelete(): array {
206
-		return [
207
-			[IShare::TYPE_USER, 'sharedWithUser'],
208
-			[IShare::TYPE_GROUP, 'sharedWithGroup'],
209
-			[IShare::TYPE_LINK, ''],
210
-			[IShare::TYPE_REMOTE, '[email protected]'],
211
-		];
212
-	}
213
-
214
-	#[DataProvider('dataTestDelete')]
215
-	public function testDelete($shareType, $sharedWith): void {
216
-		$manager = $this->createManagerMock()
217
-			->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
218
-			->getMock();
219
-
220
-		$manager->method('deleteChildren')->willReturn([]);
221
-
222
-		$path = $this->createMock(File::class);
223
-		$path->method('getId')->willReturn(1);
224
-
225
-		$share = $this->manager->newShare();
226
-		$share->setId(42)
227
-			->setProviderId('prov')
228
-			->setShareType($shareType)
229
-			->setSharedWith($sharedWith)
230
-			->setSharedBy('sharedBy')
231
-			->setNode($path)
232
-			->setTarget('myTarget');
233
-
234
-		$manager->expects($this->once())->method('deleteChildren')->with($share);
235
-		$manager->expects($this->once())->method('promoteReshares')->with($share);
236
-
237
-		$this->defaultProvider
238
-			->expects($this->once())
239
-			->method('delete')
240
-			->with($share);
241
-
242
-		$calls = [
243
-			BeforeShareDeletedEvent::class,
244
-			ShareDeletedEvent::class,
245
-		];
246
-		$this->dispatcher->expects($this->exactly(2))
247
-			->method('dispatchTyped')
248
-			->willReturnCallback(function ($event) use (&$calls, $share): void {
249
-				$expected = array_shift($calls);
250
-				$this->assertInstanceOf($expected, $event);
251
-				$this->assertEquals($share, $event->getShare());
252
-			});
253
-
254
-		$manager->deleteShare($share);
255
-	}
256
-
257
-	public function testDeleteLazyShare(): void {
258
-		$manager = $this->createManagerMock()
259
-			->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
260
-			->getMock();
261
-
262
-		$manager->method('deleteChildren')->willReturn([]);
263
-
264
-		$share = $this->manager->newShare();
265
-		$share->setId(42)
266
-			->setProviderId('prov')
267
-			->setShareType(IShare::TYPE_USER)
268
-			->setSharedWith('sharedWith')
269
-			->setSharedBy('sharedBy')
270
-			->setShareOwner('shareOwner')
271
-			->setTarget('myTarget')
272
-			->setNodeId(1)
273
-			->setNodeType('file');
274
-
275
-		$this->rootFolder->expects($this->never())->method($this->anything());
276
-
277
-		$manager->expects($this->once())->method('deleteChildren')->with($share);
278
-		$manager->expects($this->once())->method('promoteReshares')->with($share);
279
-
280
-		$this->defaultProvider
281
-			->expects($this->once())
282
-			->method('delete')
283
-			->with($share);
284
-
285
-		$calls = [
286
-			BeforeShareDeletedEvent::class,
287
-			ShareDeletedEvent::class,
288
-		];
289
-		$this->dispatcher->expects($this->exactly(2))
290
-			->method('dispatchTyped')
291
-			->willReturnCallback(function ($event) use (&$calls, $share): void {
292
-				$expected = array_shift($calls);
293
-				$this->assertInstanceOf($expected, $event);
294
-				$this->assertEquals($share, $event->getShare());
295
-			});
296
-
297
-		$manager->deleteShare($share);
298
-	}
299
-
300
-	public function testDeleteNested(): void {
301
-		$manager = $this->createManagerMock()
302
-			->onlyMethods(['getShareById', 'promoteReshares'])
303
-			->getMock();
304
-
305
-		$path = $this->createMock(File::class);
306
-		$path->method('getId')->willReturn(1);
307
-
308
-		$share1 = $this->manager->newShare();
309
-		$share1->setId(42)
310
-			->setProviderId('prov')
311
-			->setShareType(IShare::TYPE_USER)
312
-			->setSharedWith('sharedWith1')
313
-			->setSharedBy('sharedBy1')
314
-			->setNode($path)
315
-			->setTarget('myTarget1');
316
-
317
-		$share2 = $this->manager->newShare();
318
-		$share2->setId(43)
319
-			->setProviderId('prov')
320
-			->setShareType(IShare::TYPE_GROUP)
321
-			->setSharedWith('sharedWith2')
322
-			->setSharedBy('sharedBy2')
323
-			->setNode($path)
324
-			->setTarget('myTarget2')
325
-			->setParent(42);
326
-
327
-		$share3 = $this->manager->newShare();
328
-		$share3->setId(44)
329
-			->setProviderId('prov')
330
-			->setShareType(IShare::TYPE_LINK)
331
-			->setSharedBy('sharedBy3')
332
-			->setNode($path)
333
-			->setTarget('myTarget3')
334
-			->setParent(43);
335
-
336
-		$this->defaultProvider
337
-			->method('getChildren')
338
-			->willReturnMap([
339
-				[$share1, [$share2]],
340
-				[$share2, [$share3]],
341
-				[$share3, []],
342
-			]);
343
-
344
-		$deleteCalls = [
345
-			$share3,
346
-			$share2,
347
-			$share1,
348
-		];
349
-		$this->defaultProvider->expects($this->exactly(3))
350
-			->method('delete')
351
-			->willReturnCallback(function ($share) use (&$deleteCalls): void {
352
-				$expected = array_shift($deleteCalls);
353
-				$this->assertEquals($expected, $share);
354
-			});
355
-
356
-		$dispatchCalls = [
357
-			[BeforeShareDeletedEvent::class, $share1],
358
-			[BeforeShareDeletedEvent::class, $share2],
359
-			[BeforeShareDeletedEvent::class, $share3],
360
-			[ShareDeletedEvent::class, $share3],
361
-			[ShareDeletedEvent::class, $share2],
362
-			[ShareDeletedEvent::class, $share1],
363
-		];
364
-		$this->dispatcher->expects($this->exactly(6))
365
-			->method('dispatchTyped')
366
-			->willReturnCallback(function ($event) use (&$dispatchCalls): void {
367
-				$expected = array_shift($dispatchCalls);
368
-				$this->assertInstanceOf($expected[0], $event);
369
-				$this->assertEquals($expected[1]->getId(), $event->getShare()->getId());
370
-			});
371
-
372
-		$manager->deleteShare($share1);
373
-	}
374
-
375
-	public function testDeleteFromSelf(): void {
376
-		$manager = $this->createManagerMock()
377
-			->onlyMethods(['getShareById'])
378
-			->getMock();
379
-
380
-		$recipientId = 'unshareFrom';
381
-		$share = $this->manager->newShare();
382
-		$share->setId(42)
383
-			->setProviderId('prov')
384
-			->setShareType(IShare::TYPE_USER)
385
-			->setSharedWith('sharedWith')
386
-			->setSharedBy('sharedBy')
387
-			->setShareOwner('shareOwner')
388
-			->setTarget('myTarget')
389
-			->setNodeId(1)
390
-			->setNodeType('file');
391
-
392
-		$this->defaultProvider
393
-			->expects($this->once())
394
-			->method('deleteFromSelf')
395
-			->with($share, $recipientId);
396
-
397
-		$this->dispatcher->expects($this->once())
398
-			->method('dispatchTyped')
399
-			->with(
400
-				$this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) {
401
-					return $e->getShare() === $share;
402
-				})
403
-			);
404
-
405
-		$manager->deleteFromSelf($share, $recipientId);
406
-	}
407
-
408
-	public function testDeleteChildren(): void {
409
-		$manager = $this->createManagerMock()
410
-			->onlyMethods(['deleteShare'])
411
-			->getMock();
412
-
413
-		$share = $this->createMock(IShare::class);
414
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
415
-
416
-		$child1 = $this->createMock(IShare::class);
417
-		$child1->method('getShareType')->willReturn(IShare::TYPE_USER);
418
-		$child2 = $this->createMock(IShare::class);
419
-		$child2->method('getShareType')->willReturn(IShare::TYPE_USER);
420
-		$child3 = $this->createMock(IShare::class);
421
-		$child3->method('getShareType')->willReturn(IShare::TYPE_USER);
422
-
423
-		$shares = [
424
-			$child1,
425
-			$child2,
426
-			$child3,
427
-		];
428
-
429
-		$this->defaultProvider
430
-			->expects($this->exactly(4))
431
-			->method('getChildren')
432
-			->willReturnCallback(function ($_share) use ($share, $shares) {
433
-				if ($_share === $share) {
434
-					return $shares;
435
-				}
436
-				return [];
437
-			});
438
-
439
-		$calls = [
440
-			$child1,
441
-			$child2,
442
-			$child3,
443
-		];
444
-		$this->defaultProvider->expects($this->exactly(3))
445
-			->method('delete')
446
-			->willReturnCallback(function ($share) use (&$calls): void {
447
-				$expected = array_shift($calls);
448
-				$this->assertEquals($expected, $share);
449
-			});
450
-
451
-		$result = self::invokePrivate($manager, 'deleteChildren', [$share]);
452
-		$this->assertSame($shares, $result);
453
-	}
454
-
455
-	public function testPromoteReshareFile(): void {
456
-		$manager = $this->createManagerMock()
457
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
458
-			->getMock();
459
-
460
-		$file = $this->createMock(File::class);
461
-
462
-		$share = $this->createMock(IShare::class);
463
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
464
-		$share->method('getNodeType')->willReturn('folder');
465
-		$share->method('getSharedWith')->willReturn('userB');
466
-		$share->method('getNode')->willReturn($file);
467
-
468
-		$reShare = $this->createMock(IShare::class);
469
-		$reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
470
-		$reShare->method('getSharedBy')->willReturn('userB');
471
-		$reShare->method('getSharedWith')->willReturn('userC');
472
-		$reShare->method('getNode')->willReturn($file);
473
-
474
-		$this->defaultProvider->method('getSharesBy')
475
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) {
476
-				$this->assertEquals($file, $node);
477
-				if ($shareType === IShare::TYPE_USER) {
478
-					return match($userId) {
479
-						'userB' => [$reShare],
480
-					};
481
-				} else {
482
-					return [];
483
-				}
484
-			});
485
-		$manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
486
-
487
-		$manager->expects($this->exactly(1))->method('updateShare')->with($reShare)->willReturn($reShare);
488
-
489
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
490
-	}
491
-
492
-	public function testPromoteReshare(): void {
493
-		$manager = $this->createManagerMock()
494
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
495
-			->getMock();
496
-
497
-		$folder = $this->createFolderMock('/path/to/folder');
498
-
499
-		$subFolder = $this->createFolderMock('/path/to/folder/sub');
500
-
501
-		$otherFolder = $this->createFolderMock('/path/to/otherfolder/');
502
-
503
-		$share = $this->createMock(IShare::class);
504
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
505
-		$share->method('getNodeType')->willReturn('folder');
506
-		$share->method('getSharedWith')->willReturn('userB');
507
-		$share->method('getNode')->willReturn($folder);
508
-
509
-		$reShare = $this->createMock(IShare::class);
510
-		$reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
511
-		$reShare->method('getSharedBy')->willReturn('userB');
512
-		$reShare->method('getSharedWith')->willReturn('userC');
513
-		$reShare->method('getNode')->willReturn($folder);
514
-
515
-		$reShareInSubFolder = $this->createMock(IShare::class);
516
-		$reShareInSubFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
517
-		$reShareInSubFolder->method('getSharedBy')->willReturn('userB');
518
-		$reShareInSubFolder->method('getNode')->willReturn($subFolder);
519
-
520
-		$reShareInOtherFolder = $this->createMock(IShare::class);
521
-		$reShareInOtherFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
522
-		$reShareInOtherFolder->method('getSharedBy')->willReturn('userB');
523
-		$reShareInOtherFolder->method('getNode')->willReturn($otherFolder);
524
-
525
-		$this->defaultProvider->method('getSharesBy')
526
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) {
527
-				if ($shareType === IShare::TYPE_USER) {
528
-					return match($userId) {
529
-						'userB' => [$reShare,$reShareInSubFolder,$reShareInOtherFolder],
530
-					};
531
-				} else {
532
-					return [];
533
-				}
534
-			});
535
-		$manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
536
-
537
-		$calls = [
538
-			$reShare,
539
-			$reShareInSubFolder,
540
-		];
541
-		$manager->expects($this->exactly(2))
542
-			->method('updateShare')
543
-			->willReturnCallback(function ($share) use (&$calls): IShare {
544
-				$expected = array_shift($calls);
545
-				$this->assertEquals($expected, $share);
546
-				return $expected;
547
-			});
548
-
549
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
550
-	}
551
-
552
-	public function testPromoteReshareWhenUserHasAnotherShare(): void {
553
-		$manager = $this->createManagerMock()
554
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
555
-			->getMock();
556
-
557
-		$folder = $this->createFolderMock('/path/to/folder');
558
-
559
-		$share = $this->createMock(IShare::class);
560
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
561
-		$share->method('getNodeType')->willReturn('folder');
562
-		$share->method('getSharedWith')->willReturn('userB');
563
-		$share->method('getNode')->willReturn($folder);
564
-
565
-		$reShare = $this->createMock(IShare::class);
566
-		$reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
567
-		$reShare->method('getNodeType')->willReturn('folder');
568
-		$reShare->method('getSharedBy')->willReturn('userB');
569
-		$reShare->method('getNode')->willReturn($folder);
570
-
571
-		$this->defaultProvider->method('getSharesBy')->willReturn([$reShare]);
572
-		$manager->method('generalCreateChecks');
573
-
574
-		/* No share is promoted because generalCreateChecks does not throw */
575
-		$manager->expects($this->never())->method('updateShare');
576
-
577
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
578
-	}
579
-
580
-	public function testPromoteReshareOfUsersInGroupShare(): void {
581
-		$manager = $this->createManagerMock()
582
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
583
-			->getMock();
584
-
585
-		$folder = $this->createFolderMock('/path/to/folder');
586
-
587
-		$userA = $this->createMock(IUser::class);
588
-		$userA->method('getUID')->willReturn('userA');
589
-
590
-		$share = $this->createMock(IShare::class);
591
-		$share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
592
-		$share->method('getNodeType')->willReturn('folder');
593
-		$share->method('getSharedWith')->willReturn('Group');
594
-		$share->method('getNode')->willReturn($folder);
595
-		$share->method('getShareOwner')->willReturn($userA);
596
-
597
-		$reShare1 = $this->createMock(IShare::class);
598
-		$reShare1->method('getShareType')->willReturn(IShare::TYPE_USER);
599
-		$reShare1->method('getNodeType')->willReturn('folder');
600
-		$reShare1->method('getSharedBy')->willReturn('userB');
601
-		$reShare1->method('getNode')->willReturn($folder);
602
-
603
-		$reShare2 = $this->createMock(IShare::class);
604
-		$reShare2->method('getShareType')->willReturn(IShare::TYPE_USER);
605
-		$reShare2->method('getNodeType')->willReturn('folder');
606
-		$reShare2->method('getSharedBy')->willReturn('userC');
607
-		$reShare2->method('getNode')->willReturn($folder);
608
-
609
-		$userB = $this->createMock(IUser::class);
610
-		$userB->method('getUID')->willReturn('userB');
611
-		$userC = $this->createMock(IUser::class);
612
-		$userC->method('getUID')->willReturn('userC');
613
-		$group = $this->createMock(IGroup::class);
614
-		$group->method('getUsers')->willReturn([$userB, $userC]);
615
-		$this->groupManager->method('get')->with('Group')->willReturn($group);
616
-
617
-		$this->defaultProvider->method('getSharesBy')
618
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) {
619
-				if ($shareType === IShare::TYPE_USER) {
620
-					return match($userId) {
621
-						'userB' => [$reShare1],
622
-						'userC' => [$reShare2],
623
-					};
624
-				} else {
625
-					return [];
626
-				}
627
-			});
628
-		$manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
629
-
630
-		$manager->method('getSharedWith')->willReturn([]);
631
-
632
-		$calls = [
633
-			$reShare1,
634
-			$reShare2,
635
-		];
636
-		$manager->expects($this->exactly(2))
637
-			->method('updateShare')
638
-			->willReturnCallback(function ($share) use (&$calls): IShare {
639
-				$expected = array_shift($calls);
640
-				$this->assertEquals($expected, $share);
641
-				return $expected;
642
-			});
643
-
644
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
645
-	}
646
-
647
-	public function testGetShareById(): void {
648
-		$share = $this->createMock(IShare::class);
649
-
650
-		$this->defaultProvider
651
-			->expects($this->once())
652
-			->method('getShareById')
653
-			->with(42)
654
-			->willReturn($share);
655
-
656
-		$this->assertEquals($share, $this->manager->getShareById('default:42'));
657
-	}
658
-
659
-
660
-	public function testGetExpiredShareById(): void {
661
-		$this->expectException(ShareNotFound::class);
662
-
663
-		$manager = $this->createManagerMock()
664
-			->onlyMethods(['deleteShare'])
665
-			->getMock();
666
-
667
-		$date = new \DateTime();
668
-		$date->setTime(0, 0, 0);
669
-
670
-		$share = $this->manager->newShare();
671
-		$share->setExpirationDate($date)
672
-			->setShareType(IShare::TYPE_LINK);
673
-
674
-		$this->defaultProvider->expects($this->once())
675
-			->method('getShareById')
676
-			->with('42')
677
-			->willReturn($share);
678
-
679
-		$manager->expects($this->once())
680
-			->method('deleteShare')
681
-			->with($share);
682
-
683
-		$manager->getShareById('default:42');
684
-	}
685
-
686
-
687
-	public function testVerifyPasswordNullButEnforced(): void {
688
-		$this->expectException(\InvalidArgumentException::class);
689
-		$this->expectExceptionMessage('Passwords are enforced for link and mail shares');
690
-
691
-		$this->config->method('getAppValue')->willReturnMap([
692
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
693
-		]);
694
-
695
-		$this->appConfig->method('getValueBool')->willReturnMap([
696
-			['core', 'shareapi_enforce_links_password', true],
697
-		]);
698
-
699
-		self::invokePrivate($this->manager, 'verifyPassword', [null]);
700
-	}
701
-
702
-	public function testVerifyPasswordNotEnforcedGroup(): void {
703
-		$this->config->method('getAppValue')->willReturnMap([
704
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin"]'],
705
-			['core', 'shareapi_enforce_links_password', 'no', 'yes'],
706
-		]);
707
-
708
-		// Create admin user
709
-		$user = $this->createMock(IUser::class);
710
-		$this->userSession->method('getUser')->willReturn($user);
711
-		$this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['admin']);
712
-
713
-		$result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
714
-		$this->assertNull($result);
715
-	}
716
-
717
-	public function testVerifyPasswordNotEnforcedMultipleGroups(): void {
718
-		$this->config->method('getAppValue')->willReturnMap([
719
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin", "special"]'],
720
-			['core', 'shareapi_enforce_links_password', 'no', 'yes'],
721
-		]);
722
-
723
-		// Create admin user
724
-		$user = $this->createMock(IUser::class);
725
-		$this->userSession->method('getUser')->willReturn($user);
726
-		$this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['special']);
727
-
728
-		$result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
729
-		$this->assertNull($result);
730
-	}
731
-
732
-	public function testVerifyPasswordNull(): void {
733
-		$this->config->method('getAppValue')->willReturnMap([
734
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
735
-			['core', 'shareapi_enforce_links_password', 'no', 'no'],
736
-		]);
737
-
738
-		$result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
739
-		$this->assertNull($result);
740
-	}
741
-
742
-	public function testVerifyPasswordHook(): void {
743
-		$this->config->method('getAppValue')->willReturnMap([
744
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
745
-			['core', 'shareapi_enforce_links_password', 'no', 'no'],
746
-		]);
747
-
748
-		$this->dispatcher->expects($this->once())->method('dispatchTyped')
749
-			->willReturnCallback(function (Event $event): void {
750
-				$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
751
-				/** @var ValidatePasswordPolicyEvent $event */
752
-				$this->assertSame('password', $event->getPassword());
753
-			}
754
-			);
755
-
756
-		$result = self::invokePrivate($this->manager, 'verifyPassword', ['password']);
757
-		$this->assertNull($result);
758
-	}
759
-
760
-
761
-	public function testVerifyPasswordHookFails(): void {
762
-		$this->expectException(\Exception::class);
763
-		$this->expectExceptionMessage('password not accepted');
764
-
765
-		$this->config->method('getAppValue')->willReturnMap([
766
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
767
-			['core', 'shareapi_enforce_links_password', 'no', 'no'],
768
-		]);
769
-
770
-		$this->dispatcher->expects($this->once())->method('dispatchTyped')
771
-			->willReturnCallback(function (Event $event): void {
772
-				$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
773
-				/** @var ValidatePasswordPolicyEvent $event */
774
-				$this->assertSame('password', $event->getPassword());
775
-				throw new HintException('password not accepted');
776
-			}
777
-			);
778
-
779
-		self::invokePrivate($this->manager, 'verifyPassword', ['password']);
780
-	}
781
-
782
-	public function createShare($id, int $type, ?Node $node, $sharedWith, $sharedBy, $shareOwner,
783
-		$permissions, $expireDate = null, $password = null, $attributes = null): IShare&MockObject {
784
-		$share = $this->createMock(IShare::class);
785
-
786
-		$share->method('getShareType')->willReturn($type);
787
-		$share->method('getSharedWith')->willReturn($sharedWith);
788
-		$share->method('getSharedBy')->willReturn($sharedBy);
789
-		$share->method('getShareOwner')->willReturn($shareOwner);
790
-		if ($node) {
791
-			$share->method('getNode')->willReturn($node);
792
-			if ($node->getId()) {
793
-				$share->method('getNodeId')->willReturn($node->getId());
794
-			}
795
-		} else {
796
-			$share->method('getNode')->willReturnCallback(function (): never {
797
-				throw new NotFoundException();
798
-			});
799
-		}
800
-		$share->method('getPermissions')->willReturn($permissions);
801
-		$share->method('getAttributes')->willReturn($attributes);
802
-		$share->method('getExpirationDate')->willReturn($expireDate);
803
-		$share->method('getPassword')->willReturn($password);
804
-
805
-		return $share;
806
-	}
807
-
808
-	public static function dataGeneralChecks(): array {
809
-		$user0 = 'user0';
810
-		$user2 = 'user1';
811
-		$group0 = 'group0';
812
-
813
-		$file = [
814
-			File::class,
815
-			[
816
-				'getId' => 108,
817
-			],
818
-			'default',
819
-		];
820
-
821
-		$node = [
822
-			Node::class,
823
-			[
824
-				'getId' => 108,
825
-			],
826
-			'default',
827
-		];
828
-
829
-		$data = [
830
-			[[null, IShare::TYPE_USER, $file, null, $user0, $user0, 31, null, null], 'Share recipient is not a valid user', true],
831
-			[[null, IShare::TYPE_USER, $file, $group0, $user0, $user0, 31, null, null], 'Share recipient is not a valid user', true],
832
-			[[null, IShare::TYPE_USER, $file, '[email protected]', $user0, $user0, 31, null, null], 'Share recipient is not a valid user', true],
833
-			[[null, IShare::TYPE_GROUP, $file, null, $user0, $user0, 31, null, null], 'Share recipient is not a valid group', true],
834
-			[[null, IShare::TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null], 'Share recipient is not a valid group', true],
835
-			[[null, IShare::TYPE_GROUP, $file, '[email protected]', $user0, $user0, 31, null, null], 'Share recipient is not a valid group', true],
836
-			[[null, IShare::TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null], 'Share recipient should be empty', true],
837
-			[[null, IShare::TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null], 'Share recipient should be empty', true],
838
-			[[null, IShare::TYPE_LINK, $file, '[email protected]', $user0, $user0, 31, null, null], 'Share recipient should be empty', true],
839
-			[[null, -1, $file, null, $user0, $user0, 31, null, null], 'Unknown share type', true],
840
-
841
-			[[null, IShare::TYPE_USER, $file, $user2, null, $user0, 31, null, null], 'Share initiator must be set', true],
842
-			[[null, IShare::TYPE_GROUP, $file, $group0, null, $user0, 31, null, null], 'Share initiator must be set', true],
843
-			[[null, IShare::TYPE_LINK, $file, null, null, $user0, 31, null, null], 'Share initiator must be set', true],
844
-
845
-			[[null, IShare::TYPE_USER, $file, $user0, $user0, $user0, 31, null, null], 'Cannot share with yourself', true],
846
-
847
-			[[null, IShare::TYPE_USER, null, $user2, $user0, $user0, 31, null, null], 'Shared path must be set', true],
848
-			[[null, IShare::TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null], 'Shared path must be set', true],
849
-			[[null, IShare::TYPE_LINK, null, null, $user0, $user0, 31, null, null], 'Shared path must be set', true],
850
-
851
-			[[null, IShare::TYPE_USER, $node, $user2, $user0, $user0, 31, null, null], 'Shared path must be either a file or a folder', true],
852
-			[[null, IShare::TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null], 'Shared path must be either a file or a folder', true],
853
-			[[null, IShare::TYPE_LINK, $node, null, $user0, $user0, 31, null, null], 'Shared path must be either a file or a folder', true],
854
-		];
855
-
856
-		$nonShareAble = [
857
-			Folder::class,
858
-			[
859
-				'getId' => 108,
860
-				'isShareable' => false,
861
-				'getPath' => 'path',
862
-				'getName' => 'name',
863
-				'getOwner' => $user0,
864
-			],
865
-			'default',
866
-		];
867
-
868
-		$data[] = [[null, IShare::TYPE_USER, $nonShareAble, $user2, $user0, $user0, 31, null, null], 'You are not allowed to share name', true];
869
-		$data[] = [[null, IShare::TYPE_GROUP, $nonShareAble, $group0, $user0, $user0, 31, null, null], 'You are not allowed to share name', true];
870
-		$data[] = [[null, IShare::TYPE_LINK, $nonShareAble, null, $user0, $user0, 31, null, null], 'You are not allowed to share name', true];
871
-
872
-		$limitedPermssions = [
873
-			File::class,
874
-			[
875
-				'isShareable' => true,
876
-				'getPermissions' => Constants::PERMISSION_READ,
877
-				'getId' => 108,
878
-				'getPath' => 'path',
879
-				'getName' => 'name',
880
-				'getOwner' => $user0,
881
-			],
882
-			'default',
883
-		];
884
-
885
-		$data[] = [[null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null], 'Valid permissions are required for sharing', true];
886
-		$data[] = [[null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null], 'Valid permissions are required for sharing', true];
887
-		$data[] = [[null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null], 'Valid permissions are required for sharing', true];
888
-
889
-		$limitedPermssions[1]['getMountPoint'] = MoveableMount::class;
890
-
891
-		// increase permissions of a re-share
892
-		$data[] = [[null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null], 'Cannot increase permissions of path', true];
893
-		$data[] = [[null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 3, null, null], 'Cannot increase permissions of path', true];
894
-
895
-		$nonMoveableMountPermssions = [
896
-			Folder::class,
897
-			[
898
-				'isShareable' => true,
899
-				'getPermissions' => Constants::PERMISSION_READ,
900
-				'getId' => 108,
901
-				'getPath' => 'path',
902
-				'getName' => 'name',
903
-				'getInternalPath' => '',
904
-				'getOwner' => $user0,
905
-			],
906
-			'allPermssions',
907
-		];
908
-
909
-		$data[] = [[null, IShare::TYPE_USER, $nonMoveableMountPermssions, $user2, $user0, $user0, 11, null, null], 'Cannot increase permissions of path', false];
910
-		$data[] = [[null, IShare::TYPE_GROUP, $nonMoveableMountPermssions, $group0, $user0, $user0, 11, null, null], 'Cannot increase permissions of path', false];
911
-
912
-		$rootFolder = [
913
-			Folder::class,
914
-			[
915
-				'isShareable' => true,
916
-				'getPermissions' => Constants::PERMISSION_ALL,
917
-				'getId' => 42,
918
-			],
919
-			'none',
920
-		];
921
-
922
-		$data[] = [[null, IShare::TYPE_USER, $rootFolder, $user2, $user0, $user0, 30, null, null], 'You cannot share your root folder', true];
923
-		$data[] = [[null, IShare::TYPE_GROUP, $rootFolder, $group0, $user0, $user0, 2, null, null], 'You cannot share your root folder', true];
924
-		$data[] = [[null, IShare::TYPE_LINK, $rootFolder, null, $user0, $user0, 16, null, null], 'You cannot share your root folder', true];
925
-
926
-		$allPermssionsFiles = [
927
-			File::class,
928
-			[
929
-				'isShareable' => true,
930
-				'getPermissions' => Constants::PERMISSION_ALL,
931
-				'getId' => 187,
932
-				'getOwner' => $user0,
933
-			],
934
-			'default',
935
-		];
936
-
937
-		// test invalid CREATE or DELETE permissions
938
-		$data[] = [[null, IShare::TYPE_USER, $allPermssionsFiles, $user2, $user0, $user0, Constants::PERMISSION_ALL, null, null], 'File shares cannot have create or delete permissions', true];
939
-		$data[] = [[null, IShare::TYPE_GROUP, $allPermssionsFiles, $group0, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_CREATE, null, null], 'File shares cannot have create or delete permissions', true];
940
-		$data[] = [[null, IShare::TYPE_LINK, $allPermssionsFiles, null, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_DELETE, null, null], 'File shares cannot have create or delete permissions', true];
941
-
942
-		$allPermssions = [
943
-			Folder::class,
944
-			[
945
-				'isShareable' => true,
946
-				'getPermissions' => Constants::PERMISSION_ALL,
947
-				'getId' => 108,
948
-				'getOwner' => $user0,
949
-			],
950
-			'default',
951
-		];
952
-
953
-		$data[] = [[null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null], 'Shares need at least read permissions', true];
954
-		$data[] = [[null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null], 'Shares need at least read permissions', true];
955
-
956
-		// test invalid permissions
957
-		$data[] = [[null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 32, null, null], 'Valid permissions are required for sharing', true];
958
-		$data[] = [[null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 63, null, null], 'Valid permissions are required for sharing', true];
959
-		$data[] = [[null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, -1, null, null], 'Valid permissions are required for sharing', true];
960
-
961
-		// working shares
962
-		$data[] = [[null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null], null, false];
963
-		$data[] = [[null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null], null, false];
964
-		$data[] = [[null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null], null, false];
965
-
966
-		$remoteFile = [
967
-			Folder::class,
968
-			[
969
-				'isShareable' => true,
970
-				'getPermissions' => Constants::PERMISSION_READ ^ Constants::PERMISSION_UPDATE,
971
-				'getId' => 108,
972
-				'getOwner' => $user0,
973
-			],
974
-			'remote',
975
-		];
976
-
977
-		$data[] = [[null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 1, null, null], null, false];
978
-		$data[] = [[null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 3, null, null], null, false];
979
-		$data[] = [[null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 31, null, null], 'Cannot increase permissions of ', true];
980
-
981
-		return $data;
982
-	}
983
-
984
-	private function createNodeMock(string $class, array $methods, string $storageType): MockObject {
985
-		$mock = $this->createMock($class);
986
-		foreach ($methods as $methodName => $return) {
987
-			if ($methodName === 'getOwner') {
988
-				$uid = $return;
989
-				$return = $this->createMock(IUser::class);
990
-				$return->method('getUID')
991
-					->willReturn($uid);
992
-			} elseif ($methodName === 'getMountPoint') {
993
-				$return = $this->createMock($return);
994
-			}
995
-			$mock->method($methodName)->willReturn($return);
996
-		}
997
-		switch ($storageType) {
998
-			case 'default':
999
-				$storage = $this->createMock(IStorage::class);
1000
-				$storage->method('instanceOfStorage')
1001
-					->with('\OCA\Files_Sharing\External\Storage')
1002
-					->willReturn(false);
1003
-				break;
1004
-			case 'allPermssions':
1005
-				$storage = $this->createMock(IStorage::class);
1006
-				$storage->method('instanceOfStorage')
1007
-					->with('\OCA\Files_Sharing\External\Storage')
1008
-					->willReturn(false);
1009
-				$storage->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
1010
-				break;
1011
-			case 'none':
1012
-				$storage = false;
1013
-				break;
1014
-			case 'remote':
1015
-				$storage = $this->createMock(IStorage::class);
1016
-				$storage->method('instanceOfStorage')
1017
-					->with('\OCA\Files_Sharing\External\Storage')
1018
-					->willReturn(true);
1019
-				break;
1020
-			default:
1021
-				throw new \Exception('Unknown storage type ' . $storageType);
1022
-		}
1023
-		if ($storage === false) {
1024
-			$mock->expects(self::never())->method('getStorage');
1025
-		} else {
1026
-			$mock->method('getStorage')
1027
-				->willReturn($storage);
1028
-		}
1029
-
1030
-		return $mock;
1031
-	}
1032
-
1033
-	#[DataProvider('dataGeneralChecks')]
1034
-	public function testGeneralChecks(array $shareParams, ?string $exceptionMessage, bool $exception): void {
1035
-		if ($shareParams[2] !== null) {
1036
-			$shareParams[2] = $this->createNodeMock(...$shareParams[2]);
1037
-		}
1038
-		$share = $this->createShare(...$shareParams);
1039
-
1040
-		$thrown = null;
1041
-
1042
-		$this->userManager->method('userExists')->willReturnMap([
1043
-			['user0', true],
1044
-			['user1', true],
1045
-		]);
1046
-
1047
-		$this->groupManager->method('groupExists')->willReturnMap([
1048
-			['group0', true],
1049
-		]);
1050
-
1051
-		$userFolder = $this->createMock(Folder::class);
1052
-		$userFolder->expects($this->any())
1053
-			->method('getId')
1054
-			->willReturn(42);
1055
-		// Id 108 is used in the data to refer to the node of the share.
1056
-		try {
1057
-			$node = $share->getNode();
1058
-			$userFolder->method('getById')
1059
-				->with(108)
1060
-				->willReturn([$node]);
1061
-		} catch (NotFoundException $e) {
1062
-			$userFolder->method('getById')
1063
-				->with(108)
1064
-				->willReturn([]);
1065
-		}
1066
-		$userFolder->expects($this->any())
1067
-			->method('getRelativePath')
1068
-			->willReturnArgument(0);
1069
-		$this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1070
-
1071
-
1072
-		try {
1073
-			self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1074
-			$thrown = false;
1075
-		} catch (GenericShareException $e) {
1076
-			$this->assertEquals($exceptionMessage, $e->getHint());
1077
-			$thrown = true;
1078
-		} catch (\InvalidArgumentException $e) {
1079
-			$this->assertEquals($exceptionMessage, $e->getMessage());
1080
-			$thrown = true;
1081
-		}
1082
-
1083
-		$this->assertSame($exception, $thrown);
1084
-	}
1085
-
1086
-
1087
-	public function testGeneralCheckShareRoot(): void {
1088
-		$this->expectException(\InvalidArgumentException::class);
1089
-		$this->expectExceptionMessage('You cannot share your root folder');
1090
-
1091
-		$this->userManager->method('userExists')->willReturnMap([
1092
-			['user0', true],
1093
-			['user1', true],
1094
-		]);
1095
-
1096
-		$userFolder = $this->createMock(Folder::class);
1097
-		$userFolder->method('isSubNode')->with($userFolder)->willReturn(false);
1098
-		$this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1099
-
1100
-		$share = $this->manager->newShare();
1101
-
1102
-		$share->setShareType(IShare::TYPE_USER)
1103
-			->setSharedWith('user0')
1104
-			->setSharedBy('user1')
1105
-			->setNode($userFolder);
1106
-
1107
-		self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1108
-	}
1109
-
1110
-	public static function validateExpirationDateInternalProvider() {
1111
-		return [[IShare::TYPE_USER], [IShare::TYPE_REMOTE], [IShare::TYPE_REMOTE_GROUP]];
1112
-	}
1113
-
1114
-	#[DataProvider('validateExpirationDateInternalProvider')]
1115
-	public function testValidateExpirationDateInternalInPast($shareType): void {
1116
-		$this->expectException(GenericShareException::class);
1117
-		$this->expectExceptionMessage('Expiration date is in the past');
1118
-
1119
-		// Expire date in the past
1120
-		$past = new \DateTime();
1121
-		$past->sub(new \DateInterval('P1D'));
1122
-
1123
-		$share = $this->manager->newShare();
1124
-		$share->setShareType($shareType);
1125
-		$share->setExpirationDate($past);
1126
-
1127
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1128
-	}
1129
-
1130
-	#[DataProvider('validateExpirationDateInternalProvider')]
1131
-	public function testValidateExpirationDateInternalEnforceButNotSet($shareType): void {
1132
-		$this->expectException(\InvalidArgumentException::class);
1133
-		$this->expectExceptionMessage('Expiration date is enforced');
1134
-
1135
-		$share = $this->manager->newShare();
1136
-		$share->setProviderId('foo')->setId('bar');
1137
-		$share->setShareType($shareType);
1138
-		if ($shareType === IShare::TYPE_USER) {
1139
-			$this->config->method('getAppValue')
1140
-				->willReturnMap([
1141
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1142
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1143
-				]);
1144
-		} else {
1145
-			$this->config->method('getAppValue')
1146
-				->willReturnMap([
1147
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1148
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1149
-				]);
1150
-		}
1151
-
1152
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1153
-	}
1154
-
1155
-	#[DataProvider('validateExpirationDateInternalProvider')]
1156
-	public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType): void {
1157
-		$share = $this->manager->newShare();
1158
-		$share->setProviderId('foo')->setId('bar');
1159
-		$share->setShareType($shareType);
1160
-
1161
-		if ($shareType === IShare::TYPE_USER) {
1162
-			$this->config->method('getAppValue')
1163
-				->willReturnMap([
1164
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1165
-				]);
1166
-		} else {
1167
-			$this->config->method('getAppValue')
1168
-				->willReturnMap([
1169
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1170
-				]);
1171
-		}
1172
-
1173
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1174
-
1175
-		$this->assertNull($share->getExpirationDate());
1176
-	}
1177
-
1178
-	#[DataProvider('validateExpirationDateInternalProvider')]
1179
-	public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType): void {
1180
-		$share = $this->manager->newShare();
1181
-		$share->setShareType($shareType);
1182
-
1183
-		if ($shareType === IShare::TYPE_USER) {
1184
-			$this->config->method('getAppValue')
1185
-				->willReturnMap([
1186
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1187
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1188
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1189
-					['core', 'internal_defaultExpDays', '3', '3'],
1190
-				]);
1191
-		} else {
1192
-			$this->config->method('getAppValue')
1193
-				->willReturnMap([
1194
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1195
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1196
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1197
-					['core', 'remote_defaultExpDays', '3', '3'],
1198
-				]);
1199
-		}
1200
-
1201
-		$expected = new \DateTime('now', $this->timezone);
1202
-		$expected->setTime(0, 0, 0);
1203
-		$expected->add(new \DateInterval('P3D'));
1204
-
1205
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1206
-
1207
-		$this->assertNotNull($share->getExpirationDate());
1208
-		$this->assertEquals($expected, $share->getExpirationDate());
1209
-	}
1210
-
1211
-	#[DataProvider('validateExpirationDateInternalProvider')]
1212
-	public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType): void {
1213
-		$share = $this->manager->newShare();
1214
-		$share->setShareType($shareType);
1215
-
1216
-		if ($shareType === IShare::TYPE_USER) {
1217
-			$this->config->method('getAppValue')
1218
-				->willReturnMap([
1219
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1220
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1221
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1222
-					['core', 'internal_defaultExpDays', '3', '1'],
1223
-				]);
1224
-		} else {
1225
-			$this->config->method('getAppValue')
1226
-				->willReturnMap([
1227
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1228
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1229
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1230
-					['core', 'remote_defaultExpDays', '3', '1'],
1231
-				]);
1232
-		}
1233
-
1234
-		$expected = new \DateTime('now', $this->timezone);
1235
-		$expected->setTime(0, 0, 0);
1236
-		$expected->add(new \DateInterval('P1D'));
1237
-
1238
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1239
-
1240
-		$this->assertNotNull($share->getExpirationDate());
1241
-		$this->assertEquals($expected, $share->getExpirationDate());
1242
-	}
1243
-
1244
-	#[DataProvider('validateExpirationDateInternalProvider')]
1245
-	public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType): void {
1246
-		$this->expectException(GenericShareException::class);
1247
-		$this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1248
-
1249
-		$future = new \DateTime();
1250
-		$future->add(new \DateInterval('P7D'));
1251
-
1252
-		$share = $this->manager->newShare();
1253
-		$share->setShareType($shareType);
1254
-		$share->setExpirationDate($future);
1255
-
1256
-		if ($shareType === IShare::TYPE_USER) {
1257
-			$this->config->method('getAppValue')
1258
-				->willReturnMap([
1259
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1260
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1261
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1262
-				]);
1263
-		} else {
1264
-			$this->config->method('getAppValue')
1265
-				->willReturnMap([
1266
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1267
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1268
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1269
-				]);
1270
-		}
1271
-
1272
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1273
-	}
1274
-
1275
-	#[DataProvider('validateExpirationDateInternalProvider')]
1276
-	public function testValidateExpirationDateInternalEnforceValid($shareType): void {
1277
-		$future = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1278
-		$future->add(new \DateInterval('P2D'));
1279
-		$future->setTime(1, 2, 3);
1280
-
1281
-		$expected = clone $future;
1282
-		$expected->setTime(0, 0, 0);
1283
-
1284
-		$share = $this->manager->newShare();
1285
-		$share->setShareType($shareType);
1286
-		$share->setExpirationDate($future);
1287
-
1288
-		if ($shareType === IShare::TYPE_USER) {
1289
-			$this->config->method('getAppValue')
1290
-				->willReturnMap([
1291
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1292
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1293
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1294
-				]);
1295
-		} else {
1296
-			$this->config->method('getAppValue')
1297
-				->willReturnMap([
1298
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1299
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1300
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1301
-				]);
1302
-		}
1303
-
1304
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1305
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1306
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1307
-			return $data['expirationDate'] == $future;
1308
-		}));
1309
-
1310
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1311
-
1312
-		$this->assertEquals($expected, $share->getExpirationDate());
1313
-	}
1314
-
1315
-	#[DataProvider('validateExpirationDateInternalProvider')]
1316
-	public function testValidateExpirationDateInternalNoDefault($shareType): void {
1317
-		$date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1318
-		$date->add(new \DateInterval('P5D'));
1319
-		$date->setTime(1, 2, 3);
1320
-
1321
-		$expected = clone $date;
1322
-		$expected->setTime(0, 0, 0);
1323
-
1324
-		$share = $this->manager->newShare();
1325
-		$share->setShareType($shareType);
1326
-		$share->setExpirationDate($date);
1327
-
1328
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1329
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1330
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1331
-			return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1332
-		}));
1333
-
1334
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1335
-
1336
-		$this->assertEquals($expected, $share->getExpirationDate());
1337
-	}
1338
-
1339
-	#[DataProvider('validateExpirationDateInternalProvider')]
1340
-	public function testValidateExpirationDateInternalNoDateNoDefault($shareType): void {
1341
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1342
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1343
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1344
-			return $data['expirationDate'] === null && $data['passwordSet'] === true;
1345
-		}));
1346
-
1347
-		$share = $this->manager->newShare();
1348
-		$share->setShareType($shareType);
1349
-		$share->setPassword('password');
1350
-
1351
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1352
-
1353
-		$this->assertNull($share->getExpirationDate());
1354
-	}
1355
-
1356
-	#[DataProvider('validateExpirationDateInternalProvider')]
1357
-	public function testValidateExpirationDateInternalNoDateDefault($shareType): void {
1358
-		$share = $this->manager->newShare();
1359
-		$share->setShareType($shareType);
1360
-
1361
-		$expected = new \DateTime('now', $this->timezone);
1362
-		$expected->setTime(0, 0);
1363
-		$expected->add(new \DateInterval('P3D'));
1364
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1365
-
1366
-		if ($shareType === IShare::TYPE_USER) {
1367
-			$this->config->method('getAppValue')
1368
-				->willReturnMap([
1369
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1370
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1371
-					['core', 'internal_defaultExpDays', '3', '3'],
1372
-				]);
1373
-		} else {
1374
-			$this->config->method('getAppValue')
1375
-				->willReturnMap([
1376
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1377
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1378
-					['core', 'remote_defaultExpDays', '3', '3'],
1379
-				]);
1380
-		}
1381
-
1382
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1383
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1384
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1385
-			return $data['expirationDate'] == $expected;
1386
-		}));
1387
-
1388
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1389
-
1390
-		$this->assertEquals($expected, $share->getExpirationDate());
1391
-	}
1392
-
1393
-	#[DataProvider('validateExpirationDateInternalProvider')]
1394
-	public function testValidateExpirationDateInternalDefault($shareType): void {
1395
-		$future = new \DateTime('now', $this->timezone);
1396
-		$future->add(new \DateInterval('P5D'));
1397
-		$future->setTime(1, 2, 3);
1398
-
1399
-		$expected = clone $future;
1400
-		$expected->setTime(0, 0);
1401
-
1402
-		$share = $this->manager->newShare();
1403
-		$share->setShareType($shareType);
1404
-		$share->setExpirationDate($future);
1405
-
1406
-		if ($shareType === IShare::TYPE_USER) {
1407
-			$this->config->method('getAppValue')
1408
-				->willReturnMap([
1409
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1410
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1411
-					['core', 'internal_defaultExpDays', '3', '1'],
1412
-				]);
1413
-		} else {
1414
-			$this->config->method('getAppValue')
1415
-				->willReturnMap([
1416
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1417
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1418
-					['core', 'remote_defaultExpDays', '3', '1'],
1419
-				]);
1420
-		}
1421
-
1422
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1423
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1424
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1425
-			return $data['expirationDate'] == $expected;
1426
-		}));
1427
-
1428
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1429
-
1430
-		$this->assertEquals($expected, $share->getExpirationDate());
1431
-	}
1432
-
1433
-	#[DataProvider('validateExpirationDateInternalProvider')]
1434
-	public function testValidateExpirationDateInternalHookModification($shareType): void {
1435
-		$nextWeek = new \DateTime('now', $this->timezone);
1436
-		$nextWeek->add(new \DateInterval('P7D'));
1437
-		$nextWeek->setTime(0, 0, 0);
1438
-
1439
-		$save = clone $nextWeek;
1440
-
1441
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1442
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1443
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1444
-			$data['expirationDate']->sub(new \DateInterval('P2D'));
1445
-		});
1446
-
1447
-		$share = $this->manager->newShare();
1448
-		$share->setShareType($shareType);
1449
-		$share->setExpirationDate($nextWeek);
1450
-
1451
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1452
-
1453
-		$save->sub(new \DateInterval('P2D'));
1454
-		$this->assertEquals($save, $share->getExpirationDate());
1455
-	}
1456
-
1457
-	#[DataProvider('validateExpirationDateInternalProvider')]
1458
-	public function testValidateExpirationDateInternalHookException($shareType): void {
1459
-		$this->expectException(\Exception::class);
1460
-		$this->expectExceptionMessage('Invalid date!');
1461
-
1462
-		$nextWeek = new \DateTime();
1463
-		$nextWeek->add(new \DateInterval('P7D'));
1464
-		$nextWeek->setTime(0, 0, 0);
1465
-
1466
-		$share = $this->manager->newShare();
1467
-		$share->setShareType($shareType);
1468
-		$share->setExpirationDate($nextWeek);
1469
-
1470
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1471
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1472
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1473
-			$data['accepted'] = false;
1474
-			$data['message'] = 'Invalid date!';
1475
-		});
1476
-
1477
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1478
-	}
1479
-
1480
-	#[DataProvider('validateExpirationDateInternalProvider')]
1481
-	public function testValidateExpirationDateInternalExistingShareNoDefault($shareType): void {
1482
-		$share = $this->manager->newShare();
1483
-		$share->setShareType($shareType);
1484
-		$share->setId('42')->setProviderId('foo');
1485
-
1486
-		if ($shareType === IShare::TYPE_USER) {
1487
-			$this->config->method('getAppValue')
1488
-				->willReturnMap([
1489
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1490
-					['core', 'shareapi_internal_expire_after_n_days', '7', '6'],
1491
-				]);
1492
-		} else {
1493
-			$this->config->method('getAppValue')
1494
-				->willReturnMap([
1495
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1496
-					['core', 'shareapi_remote_expire_after_n_days', '7', '6'],
1497
-				]);
1498
-		}
1499
-
1500
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1501
-
1502
-		$this->assertEquals(null, $share->getExpirationDate());
1503
-	}
1504
-
1505
-	public function testValidateExpirationDateInPast(): void {
1506
-		$this->expectException(GenericShareException::class);
1507
-		$this->expectExceptionMessage('Expiration date is in the past');
1508
-
1509
-		// Expire date in the past
1510
-		$past = new \DateTime();
1511
-		$past->sub(new \DateInterval('P1D'));
1512
-
1513
-		$share = $this->manager->newShare();
1514
-		$share->setExpirationDate($past);
1515
-
1516
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1517
-	}
1518
-
1519
-	public function testValidateExpirationDateEnforceButNotSet(): void {
1520
-		$this->expectException(\InvalidArgumentException::class);
1521
-		$this->expectExceptionMessage('Expiration date is enforced');
1522
-
1523
-		$share = $this->manager->newShare();
1524
-		$share->setProviderId('foo')->setId('bar');
1525
-
1526
-		$this->appConfig->method('getValueBool')
1527
-			->willReturnMap([
1528
-				['core', 'shareapi_default_expire_date', true],
1529
-				['core', 'shareapi_enforce_expire_date', true],
1530
-			]);
1531
-
1532
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1533
-	}
1534
-
1535
-	public function testValidateExpirationDateEnforceButNotEnabledAndNotSet(): void {
1536
-		$share = $this->manager->newShare();
1537
-		$share->setProviderId('foo')->setId('bar');
1538
-
1539
-		$this->config->method('getAppValue')
1540
-			->willReturnMap([
1541
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1542
-			]);
1543
-
1544
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1545
-
1546
-		$this->assertNull($share->getExpirationDate());
1547
-	}
1548
-
1549
-	public function testValidateExpirationDateEnforceButNotSetNewShare(): void {
1550
-		$share = $this->manager->newShare();
1551
-
1552
-		$this->config->method('getAppValue')
1553
-			->willReturnMap([
1554
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1555
-				['core', 'link_defaultExpDays', '3', '3'],
1556
-			]);
1557
-
1558
-		$this->appConfig->method('getValueBool')
1559
-			->willReturnMap([
1560
-				['core', 'shareapi_default_expire_date', true],
1561
-				['core', 'shareapi_enforce_expire_date', true],
1562
-			]);
1563
-
1564
-		$expected = new \DateTime('now', $this->timezone);
1565
-		$expected->setTime(0, 0, 0);
1566
-		$expected->add(new \DateInterval('P3D'));
1567
-
1568
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1569
-
1570
-		$this->assertNotNull($share->getExpirationDate());
1571
-		$this->assertEquals($expected, $share->getExpirationDate());
1572
-	}
1573
-
1574
-	public function testValidateExpirationDateEnforceRelaxedDefaultButNotSetNewShare(): void {
1575
-		$share = $this->manager->newShare();
1576
-
1577
-		$this->config->method('getAppValue')
1578
-			->willReturnMap([
1579
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1580
-				['core', 'link_defaultExpDays', '3', '1'],
1581
-			]);
1582
-
1583
-		$this->appConfig->method('getValueBool')
1584
-			->willReturnMap([
1585
-				['core', 'shareapi_default_expire_date', true],
1586
-				['core', 'shareapi_enforce_expire_date', true],
1587
-			]);
1588
-
1589
-		$expected = new \DateTime('now', $this->timezone);
1590
-		$expected->setTime(0, 0, 0);
1591
-		$expected->add(new \DateInterval('P1D'));
80
+    protected Manager $manager;
81
+    protected LoggerInterface&MockObject $logger;
82
+    protected IConfig&MockObject $config;
83
+    protected ISecureRandom&MockObject $secureRandom;
84
+    protected IHasher&MockObject $hasher;
85
+    protected IShareProvider&MockObject $defaultProvider;
86
+    protected IMountManager&MockObject $mountManager;
87
+    protected IGroupManager&MockObject $groupManager;
88
+    protected IL10N&MockObject $l;
89
+    protected IFactory&MockObject $l10nFactory;
90
+    protected DummyFactory $factory;
91
+    protected IUserManager&MockObject $userManager;
92
+    protected IRootFolder&MockObject $rootFolder;
93
+    protected IEventDispatcher&MockObject $dispatcher;
94
+    protected IUserSession&MockObject $userSession;
95
+    protected KnownUserService&MockObject $knownUserService;
96
+    protected ShareDisableChecker $shareDisabledChecker;
97
+    private DateTimeZone $timezone;
98
+    protected IDateTimeZone&MockObject $dateTimeZone;
99
+    protected IAppConfig&MockObject $appConfig;
100
+
101
+    protected function setUp(): void {
102
+        $this->logger = $this->createMock(LoggerInterface::class);
103
+        $this->config = $this->createMock(IConfig::class);
104
+        $this->secureRandom = $this->createMock(ISecureRandom::class);
105
+        $this->hasher = $this->createMock(IHasher::class);
106
+        $this->mountManager = $this->createMock(IMountManager::class);
107
+        $this->groupManager = $this->createMock(IGroupManager::class);
108
+        $this->userManager = $this->createMock(IUserManager::class);
109
+        $this->rootFolder = $this->createMock(IRootFolder::class);
110
+        $this->dispatcher = $this->createMock(IEventDispatcher::class);
111
+        $this->userSession = $this->createMock(IUserSession::class);
112
+        $this->knownUserService = $this->createMock(KnownUserService::class);
113
+
114
+        $this->shareDisabledChecker = new ShareDisableChecker($this->config, $this->userManager, $this->groupManager);
115
+        $this->dateTimeZone = $this->createMock(IDateTimeZone::class);
116
+        $this->timezone = new \DateTimeZone('Pacific/Auckland');
117
+        $this->dateTimeZone->method('getTimeZone')->willReturnCallback(fn () => $this->timezone);
118
+
119
+        $this->appConfig = $this->createMock(IAppConfig::class);
120
+
121
+        $this->l10nFactory = $this->createMock(IFactory::class);
122
+        $this->l = $this->createMock(IL10N::class);
123
+        $this->l->method('t')
124
+            ->willReturnCallback(function ($text, $parameters = []) {
125
+                return vsprintf($text, $parameters);
126
+            });
127
+        $this->l->method('n')
128
+            ->willReturnCallback(function ($singular, $plural, $count, $parameters = []) {
129
+                return vsprintf(str_replace('%n', $count, ($count === 1) ? $singular : $plural), $parameters);
130
+            });
131
+        $this->l10nFactory->method('get')->willReturn($this->l);
132
+
133
+        $this->factory = new DummyFactory(\OC::$server);
134
+
135
+        $this->manager = $this->createManager($this->factory);
136
+
137
+        $this->defaultProvider = $this->createMock(DefaultShareProvider::class);
138
+        $this->defaultProvider->method('identifier')->willReturn('default');
139
+        $this->factory->setProvider($this->defaultProvider);
140
+    }
141
+
142
+    private function createManager(IProviderFactory $factory): Manager {
143
+        return new Manager(
144
+            $this->logger,
145
+            $this->config,
146
+            $this->secureRandom,
147
+            $this->hasher,
148
+            $this->mountManager,
149
+            $this->groupManager,
150
+            $this->l10nFactory,
151
+            $factory,
152
+            $this->userManager,
153
+            $this->rootFolder,
154
+            $this->dispatcher,
155
+            $this->userSession,
156
+            $this->knownUserService,
157
+            $this->shareDisabledChecker,
158
+            $this->dateTimeZone,
159
+            $this->appConfig,
160
+        );
161
+    }
162
+
163
+    /**
164
+     * @return MockBuilder<Manager>
165
+     */
166
+    private function createManagerMock(): MockBuilder {
167
+        return $this->getMockBuilder(Manager::class)
168
+            ->setConstructorArgs([
169
+                $this->logger,
170
+                $this->config,
171
+                $this->secureRandom,
172
+                $this->hasher,
173
+                $this->mountManager,
174
+                $this->groupManager,
175
+                $this->l10nFactory,
176
+                $this->factory,
177
+                $this->userManager,
178
+                $this->rootFolder,
179
+                $this->dispatcher,
180
+                $this->userSession,
181
+                $this->knownUserService,
182
+                $this->shareDisabledChecker,
183
+                $this->dateTimeZone,
184
+                $this->appConfig,
185
+            ]);
186
+    }
187
+
188
+    private function createFolderMock(string $folderPath): MockObject&Folder {
189
+        $folder = $this->createMock(Folder::class);
190
+        $folder->method('getPath')->willReturn($folderPath);
191
+        $folder->method('getRelativePath')->willReturnCallback(
192
+            fn (string $path): ?string => PathHelper::getRelativePath($folderPath, $path)
193
+        );
194
+        return $folder;
195
+    }
196
+
197
+    public function testDeleteNoShareId(): void {
198
+        $this->expectException(\InvalidArgumentException::class);
199
+
200
+        $share = $this->manager->newShare();
201
+
202
+        $this->manager->deleteShare($share);
203
+    }
204
+
205
+    public static function dataTestDelete(): array {
206
+        return [
207
+            [IShare::TYPE_USER, 'sharedWithUser'],
208
+            [IShare::TYPE_GROUP, 'sharedWithGroup'],
209
+            [IShare::TYPE_LINK, ''],
210
+            [IShare::TYPE_REMOTE, '[email protected]'],
211
+        ];
212
+    }
213
+
214
+    #[DataProvider('dataTestDelete')]
215
+    public function testDelete($shareType, $sharedWith): void {
216
+        $manager = $this->createManagerMock()
217
+            ->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
218
+            ->getMock();
219
+
220
+        $manager->method('deleteChildren')->willReturn([]);
221
+
222
+        $path = $this->createMock(File::class);
223
+        $path->method('getId')->willReturn(1);
224
+
225
+        $share = $this->manager->newShare();
226
+        $share->setId(42)
227
+            ->setProviderId('prov')
228
+            ->setShareType($shareType)
229
+            ->setSharedWith($sharedWith)
230
+            ->setSharedBy('sharedBy')
231
+            ->setNode($path)
232
+            ->setTarget('myTarget');
233
+
234
+        $manager->expects($this->once())->method('deleteChildren')->with($share);
235
+        $manager->expects($this->once())->method('promoteReshares')->with($share);
236
+
237
+        $this->defaultProvider
238
+            ->expects($this->once())
239
+            ->method('delete')
240
+            ->with($share);
241
+
242
+        $calls = [
243
+            BeforeShareDeletedEvent::class,
244
+            ShareDeletedEvent::class,
245
+        ];
246
+        $this->dispatcher->expects($this->exactly(2))
247
+            ->method('dispatchTyped')
248
+            ->willReturnCallback(function ($event) use (&$calls, $share): void {
249
+                $expected = array_shift($calls);
250
+                $this->assertInstanceOf($expected, $event);
251
+                $this->assertEquals($share, $event->getShare());
252
+            });
253
+
254
+        $manager->deleteShare($share);
255
+    }
256
+
257
+    public function testDeleteLazyShare(): void {
258
+        $manager = $this->createManagerMock()
259
+            ->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
260
+            ->getMock();
261
+
262
+        $manager->method('deleteChildren')->willReturn([]);
263
+
264
+        $share = $this->manager->newShare();
265
+        $share->setId(42)
266
+            ->setProviderId('prov')
267
+            ->setShareType(IShare::TYPE_USER)
268
+            ->setSharedWith('sharedWith')
269
+            ->setSharedBy('sharedBy')
270
+            ->setShareOwner('shareOwner')
271
+            ->setTarget('myTarget')
272
+            ->setNodeId(1)
273
+            ->setNodeType('file');
274
+
275
+        $this->rootFolder->expects($this->never())->method($this->anything());
276
+
277
+        $manager->expects($this->once())->method('deleteChildren')->with($share);
278
+        $manager->expects($this->once())->method('promoteReshares')->with($share);
279
+
280
+        $this->defaultProvider
281
+            ->expects($this->once())
282
+            ->method('delete')
283
+            ->with($share);
284
+
285
+        $calls = [
286
+            BeforeShareDeletedEvent::class,
287
+            ShareDeletedEvent::class,
288
+        ];
289
+        $this->dispatcher->expects($this->exactly(2))
290
+            ->method('dispatchTyped')
291
+            ->willReturnCallback(function ($event) use (&$calls, $share): void {
292
+                $expected = array_shift($calls);
293
+                $this->assertInstanceOf($expected, $event);
294
+                $this->assertEquals($share, $event->getShare());
295
+            });
296
+
297
+        $manager->deleteShare($share);
298
+    }
299
+
300
+    public function testDeleteNested(): void {
301
+        $manager = $this->createManagerMock()
302
+            ->onlyMethods(['getShareById', 'promoteReshares'])
303
+            ->getMock();
304
+
305
+        $path = $this->createMock(File::class);
306
+        $path->method('getId')->willReturn(1);
307
+
308
+        $share1 = $this->manager->newShare();
309
+        $share1->setId(42)
310
+            ->setProviderId('prov')
311
+            ->setShareType(IShare::TYPE_USER)
312
+            ->setSharedWith('sharedWith1')
313
+            ->setSharedBy('sharedBy1')
314
+            ->setNode($path)
315
+            ->setTarget('myTarget1');
316
+
317
+        $share2 = $this->manager->newShare();
318
+        $share2->setId(43)
319
+            ->setProviderId('prov')
320
+            ->setShareType(IShare::TYPE_GROUP)
321
+            ->setSharedWith('sharedWith2')
322
+            ->setSharedBy('sharedBy2')
323
+            ->setNode($path)
324
+            ->setTarget('myTarget2')
325
+            ->setParent(42);
326
+
327
+        $share3 = $this->manager->newShare();
328
+        $share3->setId(44)
329
+            ->setProviderId('prov')
330
+            ->setShareType(IShare::TYPE_LINK)
331
+            ->setSharedBy('sharedBy3')
332
+            ->setNode($path)
333
+            ->setTarget('myTarget3')
334
+            ->setParent(43);
335
+
336
+        $this->defaultProvider
337
+            ->method('getChildren')
338
+            ->willReturnMap([
339
+                [$share1, [$share2]],
340
+                [$share2, [$share3]],
341
+                [$share3, []],
342
+            ]);
343
+
344
+        $deleteCalls = [
345
+            $share3,
346
+            $share2,
347
+            $share1,
348
+        ];
349
+        $this->defaultProvider->expects($this->exactly(3))
350
+            ->method('delete')
351
+            ->willReturnCallback(function ($share) use (&$deleteCalls): void {
352
+                $expected = array_shift($deleteCalls);
353
+                $this->assertEquals($expected, $share);
354
+            });
355
+
356
+        $dispatchCalls = [
357
+            [BeforeShareDeletedEvent::class, $share1],
358
+            [BeforeShareDeletedEvent::class, $share2],
359
+            [BeforeShareDeletedEvent::class, $share3],
360
+            [ShareDeletedEvent::class, $share3],
361
+            [ShareDeletedEvent::class, $share2],
362
+            [ShareDeletedEvent::class, $share1],
363
+        ];
364
+        $this->dispatcher->expects($this->exactly(6))
365
+            ->method('dispatchTyped')
366
+            ->willReturnCallback(function ($event) use (&$dispatchCalls): void {
367
+                $expected = array_shift($dispatchCalls);
368
+                $this->assertInstanceOf($expected[0], $event);
369
+                $this->assertEquals($expected[1]->getId(), $event->getShare()->getId());
370
+            });
371
+
372
+        $manager->deleteShare($share1);
373
+    }
374
+
375
+    public function testDeleteFromSelf(): void {
376
+        $manager = $this->createManagerMock()
377
+            ->onlyMethods(['getShareById'])
378
+            ->getMock();
379
+
380
+        $recipientId = 'unshareFrom';
381
+        $share = $this->manager->newShare();
382
+        $share->setId(42)
383
+            ->setProviderId('prov')
384
+            ->setShareType(IShare::TYPE_USER)
385
+            ->setSharedWith('sharedWith')
386
+            ->setSharedBy('sharedBy')
387
+            ->setShareOwner('shareOwner')
388
+            ->setTarget('myTarget')
389
+            ->setNodeId(1)
390
+            ->setNodeType('file');
391
+
392
+        $this->defaultProvider
393
+            ->expects($this->once())
394
+            ->method('deleteFromSelf')
395
+            ->with($share, $recipientId);
396
+
397
+        $this->dispatcher->expects($this->once())
398
+            ->method('dispatchTyped')
399
+            ->with(
400
+                $this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) {
401
+                    return $e->getShare() === $share;
402
+                })
403
+            );
404
+
405
+        $manager->deleteFromSelf($share, $recipientId);
406
+    }
407
+
408
+    public function testDeleteChildren(): void {
409
+        $manager = $this->createManagerMock()
410
+            ->onlyMethods(['deleteShare'])
411
+            ->getMock();
412
+
413
+        $share = $this->createMock(IShare::class);
414
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
415
+
416
+        $child1 = $this->createMock(IShare::class);
417
+        $child1->method('getShareType')->willReturn(IShare::TYPE_USER);
418
+        $child2 = $this->createMock(IShare::class);
419
+        $child2->method('getShareType')->willReturn(IShare::TYPE_USER);
420
+        $child3 = $this->createMock(IShare::class);
421
+        $child3->method('getShareType')->willReturn(IShare::TYPE_USER);
422
+
423
+        $shares = [
424
+            $child1,
425
+            $child2,
426
+            $child3,
427
+        ];
428
+
429
+        $this->defaultProvider
430
+            ->expects($this->exactly(4))
431
+            ->method('getChildren')
432
+            ->willReturnCallback(function ($_share) use ($share, $shares) {
433
+                if ($_share === $share) {
434
+                    return $shares;
435
+                }
436
+                return [];
437
+            });
438
+
439
+        $calls = [
440
+            $child1,
441
+            $child2,
442
+            $child3,
443
+        ];
444
+        $this->defaultProvider->expects($this->exactly(3))
445
+            ->method('delete')
446
+            ->willReturnCallback(function ($share) use (&$calls): void {
447
+                $expected = array_shift($calls);
448
+                $this->assertEquals($expected, $share);
449
+            });
450
+
451
+        $result = self::invokePrivate($manager, 'deleteChildren', [$share]);
452
+        $this->assertSame($shares, $result);
453
+    }
454
+
455
+    public function testPromoteReshareFile(): void {
456
+        $manager = $this->createManagerMock()
457
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
458
+            ->getMock();
459
+
460
+        $file = $this->createMock(File::class);
461
+
462
+        $share = $this->createMock(IShare::class);
463
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
464
+        $share->method('getNodeType')->willReturn('folder');
465
+        $share->method('getSharedWith')->willReturn('userB');
466
+        $share->method('getNode')->willReturn($file);
467
+
468
+        $reShare = $this->createMock(IShare::class);
469
+        $reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
470
+        $reShare->method('getSharedBy')->willReturn('userB');
471
+        $reShare->method('getSharedWith')->willReturn('userC');
472
+        $reShare->method('getNode')->willReturn($file);
473
+
474
+        $this->defaultProvider->method('getSharesBy')
475
+            ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) {
476
+                $this->assertEquals($file, $node);
477
+                if ($shareType === IShare::TYPE_USER) {
478
+                    return match($userId) {
479
+                        'userB' => [$reShare],
480
+                    };
481
+                } else {
482
+                    return [];
483
+                }
484
+            });
485
+        $manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
486
+
487
+        $manager->expects($this->exactly(1))->method('updateShare')->with($reShare)->willReturn($reShare);
488
+
489
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
490
+    }
491
+
492
+    public function testPromoteReshare(): void {
493
+        $manager = $this->createManagerMock()
494
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
495
+            ->getMock();
496
+
497
+        $folder = $this->createFolderMock('/path/to/folder');
498
+
499
+        $subFolder = $this->createFolderMock('/path/to/folder/sub');
500
+
501
+        $otherFolder = $this->createFolderMock('/path/to/otherfolder/');
502
+
503
+        $share = $this->createMock(IShare::class);
504
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
505
+        $share->method('getNodeType')->willReturn('folder');
506
+        $share->method('getSharedWith')->willReturn('userB');
507
+        $share->method('getNode')->willReturn($folder);
508
+
509
+        $reShare = $this->createMock(IShare::class);
510
+        $reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
511
+        $reShare->method('getSharedBy')->willReturn('userB');
512
+        $reShare->method('getSharedWith')->willReturn('userC');
513
+        $reShare->method('getNode')->willReturn($folder);
514
+
515
+        $reShareInSubFolder = $this->createMock(IShare::class);
516
+        $reShareInSubFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
517
+        $reShareInSubFolder->method('getSharedBy')->willReturn('userB');
518
+        $reShareInSubFolder->method('getNode')->willReturn($subFolder);
519
+
520
+        $reShareInOtherFolder = $this->createMock(IShare::class);
521
+        $reShareInOtherFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
522
+        $reShareInOtherFolder->method('getSharedBy')->willReturn('userB');
523
+        $reShareInOtherFolder->method('getNode')->willReturn($otherFolder);
524
+
525
+        $this->defaultProvider->method('getSharesBy')
526
+            ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) {
527
+                if ($shareType === IShare::TYPE_USER) {
528
+                    return match($userId) {
529
+                        'userB' => [$reShare,$reShareInSubFolder,$reShareInOtherFolder],
530
+                    };
531
+                } else {
532
+                    return [];
533
+                }
534
+            });
535
+        $manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
536
+
537
+        $calls = [
538
+            $reShare,
539
+            $reShareInSubFolder,
540
+        ];
541
+        $manager->expects($this->exactly(2))
542
+            ->method('updateShare')
543
+            ->willReturnCallback(function ($share) use (&$calls): IShare {
544
+                $expected = array_shift($calls);
545
+                $this->assertEquals($expected, $share);
546
+                return $expected;
547
+            });
548
+
549
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
550
+    }
551
+
552
+    public function testPromoteReshareWhenUserHasAnotherShare(): void {
553
+        $manager = $this->createManagerMock()
554
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
555
+            ->getMock();
556
+
557
+        $folder = $this->createFolderMock('/path/to/folder');
558
+
559
+        $share = $this->createMock(IShare::class);
560
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
561
+        $share->method('getNodeType')->willReturn('folder');
562
+        $share->method('getSharedWith')->willReturn('userB');
563
+        $share->method('getNode')->willReturn($folder);
564
+
565
+        $reShare = $this->createMock(IShare::class);
566
+        $reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
567
+        $reShare->method('getNodeType')->willReturn('folder');
568
+        $reShare->method('getSharedBy')->willReturn('userB');
569
+        $reShare->method('getNode')->willReturn($folder);
570
+
571
+        $this->defaultProvider->method('getSharesBy')->willReturn([$reShare]);
572
+        $manager->method('generalCreateChecks');
573
+
574
+        /* No share is promoted because generalCreateChecks does not throw */
575
+        $manager->expects($this->never())->method('updateShare');
576
+
577
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
578
+    }
579
+
580
+    public function testPromoteReshareOfUsersInGroupShare(): void {
581
+        $manager = $this->createManagerMock()
582
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
583
+            ->getMock();
584
+
585
+        $folder = $this->createFolderMock('/path/to/folder');
586
+
587
+        $userA = $this->createMock(IUser::class);
588
+        $userA->method('getUID')->willReturn('userA');
589
+
590
+        $share = $this->createMock(IShare::class);
591
+        $share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
592
+        $share->method('getNodeType')->willReturn('folder');
593
+        $share->method('getSharedWith')->willReturn('Group');
594
+        $share->method('getNode')->willReturn($folder);
595
+        $share->method('getShareOwner')->willReturn($userA);
596
+
597
+        $reShare1 = $this->createMock(IShare::class);
598
+        $reShare1->method('getShareType')->willReturn(IShare::TYPE_USER);
599
+        $reShare1->method('getNodeType')->willReturn('folder');
600
+        $reShare1->method('getSharedBy')->willReturn('userB');
601
+        $reShare1->method('getNode')->willReturn($folder);
602
+
603
+        $reShare2 = $this->createMock(IShare::class);
604
+        $reShare2->method('getShareType')->willReturn(IShare::TYPE_USER);
605
+        $reShare2->method('getNodeType')->willReturn('folder');
606
+        $reShare2->method('getSharedBy')->willReturn('userC');
607
+        $reShare2->method('getNode')->willReturn($folder);
608
+
609
+        $userB = $this->createMock(IUser::class);
610
+        $userB->method('getUID')->willReturn('userB');
611
+        $userC = $this->createMock(IUser::class);
612
+        $userC->method('getUID')->willReturn('userC');
613
+        $group = $this->createMock(IGroup::class);
614
+        $group->method('getUsers')->willReturn([$userB, $userC]);
615
+        $this->groupManager->method('get')->with('Group')->willReturn($group);
616
+
617
+        $this->defaultProvider->method('getSharesBy')
618
+            ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) {
619
+                if ($shareType === IShare::TYPE_USER) {
620
+                    return match($userId) {
621
+                        'userB' => [$reShare1],
622
+                        'userC' => [$reShare2],
623
+                    };
624
+                } else {
625
+                    return [];
626
+                }
627
+            });
628
+        $manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
629
+
630
+        $manager->method('getSharedWith')->willReturn([]);
631
+
632
+        $calls = [
633
+            $reShare1,
634
+            $reShare2,
635
+        ];
636
+        $manager->expects($this->exactly(2))
637
+            ->method('updateShare')
638
+            ->willReturnCallback(function ($share) use (&$calls): IShare {
639
+                $expected = array_shift($calls);
640
+                $this->assertEquals($expected, $share);
641
+                return $expected;
642
+            });
643
+
644
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
645
+    }
646
+
647
+    public function testGetShareById(): void {
648
+        $share = $this->createMock(IShare::class);
649
+
650
+        $this->defaultProvider
651
+            ->expects($this->once())
652
+            ->method('getShareById')
653
+            ->with(42)
654
+            ->willReturn($share);
655
+
656
+        $this->assertEquals($share, $this->manager->getShareById('default:42'));
657
+    }
658
+
659
+
660
+    public function testGetExpiredShareById(): void {
661
+        $this->expectException(ShareNotFound::class);
662
+
663
+        $manager = $this->createManagerMock()
664
+            ->onlyMethods(['deleteShare'])
665
+            ->getMock();
666
+
667
+        $date = new \DateTime();
668
+        $date->setTime(0, 0, 0);
669
+
670
+        $share = $this->manager->newShare();
671
+        $share->setExpirationDate($date)
672
+            ->setShareType(IShare::TYPE_LINK);
673
+
674
+        $this->defaultProvider->expects($this->once())
675
+            ->method('getShareById')
676
+            ->with('42')
677
+            ->willReturn($share);
678
+
679
+        $manager->expects($this->once())
680
+            ->method('deleteShare')
681
+            ->with($share);
682
+
683
+        $manager->getShareById('default:42');
684
+    }
685
+
686
+
687
+    public function testVerifyPasswordNullButEnforced(): void {
688
+        $this->expectException(\InvalidArgumentException::class);
689
+        $this->expectExceptionMessage('Passwords are enforced for link and mail shares');
690
+
691
+        $this->config->method('getAppValue')->willReturnMap([
692
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
693
+        ]);
694
+
695
+        $this->appConfig->method('getValueBool')->willReturnMap([
696
+            ['core', 'shareapi_enforce_links_password', true],
697
+        ]);
698
+
699
+        self::invokePrivate($this->manager, 'verifyPassword', [null]);
700
+    }
701
+
702
+    public function testVerifyPasswordNotEnforcedGroup(): void {
703
+        $this->config->method('getAppValue')->willReturnMap([
704
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin"]'],
705
+            ['core', 'shareapi_enforce_links_password', 'no', 'yes'],
706
+        ]);
707
+
708
+        // Create admin user
709
+        $user = $this->createMock(IUser::class);
710
+        $this->userSession->method('getUser')->willReturn($user);
711
+        $this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['admin']);
712
+
713
+        $result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
714
+        $this->assertNull($result);
715
+    }
716
+
717
+    public function testVerifyPasswordNotEnforcedMultipleGroups(): void {
718
+        $this->config->method('getAppValue')->willReturnMap([
719
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin", "special"]'],
720
+            ['core', 'shareapi_enforce_links_password', 'no', 'yes'],
721
+        ]);
722
+
723
+        // Create admin user
724
+        $user = $this->createMock(IUser::class);
725
+        $this->userSession->method('getUser')->willReturn($user);
726
+        $this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['special']);
727
+
728
+        $result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
729
+        $this->assertNull($result);
730
+    }
731
+
732
+    public function testVerifyPasswordNull(): void {
733
+        $this->config->method('getAppValue')->willReturnMap([
734
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
735
+            ['core', 'shareapi_enforce_links_password', 'no', 'no'],
736
+        ]);
737
+
738
+        $result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
739
+        $this->assertNull($result);
740
+    }
741
+
742
+    public function testVerifyPasswordHook(): void {
743
+        $this->config->method('getAppValue')->willReturnMap([
744
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
745
+            ['core', 'shareapi_enforce_links_password', 'no', 'no'],
746
+        ]);
747
+
748
+        $this->dispatcher->expects($this->once())->method('dispatchTyped')
749
+            ->willReturnCallback(function (Event $event): void {
750
+                $this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
751
+                /** @var ValidatePasswordPolicyEvent $event */
752
+                $this->assertSame('password', $event->getPassword());
753
+            }
754
+            );
755
+
756
+        $result = self::invokePrivate($this->manager, 'verifyPassword', ['password']);
757
+        $this->assertNull($result);
758
+    }
759
+
760
+
761
+    public function testVerifyPasswordHookFails(): void {
762
+        $this->expectException(\Exception::class);
763
+        $this->expectExceptionMessage('password not accepted');
764
+
765
+        $this->config->method('getAppValue')->willReturnMap([
766
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
767
+            ['core', 'shareapi_enforce_links_password', 'no', 'no'],
768
+        ]);
769
+
770
+        $this->dispatcher->expects($this->once())->method('dispatchTyped')
771
+            ->willReturnCallback(function (Event $event): void {
772
+                $this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
773
+                /** @var ValidatePasswordPolicyEvent $event */
774
+                $this->assertSame('password', $event->getPassword());
775
+                throw new HintException('password not accepted');
776
+            }
777
+            );
778
+
779
+        self::invokePrivate($this->manager, 'verifyPassword', ['password']);
780
+    }
781
+
782
+    public function createShare($id, int $type, ?Node $node, $sharedWith, $sharedBy, $shareOwner,
783
+        $permissions, $expireDate = null, $password = null, $attributes = null): IShare&MockObject {
784
+        $share = $this->createMock(IShare::class);
785
+
786
+        $share->method('getShareType')->willReturn($type);
787
+        $share->method('getSharedWith')->willReturn($sharedWith);
788
+        $share->method('getSharedBy')->willReturn($sharedBy);
789
+        $share->method('getShareOwner')->willReturn($shareOwner);
790
+        if ($node) {
791
+            $share->method('getNode')->willReturn($node);
792
+            if ($node->getId()) {
793
+                $share->method('getNodeId')->willReturn($node->getId());
794
+            }
795
+        } else {
796
+            $share->method('getNode')->willReturnCallback(function (): never {
797
+                throw new NotFoundException();
798
+            });
799
+        }
800
+        $share->method('getPermissions')->willReturn($permissions);
801
+        $share->method('getAttributes')->willReturn($attributes);
802
+        $share->method('getExpirationDate')->willReturn($expireDate);
803
+        $share->method('getPassword')->willReturn($password);
804
+
805
+        return $share;
806
+    }
807
+
808
+    public static function dataGeneralChecks(): array {
809
+        $user0 = 'user0';
810
+        $user2 = 'user1';
811
+        $group0 = 'group0';
812
+
813
+        $file = [
814
+            File::class,
815
+            [
816
+                'getId' => 108,
817
+            ],
818
+            'default',
819
+        ];
820
+
821
+        $node = [
822
+            Node::class,
823
+            [
824
+                'getId' => 108,
825
+            ],
826
+            'default',
827
+        ];
828
+
829
+        $data = [
830
+            [[null, IShare::TYPE_USER, $file, null, $user0, $user0, 31, null, null], 'Share recipient is not a valid user', true],
831
+            [[null, IShare::TYPE_USER, $file, $group0, $user0, $user0, 31, null, null], 'Share recipient is not a valid user', true],
832
+            [[null, IShare::TYPE_USER, $file, '[email protected]', $user0, $user0, 31, null, null], 'Share recipient is not a valid user', true],
833
+            [[null, IShare::TYPE_GROUP, $file, null, $user0, $user0, 31, null, null], 'Share recipient is not a valid group', true],
834
+            [[null, IShare::TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null], 'Share recipient is not a valid group', true],
835
+            [[null, IShare::TYPE_GROUP, $file, '[email protected]', $user0, $user0, 31, null, null], 'Share recipient is not a valid group', true],
836
+            [[null, IShare::TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null], 'Share recipient should be empty', true],
837
+            [[null, IShare::TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null], 'Share recipient should be empty', true],
838
+            [[null, IShare::TYPE_LINK, $file, '[email protected]', $user0, $user0, 31, null, null], 'Share recipient should be empty', true],
839
+            [[null, -1, $file, null, $user0, $user0, 31, null, null], 'Unknown share type', true],
840
+
841
+            [[null, IShare::TYPE_USER, $file, $user2, null, $user0, 31, null, null], 'Share initiator must be set', true],
842
+            [[null, IShare::TYPE_GROUP, $file, $group0, null, $user0, 31, null, null], 'Share initiator must be set', true],
843
+            [[null, IShare::TYPE_LINK, $file, null, null, $user0, 31, null, null], 'Share initiator must be set', true],
844
+
845
+            [[null, IShare::TYPE_USER, $file, $user0, $user0, $user0, 31, null, null], 'Cannot share with yourself', true],
846
+
847
+            [[null, IShare::TYPE_USER, null, $user2, $user0, $user0, 31, null, null], 'Shared path must be set', true],
848
+            [[null, IShare::TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null], 'Shared path must be set', true],
849
+            [[null, IShare::TYPE_LINK, null, null, $user0, $user0, 31, null, null], 'Shared path must be set', true],
850
+
851
+            [[null, IShare::TYPE_USER, $node, $user2, $user0, $user0, 31, null, null], 'Shared path must be either a file or a folder', true],
852
+            [[null, IShare::TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null], 'Shared path must be either a file or a folder', true],
853
+            [[null, IShare::TYPE_LINK, $node, null, $user0, $user0, 31, null, null], 'Shared path must be either a file or a folder', true],
854
+        ];
855
+
856
+        $nonShareAble = [
857
+            Folder::class,
858
+            [
859
+                'getId' => 108,
860
+                'isShareable' => false,
861
+                'getPath' => 'path',
862
+                'getName' => 'name',
863
+                'getOwner' => $user0,
864
+            ],
865
+            'default',
866
+        ];
867
+
868
+        $data[] = [[null, IShare::TYPE_USER, $nonShareAble, $user2, $user0, $user0, 31, null, null], 'You are not allowed to share name', true];
869
+        $data[] = [[null, IShare::TYPE_GROUP, $nonShareAble, $group0, $user0, $user0, 31, null, null], 'You are not allowed to share name', true];
870
+        $data[] = [[null, IShare::TYPE_LINK, $nonShareAble, null, $user0, $user0, 31, null, null], 'You are not allowed to share name', true];
871
+
872
+        $limitedPermssions = [
873
+            File::class,
874
+            [
875
+                'isShareable' => true,
876
+                'getPermissions' => Constants::PERMISSION_READ,
877
+                'getId' => 108,
878
+                'getPath' => 'path',
879
+                'getName' => 'name',
880
+                'getOwner' => $user0,
881
+            ],
882
+            'default',
883
+        ];
884
+
885
+        $data[] = [[null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null], 'Valid permissions are required for sharing', true];
886
+        $data[] = [[null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null], 'Valid permissions are required for sharing', true];
887
+        $data[] = [[null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null], 'Valid permissions are required for sharing', true];
888
+
889
+        $limitedPermssions[1]['getMountPoint'] = MoveableMount::class;
890
+
891
+        // increase permissions of a re-share
892
+        $data[] = [[null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null], 'Cannot increase permissions of path', true];
893
+        $data[] = [[null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 3, null, null], 'Cannot increase permissions of path', true];
894
+
895
+        $nonMoveableMountPermssions = [
896
+            Folder::class,
897
+            [
898
+                'isShareable' => true,
899
+                'getPermissions' => Constants::PERMISSION_READ,
900
+                'getId' => 108,
901
+                'getPath' => 'path',
902
+                'getName' => 'name',
903
+                'getInternalPath' => '',
904
+                'getOwner' => $user0,
905
+            ],
906
+            'allPermssions',
907
+        ];
908
+
909
+        $data[] = [[null, IShare::TYPE_USER, $nonMoveableMountPermssions, $user2, $user0, $user0, 11, null, null], 'Cannot increase permissions of path', false];
910
+        $data[] = [[null, IShare::TYPE_GROUP, $nonMoveableMountPermssions, $group0, $user0, $user0, 11, null, null], 'Cannot increase permissions of path', false];
911
+
912
+        $rootFolder = [
913
+            Folder::class,
914
+            [
915
+                'isShareable' => true,
916
+                'getPermissions' => Constants::PERMISSION_ALL,
917
+                'getId' => 42,
918
+            ],
919
+            'none',
920
+        ];
921
+
922
+        $data[] = [[null, IShare::TYPE_USER, $rootFolder, $user2, $user0, $user0, 30, null, null], 'You cannot share your root folder', true];
923
+        $data[] = [[null, IShare::TYPE_GROUP, $rootFolder, $group0, $user0, $user0, 2, null, null], 'You cannot share your root folder', true];
924
+        $data[] = [[null, IShare::TYPE_LINK, $rootFolder, null, $user0, $user0, 16, null, null], 'You cannot share your root folder', true];
925
+
926
+        $allPermssionsFiles = [
927
+            File::class,
928
+            [
929
+                'isShareable' => true,
930
+                'getPermissions' => Constants::PERMISSION_ALL,
931
+                'getId' => 187,
932
+                'getOwner' => $user0,
933
+            ],
934
+            'default',
935
+        ];
936
+
937
+        // test invalid CREATE or DELETE permissions
938
+        $data[] = [[null, IShare::TYPE_USER, $allPermssionsFiles, $user2, $user0, $user0, Constants::PERMISSION_ALL, null, null], 'File shares cannot have create or delete permissions', true];
939
+        $data[] = [[null, IShare::TYPE_GROUP, $allPermssionsFiles, $group0, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_CREATE, null, null], 'File shares cannot have create or delete permissions', true];
940
+        $data[] = [[null, IShare::TYPE_LINK, $allPermssionsFiles, null, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_DELETE, null, null], 'File shares cannot have create or delete permissions', true];
941
+
942
+        $allPermssions = [
943
+            Folder::class,
944
+            [
945
+                'isShareable' => true,
946
+                'getPermissions' => Constants::PERMISSION_ALL,
947
+                'getId' => 108,
948
+                'getOwner' => $user0,
949
+            ],
950
+            'default',
951
+        ];
952
+
953
+        $data[] = [[null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null], 'Shares need at least read permissions', true];
954
+        $data[] = [[null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null], 'Shares need at least read permissions', true];
955
+
956
+        // test invalid permissions
957
+        $data[] = [[null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 32, null, null], 'Valid permissions are required for sharing', true];
958
+        $data[] = [[null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 63, null, null], 'Valid permissions are required for sharing', true];
959
+        $data[] = [[null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, -1, null, null], 'Valid permissions are required for sharing', true];
960
+
961
+        // working shares
962
+        $data[] = [[null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null], null, false];
963
+        $data[] = [[null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null], null, false];
964
+        $data[] = [[null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null], null, false];
965
+
966
+        $remoteFile = [
967
+            Folder::class,
968
+            [
969
+                'isShareable' => true,
970
+                'getPermissions' => Constants::PERMISSION_READ ^ Constants::PERMISSION_UPDATE,
971
+                'getId' => 108,
972
+                'getOwner' => $user0,
973
+            ],
974
+            'remote',
975
+        ];
976
+
977
+        $data[] = [[null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 1, null, null], null, false];
978
+        $data[] = [[null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 3, null, null], null, false];
979
+        $data[] = [[null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 31, null, null], 'Cannot increase permissions of ', true];
980
+
981
+        return $data;
982
+    }
983
+
984
+    private function createNodeMock(string $class, array $methods, string $storageType): MockObject {
985
+        $mock = $this->createMock($class);
986
+        foreach ($methods as $methodName => $return) {
987
+            if ($methodName === 'getOwner') {
988
+                $uid = $return;
989
+                $return = $this->createMock(IUser::class);
990
+                $return->method('getUID')
991
+                    ->willReturn($uid);
992
+            } elseif ($methodName === 'getMountPoint') {
993
+                $return = $this->createMock($return);
994
+            }
995
+            $mock->method($methodName)->willReturn($return);
996
+        }
997
+        switch ($storageType) {
998
+            case 'default':
999
+                $storage = $this->createMock(IStorage::class);
1000
+                $storage->method('instanceOfStorage')
1001
+                    ->with('\OCA\Files_Sharing\External\Storage')
1002
+                    ->willReturn(false);
1003
+                break;
1004
+            case 'allPermssions':
1005
+                $storage = $this->createMock(IStorage::class);
1006
+                $storage->method('instanceOfStorage')
1007
+                    ->with('\OCA\Files_Sharing\External\Storage')
1008
+                    ->willReturn(false);
1009
+                $storage->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
1010
+                break;
1011
+            case 'none':
1012
+                $storage = false;
1013
+                break;
1014
+            case 'remote':
1015
+                $storage = $this->createMock(IStorage::class);
1016
+                $storage->method('instanceOfStorage')
1017
+                    ->with('\OCA\Files_Sharing\External\Storage')
1018
+                    ->willReturn(true);
1019
+                break;
1020
+            default:
1021
+                throw new \Exception('Unknown storage type ' . $storageType);
1022
+        }
1023
+        if ($storage === false) {
1024
+            $mock->expects(self::never())->method('getStorage');
1025
+        } else {
1026
+            $mock->method('getStorage')
1027
+                ->willReturn($storage);
1028
+        }
1029
+
1030
+        return $mock;
1031
+    }
1032
+
1033
+    #[DataProvider('dataGeneralChecks')]
1034
+    public function testGeneralChecks(array $shareParams, ?string $exceptionMessage, bool $exception): void {
1035
+        if ($shareParams[2] !== null) {
1036
+            $shareParams[2] = $this->createNodeMock(...$shareParams[2]);
1037
+        }
1038
+        $share = $this->createShare(...$shareParams);
1039
+
1040
+        $thrown = null;
1041
+
1042
+        $this->userManager->method('userExists')->willReturnMap([
1043
+            ['user0', true],
1044
+            ['user1', true],
1045
+        ]);
1046
+
1047
+        $this->groupManager->method('groupExists')->willReturnMap([
1048
+            ['group0', true],
1049
+        ]);
1050
+
1051
+        $userFolder = $this->createMock(Folder::class);
1052
+        $userFolder->expects($this->any())
1053
+            ->method('getId')
1054
+            ->willReturn(42);
1055
+        // Id 108 is used in the data to refer to the node of the share.
1056
+        try {
1057
+            $node = $share->getNode();
1058
+            $userFolder->method('getById')
1059
+                ->with(108)
1060
+                ->willReturn([$node]);
1061
+        } catch (NotFoundException $e) {
1062
+            $userFolder->method('getById')
1063
+                ->with(108)
1064
+                ->willReturn([]);
1065
+        }
1066
+        $userFolder->expects($this->any())
1067
+            ->method('getRelativePath')
1068
+            ->willReturnArgument(0);
1069
+        $this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1070
+
1071
+
1072
+        try {
1073
+            self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1074
+            $thrown = false;
1075
+        } catch (GenericShareException $e) {
1076
+            $this->assertEquals($exceptionMessage, $e->getHint());
1077
+            $thrown = true;
1078
+        } catch (\InvalidArgumentException $e) {
1079
+            $this->assertEquals($exceptionMessage, $e->getMessage());
1080
+            $thrown = true;
1081
+        }
1082
+
1083
+        $this->assertSame($exception, $thrown);
1084
+    }
1085
+
1086
+
1087
+    public function testGeneralCheckShareRoot(): void {
1088
+        $this->expectException(\InvalidArgumentException::class);
1089
+        $this->expectExceptionMessage('You cannot share your root folder');
1090
+
1091
+        $this->userManager->method('userExists')->willReturnMap([
1092
+            ['user0', true],
1093
+            ['user1', true],
1094
+        ]);
1095
+
1096
+        $userFolder = $this->createMock(Folder::class);
1097
+        $userFolder->method('isSubNode')->with($userFolder)->willReturn(false);
1098
+        $this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1099
+
1100
+        $share = $this->manager->newShare();
1101
+
1102
+        $share->setShareType(IShare::TYPE_USER)
1103
+            ->setSharedWith('user0')
1104
+            ->setSharedBy('user1')
1105
+            ->setNode($userFolder);
1106
+
1107
+        self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1108
+    }
1109
+
1110
+    public static function validateExpirationDateInternalProvider() {
1111
+        return [[IShare::TYPE_USER], [IShare::TYPE_REMOTE], [IShare::TYPE_REMOTE_GROUP]];
1112
+    }
1113
+
1114
+    #[DataProvider('validateExpirationDateInternalProvider')]
1115
+    public function testValidateExpirationDateInternalInPast($shareType): void {
1116
+        $this->expectException(GenericShareException::class);
1117
+        $this->expectExceptionMessage('Expiration date is in the past');
1118
+
1119
+        // Expire date in the past
1120
+        $past = new \DateTime();
1121
+        $past->sub(new \DateInterval('P1D'));
1122
+
1123
+        $share = $this->manager->newShare();
1124
+        $share->setShareType($shareType);
1125
+        $share->setExpirationDate($past);
1126
+
1127
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1128
+    }
1129
+
1130
+    #[DataProvider('validateExpirationDateInternalProvider')]
1131
+    public function testValidateExpirationDateInternalEnforceButNotSet($shareType): void {
1132
+        $this->expectException(\InvalidArgumentException::class);
1133
+        $this->expectExceptionMessage('Expiration date is enforced');
1134
+
1135
+        $share = $this->manager->newShare();
1136
+        $share->setProviderId('foo')->setId('bar');
1137
+        $share->setShareType($shareType);
1138
+        if ($shareType === IShare::TYPE_USER) {
1139
+            $this->config->method('getAppValue')
1140
+                ->willReturnMap([
1141
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1142
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1143
+                ]);
1144
+        } else {
1145
+            $this->config->method('getAppValue')
1146
+                ->willReturnMap([
1147
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1148
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1149
+                ]);
1150
+        }
1151
+
1152
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1153
+    }
1154
+
1155
+    #[DataProvider('validateExpirationDateInternalProvider')]
1156
+    public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType): void {
1157
+        $share = $this->manager->newShare();
1158
+        $share->setProviderId('foo')->setId('bar');
1159
+        $share->setShareType($shareType);
1160
+
1161
+        if ($shareType === IShare::TYPE_USER) {
1162
+            $this->config->method('getAppValue')
1163
+                ->willReturnMap([
1164
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1165
+                ]);
1166
+        } else {
1167
+            $this->config->method('getAppValue')
1168
+                ->willReturnMap([
1169
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1170
+                ]);
1171
+        }
1172
+
1173
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1174
+
1175
+        $this->assertNull($share->getExpirationDate());
1176
+    }
1177
+
1178
+    #[DataProvider('validateExpirationDateInternalProvider')]
1179
+    public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType): void {
1180
+        $share = $this->manager->newShare();
1181
+        $share->setShareType($shareType);
1182
+
1183
+        if ($shareType === IShare::TYPE_USER) {
1184
+            $this->config->method('getAppValue')
1185
+                ->willReturnMap([
1186
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1187
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1188
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1189
+                    ['core', 'internal_defaultExpDays', '3', '3'],
1190
+                ]);
1191
+        } else {
1192
+            $this->config->method('getAppValue')
1193
+                ->willReturnMap([
1194
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1195
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1196
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1197
+                    ['core', 'remote_defaultExpDays', '3', '3'],
1198
+                ]);
1199
+        }
1200
+
1201
+        $expected = new \DateTime('now', $this->timezone);
1202
+        $expected->setTime(0, 0, 0);
1203
+        $expected->add(new \DateInterval('P3D'));
1204
+
1205
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1206
+
1207
+        $this->assertNotNull($share->getExpirationDate());
1208
+        $this->assertEquals($expected, $share->getExpirationDate());
1209
+    }
1210
+
1211
+    #[DataProvider('validateExpirationDateInternalProvider')]
1212
+    public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType): void {
1213
+        $share = $this->manager->newShare();
1214
+        $share->setShareType($shareType);
1215
+
1216
+        if ($shareType === IShare::TYPE_USER) {
1217
+            $this->config->method('getAppValue')
1218
+                ->willReturnMap([
1219
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1220
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1221
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1222
+                    ['core', 'internal_defaultExpDays', '3', '1'],
1223
+                ]);
1224
+        } else {
1225
+            $this->config->method('getAppValue')
1226
+                ->willReturnMap([
1227
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1228
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1229
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1230
+                    ['core', 'remote_defaultExpDays', '3', '1'],
1231
+                ]);
1232
+        }
1233
+
1234
+        $expected = new \DateTime('now', $this->timezone);
1235
+        $expected->setTime(0, 0, 0);
1236
+        $expected->add(new \DateInterval('P1D'));
1237
+
1238
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1239
+
1240
+        $this->assertNotNull($share->getExpirationDate());
1241
+        $this->assertEquals($expected, $share->getExpirationDate());
1242
+    }
1243
+
1244
+    #[DataProvider('validateExpirationDateInternalProvider')]
1245
+    public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType): void {
1246
+        $this->expectException(GenericShareException::class);
1247
+        $this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1248
+
1249
+        $future = new \DateTime();
1250
+        $future->add(new \DateInterval('P7D'));
1251
+
1252
+        $share = $this->manager->newShare();
1253
+        $share->setShareType($shareType);
1254
+        $share->setExpirationDate($future);
1255
+
1256
+        if ($shareType === IShare::TYPE_USER) {
1257
+            $this->config->method('getAppValue')
1258
+                ->willReturnMap([
1259
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1260
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1261
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1262
+                ]);
1263
+        } else {
1264
+            $this->config->method('getAppValue')
1265
+                ->willReturnMap([
1266
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1267
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1268
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1269
+                ]);
1270
+        }
1271
+
1272
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1273
+    }
1274
+
1275
+    #[DataProvider('validateExpirationDateInternalProvider')]
1276
+    public function testValidateExpirationDateInternalEnforceValid($shareType): void {
1277
+        $future = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1278
+        $future->add(new \DateInterval('P2D'));
1279
+        $future->setTime(1, 2, 3);
1280
+
1281
+        $expected = clone $future;
1282
+        $expected->setTime(0, 0, 0);
1283
+
1284
+        $share = $this->manager->newShare();
1285
+        $share->setShareType($shareType);
1286
+        $share->setExpirationDate($future);
1287
+
1288
+        if ($shareType === IShare::TYPE_USER) {
1289
+            $this->config->method('getAppValue')
1290
+                ->willReturnMap([
1291
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1292
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1293
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1294
+                ]);
1295
+        } else {
1296
+            $this->config->method('getAppValue')
1297
+                ->willReturnMap([
1298
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1299
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1300
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1301
+                ]);
1302
+        }
1303
+
1304
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1305
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1306
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1307
+            return $data['expirationDate'] == $future;
1308
+        }));
1309
+
1310
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1311
+
1312
+        $this->assertEquals($expected, $share->getExpirationDate());
1313
+    }
1314
+
1315
+    #[DataProvider('validateExpirationDateInternalProvider')]
1316
+    public function testValidateExpirationDateInternalNoDefault($shareType): void {
1317
+        $date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1318
+        $date->add(new \DateInterval('P5D'));
1319
+        $date->setTime(1, 2, 3);
1320
+
1321
+        $expected = clone $date;
1322
+        $expected->setTime(0, 0, 0);
1323
+
1324
+        $share = $this->manager->newShare();
1325
+        $share->setShareType($shareType);
1326
+        $share->setExpirationDate($date);
1327
+
1328
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1329
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1330
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1331
+            return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1332
+        }));
1333
+
1334
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1335
+
1336
+        $this->assertEquals($expected, $share->getExpirationDate());
1337
+    }
1338
+
1339
+    #[DataProvider('validateExpirationDateInternalProvider')]
1340
+    public function testValidateExpirationDateInternalNoDateNoDefault($shareType): void {
1341
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1342
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1343
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1344
+            return $data['expirationDate'] === null && $data['passwordSet'] === true;
1345
+        }));
1346
+
1347
+        $share = $this->manager->newShare();
1348
+        $share->setShareType($shareType);
1349
+        $share->setPassword('password');
1350
+
1351
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1352
+
1353
+        $this->assertNull($share->getExpirationDate());
1354
+    }
1355
+
1356
+    #[DataProvider('validateExpirationDateInternalProvider')]
1357
+    public function testValidateExpirationDateInternalNoDateDefault($shareType): void {
1358
+        $share = $this->manager->newShare();
1359
+        $share->setShareType($shareType);
1360
+
1361
+        $expected = new \DateTime('now', $this->timezone);
1362
+        $expected->setTime(0, 0);
1363
+        $expected->add(new \DateInterval('P3D'));
1364
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1365
+
1366
+        if ($shareType === IShare::TYPE_USER) {
1367
+            $this->config->method('getAppValue')
1368
+                ->willReturnMap([
1369
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1370
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1371
+                    ['core', 'internal_defaultExpDays', '3', '3'],
1372
+                ]);
1373
+        } else {
1374
+            $this->config->method('getAppValue')
1375
+                ->willReturnMap([
1376
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1377
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1378
+                    ['core', 'remote_defaultExpDays', '3', '3'],
1379
+                ]);
1380
+        }
1381
+
1382
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1383
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1384
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1385
+            return $data['expirationDate'] == $expected;
1386
+        }));
1387
+
1388
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1389
+
1390
+        $this->assertEquals($expected, $share->getExpirationDate());
1391
+    }
1392
+
1393
+    #[DataProvider('validateExpirationDateInternalProvider')]
1394
+    public function testValidateExpirationDateInternalDefault($shareType): void {
1395
+        $future = new \DateTime('now', $this->timezone);
1396
+        $future->add(new \DateInterval('P5D'));
1397
+        $future->setTime(1, 2, 3);
1398
+
1399
+        $expected = clone $future;
1400
+        $expected->setTime(0, 0);
1401
+
1402
+        $share = $this->manager->newShare();
1403
+        $share->setShareType($shareType);
1404
+        $share->setExpirationDate($future);
1405
+
1406
+        if ($shareType === IShare::TYPE_USER) {
1407
+            $this->config->method('getAppValue')
1408
+                ->willReturnMap([
1409
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1410
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1411
+                    ['core', 'internal_defaultExpDays', '3', '1'],
1412
+                ]);
1413
+        } else {
1414
+            $this->config->method('getAppValue')
1415
+                ->willReturnMap([
1416
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1417
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1418
+                    ['core', 'remote_defaultExpDays', '3', '1'],
1419
+                ]);
1420
+        }
1421
+
1422
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1423
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1424
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1425
+            return $data['expirationDate'] == $expected;
1426
+        }));
1427
+
1428
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1429
+
1430
+        $this->assertEquals($expected, $share->getExpirationDate());
1431
+    }
1432
+
1433
+    #[DataProvider('validateExpirationDateInternalProvider')]
1434
+    public function testValidateExpirationDateInternalHookModification($shareType): void {
1435
+        $nextWeek = new \DateTime('now', $this->timezone);
1436
+        $nextWeek->add(new \DateInterval('P7D'));
1437
+        $nextWeek->setTime(0, 0, 0);
1438
+
1439
+        $save = clone $nextWeek;
1440
+
1441
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1442
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1443
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1444
+            $data['expirationDate']->sub(new \DateInterval('P2D'));
1445
+        });
1446
+
1447
+        $share = $this->manager->newShare();
1448
+        $share->setShareType($shareType);
1449
+        $share->setExpirationDate($nextWeek);
1450
+
1451
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1452
+
1453
+        $save->sub(new \DateInterval('P2D'));
1454
+        $this->assertEquals($save, $share->getExpirationDate());
1455
+    }
1456
+
1457
+    #[DataProvider('validateExpirationDateInternalProvider')]
1458
+    public function testValidateExpirationDateInternalHookException($shareType): void {
1459
+        $this->expectException(\Exception::class);
1460
+        $this->expectExceptionMessage('Invalid date!');
1461
+
1462
+        $nextWeek = new \DateTime();
1463
+        $nextWeek->add(new \DateInterval('P7D'));
1464
+        $nextWeek->setTime(0, 0, 0);
1465
+
1466
+        $share = $this->manager->newShare();
1467
+        $share->setShareType($shareType);
1468
+        $share->setExpirationDate($nextWeek);
1469
+
1470
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1471
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1472
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1473
+            $data['accepted'] = false;
1474
+            $data['message'] = 'Invalid date!';
1475
+        });
1476
+
1477
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1478
+    }
1479
+
1480
+    #[DataProvider('validateExpirationDateInternalProvider')]
1481
+    public function testValidateExpirationDateInternalExistingShareNoDefault($shareType): void {
1482
+        $share = $this->manager->newShare();
1483
+        $share->setShareType($shareType);
1484
+        $share->setId('42')->setProviderId('foo');
1485
+
1486
+        if ($shareType === IShare::TYPE_USER) {
1487
+            $this->config->method('getAppValue')
1488
+                ->willReturnMap([
1489
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1490
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '6'],
1491
+                ]);
1492
+        } else {
1493
+            $this->config->method('getAppValue')
1494
+                ->willReturnMap([
1495
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1496
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '6'],
1497
+                ]);
1498
+        }
1499
+
1500
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1501
+
1502
+        $this->assertEquals(null, $share->getExpirationDate());
1503
+    }
1504
+
1505
+    public function testValidateExpirationDateInPast(): void {
1506
+        $this->expectException(GenericShareException::class);
1507
+        $this->expectExceptionMessage('Expiration date is in the past');
1508
+
1509
+        // Expire date in the past
1510
+        $past = new \DateTime();
1511
+        $past->sub(new \DateInterval('P1D'));
1512
+
1513
+        $share = $this->manager->newShare();
1514
+        $share->setExpirationDate($past);
1515
+
1516
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1517
+    }
1518
+
1519
+    public function testValidateExpirationDateEnforceButNotSet(): void {
1520
+        $this->expectException(\InvalidArgumentException::class);
1521
+        $this->expectExceptionMessage('Expiration date is enforced');
1522
+
1523
+        $share = $this->manager->newShare();
1524
+        $share->setProviderId('foo')->setId('bar');
1525
+
1526
+        $this->appConfig->method('getValueBool')
1527
+            ->willReturnMap([
1528
+                ['core', 'shareapi_default_expire_date', true],
1529
+                ['core', 'shareapi_enforce_expire_date', true],
1530
+            ]);
1531
+
1532
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1533
+    }
1534
+
1535
+    public function testValidateExpirationDateEnforceButNotEnabledAndNotSet(): void {
1536
+        $share = $this->manager->newShare();
1537
+        $share->setProviderId('foo')->setId('bar');
1538
+
1539
+        $this->config->method('getAppValue')
1540
+            ->willReturnMap([
1541
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1542
+            ]);
1543
+
1544
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1545
+
1546
+        $this->assertNull($share->getExpirationDate());
1547
+    }
1548
+
1549
+    public function testValidateExpirationDateEnforceButNotSetNewShare(): void {
1550
+        $share = $this->manager->newShare();
1551
+
1552
+        $this->config->method('getAppValue')
1553
+            ->willReturnMap([
1554
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1555
+                ['core', 'link_defaultExpDays', '3', '3'],
1556
+            ]);
1557
+
1558
+        $this->appConfig->method('getValueBool')
1559
+            ->willReturnMap([
1560
+                ['core', 'shareapi_default_expire_date', true],
1561
+                ['core', 'shareapi_enforce_expire_date', true],
1562
+            ]);
1563
+
1564
+        $expected = new \DateTime('now', $this->timezone);
1565
+        $expected->setTime(0, 0, 0);
1566
+        $expected->add(new \DateInterval('P3D'));
1567
+
1568
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1569
+
1570
+        $this->assertNotNull($share->getExpirationDate());
1571
+        $this->assertEquals($expected, $share->getExpirationDate());
1572
+    }
1573
+
1574
+    public function testValidateExpirationDateEnforceRelaxedDefaultButNotSetNewShare(): void {
1575
+        $share = $this->manager->newShare();
1576
+
1577
+        $this->config->method('getAppValue')
1578
+            ->willReturnMap([
1579
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1580
+                ['core', 'link_defaultExpDays', '3', '1'],
1581
+            ]);
1582
+
1583
+        $this->appConfig->method('getValueBool')
1584
+            ->willReturnMap([
1585
+                ['core', 'shareapi_default_expire_date', true],
1586
+                ['core', 'shareapi_enforce_expire_date', true],
1587
+            ]);
1588
+
1589
+        $expected = new \DateTime('now', $this->timezone);
1590
+        $expected->setTime(0, 0, 0);
1591
+        $expected->add(new \DateInterval('P1D'));
1592 1592
 
1593
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1593
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1594 1594
 
1595
-		$this->assertNotNull($share->getExpirationDate());
1596
-		$this->assertEquals($expected, $share->getExpirationDate());
1597
-	}
1595
+        $this->assertNotNull($share->getExpirationDate());
1596
+        $this->assertEquals($expected, $share->getExpirationDate());
1597
+    }
1598 1598
 
1599
-	public function testValidateExpirationDateEnforceTooFarIntoFuture(): void {
1600
-		$this->expectException(GenericShareException::class);
1601
-		$this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1599
+    public function testValidateExpirationDateEnforceTooFarIntoFuture(): void {
1600
+        $this->expectException(GenericShareException::class);
1601
+        $this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1602 1602
 
1603
-		$future = new \DateTime();
1604
-		$future->add(new \DateInterval('P7D'));
1603
+        $future = new \DateTime();
1604
+        $future->add(new \DateInterval('P7D'));
1605 1605
 
1606
-		$share = $this->manager->newShare();
1607
-		$share->setExpirationDate($future);
1606
+        $share = $this->manager->newShare();
1607
+        $share->setExpirationDate($future);
1608 1608
 
1609
-		$this->config->method('getAppValue')
1610
-			->willReturnMap([
1611
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1612
-			]);
1609
+        $this->config->method('getAppValue')
1610
+            ->willReturnMap([
1611
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1612
+            ]);
1613 1613
 
1614
-		$this->appConfig->method('getValueBool')
1615
-			->willReturnMap([
1616
-				['core', 'shareapi_default_expire_date', true],
1617
-				['core', 'shareapi_enforce_expire_date', true],
1618
-			]);
1619
-
1620
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1621
-	}
1614
+        $this->appConfig->method('getValueBool')
1615
+            ->willReturnMap([
1616
+                ['core', 'shareapi_default_expire_date', true],
1617
+                ['core', 'shareapi_enforce_expire_date', true],
1618
+            ]);
1619
+
1620
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1621
+    }
1622 1622
 
1623
-	public function testValidateExpirationDateEnforceValid(): void {
1624
-		$future = new \DateTime('now', $this->timezone);
1625
-		$future->add(new \DateInterval('P2D'));
1626
-		$future->setTime(1, 2, 3);
1627
-
1628
-		$expected = clone $future;
1629
-		$expected->setTime(0, 0, 0);
1623
+    public function testValidateExpirationDateEnforceValid(): void {
1624
+        $future = new \DateTime('now', $this->timezone);
1625
+        $future->add(new \DateInterval('P2D'));
1626
+        $future->setTime(1, 2, 3);
1627
+
1628
+        $expected = clone $future;
1629
+        $expected->setTime(0, 0, 0);
1630 1630
 
1631
-		$share = $this->manager->newShare();
1632
-		$share->setExpirationDate($future);
1631
+        $share = $this->manager->newShare();
1632
+        $share->setExpirationDate($future);
1633 1633
 
1634
-		$this->config->method('getAppValue')
1635
-			->willReturnMap([
1636
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1637
-			]);
1634
+        $this->config->method('getAppValue')
1635
+            ->willReturnMap([
1636
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1637
+            ]);
1638 1638
 
1639
-		$this->appConfig->method('getValueBool')
1640
-			->willReturnMap([
1641
-				['core', 'shareapi_default_expire_date', true],
1642
-				['core', 'shareapi_enforce_expire_date', true],
1643
-			]);
1644
-
1645
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1646
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1647
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1648
-			return $data['expirationDate'] == $future;
1649
-		}));
1650
-
1651
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1652
-
1653
-		$this->assertEquals($expected, $share->getExpirationDate());
1654
-	}
1655
-
1656
-	public function testValidateExpirationDateNoDefault(): void {
1657
-		$date = new \DateTime('now', $this->timezone);
1658
-		$date->add(new \DateInterval('P5D'));
1659
-		$date->setTime(1, 2, 3);
1660
-
1661
-		$expected = clone $date;
1662
-		$expected->setTime(0, 0);
1663
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1664
-
1665
-		$share = $this->manager->newShare();
1666
-		$share->setExpirationDate($date);
1667
-
1668
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1669
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1670
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1671
-			return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1672
-		}));
1673
-
1674
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1675
-
1676
-		$this->assertEquals($expected, $share->getExpirationDate());
1677
-	}
1678
-
1679
-	public function testValidateExpirationDateNoDateNoDefault(): void {
1680
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1681
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1682
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1683
-			return $data['expirationDate'] === null && $data['passwordSet'] === true;
1684
-		}));
1685
-
1686
-		$share = $this->manager->newShare();
1687
-		$share->setPassword('password');
1688
-
1689
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1690
-
1691
-		$this->assertNull($share->getExpirationDate());
1692
-	}
1693
-
1694
-	public function testValidateExpirationDateNoDateDefault(): void {
1695
-		$share = $this->manager->newShare();
1696
-
1697
-		$expected = new \DateTime('now', $this->timezone);
1698
-		$expected->add(new \DateInterval('P3D'));
1699
-		$expected->setTime(0, 0);
1700
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1701
-
1702
-		$this->config->method('getAppValue')
1703
-			->willReturnMap([
1704
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1705
-				['core', 'link_defaultExpDays', '3', '3'],
1706
-			]);
1707
-
1708
-		$this->appConfig->method('getValueBool')
1709
-			->willReturnMap([
1710
-				['core', 'shareapi_default_expire_date', true],
1711
-				['core', 'shareapi_enforce_expire_date', false],
1712
-			]);
1713
-
1714
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1715
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1716
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1717
-			return $data['expirationDate'] == $expected;
1718
-		}));
1719
-
1720
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1721
-
1722
-		$this->assertEquals($expected, $share->getExpirationDate());
1723
-	}
1724
-
1725
-	public function testValidateExpirationDateDefault(): void {
1726
-		$future = new \DateTime('now', $this->timezone);
1727
-		$future->add(new \DateInterval('P5D'));
1728
-		$future->setTime(1, 2, 3);
1729
-
1730
-		$expected = clone $future;
1731
-		$expected->setTime(0, 0);
1732
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1733
-
1734
-		$share = $this->manager->newShare();
1735
-		$share->setExpirationDate($future);
1736
-
1737
-		$this->config->method('getAppValue')
1738
-			->willReturnMap([
1739
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1740
-				['core', 'link_defaultExpDays', '3', '1'],
1741
-			]);
1742
-
1743
-		$this->appConfig->method('getValueBool')
1744
-			->willReturnMap([
1745
-				['core', 'shareapi_default_expire_date', true],
1746
-				['core', 'shareapi_enforce_expire_date', false],
1747
-			]);
1748
-
1749
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1750
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1751
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1752
-			return $data['expirationDate'] == $expected;
1753
-		}));
1754
-
1755
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1756
-
1757
-		$this->assertEquals($expected, $share->getExpirationDate());
1758
-	}
1759
-
1760
-	public function testValidateExpirationNegativeOffsetTimezone(): void {
1761
-		$this->timezone = new \DateTimeZone('Pacific/Tahiti');
1762
-		$future = new \DateTime();
1763
-		$future->add(new \DateInterval('P5D'));
1764
-
1765
-		$expected = clone $future;
1766
-		$expected->setTimezone($this->timezone);
1767
-		$expected->setTime(0, 0);
1768
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1769
-
1770
-		$share = $this->manager->newShare();
1771
-		$share->setExpirationDate($future);
1772
-
1773
-		$this->config->method('getAppValue')
1774
-			->willReturnMap([
1775
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1776
-				['core', 'link_defaultExpDays', '3', '1'],
1777
-			]);
1778
-
1779
-		$this->appConfig->method('getValueBool')
1780
-			->willReturnMap([
1781
-				['core', 'shareapi_default_expire_date', true],
1782
-				['core', 'shareapi_enforce_expire_date', false],
1783
-			]);
1784
-
1785
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1786
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1787
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1788
-			return $data['expirationDate'] == $expected;
1789
-		}));
1790
-
1791
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1792
-
1793
-		$this->assertEquals($expected, $share->getExpirationDate());
1794
-	}
1795
-
1796
-	public function testValidateExpirationDateHookModification(): void {
1797
-		$nextWeek = new \DateTime('now', $this->timezone);
1798
-		$nextWeek->add(new \DateInterval('P7D'));
1799
-
1800
-		$save = clone $nextWeek;
1801
-		$save->setTime(0, 0);
1802
-		$save->sub(new \DateInterval('P2D'));
1803
-		$save->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1804
-
1805
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1806
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1807
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1808
-			$data['expirationDate']->sub(new \DateInterval('P2D'));
1809
-		});
1810
-
1811
-		$share = $this->manager->newShare();
1812
-		$share->setExpirationDate($nextWeek);
1813
-
1814
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1815
-
1816
-		$this->assertEquals($save, $share->getExpirationDate());
1817
-	}
1818
-
1819
-	public function testValidateExpirationDateHookException(): void {
1820
-		$this->expectException(\Exception::class);
1821
-		$this->expectExceptionMessage('Invalid date!');
1822
-
1823
-		$nextWeek = new \DateTime();
1824
-		$nextWeek->add(new \DateInterval('P7D'));
1825
-		$nextWeek->setTime(0, 0, 0);
1826
-
1827
-		$share = $this->manager->newShare();
1828
-		$share->setExpirationDate($nextWeek);
1829
-
1830
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1831
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1832
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1833
-			$data['accepted'] = false;
1834
-			$data['message'] = 'Invalid date!';
1835
-		});
1836
-
1837
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1838
-	}
1839
-
1840
-	public function testValidateExpirationDateExistingShareNoDefault(): void {
1841
-		$share = $this->manager->newShare();
1842
-
1843
-		$share->setId('42')->setProviderId('foo');
1844
-
1845
-		$this->config->method('getAppValue')
1846
-			->willReturnMap([
1847
-				['core', 'shareapi_expire_after_n_days', '7', '6'],
1848
-			]);
1849
-
1850
-		$this->appConfig->method('getValueBool')
1851
-			->willReturnMap([
1852
-				['core', 'shareapi_default_expire_date', true],
1853
-				['core', 'shareapi_enforce_expire_date', false],
1854
-			]);
1855
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1856
-
1857
-		$this->assertEquals(null, $share->getExpirationDate());
1858
-	}
1859
-
1860
-	public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups(): void {
1861
-		$this->expectException(\Exception::class);
1862
-		$this->expectExceptionMessage('Sharing is only allowed with group members');
1863
-
1864
-		$share = $this->manager->newShare();
1865
-
1866
-		$sharedBy = $this->createMock(IUser::class);
1867
-		$sharedWith = $this->createMock(IUser::class);
1868
-		$share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1639
+        $this->appConfig->method('getValueBool')
1640
+            ->willReturnMap([
1641
+                ['core', 'shareapi_default_expire_date', true],
1642
+                ['core', 'shareapi_enforce_expire_date', true],
1643
+            ]);
1644
+
1645
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1646
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1647
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1648
+            return $data['expirationDate'] == $future;
1649
+        }));
1650
+
1651
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1652
+
1653
+        $this->assertEquals($expected, $share->getExpirationDate());
1654
+    }
1655
+
1656
+    public function testValidateExpirationDateNoDefault(): void {
1657
+        $date = new \DateTime('now', $this->timezone);
1658
+        $date->add(new \DateInterval('P5D'));
1659
+        $date->setTime(1, 2, 3);
1660
+
1661
+        $expected = clone $date;
1662
+        $expected->setTime(0, 0);
1663
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1664
+
1665
+        $share = $this->manager->newShare();
1666
+        $share->setExpirationDate($date);
1667
+
1668
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1669
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1670
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1671
+            return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1672
+        }));
1673
+
1674
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1675
+
1676
+        $this->assertEquals($expected, $share->getExpirationDate());
1677
+    }
1678
+
1679
+    public function testValidateExpirationDateNoDateNoDefault(): void {
1680
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1681
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1682
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1683
+            return $data['expirationDate'] === null && $data['passwordSet'] === true;
1684
+        }));
1685
+
1686
+        $share = $this->manager->newShare();
1687
+        $share->setPassword('password');
1688
+
1689
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1690
+
1691
+        $this->assertNull($share->getExpirationDate());
1692
+    }
1693
+
1694
+    public function testValidateExpirationDateNoDateDefault(): void {
1695
+        $share = $this->manager->newShare();
1696
+
1697
+        $expected = new \DateTime('now', $this->timezone);
1698
+        $expected->add(new \DateInterval('P3D'));
1699
+        $expected->setTime(0, 0);
1700
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1701
+
1702
+        $this->config->method('getAppValue')
1703
+            ->willReturnMap([
1704
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1705
+                ['core', 'link_defaultExpDays', '3', '3'],
1706
+            ]);
1707
+
1708
+        $this->appConfig->method('getValueBool')
1709
+            ->willReturnMap([
1710
+                ['core', 'shareapi_default_expire_date', true],
1711
+                ['core', 'shareapi_enforce_expire_date', false],
1712
+            ]);
1713
+
1714
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1715
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1716
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1717
+            return $data['expirationDate'] == $expected;
1718
+        }));
1719
+
1720
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1721
+
1722
+        $this->assertEquals($expected, $share->getExpirationDate());
1723
+    }
1724
+
1725
+    public function testValidateExpirationDateDefault(): void {
1726
+        $future = new \DateTime('now', $this->timezone);
1727
+        $future->add(new \DateInterval('P5D'));
1728
+        $future->setTime(1, 2, 3);
1729
+
1730
+        $expected = clone $future;
1731
+        $expected->setTime(0, 0);
1732
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1733
+
1734
+        $share = $this->manager->newShare();
1735
+        $share->setExpirationDate($future);
1736
+
1737
+        $this->config->method('getAppValue')
1738
+            ->willReturnMap([
1739
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1740
+                ['core', 'link_defaultExpDays', '3', '1'],
1741
+            ]);
1742
+
1743
+        $this->appConfig->method('getValueBool')
1744
+            ->willReturnMap([
1745
+                ['core', 'shareapi_default_expire_date', true],
1746
+                ['core', 'shareapi_enforce_expire_date', false],
1747
+            ]);
1748
+
1749
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1750
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1751
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1752
+            return $data['expirationDate'] == $expected;
1753
+        }));
1754
+
1755
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1756
+
1757
+        $this->assertEquals($expected, $share->getExpirationDate());
1758
+    }
1759
+
1760
+    public function testValidateExpirationNegativeOffsetTimezone(): void {
1761
+        $this->timezone = new \DateTimeZone('Pacific/Tahiti');
1762
+        $future = new \DateTime();
1763
+        $future->add(new \DateInterval('P5D'));
1764
+
1765
+        $expected = clone $future;
1766
+        $expected->setTimezone($this->timezone);
1767
+        $expected->setTime(0, 0);
1768
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1769
+
1770
+        $share = $this->manager->newShare();
1771
+        $share->setExpirationDate($future);
1772
+
1773
+        $this->config->method('getAppValue')
1774
+            ->willReturnMap([
1775
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1776
+                ['core', 'link_defaultExpDays', '3', '1'],
1777
+            ]);
1778
+
1779
+        $this->appConfig->method('getValueBool')
1780
+            ->willReturnMap([
1781
+                ['core', 'shareapi_default_expire_date', true],
1782
+                ['core', 'shareapi_enforce_expire_date', false],
1783
+            ]);
1784
+
1785
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1786
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1787
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1788
+            return $data['expirationDate'] == $expected;
1789
+        }));
1790
+
1791
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1792
+
1793
+        $this->assertEquals($expected, $share->getExpirationDate());
1794
+    }
1795
+
1796
+    public function testValidateExpirationDateHookModification(): void {
1797
+        $nextWeek = new \DateTime('now', $this->timezone);
1798
+        $nextWeek->add(new \DateInterval('P7D'));
1799
+
1800
+        $save = clone $nextWeek;
1801
+        $save->setTime(0, 0);
1802
+        $save->sub(new \DateInterval('P2D'));
1803
+        $save->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1804
+
1805
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1806
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1807
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1808
+            $data['expirationDate']->sub(new \DateInterval('P2D'));
1809
+        });
1810
+
1811
+        $share = $this->manager->newShare();
1812
+        $share->setExpirationDate($nextWeek);
1813
+
1814
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1815
+
1816
+        $this->assertEquals($save, $share->getExpirationDate());
1817
+    }
1818
+
1819
+    public function testValidateExpirationDateHookException(): void {
1820
+        $this->expectException(\Exception::class);
1821
+        $this->expectExceptionMessage('Invalid date!');
1822
+
1823
+        $nextWeek = new \DateTime();
1824
+        $nextWeek->add(new \DateInterval('P7D'));
1825
+        $nextWeek->setTime(0, 0, 0);
1826
+
1827
+        $share = $this->manager->newShare();
1828
+        $share->setExpirationDate($nextWeek);
1829
+
1830
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1831
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1832
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1833
+            $data['accepted'] = false;
1834
+            $data['message'] = 'Invalid date!';
1835
+        });
1836
+
1837
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1838
+    }
1839
+
1840
+    public function testValidateExpirationDateExistingShareNoDefault(): void {
1841
+        $share = $this->manager->newShare();
1842
+
1843
+        $share->setId('42')->setProviderId('foo');
1844
+
1845
+        $this->config->method('getAppValue')
1846
+            ->willReturnMap([
1847
+                ['core', 'shareapi_expire_after_n_days', '7', '6'],
1848
+            ]);
1849
+
1850
+        $this->appConfig->method('getValueBool')
1851
+            ->willReturnMap([
1852
+                ['core', 'shareapi_default_expire_date', true],
1853
+                ['core', 'shareapi_enforce_expire_date', false],
1854
+            ]);
1855
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1856
+
1857
+        $this->assertEquals(null, $share->getExpirationDate());
1858
+    }
1859
+
1860
+    public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups(): void {
1861
+        $this->expectException(\Exception::class);
1862
+        $this->expectExceptionMessage('Sharing is only allowed with group members');
1863
+
1864
+        $share = $this->manager->newShare();
1865
+
1866
+        $sharedBy = $this->createMock(IUser::class);
1867
+        $sharedWith = $this->createMock(IUser::class);
1868
+        $share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1869 1869
 
1870
-		$this->groupManager
1871
-			->method('getUserGroupIds')
1872
-			->willReturnMap(
1873
-				[
1874
-					[$sharedBy, ['group1']],
1875
-					[$sharedWith, ['group2']],
1876
-				]
1877
-			);
1870
+        $this->groupManager
1871
+            ->method('getUserGroupIds')
1872
+            ->willReturnMap(
1873
+                [
1874
+                    [$sharedBy, ['group1']],
1875
+                    [$sharedWith, ['group2']],
1876
+                ]
1877
+            );
1878 1878
 
1879
-		$this->userManager->method('get')->willReturnMap([
1880
-			['sharedBy', $sharedBy],
1881
-			['sharedWith', $sharedWith],
1882
-		]);
1879
+        $this->userManager->method('get')->willReturnMap([
1880
+            ['sharedBy', $sharedBy],
1881
+            ['sharedWith', $sharedWith],
1882
+        ]);
1883 1883
 
1884
-		$this->config
1885
-			->method('getAppValue')
1886
-			->willReturnMap([
1887
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1888
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1889
-			]);
1884
+        $this->config
1885
+            ->method('getAppValue')
1886
+            ->willReturnMap([
1887
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1888
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1889
+            ]);
1890 1890
 
1891
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1892
-	}
1893
-
1894
-	public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup(): void {
1895
-		$share = $this->manager->newShare();
1896
-
1897
-		$sharedBy = $this->createMock(IUser::class);
1898
-		$sharedWith = $this->createMock(IUser::class);
1899
-		$share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1900
-
1901
-		$path = $this->createMock(Node::class);
1902
-		$share->setNode($path);
1891
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1892
+    }
1893
+
1894
+    public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup(): void {
1895
+        $share = $this->manager->newShare();
1896
+
1897
+        $sharedBy = $this->createMock(IUser::class);
1898
+        $sharedWith = $this->createMock(IUser::class);
1899
+        $share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1900
+
1901
+        $path = $this->createMock(Node::class);
1902
+        $share->setNode($path);
1903 1903
 
1904
-		$this->groupManager
1905
-			->method('getUserGroupIds')
1906
-			->willReturnMap(
1907
-				[
1908
-					[$sharedBy, ['group1', 'group3']],
1909
-					[$sharedWith, ['group2', 'group3']],
1910
-				]
1911
-			);
1904
+        $this->groupManager
1905
+            ->method('getUserGroupIds')
1906
+            ->willReturnMap(
1907
+                [
1908
+                    [$sharedBy, ['group1', 'group3']],
1909
+                    [$sharedWith, ['group2', 'group3']],
1910
+                ]
1911
+            );
1912 1912
 
1913
-		$this->userManager->method('get')->willReturnMap([
1914
-			['sharedBy', $sharedBy],
1915
-			['sharedWith', $sharedWith],
1916
-		]);
1913
+        $this->userManager->method('get')->willReturnMap([
1914
+            ['sharedBy', $sharedBy],
1915
+            ['sharedWith', $sharedWith],
1916
+        ]);
1917 1917
 
1918
-		$this->config
1919
-			->method('getAppValue')
1920
-			->willReturnMap([
1921
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1922
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1923
-			]);
1918
+        $this->config
1919
+            ->method('getAppValue')
1920
+            ->willReturnMap([
1921
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1922
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1923
+            ]);
1924 1924
 
1925
-		$this->defaultProvider
1926
-			->method('getSharesByPath')
1927
-			->with($path)
1928
-			->willReturn([]);
1925
+        $this->defaultProvider
1926
+            ->method('getSharesByPath')
1927
+            ->with($path)
1928
+            ->willReturn([]);
1929 1929
 
1930
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1931
-		$this->addToAssertionCount(1);
1932
-	}
1930
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1931
+        $this->addToAssertionCount(1);
1932
+    }
1933 1933
 
1934 1934
 
1935
-	public function testUserCreateChecksIdenticalShareExists(): void {
1936
-		$this->expectException(AlreadySharedException::class);
1937
-		$this->expectExceptionMessage('Sharing name.txt failed, because this item is already shared with the account user');
1935
+    public function testUserCreateChecksIdenticalShareExists(): void {
1936
+        $this->expectException(AlreadySharedException::class);
1937
+        $this->expectExceptionMessage('Sharing name.txt failed, because this item is already shared with the account user');
1938 1938
 
1939
-		$share = $this->manager->newShare();
1940
-		$share->setSharedWithDisplayName('user');
1941
-		$share2 = $this->manager->newShare();
1939
+        $share = $this->manager->newShare();
1940
+        $share->setSharedWithDisplayName('user');
1941
+        $share2 = $this->manager->newShare();
1942 1942
 
1943
-		$sharedWith = $this->createMock(IUser::class);
1944
-		$path = $this->createMock(Node::class);
1945
-
1946
-		$share->setSharedWith('sharedWith')->setNode($path)
1947
-			->setProviderId('foo')->setId('bar');
1948
-
1949
-		$share2->setSharedWith('sharedWith')->setNode($path)
1950
-			->setProviderId('foo')->setId('baz');
1951
-
1952
-		$this->defaultProvider
1953
-			->method('getSharesByPath')
1954
-			->with($path)
1955
-			->willReturn([$share2]);
1943
+        $sharedWith = $this->createMock(IUser::class);
1944
+        $path = $this->createMock(Node::class);
1945
+
1946
+        $share->setSharedWith('sharedWith')->setNode($path)
1947
+            ->setProviderId('foo')->setId('bar');
1948
+
1949
+        $share2->setSharedWith('sharedWith')->setNode($path)
1950
+            ->setProviderId('foo')->setId('baz');
1951
+
1952
+        $this->defaultProvider
1953
+            ->method('getSharesByPath')
1954
+            ->with($path)
1955
+            ->willReturn([$share2]);
1956 1956
 
1957
-		$path->method('getName')
1958
-			->willReturn('name.txt');
1957
+        $path->method('getName')
1958
+            ->willReturn('name.txt');
1959 1959
 
1960
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1961
-	}
1962
-
1963
-
1964
-	public function testUserCreateChecksIdenticalPathSharedViaGroup(): void {
1965
-		$this->expectException(AlreadySharedException::class);
1966
-		$this->expectExceptionMessage('Sharing name2.txt failed, because this item is already shared with the account userName');
1967
-
1968
-		$share = $this->manager->newShare();
1960
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1961
+    }
1962
+
1963
+
1964
+    public function testUserCreateChecksIdenticalPathSharedViaGroup(): void {
1965
+        $this->expectException(AlreadySharedException::class);
1966
+        $this->expectExceptionMessage('Sharing name2.txt failed, because this item is already shared with the account userName');
1967
+
1968
+        $share = $this->manager->newShare();
1969 1969
 
1970
-		$sharedWith = $this->createMock(IUser::class);
1971
-		$sharedWith->method('getUID')->willReturn('sharedWith');
1972
-
1973
-		$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1970
+        $sharedWith = $this->createMock(IUser::class);
1971
+        $sharedWith->method('getUID')->willReturn('sharedWith');
1972
+
1973
+        $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1974 1974
 
1975
-		$path = $this->createMock(Node::class);
1975
+        $path = $this->createMock(Node::class);
1976 1976
 
1977
-		$share->setSharedWith('sharedWith')
1978
-			->setNode($path)
1979
-			->setShareOwner('shareOwner')
1980
-			->setSharedWithDisplayName('userName')
1981
-			->setProviderId('foo')
1982
-			->setId('bar');
1977
+        $share->setSharedWith('sharedWith')
1978
+            ->setNode($path)
1979
+            ->setShareOwner('shareOwner')
1980
+            ->setSharedWithDisplayName('userName')
1981
+            ->setProviderId('foo')
1982
+            ->setId('bar');
1983 1983
 
1984
-		$share2 = $this->manager->newShare();
1985
-		$share2->setShareType(IShare::TYPE_GROUP)
1986
-			->setShareOwner('shareOwner2')
1987
-			->setProviderId('foo')
1988
-			->setId('baz')
1989
-			->setSharedWith('group');
1984
+        $share2 = $this->manager->newShare();
1985
+        $share2->setShareType(IShare::TYPE_GROUP)
1986
+            ->setShareOwner('shareOwner2')
1987
+            ->setProviderId('foo')
1988
+            ->setId('baz')
1989
+            ->setSharedWith('group');
1990 1990
 
1991
-		$group = $this->createMock(IGroup::class);
1992
-		$group->method('inGroup')
1993
-			->with($sharedWith)
1994
-			->willReturn(true);
1991
+        $group = $this->createMock(IGroup::class);
1992
+        $group->method('inGroup')
1993
+            ->with($sharedWith)
1994
+            ->willReturn(true);
1995 1995
 
1996
-		$this->groupManager->method('get')->with('group')->willReturn($group);
1996
+        $this->groupManager->method('get')->with('group')->willReturn($group);
1997 1997
 
1998
-		$this->defaultProvider
1999
-			->method('getSharesByPath')
2000
-			->with($path)
2001
-			->willReturn([$share2]);
1998
+        $this->defaultProvider
1999
+            ->method('getSharesByPath')
2000
+            ->with($path)
2001
+            ->willReturn([$share2]);
2002 2002
 
2003
-		$path->method('getName')
2004
-			->willReturn('name2.txt');
2003
+        $path->method('getName')
2004
+            ->willReturn('name2.txt');
2005 2005
 
2006
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
2007
-	}
2006
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
2007
+    }
2008 2008
 
2009
-	public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup(): void {
2010
-		$share = $this->manager->newShare();
2009
+    public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup(): void {
2010
+        $share = $this->manager->newShare();
2011 2011
 
2012
-		$sharedWith = $this->createMock(IUser::class);
2013
-		$sharedWith->method('getUID')->willReturn('sharedWith');
2012
+        $sharedWith = $this->createMock(IUser::class);
2013
+        $sharedWith->method('getUID')->willReturn('sharedWith');
2014 2014
 
2015
-		$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
2015
+        $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
2016 2016
 
2017
-		$path = $this->createMock(Node::class);
2017
+        $path = $this->createMock(Node::class);
2018 2018
 
2019
-		$share->setSharedWith('sharedWith')
2020
-			->setNode($path)
2021
-			->setShareOwner('shareOwner')
2022
-			->setProviderId('foo')
2023
-			->setId('bar');
2019
+        $share->setSharedWith('sharedWith')
2020
+            ->setNode($path)
2021
+            ->setShareOwner('shareOwner')
2022
+            ->setProviderId('foo')
2023
+            ->setId('bar');
2024 2024
 
2025
-		$share2 = $this->manager->newShare();
2026
-		$share2->setShareType(IShare::TYPE_GROUP)
2027
-			->setShareOwner('shareOwner2')
2028
-			->setProviderId('foo')
2029
-			->setId('baz')
2030
-			->setSharedWith('group');
2025
+        $share2 = $this->manager->newShare();
2026
+        $share2->setShareType(IShare::TYPE_GROUP)
2027
+            ->setShareOwner('shareOwner2')
2028
+            ->setProviderId('foo')
2029
+            ->setId('baz')
2030
+            ->setSharedWith('group');
2031 2031
 
2032
-		$this->groupManager->method('get')->with('group')->willReturn(null);
2032
+        $this->groupManager->method('get')->with('group')->willReturn(null);
2033 2033
 
2034
-		$this->defaultProvider
2035
-			->method('getSharesByPath')
2036
-			->with($path)
2037
-			->willReturn([$share2]);
2034
+        $this->defaultProvider
2035
+            ->method('getSharesByPath')
2036
+            ->with($path)
2037
+            ->willReturn([$share2]);
2038 2038
 
2039
-		$this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share]));
2040
-	}
2039
+        $this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share]));
2040
+    }
2041 2041
 
2042
-	public function testUserCreateChecksIdenticalPathNotSharedWithUser(): void {
2043
-		$share = $this->manager->newShare();
2044
-		$sharedWith = $this->createMock(IUser::class);
2045
-		$path = $this->createMock(Node::class);
2046
-		$share->setSharedWith('sharedWith')
2047
-			->setNode($path)
2048
-			->setShareOwner('shareOwner')
2049
-			->setProviderId('foo')
2050
-			->setId('bar');
2042
+    public function testUserCreateChecksIdenticalPathNotSharedWithUser(): void {
2043
+        $share = $this->manager->newShare();
2044
+        $sharedWith = $this->createMock(IUser::class);
2045
+        $path = $this->createMock(Node::class);
2046
+        $share->setSharedWith('sharedWith')
2047
+            ->setNode($path)
2048
+            ->setShareOwner('shareOwner')
2049
+            ->setProviderId('foo')
2050
+            ->setId('bar');
2051 2051
 
2052
-		$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
2052
+        $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
2053 2053
 
2054
-		$share2 = $this->manager->newShare();
2055
-		$share2->setShareType(IShare::TYPE_GROUP)
2056
-			->setShareOwner('shareOwner2')
2057
-			->setProviderId('foo')
2058
-			->setId('baz');
2054
+        $share2 = $this->manager->newShare();
2055
+        $share2->setShareType(IShare::TYPE_GROUP)
2056
+            ->setShareOwner('shareOwner2')
2057
+            ->setProviderId('foo')
2058
+            ->setId('baz');
2059 2059
 
2060
-		$group = $this->createMock(IGroup::class);
2061
-		$group->method('inGroup')
2062
-			->with($sharedWith)
2063
-			->willReturn(false);
2060
+        $group = $this->createMock(IGroup::class);
2061
+        $group->method('inGroup')
2062
+            ->with($sharedWith)
2063
+            ->willReturn(false);
2064 2064
 
2065
-		$this->groupManager->method('get')->with('group')->willReturn($group);
2065
+        $this->groupManager->method('get')->with('group')->willReturn($group);
2066 2066
 
2067
-		$share2->setSharedWith('group');
2067
+        $share2->setSharedWith('group');
2068 2068
 
2069
-		$this->defaultProvider
2070
-			->method('getSharesByPath')
2071
-			->with($path)
2072
-			->willReturn([$share2]);
2069
+        $this->defaultProvider
2070
+            ->method('getSharesByPath')
2071
+            ->with($path)
2072
+            ->willReturn([$share2]);
2073 2073
 
2074
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
2075
-		$this->addToAssertionCount(1);
2076
-	}
2074
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
2075
+        $this->addToAssertionCount(1);
2076
+    }
2077 2077
 
2078 2078
 
2079
-	public function testGroupCreateChecksShareWithGroupMembersGroupSharingNotAllowed(): void {
2080
-		$this->expectException(\Exception::class);
2081
-		$this->expectExceptionMessage('Group sharing is now allowed');
2079
+    public function testGroupCreateChecksShareWithGroupMembersGroupSharingNotAllowed(): void {
2080
+        $this->expectException(\Exception::class);
2081
+        $this->expectExceptionMessage('Group sharing is now allowed');
2082 2082
 
2083
-		$share = $this->manager->newShare();
2083
+        $share = $this->manager->newShare();
2084 2084
 
2085
-		$this->config
2086
-			->method('getAppValue')
2087
-			->willReturnMap([
2088
-				['core', 'shareapi_allow_group_sharing', 'yes', 'no'],
2089
-			]);
2085
+        $this->config
2086
+            ->method('getAppValue')
2087
+            ->willReturnMap([
2088
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'no'],
2089
+            ]);
2090 2090
 
2091
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2092
-	}
2091
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2092
+    }
2093 2093
 
2094 2094
 
2095
-	public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup(): void {
2096
-		$this->expectException(\Exception::class);
2097
-		$this->expectExceptionMessage('Sharing is only allowed within your own groups');
2095
+    public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup(): void {
2096
+        $this->expectException(\Exception::class);
2097
+        $this->expectExceptionMessage('Sharing is only allowed within your own groups');
2098 2098
 
2099
-		$share = $this->manager->newShare();
2099
+        $share = $this->manager->newShare();
2100 2100
 
2101
-		$user = $this->createMock(IUser::class);
2102
-		$group = $this->createMock(IGroup::class);
2103
-		$share->setSharedBy('user')->setSharedWith('group');
2101
+        $user = $this->createMock(IUser::class);
2102
+        $group = $this->createMock(IGroup::class);
2103
+        $share->setSharedBy('user')->setSharedWith('group');
2104 2104
 
2105
-		$group->method('inGroup')->with($user)->willReturn(false);
2105
+        $group->method('inGroup')->with($user)->willReturn(false);
2106 2106
 
2107
-		$this->groupManager->method('get')->with('group')->willReturn($group);
2108
-		$this->userManager->method('get')->with('user')->willReturn($user);
2107
+        $this->groupManager->method('get')->with('group')->willReturn($group);
2108
+        $this->userManager->method('get')->with('user')->willReturn($user);
2109 2109
 
2110
-		$this->config
2111
-			->method('getAppValue')
2112
-			->willReturnMap([
2113
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2114
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2115
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2116
-			]);
2110
+        $this->config
2111
+            ->method('getAppValue')
2112
+            ->willReturnMap([
2113
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2114
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2115
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2116
+            ]);
2117 2117
 
2118
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2119
-	}
2118
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2119
+    }
2120 2120
 
2121 2121
 
2122
-	public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup(): void {
2123
-		$this->expectException(\Exception::class);
2124
-		$this->expectExceptionMessage('Sharing is only allowed within your own groups');
2122
+    public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup(): void {
2123
+        $this->expectException(\Exception::class);
2124
+        $this->expectExceptionMessage('Sharing is only allowed within your own groups');
2125 2125
 
2126
-		$share = $this->manager->newShare();
2126
+        $share = $this->manager->newShare();
2127 2127
 
2128
-		$user = $this->createMock(IUser::class);
2129
-		$share->setSharedBy('user')->setSharedWith('group');
2128
+        $user = $this->createMock(IUser::class);
2129
+        $share->setSharedBy('user')->setSharedWith('group');
2130 2130
 
2131
-		$this->groupManager->method('get')->with('group')->willReturn(null);
2132
-		$this->userManager->method('get')->with('user')->willReturn($user);
2131
+        $this->groupManager->method('get')->with('group')->willReturn(null);
2132
+        $this->userManager->method('get')->with('user')->willReturn($user);
2133 2133
 
2134
-		$this->config
2135
-			->method('getAppValue')
2136
-			->willReturnMap([
2137
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2138
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2139
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2140
-			]);
2134
+        $this->config
2135
+            ->method('getAppValue')
2136
+            ->willReturnMap([
2137
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2138
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2139
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2140
+            ]);
2141 2141
 
2142
-		$this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
2143
-	}
2142
+        $this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
2143
+    }
2144 2144
 
2145
-	public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup(): void {
2146
-		$share = $this->manager->newShare();
2145
+    public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup(): void {
2146
+        $share = $this->manager->newShare();
2147 2147
 
2148
-		$user = $this->createMock(IUser::class);
2149
-		$group = $this->createMock(IGroup::class);
2150
-		$share->setSharedBy('user')->setSharedWith('group');
2148
+        $user = $this->createMock(IUser::class);
2149
+        $group = $this->createMock(IGroup::class);
2150
+        $share->setSharedBy('user')->setSharedWith('group');
2151 2151
 
2152
-		$this->userManager->method('get')->with('user')->willReturn($user);
2153
-		$this->groupManager->method('get')->with('group')->willReturn($group);
2152
+        $this->userManager->method('get')->with('user')->willReturn($user);
2153
+        $this->groupManager->method('get')->with('group')->willReturn($group);
2154 2154
 
2155
-		$group->method('inGroup')->with($user)->willReturn(true);
2155
+        $group->method('inGroup')->with($user)->willReturn(true);
2156 2156
 
2157
-		$path = $this->createMock(Node::class);
2158
-		$share->setNode($path);
2157
+        $path = $this->createMock(Node::class);
2158
+        $share->setNode($path);
2159 2159
 
2160
-		$this->defaultProvider->method('getSharesByPath')
2161
-			->with($path)
2162
-			->willReturn([]);
2160
+        $this->defaultProvider->method('getSharesByPath')
2161
+            ->with($path)
2162
+            ->willReturn([]);
2163 2163
 
2164
-		$this->config
2165
-			->method('getAppValue')
2166
-			->willReturnMap([
2167
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2168
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2169
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2170
-			]);
2164
+        $this->config
2165
+            ->method('getAppValue')
2166
+            ->willReturnMap([
2167
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2168
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2169
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2170
+            ]);
2171 2171
 
2172
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2173
-		$this->addToAssertionCount(1);
2174
-	}
2172
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2173
+        $this->addToAssertionCount(1);
2174
+    }
2175 2175
 
2176 2176
 
2177
-	public function testGroupCreateChecksPathAlreadySharedWithSameGroup(): void {
2178
-		$this->expectException(\Exception::class);
2179
-		$this->expectExceptionMessage('Path is already shared with this group');
2177
+    public function testGroupCreateChecksPathAlreadySharedWithSameGroup(): void {
2178
+        $this->expectException(\Exception::class);
2179
+        $this->expectExceptionMessage('Path is already shared with this group');
2180 2180
 
2181
-		$share = $this->manager->newShare();
2181
+        $share = $this->manager->newShare();
2182 2182
 
2183
-		$path = $this->createMock(Node::class);
2184
-		$share->setSharedWith('sharedWith')
2185
-			->setNode($path)
2186
-			->setProviderId('foo')
2187
-			->setId('bar');
2183
+        $path = $this->createMock(Node::class);
2184
+        $share->setSharedWith('sharedWith')
2185
+            ->setNode($path)
2186
+            ->setProviderId('foo')
2187
+            ->setId('bar');
2188 2188
 
2189
-		$share2 = $this->manager->newShare();
2190
-		$share2->setSharedWith('sharedWith')
2191
-			->setProviderId('foo')
2192
-			->setId('baz');
2189
+        $share2 = $this->manager->newShare();
2190
+        $share2->setSharedWith('sharedWith')
2191
+            ->setProviderId('foo')
2192
+            ->setId('baz');
2193 2193
 
2194
-		$this->defaultProvider->method('getSharesByPath')
2195
-			->with($path)
2196
-			->willReturn([$share2]);
2194
+        $this->defaultProvider->method('getSharesByPath')
2195
+            ->with($path)
2196
+            ->willReturn([$share2]);
2197 2197
 
2198
-		$this->config
2199
-			->method('getAppValue')
2200
-			->willReturnMap([
2201
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2202
-			]);
2198
+        $this->config
2199
+            ->method('getAppValue')
2200
+            ->willReturnMap([
2201
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2202
+            ]);
2203 2203
 
2204
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2205
-	}
2204
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2205
+    }
2206 2206
 
2207
-	public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup(): void {
2208
-		$share = $this->manager->newShare();
2207
+    public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup(): void {
2208
+        $share = $this->manager->newShare();
2209 2209
 
2210
-		$share->setSharedWith('sharedWith');
2210
+        $share->setSharedWith('sharedWith');
2211 2211
 
2212
-		$path = $this->createMock(Node::class);
2213
-		$share->setNode($path);
2212
+        $path = $this->createMock(Node::class);
2213
+        $share->setNode($path);
2214 2214
 
2215
-		$share2 = $this->manager->newShare();
2216
-		$share2->setSharedWith('sharedWith2');
2215
+        $share2 = $this->manager->newShare();
2216
+        $share2->setSharedWith('sharedWith2');
2217 2217
 
2218
-		$this->defaultProvider->method('getSharesByPath')
2219
-			->with($path)
2220
-			->willReturn([$share2]);
2218
+        $this->defaultProvider->method('getSharesByPath')
2219
+            ->with($path)
2220
+            ->willReturn([$share2]);
2221 2221
 
2222
-		$this->config
2223
-			->method('getAppValue')
2224
-			->willReturnMap([
2225
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2226
-			]);
2222
+        $this->config
2223
+            ->method('getAppValue')
2224
+            ->willReturnMap([
2225
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2226
+            ]);
2227 2227
 
2228
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2229
-		$this->addToAssertionCount(1);
2230
-	}
2228
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2229
+        $this->addToAssertionCount(1);
2230
+    }
2231 2231
 
2232 2232
 
2233
-	public function testLinkCreateChecksNoLinkSharesAllowed(): void {
2234
-		$this->expectException(\Exception::class);
2235
-		$this->expectExceptionMessage('Link sharing is not allowed');
2233
+    public function testLinkCreateChecksNoLinkSharesAllowed(): void {
2234
+        $this->expectException(\Exception::class);
2235
+        $this->expectExceptionMessage('Link sharing is not allowed');
2236 2236
 
2237
-		$share = $this->manager->newShare();
2237
+        $share = $this->manager->newShare();
2238 2238
 
2239
-		$this->config
2240
-			->method('getAppValue')
2241
-			->willReturnMap([
2242
-				['core', 'shareapi_allow_links', 'yes', 'no'],
2243
-			]);
2239
+        $this->config
2240
+            ->method('getAppValue')
2241
+            ->willReturnMap([
2242
+                ['core', 'shareapi_allow_links', 'yes', 'no'],
2243
+            ]);
2244 2244
 
2245
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2246
-	}
2245
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2246
+    }
2247 2247
 
2248 2248
 
2249
-	public function testFileLinkCreateChecksNoPublicUpload(): void {
2250
-		$share = $this->manager->newShare();
2249
+    public function testFileLinkCreateChecksNoPublicUpload(): void {
2250
+        $share = $this->manager->newShare();
2251 2251
 
2252
-		$share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2253
-		$share->setNodeType('file');
2252
+        $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2253
+        $share->setNodeType('file');
2254 2254
 
2255
-		$this->config
2256
-			->method('getAppValue')
2257
-			->willReturnMap([
2258
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2259
-				['core', 'shareapi_allow_public_upload', 'yes', 'no']
2260
-			]);
2255
+        $this->config
2256
+            ->method('getAppValue')
2257
+            ->willReturnMap([
2258
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2259
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no']
2260
+            ]);
2261 2261
 
2262
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2263
-		$this->addToAssertionCount(1);
2264
-	}
2262
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2263
+        $this->addToAssertionCount(1);
2264
+    }
2265 2265
 
2266
-	public function testFolderLinkCreateChecksNoPublicUpload(): void {
2267
-		$this->expectException(\Exception::class);
2268
-		$this->expectExceptionMessage('Public upload is not allowed');
2266
+    public function testFolderLinkCreateChecksNoPublicUpload(): void {
2267
+        $this->expectException(\Exception::class);
2268
+        $this->expectExceptionMessage('Public upload is not allowed');
2269 2269
 
2270
-		$share = $this->manager->newShare();
2270
+        $share = $this->manager->newShare();
2271 2271
 
2272
-		$share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2273
-		$share->setNodeType('folder');
2272
+        $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2273
+        $share->setNodeType('folder');
2274 2274
 
2275
-		$this->config
2276
-			->method('getAppValue')
2277
-			->willReturnMap([
2278
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2279
-				['core', 'shareapi_allow_public_upload', 'yes', 'no']
2280
-			]);
2275
+        $this->config
2276
+            ->method('getAppValue')
2277
+            ->willReturnMap([
2278
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2279
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no']
2280
+            ]);
2281 2281
 
2282
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2283
-	}
2282
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2283
+    }
2284 2284
 
2285
-	public function testLinkCreateChecksPublicUpload(): void {
2286
-		$share = $this->manager->newShare();
2285
+    public function testLinkCreateChecksPublicUpload(): void {
2286
+        $share = $this->manager->newShare();
2287 2287
 
2288
-		$share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2289
-		$share->setSharedWith('sharedWith');
2290
-		$folder = $this->createMock(\OC\Files\Node\Folder::class);
2291
-		$share->setNode($folder);
2288
+        $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2289
+        $share->setSharedWith('sharedWith');
2290
+        $folder = $this->createMock(\OC\Files\Node\Folder::class);
2291
+        $share->setNode($folder);
2292 2292
 
2293
-		$this->config
2294
-			->method('getAppValue')
2295
-			->willReturnMap([
2296
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2297
-				['core', 'shareapi_allow_public_upload', 'yes', 'yes']
2298
-			]);
2293
+        $this->config
2294
+            ->method('getAppValue')
2295
+            ->willReturnMap([
2296
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2297
+                ['core', 'shareapi_allow_public_upload', 'yes', 'yes']
2298
+            ]);
2299 2299
 
2300
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2301
-		$this->addToAssertionCount(1);
2302
-	}
2300
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2301
+        $this->addToAssertionCount(1);
2302
+    }
2303 2303
 
2304
-	public function testLinkCreateChecksReadOnly(): void {
2305
-		$share = $this->manager->newShare();
2304
+    public function testLinkCreateChecksReadOnly(): void {
2305
+        $share = $this->manager->newShare();
2306 2306
 
2307
-		$share->setPermissions(Constants::PERMISSION_READ);
2308
-		$share->setSharedWith('sharedWith');
2309
-		$folder = $this->createMock(\OC\Files\Node\Folder::class);
2310
-		$share->setNode($folder);
2307
+        $share->setPermissions(Constants::PERMISSION_READ);
2308
+        $share->setSharedWith('sharedWith');
2309
+        $folder = $this->createMock(\OC\Files\Node\Folder::class);
2310
+        $share->setNode($folder);
2311 2311
 
2312
-		$this->config
2313
-			->method('getAppValue')
2314
-			->willReturnMap([
2315
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2316
-				['core', 'shareapi_allow_public_upload', 'yes', 'no']
2317
-			]);
2312
+        $this->config
2313
+            ->method('getAppValue')
2314
+            ->willReturnMap([
2315
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2316
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no']
2317
+            ]);
2318 2318
 
2319
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2320
-		$this->addToAssertionCount(1);
2321
-	}
2322
-
2323
-
2324
-	public function testPathCreateChecksContainsSharedMount(): void {
2325
-		$this->expectException(\InvalidArgumentException::class);
2326
-		$this->expectExceptionMessage('You cannot share a folder that contains other shares');
2319
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2320
+        $this->addToAssertionCount(1);
2321
+    }
2322
+
2323
+
2324
+    public function testPathCreateChecksContainsSharedMount(): void {
2325
+        $this->expectException(\InvalidArgumentException::class);
2326
+        $this->expectExceptionMessage('You cannot share a folder that contains other shares');
2327 2327
 
2328
-		$path = $this->createMock(Folder::class);
2329
-		$path->method('getPath')->willReturn('path');
2328
+        $path = $this->createMock(Folder::class);
2329
+        $path->method('getPath')->willReturn('path');
2330 2330
 
2331
-		$mount = $this->createMock(IMountPoint::class);
2332
-		$storage = $this->createMock(IStorage::class);
2333
-		$mount->method('getStorage')->willReturn($storage);
2334
-		$storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(true);
2335
-
2336
-		$this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2337
-
2338
-		self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2339
-	}
2340
-
2341
-	public function testPathCreateChecksContainsNoSharedMount(): void {
2342
-		$path = $this->createMock(Folder::class);
2343
-		$path->method('getPath')->willReturn('path');
2331
+        $mount = $this->createMock(IMountPoint::class);
2332
+        $storage = $this->createMock(IStorage::class);
2333
+        $mount->method('getStorage')->willReturn($storage);
2334
+        $storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(true);
2335
+
2336
+        $this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2337
+
2338
+        self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2339
+    }
2340
+
2341
+    public function testPathCreateChecksContainsNoSharedMount(): void {
2342
+        $path = $this->createMock(Folder::class);
2343
+        $path->method('getPath')->willReturn('path');
2344 2344
 
2345
-		$mount = $this->createMock(IMountPoint::class);
2346
-		$storage = $this->createMock(IStorage::class);
2347
-		$mount->method('getStorage')->willReturn($storage);
2348
-		$storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(false);
2349
-
2350
-		$this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2351
-
2352
-		self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2353
-		$this->addToAssertionCount(1);
2354
-	}
2355
-
2356
-	public function testPathCreateChecksContainsNoFolder(): void {
2357
-		$path = $this->createMock(File::class);
2358
-
2359
-		self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2360
-		$this->addToAssertionCount(1);
2361
-	}
2362
-
2363
-	public static function dataIsSharingDisabledForUser() {
2364
-		$data = [];
2365
-
2366
-		// No exclude groups
2367
-		$data[] = ['no', null, null, [], false];
2368
-
2369
-		// empty exclude / allow list, user no groups
2370
-		$data[] = ['yes', '', json_encode(['']), [], false];
2371
-		$data[] = ['allow', '', json_encode(['']), [], true];
2372
-
2373
-		// empty exclude / allow list, user groups
2374
-		$data[] = ['yes', '', json_encode(['']), ['group1', 'group2'], false];
2375
-		$data[] = ['allow', '', json_encode(['']), ['group1', 'group2'], true];
2376
-
2377
-		// Convert old list to json
2378
-		$data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), [], false];
2379
-		$data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), [], true];
2380
-
2381
-		// Old list partly groups in common
2382
-		$data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2383
-		$data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2384
-
2385
-		// Old list only groups in common
2386
-		$data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], true];
2387
-		$data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], false];
2388
-
2389
-		// New list partly in common
2390
-		$data[] = ['yes', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2391
-		$data[] = ['allow', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2392
-
2393
-		// New list only groups in common
2394
-		$data[] = ['yes', json_encode(['group1', 'group2']), null, ['group2'], true];
2395
-		$data[] = ['allow', json_encode(['group1', 'group2']), null, ['group2'], false];
2396
-
2397
-		return $data;
2398
-	}
2345
+        $mount = $this->createMock(IMountPoint::class);
2346
+        $storage = $this->createMock(IStorage::class);
2347
+        $mount->method('getStorage')->willReturn($storage);
2348
+        $storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(false);
2349
+
2350
+        $this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2351
+
2352
+        self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2353
+        $this->addToAssertionCount(1);
2354
+    }
2355
+
2356
+    public function testPathCreateChecksContainsNoFolder(): void {
2357
+        $path = $this->createMock(File::class);
2358
+
2359
+        self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2360
+        $this->addToAssertionCount(1);
2361
+    }
2362
+
2363
+    public static function dataIsSharingDisabledForUser() {
2364
+        $data = [];
2365
+
2366
+        // No exclude groups
2367
+        $data[] = ['no', null, null, [], false];
2368
+
2369
+        // empty exclude / allow list, user no groups
2370
+        $data[] = ['yes', '', json_encode(['']), [], false];
2371
+        $data[] = ['allow', '', json_encode(['']), [], true];
2372
+
2373
+        // empty exclude / allow list, user groups
2374
+        $data[] = ['yes', '', json_encode(['']), ['group1', 'group2'], false];
2375
+        $data[] = ['allow', '', json_encode(['']), ['group1', 'group2'], true];
2376
+
2377
+        // Convert old list to json
2378
+        $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), [], false];
2379
+        $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), [], true];
2380
+
2381
+        // Old list partly groups in common
2382
+        $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2383
+        $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2384
+
2385
+        // Old list only groups in common
2386
+        $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], true];
2387
+        $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], false];
2388
+
2389
+        // New list partly in common
2390
+        $data[] = ['yes', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2391
+        $data[] = ['allow', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2392
+
2393
+        // New list only groups in common
2394
+        $data[] = ['yes', json_encode(['group1', 'group2']), null, ['group2'], true];
2395
+        $data[] = ['allow', json_encode(['group1', 'group2']), null, ['group2'], false];
2396
+
2397
+        return $data;
2398
+    }
2399 2399
 
2400
-	/**
2401
-	 *
2402
-	 * @param string $excludeGroups
2403
-	 * @param string $groupList
2404
-	 * @param string $setList
2405
-	 * @param string[] $groupIds
2406
-	 * @param bool $expected
2407
-	 */
2408
-	#[DataProvider('dataIsSharingDisabledForUser')]
2409
-	public function testIsSharingDisabledForUser($excludeGroups, $groupList, $setList, $groupIds, $expected): void {
2410
-		$user = $this->createMock(IUser::class);
2400
+    /**
2401
+     *
2402
+     * @param string $excludeGroups
2403
+     * @param string $groupList
2404
+     * @param string $setList
2405
+     * @param string[] $groupIds
2406
+     * @param bool $expected
2407
+     */
2408
+    #[DataProvider('dataIsSharingDisabledForUser')]
2409
+    public function testIsSharingDisabledForUser($excludeGroups, $groupList, $setList, $groupIds, $expected): void {
2410
+        $user = $this->createMock(IUser::class);
2411 2411
 
2412
-		$this->config->method('getAppValue')
2413
-			->willReturnMap([
2414
-				['core', 'shareapi_exclude_groups', 'no', $excludeGroups],
2415
-				['core', 'shareapi_exclude_groups_list', '', $groupList],
2416
-			]);
2412
+        $this->config->method('getAppValue')
2413
+            ->willReturnMap([
2414
+                ['core', 'shareapi_exclude_groups', 'no', $excludeGroups],
2415
+                ['core', 'shareapi_exclude_groups_list', '', $groupList],
2416
+            ]);
2417 2417
 
2418
-		if ($setList !== null) {
2419
-			$this->config->expects($this->once())
2420
-				->method('setAppValue')
2421
-				->with('core', 'shareapi_exclude_groups_list', $setList);
2422
-		} else {
2423
-			$this->config->expects($this->never())
2424
-				->method('setAppValue');
2425
-		}
2418
+        if ($setList !== null) {
2419
+            $this->config->expects($this->once())
2420
+                ->method('setAppValue')
2421
+                ->with('core', 'shareapi_exclude_groups_list', $setList);
2422
+        } else {
2423
+            $this->config->expects($this->never())
2424
+                ->method('setAppValue');
2425
+        }
2426 2426
 
2427
-		$this->groupManager->method('getUserGroupIds')
2428
-			->with($user)
2429
-			->willReturn($groupIds);
2427
+        $this->groupManager->method('getUserGroupIds')
2428
+            ->with($user)
2429
+            ->willReturn($groupIds);
2430 2430
 
2431
-		$this->userManager->method('get')->with('user')->willReturn($user);
2432
-
2433
-		$res = $this->manager->sharingDisabledForUser('user');
2434
-		$this->assertEquals($expected, $res);
2435
-	}
2436
-
2437
-	public static function dataCanShare() {
2438
-		$data = [];
2439
-
2440
-		/*
2431
+        $this->userManager->method('get')->with('user')->willReturn($user);
2432
+
2433
+        $res = $this->manager->sharingDisabledForUser('user');
2434
+        $this->assertEquals($expected, $res);
2435
+    }
2436
+
2437
+    public static function dataCanShare() {
2438
+        $data = [];
2439
+
2440
+        /*
2441 2441
 		 * [expected, sharing enabled, disabled for user]
2442 2442
 		 */
2443 2443
 
2444
-		$data[] = [false, 'no', false];
2445
-		$data[] = [false, 'no', true];
2446
-		$data[] = [true, 'yes', false];
2447
-		$data[] = [false, 'yes', true];
2448
-
2449
-		return $data;
2450
-	}
2451
-
2452
-	/**
2453
-	 *
2454
-	 * @param bool $expected
2455
-	 * @param string $sharingEnabled
2456
-	 * @param bool $disabledForUser
2457
-	 */
2458
-	#[DataProvider('dataCanShare')]
2459
-	public function testCanShare($expected, $sharingEnabled, $disabledForUser): void {
2460
-		$this->config->method('getAppValue')
2461
-			->willReturnMap([
2462
-				['core', 'shareapi_enabled', 'yes', $sharingEnabled],
2463
-			]);
2464
-
2465
-		$manager = $this->createManagerMock()
2466
-			->onlyMethods(['sharingDisabledForUser'])
2467
-			->getMock();
2468
-
2469
-		$manager->method('sharingDisabledForUser')
2470
-			->with('user')
2471
-			->willReturn($disabledForUser);
2472
-
2473
-		$share = $this->manager->newShare();
2474
-		$share->setSharedBy('user');
2475
-
2476
-		$exception = false;
2477
-		try {
2478
-			$res = self::invokePrivate($manager, 'canShare', [$share]);
2479
-		} catch (\Exception $e) {
2480
-			$exception = true;
2481
-		}
2482
-
2483
-		$this->assertEquals($expected, !$exception);
2484
-	}
2485
-
2486
-	public function testCreateShareUser(): void {
2487
-		/** @var Manager&MockObject $manager */
2488
-		$manager = $this->createManagerMock()
2489
-			->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2490
-			->getMock();
2491
-
2492
-		$shareOwner = $this->createMock(IUser::class);
2493
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2494
-
2495
-		$storage = $this->createMock(IStorage::class);
2496
-		$path = $this->createMock(File::class);
2497
-		$path->method('getOwner')->willReturn($shareOwner);
2498
-		$path->method('getName')->willReturn('target');
2499
-		$path->method('getStorage')->willReturn($storage);
2500
-
2501
-		$share = $this->createShare(
2502
-			null,
2503
-			IShare::TYPE_USER,
2504
-			$path,
2505
-			'sharedWith',
2506
-			'sharedBy',
2507
-			null,
2508
-			Constants::PERMISSION_ALL);
2509
-
2510
-		$manager->expects($this->once())
2511
-			->method('canShare')
2512
-			->with($share);
2513
-		$manager->expects($this->once())
2514
-			->method('generalCreateChecks')
2515
-			->with($share);
2516
-		;
2517
-		$manager->expects($this->once())
2518
-			->method('userCreateChecks')
2519
-			->with($share);
2520
-		;
2521
-		$manager->expects($this->once())
2522
-			->method('pathCreateChecks')
2523
-			->with($path);
2524
-
2525
-		$this->defaultProvider
2526
-			->expects($this->once())
2527
-			->method('create')
2528
-			->with($share)
2529
-			->willReturnArgument(0);
2530
-
2531
-		$share->expects($this->once())
2532
-			->method('setShareOwner')
2533
-			->with('shareOwner');
2534
-		$share->expects($this->once())
2535
-			->method('setTarget')
2536
-			->with('/target');
2537
-
2538
-		$manager->createShare($share);
2539
-	}
2540
-
2541
-	public function testCreateShareGroup(): void {
2542
-		$manager = $this->createManagerMock()
2543
-			->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
2544
-			->getMock();
2545
-
2546
-		$shareOwner = $this->createMock(IUser::class);
2547
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2548
-
2549
-		$storage = $this->createMock(IStorage::class);
2550
-		$path = $this->createMock(File::class);
2551
-		$path->method('getOwner')->willReturn($shareOwner);
2552
-		$path->method('getName')->willReturn('target');
2553
-		$path->method('getStorage')->willReturn($storage);
2554
-
2555
-		$share = $this->createShare(
2556
-			null,
2557
-			IShare::TYPE_GROUP,
2558
-			$path,
2559
-			'sharedWith',
2560
-			'sharedBy',
2561
-			null,
2562
-			Constants::PERMISSION_ALL);
2563
-
2564
-		$manager->expects($this->once())
2565
-			->method('canShare')
2566
-			->with($share);
2567
-		$manager->expects($this->once())
2568
-			->method('generalCreateChecks')
2569
-			->with($share);
2570
-		;
2571
-		$manager->expects($this->once())
2572
-			->method('groupCreateChecks')
2573
-			->with($share);
2574
-		;
2575
-		$manager->expects($this->once())
2576
-			->method('pathCreateChecks')
2577
-			->with($path);
2578
-
2579
-		$this->defaultProvider
2580
-			->expects($this->once())
2581
-			->method('create')
2582
-			->with($share)
2583
-			->willReturnArgument(0);
2584
-
2585
-		$share->expects($this->once())
2586
-			->method('setShareOwner')
2587
-			->with('shareOwner');
2588
-		$share->expects($this->once())
2589
-			->method('setTarget')
2590
-			->with('/target');
2591
-
2592
-		$manager->createShare($share);
2593
-	}
2594
-
2595
-	public function testCreateShareLink(): void {
2596
-		$manager = $this->createManagerMock()
2597
-			->onlyMethods([
2598
-				'canShare',
2599
-				'generalCreateChecks',
2600
-				'linkCreateChecks',
2601
-				'pathCreateChecks',
2602
-				'validateExpirationDateLink',
2603
-				'verifyPassword',
2604
-				'setLinkParent',
2605
-			])
2606
-			->getMock();
2607
-
2608
-		$shareOwner = $this->createMock(IUser::class);
2609
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2610
-
2611
-		$storage = $this->createMock(IStorage::class);
2612
-		$path = $this->createMock(File::class);
2613
-		$path->method('getOwner')->willReturn($shareOwner);
2614
-		$path->method('getName')->willReturn('target');
2615
-		$path->method('getId')->willReturn(1);
2616
-		$path->method('getStorage')->willReturn($storage);
2617
-
2618
-		$date = new \DateTime();
2619
-
2620
-		$share = $this->manager->newShare();
2621
-		$share->setShareType(IShare::TYPE_LINK)
2622
-			->setNode($path)
2623
-			->setSharedBy('sharedBy')
2624
-			->setPermissions(Constants::PERMISSION_ALL)
2625
-			->setExpirationDate($date)
2626
-			->setPassword('password');
2627
-
2628
-		$manager->expects($this->once())
2629
-			->method('canShare')
2630
-			->with($share);
2631
-		$manager->expects($this->once())
2632
-			->method('generalCreateChecks')
2633
-			->with($share);
2634
-		;
2635
-		$manager->expects($this->once())
2636
-			->method('linkCreateChecks')
2637
-			->with($share);
2638
-		;
2639
-		$manager->expects($this->once())
2640
-			->method('pathCreateChecks')
2641
-			->with($path);
2642
-		$manager->expects($this->once())
2643
-			->method('validateExpirationDateLink')
2644
-			->with($share)
2645
-			->willReturn($share);
2646
-		$manager->expects($this->once())
2647
-			->method('verifyPassword')
2648
-			->with('password');
2649
-		$manager->expects($this->once())
2650
-			->method('setLinkParent')
2651
-			->with($share);
2652
-
2653
-		$this->hasher->expects($this->once())
2654
-			->method('hash')
2655
-			->with('password')
2656
-			->willReturn('hashed');
2657
-
2658
-		$this->secureRandom->method('generate')
2659
-			->willReturn('token');
2660
-
2661
-		$this->defaultProvider
2662
-			->expects($this->once())
2663
-			->method('create')
2664
-			->with($share)
2665
-			->willReturnCallback(function (Share $share) {
2666
-				return $share->setId(42);
2667
-			});
2668
-
2669
-		$calls = [
2670
-			BeforeShareCreatedEvent::class,
2671
-			ShareCreatedEvent::class,
2672
-		];
2673
-		$this->dispatcher->expects($this->exactly(2))
2674
-			->method('dispatchTyped')
2675
-			->willReturnCallback(function ($event) use (&$calls, $date, $path): void {
2676
-				$expected = array_shift($calls);
2677
-				$this->assertInstanceOf($expected, $event);
2678
-				$share = $event->getShare();
2679
-
2680
-				$this->assertEquals(IShare::TYPE_LINK, $share->getShareType(), 'getShareType');
2681
-				$this->assertEquals($path, $share->getNode(), 'getNode');
2682
-				$this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2683
-				$this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2684
-				$this->assertEquals($date, $share->getExpirationDate(), 'getExpirationDate');
2685
-				$this->assertEquals('hashed', $share->getPassword(), 'getPassword');
2686
-				$this->assertEquals('token', $share->getToken(), 'getToken');
2687
-
2688
-				if ($expected === ShareCreatedEvent::class) {
2689
-					$this->assertEquals('42', $share->getId(), 'getId');
2690
-					$this->assertEquals('/target', $share->getTarget(), 'getTarget');
2691
-				}
2692
-			});
2693
-
2694
-		/** @var IShare $share */
2695
-		$share = $manager->createShare($share);
2696
-
2697
-		$this->assertSame('shareOwner', $share->getShareOwner());
2698
-		$this->assertEquals('/target', $share->getTarget());
2699
-		$this->assertSame($date, $share->getExpirationDate());
2700
-		$this->assertEquals('token', $share->getToken());
2701
-		$this->assertEquals('hashed', $share->getPassword());
2702
-	}
2703
-
2704
-	public function testCreateShareMail(): void {
2705
-		$manager = $this->createManagerMock()
2706
-			->onlyMethods([
2707
-				'canShare',
2708
-				'generalCreateChecks',
2709
-				'linkCreateChecks',
2710
-				'pathCreateChecks',
2711
-				'validateExpirationDateLink',
2712
-				'verifyPassword',
2713
-				'setLinkParent',
2714
-			])
2715
-			->getMock();
2716
-
2717
-		$shareOwner = $this->createMock(IUser::class);
2718
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2719
-
2720
-		$storage = $this->createMock(IStorage::class);
2721
-		$path = $this->createMock(File::class);
2722
-		$path->method('getOwner')->willReturn($shareOwner);
2723
-		$path->method('getName')->willReturn('target');
2724
-		$path->method('getId')->willReturn(1);
2725
-		$path->method('getStorage')->willReturn($storage);
2726
-
2727
-		$share = $this->manager->newShare();
2728
-		$share->setShareType(IShare::TYPE_EMAIL)
2729
-			->setNode($path)
2730
-			->setSharedBy('sharedBy')
2731
-			->setPermissions(Constants::PERMISSION_ALL);
2732
-
2733
-		$manager->expects($this->once())
2734
-			->method('canShare')
2735
-			->with($share);
2736
-		$manager->expects($this->once())
2737
-			->method('generalCreateChecks')
2738
-			->with($share);
2739
-
2740
-		$manager->expects($this->once())
2741
-			->method('linkCreateChecks');
2742
-		$manager->expects($this->once())
2743
-			->method('pathCreateChecks')
2744
-			->with($path);
2745
-		$manager->expects($this->once())
2746
-			->method('validateExpirationDateLink')
2747
-			->with($share)
2748
-			->willReturn($share);
2749
-		$manager->expects($this->once())
2750
-			->method('verifyPassword');
2751
-		$manager->expects($this->once())
2752
-			->method('setLinkParent');
2753
-
2754
-		$this->secureRandom->method('generate')
2755
-			->willReturn('token');
2756
-
2757
-		$this->defaultProvider
2758
-			->expects($this->once())
2759
-			->method('create')
2760
-			->with($share)
2761
-			->willReturnCallback(function (Share $share) {
2762
-				return $share->setId(42);
2763
-			});
2764
-
2765
-		$calls = [
2766
-			BeforeShareCreatedEvent::class,
2767
-			ShareCreatedEvent::class,
2768
-		];
2769
-		$this->dispatcher->expects($this->exactly(2))
2770
-			->method('dispatchTyped')
2771
-			->willReturnCallback(function ($event) use (&$calls, $path): void {
2772
-				$expected = array_shift($calls);
2773
-				$this->assertInstanceOf($expected, $event);
2774
-				$share = $event->getShare();
2775
-
2776
-				$this->assertEquals(IShare::TYPE_EMAIL, $share->getShareType(), 'getShareType');
2777
-				$this->assertEquals($path, $share->getNode(), 'getNode');
2778
-				$this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2779
-				$this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2780
-				$this->assertNull($share->getExpirationDate(), 'getExpirationDate');
2781
-				$this->assertNull($share->getPassword(), 'getPassword');
2782
-				$this->assertEquals('token', $share->getToken(), 'getToken');
2783
-
2784
-				if ($expected === ShareCreatedEvent::class) {
2785
-					$this->assertEquals('42', $share->getId(), 'getId');
2786
-					$this->assertEquals('/target', $share->getTarget(), 'getTarget');
2787
-				}
2788
-			});
2789
-
2790
-		/** @var IShare $share */
2791
-		$share = $manager->createShare($share);
2792
-
2793
-		$this->assertSame('shareOwner', $share->getShareOwner());
2794
-		$this->assertEquals('/target', $share->getTarget());
2795
-		$this->assertEquals('token', $share->getToken());
2796
-	}
2797
-
2798
-
2799
-	public function testCreateShareHookError(): void {
2800
-		$this->expectException(\Exception::class);
2801
-		$this->expectExceptionMessage('I won\'t let you share');
2802
-
2803
-		$manager = $this->createManagerMock()
2804
-			->onlyMethods([
2805
-				'canShare',
2806
-				'generalCreateChecks',
2807
-				'userCreateChecks',
2808
-				'pathCreateChecks',
2809
-			])
2810
-			->getMock();
2811
-
2812
-		$shareOwner = $this->createMock(IUser::class);
2813
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2814
-
2815
-		$storage = $this->createMock(IStorage::class);
2816
-		$path = $this->createMock(File::class);
2817
-		$path->method('getOwner')->willReturn($shareOwner);
2818
-		$path->method('getName')->willReturn('target');
2819
-		$path->method('getStorage')->willReturn($storage);
2820
-
2821
-		$share = $this->createShare(
2822
-			null,
2823
-			IShare::TYPE_USER,
2824
-			$path,
2825
-			'sharedWith',
2826
-			'sharedBy',
2827
-			null,
2828
-			Constants::PERMISSION_ALL);
2829
-
2830
-		$manager->expects($this->once())
2831
-			->method('canShare')
2832
-			->with($share);
2833
-		$manager->expects($this->once())
2834
-			->method('generalCreateChecks')
2835
-			->with($share);
2836
-		;
2837
-		$manager->expects($this->once())
2838
-			->method('userCreateChecks')
2839
-			->with($share);
2840
-		;
2841
-		$manager->expects($this->once())
2842
-			->method('pathCreateChecks')
2843
-			->with($path);
2844
-
2845
-		$share->expects($this->once())
2846
-			->method('setShareOwner')
2847
-			->with('shareOwner');
2848
-		$share->expects($this->once())
2849
-			->method('setTarget')
2850
-			->with('/target');
2851
-
2852
-		// Pre share
2853
-		$this->dispatcher->expects($this->once())
2854
-			->method('dispatchTyped')
2855
-			->with(
2856
-				$this->isInstanceOf(BeforeShareCreatedEvent::class)
2857
-			)->willReturnCallback(function (BeforeShareCreatedEvent $e): void {
2858
-				$e->setError('I won\'t let you share!');
2859
-				$e->stopPropagation();
2860
-			}
2861
-			);
2862
-
2863
-		$manager->createShare($share);
2864
-	}
2865
-
2866
-	public function testCreateShareOfIncomingFederatedShare(): void {
2867
-		$manager = $this->createManagerMock()
2868
-			->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2869
-			->getMock();
2870
-
2871
-		$shareOwner = $this->createMock(IUser::class);
2872
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2873
-
2874
-		$storage = $this->createMock(IStorage::class);
2875
-		$storage->method('instanceOfStorage')
2876
-			->with('OCA\Files_Sharing\External\Storage')
2877
-			->willReturn(true);
2878
-
2879
-		$storage2 = $this->createMock(IStorage::class);
2880
-		$storage2->method('instanceOfStorage')
2881
-			->with('OCA\Files_Sharing\External\Storage')
2882
-			->willReturn(false);
2883
-
2884
-		$path = $this->createMock(File::class);
2885
-		$path->expects($this->never())->method('getOwner');
2886
-		$path->method('getName')->willReturn('target');
2887
-		$path->method('getStorage')->willReturn($storage);
2888
-
2889
-		$parent = $this->createMock(Folder::class);
2890
-		$parent->method('getStorage')->willReturn($storage);
2891
-
2892
-		$parentParent = $this->createMock(Folder::class);
2893
-		$parentParent->method('getStorage')->willReturn($storage2);
2894
-		$parentParent->method('getOwner')->willReturn($shareOwner);
2895
-
2896
-		$path->method('getParent')->willReturn($parent);
2897
-		$parent->method('getParent')->willReturn($parentParent);
2898
-
2899
-		$share = $this->createShare(
2900
-			null,
2901
-			IShare::TYPE_USER,
2902
-			$path,
2903
-			'sharedWith',
2904
-			'sharedBy',
2905
-			null,
2906
-			Constants::PERMISSION_ALL);
2907
-
2908
-		$manager->expects($this->once())
2909
-			->method('canShare')
2910
-			->with($share);
2911
-		$manager->expects($this->once())
2912
-			->method('generalCreateChecks')
2913
-			->with($share);
2914
-		;
2915
-		$manager->expects($this->once())
2916
-			->method('userCreateChecks')
2917
-			->with($share);
2918
-		;
2919
-		$manager->expects($this->once())
2920
-			->method('pathCreateChecks')
2921
-			->with($path);
2922
-
2923
-		$this->defaultProvider
2924
-			->expects($this->once())
2925
-			->method('create')
2926
-			->with($share)
2927
-			->willReturnArgument(0);
2928
-
2929
-		$share->expects($this->once())
2930
-			->method('setShareOwner')
2931
-			->with('shareOwner');
2932
-		$share->expects($this->once())
2933
-			->method('setTarget')
2934
-			->with('/target');
2935
-
2936
-		$manager->createShare($share);
2937
-	}
2938
-
2939
-	public function testGetSharesBy(): void {
2940
-		$share = $this->manager->newShare();
2941
-
2942
-		$node = $this->createMock(Folder::class);
2943
-
2944
-		$this->defaultProvider->expects($this->once())
2945
-			->method('getSharesBy')
2946
-			->with(
2947
-				$this->equalTo('user'),
2948
-				$this->equalTo(IShare::TYPE_USER),
2949
-				$this->equalTo($node),
2950
-				$this->equalTo(true),
2951
-				$this->equalTo(1),
2952
-				$this->equalTo(1)
2953
-			)->willReturn([$share]);
2954
-
2955
-		$shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2956
-
2957
-		$this->assertCount(1, $shares);
2958
-		$this->assertSame($share, $shares[0]);
2959
-	}
2960
-
2961
-	public function testGetSharesByOwnerless(): void {
2962
-		$mount = $this->createMock(IShareOwnerlessMount::class);
2963
-
2964
-		$node = $this->createMock(Folder::class);
2965
-		$node
2966
-			->expects($this->once())
2967
-			->method('getMountPoint')
2968
-			->willReturn($mount);
2969
-
2970
-		$share = $this->manager->newShare();
2971
-		$share->setNode($node);
2972
-		$share->setShareType(IShare::TYPE_USER);
2973
-
2974
-		$this->defaultProvider
2975
-			->expects($this->once())
2976
-			->method('getSharesByPath')
2977
-			->with($this->equalTo($node))
2978
-			->willReturn([$share]);
2979
-
2980
-		$shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2981
-
2982
-		$this->assertCount(1, $shares);
2983
-		$this->assertSame($share, $shares[0]);
2984
-	}
2985
-
2986
-	/**
2987
-	 * Test to ensure we correctly remove expired link shares
2988
-	 *
2989
-	 * We have 8 Shares and we want the 3 first valid shares.
2990
-	 * share 3-6 and 8 are expired. Thus at the end of this test we should
2991
-	 * have received share 1,2 and 7. And from the manager. Share 3-6 should be
2992
-	 * deleted (as they are evaluated). but share 8 should still be there.
2993
-	 */
2994
-	public function testGetSharesByExpiredLinkShares(): void {
2995
-		$manager = $this->createManagerMock()
2996
-			->onlyMethods(['deleteShare'])
2997
-			->getMock();
2998
-
2999
-		/** @var IShare[] $shares */
3000
-		$shares = [];
3001
-
3002
-		/*
2444
+        $data[] = [false, 'no', false];
2445
+        $data[] = [false, 'no', true];
2446
+        $data[] = [true, 'yes', false];
2447
+        $data[] = [false, 'yes', true];
2448
+
2449
+        return $data;
2450
+    }
2451
+
2452
+    /**
2453
+     *
2454
+     * @param bool $expected
2455
+     * @param string $sharingEnabled
2456
+     * @param bool $disabledForUser
2457
+     */
2458
+    #[DataProvider('dataCanShare')]
2459
+    public function testCanShare($expected, $sharingEnabled, $disabledForUser): void {
2460
+        $this->config->method('getAppValue')
2461
+            ->willReturnMap([
2462
+                ['core', 'shareapi_enabled', 'yes', $sharingEnabled],
2463
+            ]);
2464
+
2465
+        $manager = $this->createManagerMock()
2466
+            ->onlyMethods(['sharingDisabledForUser'])
2467
+            ->getMock();
2468
+
2469
+        $manager->method('sharingDisabledForUser')
2470
+            ->with('user')
2471
+            ->willReturn($disabledForUser);
2472
+
2473
+        $share = $this->manager->newShare();
2474
+        $share->setSharedBy('user');
2475
+
2476
+        $exception = false;
2477
+        try {
2478
+            $res = self::invokePrivate($manager, 'canShare', [$share]);
2479
+        } catch (\Exception $e) {
2480
+            $exception = true;
2481
+        }
2482
+
2483
+        $this->assertEquals($expected, !$exception);
2484
+    }
2485
+
2486
+    public function testCreateShareUser(): void {
2487
+        /** @var Manager&MockObject $manager */
2488
+        $manager = $this->createManagerMock()
2489
+            ->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2490
+            ->getMock();
2491
+
2492
+        $shareOwner = $this->createMock(IUser::class);
2493
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2494
+
2495
+        $storage = $this->createMock(IStorage::class);
2496
+        $path = $this->createMock(File::class);
2497
+        $path->method('getOwner')->willReturn($shareOwner);
2498
+        $path->method('getName')->willReturn('target');
2499
+        $path->method('getStorage')->willReturn($storage);
2500
+
2501
+        $share = $this->createShare(
2502
+            null,
2503
+            IShare::TYPE_USER,
2504
+            $path,
2505
+            'sharedWith',
2506
+            'sharedBy',
2507
+            null,
2508
+            Constants::PERMISSION_ALL);
2509
+
2510
+        $manager->expects($this->once())
2511
+            ->method('canShare')
2512
+            ->with($share);
2513
+        $manager->expects($this->once())
2514
+            ->method('generalCreateChecks')
2515
+            ->with($share);
2516
+        ;
2517
+        $manager->expects($this->once())
2518
+            ->method('userCreateChecks')
2519
+            ->with($share);
2520
+        ;
2521
+        $manager->expects($this->once())
2522
+            ->method('pathCreateChecks')
2523
+            ->with($path);
2524
+
2525
+        $this->defaultProvider
2526
+            ->expects($this->once())
2527
+            ->method('create')
2528
+            ->with($share)
2529
+            ->willReturnArgument(0);
2530
+
2531
+        $share->expects($this->once())
2532
+            ->method('setShareOwner')
2533
+            ->with('shareOwner');
2534
+        $share->expects($this->once())
2535
+            ->method('setTarget')
2536
+            ->with('/target');
2537
+
2538
+        $manager->createShare($share);
2539
+    }
2540
+
2541
+    public function testCreateShareGroup(): void {
2542
+        $manager = $this->createManagerMock()
2543
+            ->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
2544
+            ->getMock();
2545
+
2546
+        $shareOwner = $this->createMock(IUser::class);
2547
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2548
+
2549
+        $storage = $this->createMock(IStorage::class);
2550
+        $path = $this->createMock(File::class);
2551
+        $path->method('getOwner')->willReturn($shareOwner);
2552
+        $path->method('getName')->willReturn('target');
2553
+        $path->method('getStorage')->willReturn($storage);
2554
+
2555
+        $share = $this->createShare(
2556
+            null,
2557
+            IShare::TYPE_GROUP,
2558
+            $path,
2559
+            'sharedWith',
2560
+            'sharedBy',
2561
+            null,
2562
+            Constants::PERMISSION_ALL);
2563
+
2564
+        $manager->expects($this->once())
2565
+            ->method('canShare')
2566
+            ->with($share);
2567
+        $manager->expects($this->once())
2568
+            ->method('generalCreateChecks')
2569
+            ->with($share);
2570
+        ;
2571
+        $manager->expects($this->once())
2572
+            ->method('groupCreateChecks')
2573
+            ->with($share);
2574
+        ;
2575
+        $manager->expects($this->once())
2576
+            ->method('pathCreateChecks')
2577
+            ->with($path);
2578
+
2579
+        $this->defaultProvider
2580
+            ->expects($this->once())
2581
+            ->method('create')
2582
+            ->with($share)
2583
+            ->willReturnArgument(0);
2584
+
2585
+        $share->expects($this->once())
2586
+            ->method('setShareOwner')
2587
+            ->with('shareOwner');
2588
+        $share->expects($this->once())
2589
+            ->method('setTarget')
2590
+            ->with('/target');
2591
+
2592
+        $manager->createShare($share);
2593
+    }
2594
+
2595
+    public function testCreateShareLink(): void {
2596
+        $manager = $this->createManagerMock()
2597
+            ->onlyMethods([
2598
+                'canShare',
2599
+                'generalCreateChecks',
2600
+                'linkCreateChecks',
2601
+                'pathCreateChecks',
2602
+                'validateExpirationDateLink',
2603
+                'verifyPassword',
2604
+                'setLinkParent',
2605
+            ])
2606
+            ->getMock();
2607
+
2608
+        $shareOwner = $this->createMock(IUser::class);
2609
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2610
+
2611
+        $storage = $this->createMock(IStorage::class);
2612
+        $path = $this->createMock(File::class);
2613
+        $path->method('getOwner')->willReturn($shareOwner);
2614
+        $path->method('getName')->willReturn('target');
2615
+        $path->method('getId')->willReturn(1);
2616
+        $path->method('getStorage')->willReturn($storage);
2617
+
2618
+        $date = new \DateTime();
2619
+
2620
+        $share = $this->manager->newShare();
2621
+        $share->setShareType(IShare::TYPE_LINK)
2622
+            ->setNode($path)
2623
+            ->setSharedBy('sharedBy')
2624
+            ->setPermissions(Constants::PERMISSION_ALL)
2625
+            ->setExpirationDate($date)
2626
+            ->setPassword('password');
2627
+
2628
+        $manager->expects($this->once())
2629
+            ->method('canShare')
2630
+            ->with($share);
2631
+        $manager->expects($this->once())
2632
+            ->method('generalCreateChecks')
2633
+            ->with($share);
2634
+        ;
2635
+        $manager->expects($this->once())
2636
+            ->method('linkCreateChecks')
2637
+            ->with($share);
2638
+        ;
2639
+        $manager->expects($this->once())
2640
+            ->method('pathCreateChecks')
2641
+            ->with($path);
2642
+        $manager->expects($this->once())
2643
+            ->method('validateExpirationDateLink')
2644
+            ->with($share)
2645
+            ->willReturn($share);
2646
+        $manager->expects($this->once())
2647
+            ->method('verifyPassword')
2648
+            ->with('password');
2649
+        $manager->expects($this->once())
2650
+            ->method('setLinkParent')
2651
+            ->with($share);
2652
+
2653
+        $this->hasher->expects($this->once())
2654
+            ->method('hash')
2655
+            ->with('password')
2656
+            ->willReturn('hashed');
2657
+
2658
+        $this->secureRandom->method('generate')
2659
+            ->willReturn('token');
2660
+
2661
+        $this->defaultProvider
2662
+            ->expects($this->once())
2663
+            ->method('create')
2664
+            ->with($share)
2665
+            ->willReturnCallback(function (Share $share) {
2666
+                return $share->setId(42);
2667
+            });
2668
+
2669
+        $calls = [
2670
+            BeforeShareCreatedEvent::class,
2671
+            ShareCreatedEvent::class,
2672
+        ];
2673
+        $this->dispatcher->expects($this->exactly(2))
2674
+            ->method('dispatchTyped')
2675
+            ->willReturnCallback(function ($event) use (&$calls, $date, $path): void {
2676
+                $expected = array_shift($calls);
2677
+                $this->assertInstanceOf($expected, $event);
2678
+                $share = $event->getShare();
2679
+
2680
+                $this->assertEquals(IShare::TYPE_LINK, $share->getShareType(), 'getShareType');
2681
+                $this->assertEquals($path, $share->getNode(), 'getNode');
2682
+                $this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2683
+                $this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2684
+                $this->assertEquals($date, $share->getExpirationDate(), 'getExpirationDate');
2685
+                $this->assertEquals('hashed', $share->getPassword(), 'getPassword');
2686
+                $this->assertEquals('token', $share->getToken(), 'getToken');
2687
+
2688
+                if ($expected === ShareCreatedEvent::class) {
2689
+                    $this->assertEquals('42', $share->getId(), 'getId');
2690
+                    $this->assertEquals('/target', $share->getTarget(), 'getTarget');
2691
+                }
2692
+            });
2693
+
2694
+        /** @var IShare $share */
2695
+        $share = $manager->createShare($share);
2696
+
2697
+        $this->assertSame('shareOwner', $share->getShareOwner());
2698
+        $this->assertEquals('/target', $share->getTarget());
2699
+        $this->assertSame($date, $share->getExpirationDate());
2700
+        $this->assertEquals('token', $share->getToken());
2701
+        $this->assertEquals('hashed', $share->getPassword());
2702
+    }
2703
+
2704
+    public function testCreateShareMail(): void {
2705
+        $manager = $this->createManagerMock()
2706
+            ->onlyMethods([
2707
+                'canShare',
2708
+                'generalCreateChecks',
2709
+                'linkCreateChecks',
2710
+                'pathCreateChecks',
2711
+                'validateExpirationDateLink',
2712
+                'verifyPassword',
2713
+                'setLinkParent',
2714
+            ])
2715
+            ->getMock();
2716
+
2717
+        $shareOwner = $this->createMock(IUser::class);
2718
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2719
+
2720
+        $storage = $this->createMock(IStorage::class);
2721
+        $path = $this->createMock(File::class);
2722
+        $path->method('getOwner')->willReturn($shareOwner);
2723
+        $path->method('getName')->willReturn('target');
2724
+        $path->method('getId')->willReturn(1);
2725
+        $path->method('getStorage')->willReturn($storage);
2726
+
2727
+        $share = $this->manager->newShare();
2728
+        $share->setShareType(IShare::TYPE_EMAIL)
2729
+            ->setNode($path)
2730
+            ->setSharedBy('sharedBy')
2731
+            ->setPermissions(Constants::PERMISSION_ALL);
2732
+
2733
+        $manager->expects($this->once())
2734
+            ->method('canShare')
2735
+            ->with($share);
2736
+        $manager->expects($this->once())
2737
+            ->method('generalCreateChecks')
2738
+            ->with($share);
2739
+
2740
+        $manager->expects($this->once())
2741
+            ->method('linkCreateChecks');
2742
+        $manager->expects($this->once())
2743
+            ->method('pathCreateChecks')
2744
+            ->with($path);
2745
+        $manager->expects($this->once())
2746
+            ->method('validateExpirationDateLink')
2747
+            ->with($share)
2748
+            ->willReturn($share);
2749
+        $manager->expects($this->once())
2750
+            ->method('verifyPassword');
2751
+        $manager->expects($this->once())
2752
+            ->method('setLinkParent');
2753
+
2754
+        $this->secureRandom->method('generate')
2755
+            ->willReturn('token');
2756
+
2757
+        $this->defaultProvider
2758
+            ->expects($this->once())
2759
+            ->method('create')
2760
+            ->with($share)
2761
+            ->willReturnCallback(function (Share $share) {
2762
+                return $share->setId(42);
2763
+            });
2764
+
2765
+        $calls = [
2766
+            BeforeShareCreatedEvent::class,
2767
+            ShareCreatedEvent::class,
2768
+        ];
2769
+        $this->dispatcher->expects($this->exactly(2))
2770
+            ->method('dispatchTyped')
2771
+            ->willReturnCallback(function ($event) use (&$calls, $path): void {
2772
+                $expected = array_shift($calls);
2773
+                $this->assertInstanceOf($expected, $event);
2774
+                $share = $event->getShare();
2775
+
2776
+                $this->assertEquals(IShare::TYPE_EMAIL, $share->getShareType(), 'getShareType');
2777
+                $this->assertEquals($path, $share->getNode(), 'getNode');
2778
+                $this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2779
+                $this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2780
+                $this->assertNull($share->getExpirationDate(), 'getExpirationDate');
2781
+                $this->assertNull($share->getPassword(), 'getPassword');
2782
+                $this->assertEquals('token', $share->getToken(), 'getToken');
2783
+
2784
+                if ($expected === ShareCreatedEvent::class) {
2785
+                    $this->assertEquals('42', $share->getId(), 'getId');
2786
+                    $this->assertEquals('/target', $share->getTarget(), 'getTarget');
2787
+                }
2788
+            });
2789
+
2790
+        /** @var IShare $share */
2791
+        $share = $manager->createShare($share);
2792
+
2793
+        $this->assertSame('shareOwner', $share->getShareOwner());
2794
+        $this->assertEquals('/target', $share->getTarget());
2795
+        $this->assertEquals('token', $share->getToken());
2796
+    }
2797
+
2798
+
2799
+    public function testCreateShareHookError(): void {
2800
+        $this->expectException(\Exception::class);
2801
+        $this->expectExceptionMessage('I won\'t let you share');
2802
+
2803
+        $manager = $this->createManagerMock()
2804
+            ->onlyMethods([
2805
+                'canShare',
2806
+                'generalCreateChecks',
2807
+                'userCreateChecks',
2808
+                'pathCreateChecks',
2809
+            ])
2810
+            ->getMock();
2811
+
2812
+        $shareOwner = $this->createMock(IUser::class);
2813
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2814
+
2815
+        $storage = $this->createMock(IStorage::class);
2816
+        $path = $this->createMock(File::class);
2817
+        $path->method('getOwner')->willReturn($shareOwner);
2818
+        $path->method('getName')->willReturn('target');
2819
+        $path->method('getStorage')->willReturn($storage);
2820
+
2821
+        $share = $this->createShare(
2822
+            null,
2823
+            IShare::TYPE_USER,
2824
+            $path,
2825
+            'sharedWith',
2826
+            'sharedBy',
2827
+            null,
2828
+            Constants::PERMISSION_ALL);
2829
+
2830
+        $manager->expects($this->once())
2831
+            ->method('canShare')
2832
+            ->with($share);
2833
+        $manager->expects($this->once())
2834
+            ->method('generalCreateChecks')
2835
+            ->with($share);
2836
+        ;
2837
+        $manager->expects($this->once())
2838
+            ->method('userCreateChecks')
2839
+            ->with($share);
2840
+        ;
2841
+        $manager->expects($this->once())
2842
+            ->method('pathCreateChecks')
2843
+            ->with($path);
2844
+
2845
+        $share->expects($this->once())
2846
+            ->method('setShareOwner')
2847
+            ->with('shareOwner');
2848
+        $share->expects($this->once())
2849
+            ->method('setTarget')
2850
+            ->with('/target');
2851
+
2852
+        // Pre share
2853
+        $this->dispatcher->expects($this->once())
2854
+            ->method('dispatchTyped')
2855
+            ->with(
2856
+                $this->isInstanceOf(BeforeShareCreatedEvent::class)
2857
+            )->willReturnCallback(function (BeforeShareCreatedEvent $e): void {
2858
+                $e->setError('I won\'t let you share!');
2859
+                $e->stopPropagation();
2860
+            }
2861
+            );
2862
+
2863
+        $manager->createShare($share);
2864
+    }
2865
+
2866
+    public function testCreateShareOfIncomingFederatedShare(): void {
2867
+        $manager = $this->createManagerMock()
2868
+            ->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2869
+            ->getMock();
2870
+
2871
+        $shareOwner = $this->createMock(IUser::class);
2872
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2873
+
2874
+        $storage = $this->createMock(IStorage::class);
2875
+        $storage->method('instanceOfStorage')
2876
+            ->with('OCA\Files_Sharing\External\Storage')
2877
+            ->willReturn(true);
2878
+
2879
+        $storage2 = $this->createMock(IStorage::class);
2880
+        $storage2->method('instanceOfStorage')
2881
+            ->with('OCA\Files_Sharing\External\Storage')
2882
+            ->willReturn(false);
2883
+
2884
+        $path = $this->createMock(File::class);
2885
+        $path->expects($this->never())->method('getOwner');
2886
+        $path->method('getName')->willReturn('target');
2887
+        $path->method('getStorage')->willReturn($storage);
2888
+
2889
+        $parent = $this->createMock(Folder::class);
2890
+        $parent->method('getStorage')->willReturn($storage);
2891
+
2892
+        $parentParent = $this->createMock(Folder::class);
2893
+        $parentParent->method('getStorage')->willReturn($storage2);
2894
+        $parentParent->method('getOwner')->willReturn($shareOwner);
2895
+
2896
+        $path->method('getParent')->willReturn($parent);
2897
+        $parent->method('getParent')->willReturn($parentParent);
2898
+
2899
+        $share = $this->createShare(
2900
+            null,
2901
+            IShare::TYPE_USER,
2902
+            $path,
2903
+            'sharedWith',
2904
+            'sharedBy',
2905
+            null,
2906
+            Constants::PERMISSION_ALL);
2907
+
2908
+        $manager->expects($this->once())
2909
+            ->method('canShare')
2910
+            ->with($share);
2911
+        $manager->expects($this->once())
2912
+            ->method('generalCreateChecks')
2913
+            ->with($share);
2914
+        ;
2915
+        $manager->expects($this->once())
2916
+            ->method('userCreateChecks')
2917
+            ->with($share);
2918
+        ;
2919
+        $manager->expects($this->once())
2920
+            ->method('pathCreateChecks')
2921
+            ->with($path);
2922
+
2923
+        $this->defaultProvider
2924
+            ->expects($this->once())
2925
+            ->method('create')
2926
+            ->with($share)
2927
+            ->willReturnArgument(0);
2928
+
2929
+        $share->expects($this->once())
2930
+            ->method('setShareOwner')
2931
+            ->with('shareOwner');
2932
+        $share->expects($this->once())
2933
+            ->method('setTarget')
2934
+            ->with('/target');
2935
+
2936
+        $manager->createShare($share);
2937
+    }
2938
+
2939
+    public function testGetSharesBy(): void {
2940
+        $share = $this->manager->newShare();
2941
+
2942
+        $node = $this->createMock(Folder::class);
2943
+
2944
+        $this->defaultProvider->expects($this->once())
2945
+            ->method('getSharesBy')
2946
+            ->with(
2947
+                $this->equalTo('user'),
2948
+                $this->equalTo(IShare::TYPE_USER),
2949
+                $this->equalTo($node),
2950
+                $this->equalTo(true),
2951
+                $this->equalTo(1),
2952
+                $this->equalTo(1)
2953
+            )->willReturn([$share]);
2954
+
2955
+        $shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2956
+
2957
+        $this->assertCount(1, $shares);
2958
+        $this->assertSame($share, $shares[0]);
2959
+    }
2960
+
2961
+    public function testGetSharesByOwnerless(): void {
2962
+        $mount = $this->createMock(IShareOwnerlessMount::class);
2963
+
2964
+        $node = $this->createMock(Folder::class);
2965
+        $node
2966
+            ->expects($this->once())
2967
+            ->method('getMountPoint')
2968
+            ->willReturn($mount);
2969
+
2970
+        $share = $this->manager->newShare();
2971
+        $share->setNode($node);
2972
+        $share->setShareType(IShare::TYPE_USER);
2973
+
2974
+        $this->defaultProvider
2975
+            ->expects($this->once())
2976
+            ->method('getSharesByPath')
2977
+            ->with($this->equalTo($node))
2978
+            ->willReturn([$share]);
2979
+
2980
+        $shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2981
+
2982
+        $this->assertCount(1, $shares);
2983
+        $this->assertSame($share, $shares[0]);
2984
+    }
2985
+
2986
+    /**
2987
+     * Test to ensure we correctly remove expired link shares
2988
+     *
2989
+     * We have 8 Shares and we want the 3 first valid shares.
2990
+     * share 3-6 and 8 are expired. Thus at the end of this test we should
2991
+     * have received share 1,2 and 7. And from the manager. Share 3-6 should be
2992
+     * deleted (as they are evaluated). but share 8 should still be there.
2993
+     */
2994
+    public function testGetSharesByExpiredLinkShares(): void {
2995
+        $manager = $this->createManagerMock()
2996
+            ->onlyMethods(['deleteShare'])
2997
+            ->getMock();
2998
+
2999
+        /** @var IShare[] $shares */
3000
+        $shares = [];
3001
+
3002
+        /*
3003 3003
 		 * This results in an array of 8 IShare elements
3004 3004
 		 */
3005
-		for ($i = 0; $i < 8; $i++) {
3006
-			$share = $this->manager->newShare();
3007
-			$share->setId($i);
3008
-			$shares[] = $share;
3009
-		}
3005
+        for ($i = 0; $i < 8; $i++) {
3006
+            $share = $this->manager->newShare();
3007
+            $share->setId($i);
3008
+            $shares[] = $share;
3009
+        }
3010 3010
 
3011
-		$today = new \DateTime();
3012
-		$today->setTime(0, 0, 0);
3011
+        $today = new \DateTime();
3012
+        $today->setTime(0, 0, 0);
3013 3013
 
3014
-		/*
3014
+        /*
3015 3015
 		 * Set the expiration date to today for some shares
3016 3016
 		 */
3017
-		$shares[2]->setExpirationDate($today);
3018
-		$shares[3]->setExpirationDate($today);
3019
-		$shares[4]->setExpirationDate($today);
3020
-		$shares[5]->setExpirationDate($today);
3017
+        $shares[2]->setExpirationDate($today);
3018
+        $shares[3]->setExpirationDate($today);
3019
+        $shares[4]->setExpirationDate($today);
3020
+        $shares[5]->setExpirationDate($today);
3021 3021
 
3022
-		/** @var IShare[] $i */
3023
-		$shares2 = [];
3024
-		for ($i = 0; $i < 8; $i++) {
3025
-			$shares2[] = clone $shares[$i];
3026
-		}
3022
+        /** @var IShare[] $i */
3023
+        $shares2 = [];
3024
+        for ($i = 0; $i < 8; $i++) {
3025
+            $shares2[] = clone $shares[$i];
3026
+        }
3027 3027
 
3028
-		$node = $this->createMock(File::class);
3028
+        $node = $this->createMock(File::class);
3029 3029
 
3030
-		/*
3030
+        /*
3031 3031
 		 * Simulate the getSharesBy call.
3032 3032
 		 */
3033
-		$this->defaultProvider
3034
-			->method('getSharesBy')
3035
-			->willReturnCallback(function ($uid, $type, $node, $reshares, $limit, $offset) use (&$shares2) {
3036
-				return array_slice($shares2, $offset, $limit);
3037
-			});
3033
+        $this->defaultProvider
3034
+            ->method('getSharesBy')
3035
+            ->willReturnCallback(function ($uid, $type, $node, $reshares, $limit, $offset) use (&$shares2) {
3036
+                return array_slice($shares2, $offset, $limit);
3037
+            });
3038 3038
 
3039
-		/*
3039
+        /*
3040 3040
 		 * Simulate the deleteShare call.
3041 3041
 		 */
3042
-		$manager->method('deleteShare')
3043
-			->willReturnCallback(function ($share) use (&$shares2): void {
3044
-				for ($i = 0; $i < count($shares2); $i++) {
3045
-					if ($shares2[$i]->getId() === $share->getId()) {
3046
-						array_splice($shares2, $i, 1);
3047
-						break;
3048
-					}
3049
-				}
3050
-			});
3051
-
3052
-		$res = $manager->getSharesBy('user', IShare::TYPE_LINK, $node, true, 3, 0);
3053
-
3054
-		$this->assertCount(3, $res);
3055
-		$this->assertEquals($shares[0]->getId(), $res[0]->getId());
3056
-		$this->assertEquals($shares[1]->getId(), $res[1]->getId());
3057
-		$this->assertEquals($shares[6]->getId(), $res[2]->getId());
3058
-
3059
-		$this->assertCount(4, $shares2);
3060
-		$this->assertEquals(0, $shares2[0]->getId());
3061
-		$this->assertEquals(1, $shares2[1]->getId());
3062
-		$this->assertEquals(6, $shares2[2]->getId());
3063
-		$this->assertEquals(7, $shares2[3]->getId());
3064
-		$this->assertSame($today, $shares[3]->getExpirationDate());
3065
-	}
3066
-
3067
-	public function testGetShareByToken(): void {
3068
-		$this->config
3069
-			->expects($this->exactly(2))
3070
-			->method('getAppValue')
3071
-			->willReturnMap([
3072
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3073
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3074
-			]);
3075
-
3076
-		$factory = $this->createMock(IProviderFactory::class);
3077
-
3078
-		$manager = $this->createManager($factory);
3079
-
3080
-		$share = $this->createMock(IShare::class);
3081
-
3082
-		$factory->expects($this->once())
3083
-			->method('getProviderForType')
3084
-			->with(IShare::TYPE_LINK)
3085
-			->willReturn($this->defaultProvider);
3086
-
3087
-		$this->defaultProvider->expects($this->once())
3088
-			->method('getShareByToken')
3089
-			->with('token')
3090
-			->willReturn($share);
3091
-
3092
-		$ret = $manager->getShareByToken('token');
3093
-		$this->assertSame($share, $ret);
3094
-	}
3095
-
3096
-	public function testGetShareByTokenRoom(): void {
3097
-		$this->config
3098
-			->expects($this->exactly(2))
3099
-			->method('getAppValue')
3100
-			->willReturnMap([
3101
-				['core', 'shareapi_allow_links', 'yes', 'no'],
3102
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3103
-			]);
3104
-
3105
-		$factory = $this->createMock(IProviderFactory::class);
3106
-
3107
-		$manager = $this->createManager($factory);
3108
-
3109
-		$share = $this->createMock(IShare::class);
3110
-
3111
-		$roomShareProvider = $this->createMock(IShareProvider::class);
3112
-
3113
-		$factory->expects($this->any())
3114
-			->method('getProviderForType')
3115
-			->willReturnCallback(function ($shareType) use ($roomShareProvider) {
3116
-				if ($shareType !== IShare::TYPE_ROOM) {
3117
-					throw new ProviderException();
3118
-				}
3119
-
3120
-				return $roomShareProvider;
3121
-			});
3122
-
3123
-		$roomShareProvider->expects($this->once())
3124
-			->method('getShareByToken')
3125
-			->with('token')
3126
-			->willReturn($share);
3127
-
3128
-		$ret = $manager->getShareByToken('token');
3129
-		$this->assertSame($share, $ret);
3130
-	}
3131
-
3132
-	public function testGetShareByTokenWithException(): void {
3133
-		$this->config
3134
-			->expects($this->exactly(2))
3135
-			->method('getAppValue')
3136
-			->willReturnMap([
3137
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3138
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3139
-			]);
3140
-
3141
-		$factory = $this->createMock(IProviderFactory::class);
3142
-
3143
-		$manager = $this->createManager($factory);
3144
-
3145
-		$share = $this->createMock(IShare::class);
3146
-
3147
-		$calls = [
3148
-			[IShare::TYPE_LINK],
3149
-			[IShare::TYPE_REMOTE],
3150
-		];
3151
-		$factory->expects($this->exactly(2))
3152
-			->method('getProviderForType')
3153
-			->willReturnCallback(function () use (&$calls) {
3154
-				$expected = array_shift($calls);
3155
-				$this->assertEquals($expected, func_get_args());
3156
-				return $this->defaultProvider;
3157
-			});
3158
-
3159
-		$this->defaultProvider->expects($this->exactly(2))
3160
-			->method('getShareByToken')
3161
-			->with('token')
3162
-			->willReturnOnConsecutiveCalls(
3163
-				$this->throwException(new ShareNotFound()),
3164
-				$share
3165
-			);
3166
-
3167
-		$ret = $manager->getShareByToken('token');
3168
-		$this->assertSame($share, $ret);
3169
-	}
3170
-
3171
-
3172
-	public function testGetShareByTokenHideDisabledUser(): void {
3173
-		$this->expectException(ShareNotFound::class);
3174
-		$this->expectExceptionMessage('The requested share comes from a disabled user');
3175
-
3176
-		$this->config
3177
-			->expects($this->exactly(2))
3178
-			->method('getAppValue')
3179
-			->willReturnMap([
3180
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3181
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'yes'],
3182
-			]);
3183
-
3184
-		$this->l->expects($this->once())
3185
-			->method('t')
3186
-			->willReturnArgument(0);
3187
-
3188
-		$manager = $this->createManagerMock()
3189
-			->onlyMethods(['deleteShare'])
3190
-			->getMock();
3191
-
3192
-		$date = new \DateTime();
3193
-		$date->setTime(0, 0, 0);
3194
-		$date->add(new \DateInterval('P2D'));
3195
-		$share = $this->manager->newShare();
3196
-		$share->setExpirationDate($date);
3197
-		$share->setShareOwner('owner');
3198
-		$share->setSharedBy('sharedBy');
3199
-
3200
-		$sharedBy = $this->createMock(IUser::class);
3201
-		$owner = $this->createMock(IUser::class);
3202
-
3203
-		$this->userManager->method('get')->willReturnMap([
3204
-			['sharedBy', $sharedBy],
3205
-			['owner', $owner],
3206
-		]);
3207
-
3208
-		$owner->expects($this->once())
3209
-			->method('isEnabled')
3210
-			->willReturn(true);
3211
-		$sharedBy->expects($this->once())
3212
-			->method('isEnabled')
3213
-			->willReturn(false);
3214
-
3215
-		$this->defaultProvider->expects($this->once())
3216
-			->method('getShareByToken')
3217
-			->with('expiredToken')
3218
-			->willReturn($share);
3219
-
3220
-		$manager->expects($this->never())
3221
-			->method('deleteShare');
3222
-
3223
-		$manager->getShareByToken('expiredToken');
3224
-	}
3225
-
3226
-
3227
-	public function testGetShareByTokenExpired(): void {
3228
-		$this->expectException(ShareNotFound::class);
3229
-		$this->expectExceptionMessage('The requested share does not exist anymore');
3230
-
3231
-		$this->config
3232
-			->expects($this->once())
3233
-			->method('getAppValue')
3234
-			->with('core', 'shareapi_allow_links', 'yes')
3235
-			->willReturn('yes');
3236
-
3237
-		$this->l->expects($this->once())
3238
-			->method('t')
3239
-			->willReturnArgument(0);
3240
-
3241
-		$manager = $this->createManagerMock()
3242
-			->onlyMethods(['deleteShare'])
3243
-			->getMock();
3244
-
3245
-		$date = new \DateTime();
3246
-		$date->setTime(0, 0, 0);
3247
-		$share = $this->manager->newShare();
3248
-		$share->setExpirationDate($date);
3249
-
3250
-		$this->defaultProvider->expects($this->once())
3251
-			->method('getShareByToken')
3252
-			->with('expiredToken')
3253
-			->willReturn($share);
3254
-
3255
-		$manager->expects($this->once())
3256
-			->method('deleteShare')
3257
-			->with($this->equalTo($share));
3258
-
3259
-		$manager->getShareByToken('expiredToken');
3260
-	}
3261
-
3262
-	public function testGetShareByTokenNotExpired(): void {
3263
-		$this->config
3264
-			->expects($this->exactly(2))
3265
-			->method('getAppValue')
3266
-			->willReturnMap([
3267
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3268
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3269
-			]);
3270
-
3271
-		$date = new \DateTime();
3272
-		$date->setTime(0, 0, 0);
3273
-		$date->add(new \DateInterval('P2D'));
3274
-		$share = $this->manager->newShare();
3275
-		$share->setExpirationDate($date);
3276
-
3277
-		$this->defaultProvider->expects($this->once())
3278
-			->method('getShareByToken')
3279
-			->with('expiredToken')
3280
-			->willReturn($share);
3281
-
3282
-		$res = $this->manager->getShareByToken('expiredToken');
3283
-
3284
-		$this->assertSame($share, $res);
3285
-	}
3286
-
3287
-
3288
-	public function testGetShareByTokenWithPublicLinksDisabled(): void {
3289
-		$this->expectException(ShareNotFound::class);
3290
-
3291
-		$this->config
3292
-			->expects($this->once())
3293
-			->method('getAppValue')
3294
-			->with('core', 'shareapi_allow_links', 'yes')
3295
-			->willReturn('no');
3296
-		$this->manager->getShareByToken('validToken');
3297
-	}
3298
-
3299
-	public function testGetShareByTokenPublicUploadDisabled(): void {
3300
-		$this->config
3301
-			->expects($this->exactly(5))
3302
-			->method('getAppValue')
3303
-			->willReturnMap([
3304
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3305
-				['core', 'shareapi_allow_public_upload', 'yes', 'no'],
3306
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3307
-				['core', 'shareapi_allow_links_exclude_groups', '[]', '[]'],
3308
-			]);
3309
-
3310
-		$share = $this->manager->newShare();
3311
-		$share->setShareType(IShare::TYPE_LINK)
3312
-			->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
3313
-		$share->setSharedWith('sharedWith');
3314
-		$share->setShareOwner('shareOwner');
3315
-		$folder = $this->createMock(\OC\Files\Node\Folder::class);
3316
-		$share->setNode($folder);
3317
-
3318
-		$shareOwner = $this->createMock(IUser::class);
3319
-		$this->userManager->expects($this->once())
3320
-			->method('get')
3321
-			->with('shareOwner')
3322
-			->willReturn($shareOwner);
3323
-
3324
-		$this->defaultProvider->expects($this->once())
3325
-			->method('getShareByToken')
3326
-			->willReturn('validToken')
3327
-			->willReturn($share);
3328
-
3329
-		$res = $this->manager->getShareByToken('validToken');
3330
-
3331
-		$this->assertSame(Constants::PERMISSION_READ, $res->getPermissions());
3332
-	}
3333
-
3334
-	public function testGetShareByTokenShareOwnerExcludedFromLinkShares(): void {
3335
-		$this->expectException(ShareNotFound::class);
3336
-		$this->expectExceptionMessage('The requested share does not exist anymore');
3337
-
3338
-		$this->config
3339
-			->expects($this->exactly(4))
3340
-			->method('getAppValue')
3341
-			->willReturnMap([
3342
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3343
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3344
-				['core', 'shareapi_allow_links_exclude_groups', '[]', '["excludedGroup"]'],
3345
-			]);
3346
-
3347
-		$this->l->expects($this->once())
3348
-			->method('t')
3349
-			->willReturnArgument(0);
3350
-
3351
-		$share = $this->manager->newShare();
3352
-		$share->setShareType(IShare::TYPE_LINK)
3353
-			->setPermissions(Constants::PERMISSION_READ);
3354
-		$share->setShareOwner('shareOwner');
3355
-		$file = $this->createMock(File::class);
3356
-		$share->setNode($file);
3357
-
3358
-		$shareOwner = $this->createMock(IUser::class);
3359
-		$this->userManager->expects($this->once())
3360
-			->method('get')
3361
-			->with('shareOwner')
3362
-			->willReturn($shareOwner);
3363
-
3364
-		$this->groupManager->expects($this->once())
3365
-			->method('getUserGroupIds')
3366
-			->with($shareOwner)
3367
-			->willReturn(['excludedGroup', 'otherGroup']);
3368
-
3369
-		$this->defaultProvider->expects($this->once())
3370
-			->method('getShareByToken')
3371
-			->with('token')
3372
-			->willReturn($share);
3373
-
3374
-		$this->manager->getShareByToken('token');
3375
-	}
3376
-
3377
-	public function testGetShareByTokenShareOwnerNotExcludedFromLinkShares(): void {
3378
-		$this->config
3379
-			->expects($this->exactly(4))
3380
-			->method('getAppValue')
3381
-			->willReturnMap([
3382
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3383
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3384
-				['core', 'shareapi_allow_links_exclude_groups', '[]', '["excludedGroup"]'],
3385
-			]);
3386
-
3387
-		$share = $this->manager->newShare();
3388
-		$share->setShareType(IShare::TYPE_LINK)
3389
-			->setPermissions(Constants::PERMISSION_READ);
3390
-		$share->setShareOwner('shareOwner');
3391
-		$file = $this->createMock(File::class);
3392
-		$share->setNode($file);
3393
-
3394
-		$shareOwner = $this->createMock(IUser::class);
3395
-		$this->userManager->expects($this->once())
3396
-			->method('get')
3397
-			->with('shareOwner')
3398
-			->willReturn($shareOwner);
3399
-
3400
-		$this->groupManager->expects($this->once())
3401
-			->method('getUserGroupIds')
3402
-			->with($shareOwner)
3403
-			->willReturn(['allowedGroup', 'otherGroup']);
3404
-
3405
-		$this->defaultProvider->expects($this->once())
3406
-			->method('getShareByToken')
3407
-			->with('token')
3408
-			->willReturn($share);
3409
-
3410
-		$res = $this->manager->getShareByToken('token');
3411
-
3412
-		$this->assertSame($share, $res);
3413
-	}
3414
-
3415
-	public function testCheckPasswordNoLinkShare(): void {
3416
-		$share = $this->createMock(IShare::class);
3417
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
3418
-		$this->assertFalse($this->manager->checkPassword($share, 'password'));
3419
-	}
3420
-
3421
-	public function testCheckPasswordNoPassword(): void {
3422
-		$share = $this->createMock(IShare::class);
3423
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3424
-		$this->assertFalse($this->manager->checkPassword($share, 'password'));
3425
-
3426
-		$share->method('getPassword')->willReturn('password');
3427
-		$this->assertFalse($this->manager->checkPassword($share, null));
3428
-	}
3429
-
3430
-	public function testCheckPasswordInvalidPassword(): void {
3431
-		$share = $this->createMock(IShare::class);
3432
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3433
-		$share->method('getPassword')->willReturn('password');
3434
-
3435
-		$this->hasher->method('verify')->with('invalidpassword', 'password', '')->willReturn(false);
3436
-
3437
-		$this->assertFalse($this->manager->checkPassword($share, 'invalidpassword'));
3438
-	}
3439
-
3440
-	public function testCheckPasswordValidPassword(): void {
3441
-		$share = $this->createMock(IShare::class);
3442
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3443
-		$share->method('getPassword')->willReturn('passwordHash');
3444
-
3445
-		$this->hasher->method('verify')->with('password', 'passwordHash', '')->willReturn(true);
3446
-
3447
-		$this->assertTrue($this->manager->checkPassword($share, 'password'));
3448
-	}
3449
-
3450
-	public function testCheckPasswordUpdateShare(): void {
3451
-		$share = $this->manager->newShare();
3452
-		$share->setShareType(IShare::TYPE_LINK)
3453
-			->setPassword('passwordHash');
3454
-
3455
-		$this->hasher->method('verify')->with('password', 'passwordHash', '')
3456
-			->willReturnCallback(function ($pass, $hash, &$newHash) {
3457
-				$newHash = 'newHash';
3458
-
3459
-				return true;
3460
-			});
3461
-
3462
-		$this->defaultProvider->expects($this->once())
3463
-			->method('update')
3464
-			->with($this->callback(function (IShare $share) {
3465
-				return $share->getPassword() === 'newHash';
3466
-			}));
3467
-
3468
-		$this->assertTrue($this->manager->checkPassword($share, 'password'));
3469
-	}
3470
-
3471
-
3472
-	public function testUpdateShareCantChangeShareType(): void {
3473
-		$this->expectException(\Exception::class);
3474
-		$this->expectExceptionMessage('Cannot change share type');
3475
-
3476
-		$manager = $this->createManagerMock()
3477
-			->onlyMethods([
3478
-				'canShare',
3479
-				'getShareById'
3480
-			])
3481
-			->getMock();
3482
-
3483
-		$originalShare = $this->manager->newShare();
3484
-		$originalShare->setShareType(IShare::TYPE_GROUP);
3485
-
3486
-		$manager->expects($this->once())->method('canShare');
3487
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3488
-
3489
-		$share = $this->manager->newShare();
3490
-		$attrs = $this->manager->newShare()->newAttributes();
3491
-		$attrs->setAttribute('app1', 'perm1', true);
3492
-		$share->setProviderId('foo')
3493
-			->setId('42')
3494
-			->setShareType(IShare::TYPE_USER);
3495
-
3496
-		$manager->updateShare($share);
3497
-	}
3498
-
3499
-
3500
-	public function testUpdateShareCantChangeRecipientForGroupShare(): void {
3501
-		$this->expectException(\Exception::class);
3502
-		$this->expectExceptionMessage('Can only update recipient on user shares');
3503
-
3504
-		$manager = $this->createManagerMock()
3505
-			->onlyMethods([
3506
-				'canShare',
3507
-				'getShareById'
3508
-			])
3509
-			->getMock();
3510
-
3511
-		$originalShare = $this->manager->newShare();
3512
-		$originalShare->setShareType(IShare::TYPE_GROUP)
3513
-			->setSharedWith('origGroup');
3514
-
3515
-		$manager->expects($this->once())->method('canShare');
3516
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3517
-
3518
-		$share = $this->manager->newShare();
3519
-		$share->setProviderId('foo')
3520
-			->setId('42')
3521
-			->setShareType(IShare::TYPE_GROUP)
3522
-			->setSharedWith('newGroup');
3523
-
3524
-		$manager->updateShare($share);
3525
-	}
3526
-
3527
-
3528
-	public function testUpdateShareCantShareWithOwner(): void {
3529
-		$this->expectException(\Exception::class);
3530
-		$this->expectExceptionMessage('Cannot share with the share owner');
3531
-
3532
-		$manager = $this->createManagerMock()
3533
-			->onlyMethods([
3534
-				'canShare',
3535
-				'getShareById'
3536
-			])
3537
-			->getMock();
3538
-
3539
-		$originalShare = $this->manager->newShare();
3540
-		$originalShare->setShareType(IShare::TYPE_USER)
3541
-			->setSharedWith('sharedWith');
3542
-
3543
-		$manager->expects($this->once())->method('canShare');
3544
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3545
-
3546
-		$share = $this->manager->newShare();
3547
-		$share->setProviderId('foo')
3548
-			->setId('42')
3549
-			->setShareType(IShare::TYPE_USER)
3550
-			->setSharedWith('newUser')
3551
-			->setShareOwner('newUser');
3552
-
3553
-		$manager->updateShare($share);
3554
-	}
3555
-
3556
-	public function testUpdateShareUser(): void {
3557
-		$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
3558
-
3559
-		$manager = $this->createManagerMock()
3560
-			->onlyMethods([
3561
-				'canShare',
3562
-				'getShareById',
3563
-				'generalCreateChecks',
3564
-				'userCreateChecks',
3565
-				'pathCreateChecks',
3566
-			])
3567
-			->getMock();
3568
-
3569
-		$originalShare = $this->manager->newShare();
3570
-		$originalShare->setShareType(IShare::TYPE_USER)
3571
-			->setSharedWith('origUser')
3572
-			->setPermissions(1);
3573
-
3574
-		$node = $this->createMock(File::class);
3575
-		$node->method('getId')->willReturn(100);
3576
-		$node->method('getPath')->willReturn('/newUser/files/myPath');
3577
-
3578
-		$manager->expects($this->once())->method('canShare');
3579
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3580
-
3581
-		$share = $this->manager->newShare();
3582
-		$attrs = $this->manager->newShare()->newAttributes();
3583
-		$attrs->setAttribute('app1', 'perm1', true);
3584
-		$share->setProviderId('foo')
3585
-			->setId('42')
3586
-			->setShareType(IShare::TYPE_USER)
3587
-			->setSharedWith('origUser')
3588
-			->setShareOwner('newUser')
3589
-			->setSharedBy('sharer')
3590
-			->setPermissions(31)
3591
-			->setAttributes($attrs)
3592
-			->setNode($node);
3593
-
3594
-		$this->defaultProvider->expects($this->once())
3595
-			->method('update')
3596
-			->with($share)
3597
-			->willReturn($share);
3598
-
3599
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3600
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3601
-		$hookListener->expects($this->never())->method('post');
3602
-
3603
-		$this->rootFolder->method('getUserFolder')->with('newUser')->willReturnSelf();
3604
-		$this->rootFolder->method('getRelativePath')->with('/newUser/files/myPath')->willReturn('/myPath');
3605
-
3606
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3607
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3608
-		$hookListener2->expects($this->once())->method('post')->with([
3609
-			'itemType' => 'file',
3610
-			'itemSource' => 100,
3611
-			'shareType' => IShare::TYPE_USER,
3612
-			'shareWith' => 'origUser',
3613
-			'uidOwner' => 'sharer',
3614
-			'permissions' => 31,
3615
-			'path' => '/myPath',
3616
-			'attributes' => $attrs->toArray(),
3617
-		]);
3618
-
3619
-		$manager->updateShare($share);
3620
-	}
3621
-
3622
-	public function testUpdateShareGroup(): void {
3623
-		$manager = $this->createManagerMock()
3624
-			->onlyMethods([
3625
-				'canShare',
3626
-				'getShareById',
3627
-				'generalCreateChecks',
3628
-				'groupCreateChecks',
3629
-				'pathCreateChecks',
3630
-			])
3631
-			->getMock();
3632
-
3633
-		$originalShare = $this->manager->newShare();
3634
-		$originalShare->setShareType(IShare::TYPE_GROUP)
3635
-			->setSharedWith('origUser')
3636
-			->setPermissions(31);
3637
-
3638
-		$manager->expects($this->once())->method('canShare');
3639
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3640
-
3641
-		$node = $this->createMock(File::class);
3642
-
3643
-		$share = $this->manager->newShare();
3644
-		$share->setProviderId('foo')
3645
-			->setId('42')
3646
-			->setShareType(IShare::TYPE_GROUP)
3647
-			->setSharedWith('origUser')
3648
-			->setShareOwner('owner')
3649
-			->setNode($node)
3650
-			->setPermissions(31);
3651
-
3652
-		$this->defaultProvider->expects($this->once())
3653
-			->method('update')
3654
-			->with($share)
3655
-			->willReturn($share);
3656
-
3657
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3658
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3659
-		$hookListener->expects($this->never())->method('post');
3660
-
3661
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3662
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3663
-		$hookListener2->expects($this->never())->method('post');
3664
-
3665
-		$manager->updateShare($share);
3666
-	}
3667
-
3668
-	public function testUpdateShareLink(): void {
3669
-		$manager = $this->createManagerMock()
3670
-			->onlyMethods([
3671
-				'canShare',
3672
-				'getShareById',
3673
-				'generalCreateChecks',
3674
-				'linkCreateChecks',
3675
-				'pathCreateChecks',
3676
-				'verifyPassword',
3677
-				'validateExpirationDateLink',
3678
-			])
3679
-			->getMock();
3680
-
3681
-		$originalShare = $this->manager->newShare();
3682
-		$originalShare->setShareType(IShare::TYPE_LINK)
3683
-			->setPermissions(15);
3684
-
3685
-		$tomorrow = new \DateTime();
3686
-		$tomorrow->setTime(0, 0, 0);
3687
-		$tomorrow->add(new \DateInterval('P1D'));
3688
-
3689
-		$file = $this->createMock(File::class);
3690
-		$file->method('getId')->willReturn(100);
3691
-
3692
-		$share = $this->manager->newShare();
3693
-		$share->setProviderId('foo')
3694
-			->setId('42')
3695
-			->setShareType(IShare::TYPE_LINK)
3696
-			->setToken('token')
3697
-			->setSharedBy('owner')
3698
-			->setShareOwner('owner')
3699
-			->setPassword('password')
3700
-			->setExpirationDate($tomorrow)
3701
-			->setNode($file)
3702
-			->setPermissions(15);
3703
-
3704
-		$manager->expects($this->once())->method('canShare');
3705
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3706
-		$manager->expects($this->once())->method('validateExpirationDateLink')->with($share);
3707
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3708
-
3709
-		$this->hasher->expects($this->once())
3710
-			->method('hash')
3711
-			->with('password')
3712
-			->willReturn('hashed');
3713
-
3714
-		$this->defaultProvider->expects($this->once())
3715
-			->method('update')
3716
-			->with($share)
3717
-			->willReturn($share);
3718
-
3719
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3720
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3721
-		$hookListener->expects($this->once())->method('post')->with([
3722
-			'itemType' => 'file',
3723
-			'itemSource' => 100,
3724
-			'date' => $tomorrow,
3725
-			'uidOwner' => 'owner',
3726
-		]);
3727
-
3728
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3729
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3730
-		$hookListener2->expects($this->once())->method('post')->with([
3731
-			'itemType' => 'file',
3732
-			'itemSource' => 100,
3733
-			'uidOwner' => 'owner',
3734
-			'token' => 'token',
3735
-			'disabled' => false,
3736
-		]);
3737
-
3738
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3739
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3740
-		$hookListener3->expects($this->never())->method('post');
3741
-
3742
-
3743
-		$manager->updateShare($share);
3744
-	}
3745
-
3746
-	public function testUpdateShareLinkEnableSendPasswordByTalkWithNoPassword(): void {
3747
-		$this->expectException(\InvalidArgumentException::class);
3748
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3749
-
3750
-		$manager = $this->createManagerMock()
3751
-			->onlyMethods([
3752
-				'canShare',
3753
-				'getShareById',
3754
-				'generalCreateChecks',
3755
-				'linkCreateChecks',
3756
-				'pathCreateChecks',
3757
-				'verifyPassword',
3758
-				'validateExpirationDateLink',
3759
-			])
3760
-			->getMock();
3761
-
3762
-		$originalShare = $this->manager->newShare();
3763
-		$originalShare->setShareType(IShare::TYPE_LINK)
3764
-			->setPermissions(15);
3765
-
3766
-		$tomorrow = new \DateTime();
3767
-		$tomorrow->setTime(0, 0, 0);
3768
-		$tomorrow->add(new \DateInterval('P1D'));
3769
-
3770
-		$file = $this->createMock(File::class);
3771
-		$file->method('getId')->willReturn(100);
3772
-
3773
-		$share = $this->manager->newShare();
3774
-		$share->setProviderId('foo')
3775
-			->setId('42')
3776
-			->setShareType(IShare::TYPE_LINK)
3777
-			->setToken('token')
3778
-			->setSharedBy('owner')
3779
-			->setShareOwner('owner')
3780
-			->setPassword(null)
3781
-			->setSendPasswordByTalk(true)
3782
-			->setExpirationDate($tomorrow)
3783
-			->setNode($file)
3784
-			->setPermissions(15);
3785
-
3786
-		$manager->expects($this->once())->method('canShare');
3787
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3788
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3789
-		$manager->expects($this->once())->method('linkCreateChecks')->with($share);
3790
-		$manager->expects($this->never())->method('verifyPassword');
3791
-		$manager->expects($this->never())->method('pathCreateChecks');
3792
-		$manager->expects($this->never())->method('validateExpirationDateLink');
3793
-
3794
-		$this->hasher->expects($this->never())
3795
-			->method('hash');
3796
-
3797
-		$this->defaultProvider->expects($this->never())
3798
-			->method('update');
3799
-
3800
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3801
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3802
-		$hookListener->expects($this->never())->method('post');
3803
-
3804
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3805
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3806
-		$hookListener2->expects($this->never())->method('post');
3807
-
3808
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3809
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3810
-		$hookListener3->expects($this->never())->method('post');
3811
-
3812
-		$manager->updateShare($share);
3813
-	}
3814
-
3815
-	public function testUpdateShareMail(): void {
3816
-		$manager = $this->createManagerMock()
3817
-			->onlyMethods([
3818
-				'canShare',
3819
-				'getShareById',
3820
-				'generalCreateChecks',
3821
-				'verifyPassword',
3822
-				'pathCreateChecks',
3823
-				'linkCreateChecks',
3824
-				'validateExpirationDateLink',
3825
-			])
3826
-			->getMock();
3827
-
3828
-		$originalShare = $this->manager->newShare();
3829
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3830
-			->setPermissions(Constants::PERMISSION_ALL);
3831
-
3832
-		$tomorrow = new \DateTime();
3833
-		$tomorrow->setTime(0, 0, 0);
3834
-		$tomorrow->add(new \DateInterval('P1D'));
3835
-
3836
-		$file = $this->createMock(File::class);
3837
-		$file->method('getId')->willReturn(100);
3838
-
3839
-		$share = $this->manager->newShare();
3840
-		$share->setProviderId('foo')
3841
-			->setId('42')
3842
-			->setShareType(IShare::TYPE_EMAIL)
3843
-			->setToken('token')
3844
-			->setSharedBy('owner')
3845
-			->setShareOwner('owner')
3846
-			->setPassword('password')
3847
-			->setExpirationDate($tomorrow)
3848
-			->setNode($file)
3849
-			->setPermissions(Constants::PERMISSION_ALL);
3850
-
3851
-		$manager->expects($this->once())->method('canShare');
3852
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3853
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3854
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3855
-		$manager->expects($this->once())->method('pathCreateChecks')->with($file);
3856
-		$manager->expects($this->once())->method('linkCreateChecks');
3857
-		$manager->expects($this->once())->method('validateExpirationDateLink');
3858
-
3859
-		$this->hasher->expects($this->once())
3860
-			->method('hash')
3861
-			->with('password')
3862
-			->willReturn('hashed');
3863
-
3864
-		$this->defaultProvider->expects($this->once())
3865
-			->method('update')
3866
-			->with($share, 'password')
3867
-			->willReturn($share);
3868
-
3869
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3870
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3871
-		$hookListener->expects($this->once())->method('post')->with([
3872
-			'itemType' => 'file',
3873
-			'itemSource' => 100,
3874
-			'date' => $tomorrow,
3875
-			'uidOwner' => 'owner',
3876
-		]);
3877
-
3878
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3879
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3880
-		$hookListener2->expects($this->once())->method('post')->with([
3881
-			'itemType' => 'file',
3882
-			'itemSource' => 100,
3883
-			'uidOwner' => 'owner',
3884
-			'token' => 'token',
3885
-			'disabled' => false,
3886
-		]);
3887
-
3888
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3889
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3890
-		$hookListener3->expects($this->never())->method('post');
3891
-
3892
-		$manager->updateShare($share);
3893
-	}
3894
-
3895
-	public function testUpdateShareMailEnableSendPasswordByTalk(): void {
3896
-		$manager = $this->createManagerMock()
3897
-			->onlyMethods([
3898
-				'canShare',
3899
-				'getShareById',
3900
-				'generalCreateChecks',
3901
-				'verifyPassword',
3902
-				'pathCreateChecks',
3903
-				'linkCreateChecks',
3904
-				'validateExpirationDateLink',
3905
-			])
3906
-			->getMock();
3907
-
3908
-		$originalShare = $this->manager->newShare();
3909
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3910
-			->setPermissions(Constants::PERMISSION_ALL)
3911
-			->setPassword(null)
3912
-			->setSendPasswordByTalk(false);
3913
-
3914
-		$tomorrow = new \DateTime();
3915
-		$tomorrow->setTime(0, 0, 0);
3916
-		$tomorrow->add(new \DateInterval('P1D'));
3917
-
3918
-		$file = $this->createMock(File::class);
3919
-		$file->method('getId')->willReturn(100);
3920
-
3921
-		$share = $this->manager->newShare();
3922
-		$share->setProviderId('foo')
3923
-			->setId('42')
3924
-			->setShareType(IShare::TYPE_EMAIL)
3925
-			->setToken('token')
3926
-			->setSharedBy('owner')
3927
-			->setShareOwner('owner')
3928
-			->setPassword('password')
3929
-			->setSendPasswordByTalk(true)
3930
-			->setExpirationDate($tomorrow)
3931
-			->setNode($file)
3932
-			->setPermissions(Constants::PERMISSION_ALL);
3933
-
3934
-		$manager->expects($this->once())->method('canShare');
3935
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3936
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3937
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3938
-		$manager->expects($this->once())->method('pathCreateChecks')->with($file);
3939
-		$manager->expects($this->once())->method('linkCreateChecks');
3940
-		$manager->expects($this->once())->method('validateExpirationDateLink');
3941
-
3942
-		$this->hasher->expects($this->once())
3943
-			->method('hash')
3944
-			->with('password')
3945
-			->willReturn('hashed');
3946
-
3947
-		$this->defaultProvider->expects($this->once())
3948
-			->method('update')
3949
-			->with($share, 'password')
3950
-			->willReturn($share);
3951
-
3952
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3953
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3954
-		$hookListener->expects($this->once())->method('post')->with([
3955
-			'itemType' => 'file',
3956
-			'itemSource' => 100,
3957
-			'date' => $tomorrow,
3958
-			'uidOwner' => 'owner',
3959
-		]);
3960
-
3961
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3962
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3963
-		$hookListener2->expects($this->once())->method('post')->with([
3964
-			'itemType' => 'file',
3965
-			'itemSource' => 100,
3966
-			'uidOwner' => 'owner',
3967
-			'token' => 'token',
3968
-			'disabled' => false,
3969
-		]);
3970
-
3971
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3972
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3973
-		$hookListener3->expects($this->never())->method('post');
3974
-
3975
-		$manager->updateShare($share);
3976
-	}
3977
-
3978
-	public function testUpdateShareMailEnableSendPasswordByTalkWithDifferentPassword(): void {
3979
-		$manager = $this->createManagerMock()
3980
-			->onlyMethods([
3981
-				'canShare',
3982
-				'getShareById',
3983
-				'generalCreateChecks',
3984
-				'verifyPassword',
3985
-				'pathCreateChecks',
3986
-				'linkCreateChecks',
3987
-				'validateExpirationDateLink',
3988
-			])
3989
-			->getMock();
3990
-
3991
-		$originalShare = $this->manager->newShare();
3992
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3993
-			->setPermissions(Constants::PERMISSION_ALL)
3994
-			->setPassword('anotherPasswordHash')
3995
-			->setSendPasswordByTalk(false);
3996
-
3997
-		$tomorrow = new \DateTime();
3998
-		$tomorrow->setTime(0, 0, 0);
3999
-		$tomorrow->add(new \DateInterval('P1D'));
4000
-
4001
-		$file = $this->createMock(File::class);
4002
-		$file->method('getId')->willReturn(100);
4003
-
4004
-		$share = $this->manager->newShare();
4005
-		$share->setProviderId('foo')
4006
-			->setId('42')
4007
-			->setShareType(IShare::TYPE_EMAIL)
4008
-			->setToken('token')
4009
-			->setSharedBy('owner')
4010
-			->setShareOwner('owner')
4011
-			->setPassword('password')
4012
-			->setSendPasswordByTalk(true)
4013
-			->setExpirationDate($tomorrow)
4014
-			->setNode($file)
4015
-			->setPermissions(Constants::PERMISSION_ALL);
4016
-
4017
-		$manager->expects($this->once())->method('canShare');
4018
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4019
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4020
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
4021
-		$manager->expects($this->once())->method('pathCreateChecks')->with($file);
4022
-		$manager->expects($this->once())->method('linkCreateChecks');
4023
-		$manager->expects($this->once())->method('validateExpirationDateLink');
4024
-
4025
-		$this->hasher->expects($this->once())
4026
-			->method('verify')
4027
-			->with('password', 'anotherPasswordHash')
4028
-			->willReturn(false);
4029
-
4030
-		$this->hasher->expects($this->once())
4031
-			->method('hash')
4032
-			->with('password')
4033
-			->willReturn('hashed');
4034
-
4035
-		$this->defaultProvider->expects($this->once())
4036
-			->method('update')
4037
-			->with($share, 'password')
4038
-			->willReturn($share);
4039
-
4040
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4041
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4042
-		$hookListener->expects($this->once())->method('post')->with([
4043
-			'itemType' => 'file',
4044
-			'itemSource' => 100,
4045
-			'date' => $tomorrow,
4046
-			'uidOwner' => 'owner',
4047
-		]);
4048
-
4049
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4050
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4051
-		$hookListener2->expects($this->once())->method('post')->with([
4052
-			'itemType' => 'file',
4053
-			'itemSource' => 100,
4054
-			'uidOwner' => 'owner',
4055
-			'token' => 'token',
4056
-			'disabled' => false,
4057
-		]);
4058
-
4059
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4060
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4061
-		$hookListener3->expects($this->never())->method('post');
4062
-
4063
-		$manager->updateShare($share);
4064
-	}
4065
-
4066
-	public function testUpdateShareMailEnableSendPasswordByTalkWithNoPassword(): void {
4067
-		$this->expectException(\InvalidArgumentException::class);
4068
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4069
-
4070
-		$manager = $this->createManagerMock()
4071
-			->onlyMethods([
4072
-				'canShare',
4073
-				'getShareById',
4074
-				'generalCreateChecks',
4075
-				'verifyPassword',
4076
-				'pathCreateChecks',
4077
-				'linkCreateChecks',
4078
-				'validateExpirationDateLink',
4079
-			])
4080
-			->getMock();
4081
-
4082
-		$originalShare = $this->manager->newShare();
4083
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4084
-			->setPermissions(Constants::PERMISSION_ALL)
4085
-			->setPassword(null)
4086
-			->setSendPasswordByTalk(false);
4087
-
4088
-		$tomorrow = new \DateTime();
4089
-		$tomorrow->setTime(0, 0, 0);
4090
-		$tomorrow->add(new \DateInterval('P1D'));
4091
-
4092
-		$file = $this->createMock(File::class);
4093
-		$file->method('getId')->willReturn(100);
4094
-
4095
-		$share = $this->manager->newShare();
4096
-		$share->setProviderId('foo')
4097
-			->setId('42')
4098
-			->setShareType(IShare::TYPE_EMAIL)
4099
-			->setToken('token')
4100
-			->setSharedBy('owner')
4101
-			->setShareOwner('owner')
4102
-			->setPassword(null)
4103
-			->setSendPasswordByTalk(true)
4104
-			->setExpirationDate($tomorrow)
4105
-			->setNode($file)
4106
-			->setPermissions(Constants::PERMISSION_ALL);
4107
-
4108
-		$manager->expects($this->once())->method('canShare');
4109
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4110
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4111
-		$manager->expects($this->never())->method('verifyPassword');
4112
-		$manager->expects($this->never())->method('pathCreateChecks');
4113
-		$manager->expects($this->once())->method('linkCreateChecks');
4114
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4115
-
4116
-		// If the password is empty, we have nothing to hash
4117
-		$this->hasher->expects($this->never())
4118
-			->method('hash');
4119
-
4120
-		$this->defaultProvider->expects($this->never())
4121
-			->method('update');
4122
-
4123
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4124
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4125
-		$hookListener->expects($this->never())->method('post');
4126
-
4127
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4128
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4129
-		$hookListener2->expects($this->never())->method('post');
4130
-
4131
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4132
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4133
-		$hookListener3->expects($this->never())->method('post');
4134
-
4135
-		$manager->updateShare($share);
4136
-	}
4137
-
4138
-
4139
-	public function testUpdateShareMailEnableSendPasswordByTalkRemovingPassword(): void {
4140
-		$this->expectException(\InvalidArgumentException::class);
4141
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4142
-
4143
-		$manager = $this->createManagerMock()
4144
-			->onlyMethods([
4145
-				'canShare',
4146
-				'getShareById',
4147
-				'generalCreateChecks',
4148
-				'verifyPassword',
4149
-				'pathCreateChecks',
4150
-				'linkCreateChecks',
4151
-				'validateExpirationDateLink',
4152
-			])
4153
-			->getMock();
4154
-
4155
-		$originalShare = $this->manager->newShare();
4156
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4157
-			->setPermissions(Constants::PERMISSION_ALL)
4158
-			->setPassword('passwordHash')
4159
-			->setSendPasswordByTalk(false);
4160
-
4161
-		$tomorrow = new \DateTime();
4162
-		$tomorrow->setTime(0, 0, 0);
4163
-		$tomorrow->add(new \DateInterval('P1D'));
4164
-
4165
-		$file = $this->createMock(File::class);
4166
-		$file->method('getId')->willReturn(100);
4167
-
4168
-		$share = $this->manager->newShare();
4169
-		$share->setProviderId('foo')
4170
-			->setId('42')
4171
-			->setShareType(IShare::TYPE_EMAIL)
4172
-			->setToken('token')
4173
-			->setSharedBy('owner')
4174
-			->setShareOwner('owner')
4175
-			->setPassword(null)
4176
-			->setSendPasswordByTalk(true)
4177
-			->setExpirationDate($tomorrow)
4178
-			->setNode($file)
4179
-			->setPermissions(Constants::PERMISSION_ALL);
4180
-
4181
-		$manager->expects($this->once())->method('canShare');
4182
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4183
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4184
-		$manager->expects($this->once())->method('verifyPassword');
4185
-		$manager->expects($this->never())->method('pathCreateChecks');
4186
-		$manager->expects($this->once())->method('linkCreateChecks');
4187
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4188
-
4189
-		// If the password is empty, we have nothing to hash
4190
-		$this->hasher->expects($this->never())
4191
-			->method('hash');
4192
-
4193
-		$this->defaultProvider->expects($this->never())
4194
-			->method('update');
4195
-
4196
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4197
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4198
-		$hookListener->expects($this->never())->method('post');
4199
-
4200
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4201
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4202
-		$hookListener2->expects($this->never())->method('post');
4203
-
4204
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4205
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4206
-		$hookListener3->expects($this->never())->method('post');
4207
-
4208
-		$manager->updateShare($share);
4209
-	}
4210
-
4211
-
4212
-	public function testUpdateShareMailEnableSendPasswordByTalkRemovingPasswordWithEmptyString(): void {
4213
-		$this->expectException(\InvalidArgumentException::class);
4214
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4215
-
4216
-		$manager = $this->createManagerMock()
4217
-			->onlyMethods([
4218
-				'canShare',
4219
-				'getShareById',
4220
-				'generalCreateChecks',
4221
-				'verifyPassword',
4222
-				'pathCreateChecks',
4223
-				'linkCreateChecks',
4224
-				'validateExpirationDateLink',
4225
-			])
4226
-			->getMock();
4227
-
4228
-		$originalShare = $this->manager->newShare();
4229
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4230
-			->setPermissions(Constants::PERMISSION_ALL)
4231
-			->setPassword('passwordHash')
4232
-			->setSendPasswordByTalk(false);
4233
-
4234
-		$tomorrow = new \DateTime();
4235
-		$tomorrow->setTime(0, 0, 0);
4236
-		$tomorrow->add(new \DateInterval('P1D'));
4237
-
4238
-		$file = $this->createMock(File::class);
4239
-		$file->method('getId')->willReturn(100);
4240
-
4241
-		$share = $this->manager->newShare();
4242
-		$share->setProviderId('foo')
4243
-			->setId('42')
4244
-			->setShareType(IShare::TYPE_EMAIL)
4245
-			->setToken('token')
4246
-			->setSharedBy('owner')
4247
-			->setShareOwner('owner')
4248
-			->setPassword('')
4249
-			->setSendPasswordByTalk(true)
4250
-			->setExpirationDate($tomorrow)
4251
-			->setNode($file)
4252
-			->setPermissions(Constants::PERMISSION_ALL);
4253
-
4254
-		$manager->expects($this->once())->method('canShare');
4255
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4256
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4257
-		$manager->expects($this->once())->method('verifyPassword');
4258
-		$manager->expects($this->never())->method('pathCreateChecks');
4259
-		$manager->expects($this->once())->method('linkCreateChecks');
4260
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4261
-
4262
-		// If the password is empty, we have nothing to hash
4263
-		$this->hasher->expects($this->never())
4264
-			->method('hash');
4265
-
4266
-		$this->defaultProvider->expects($this->never())
4267
-			->method('update');
4268
-
4269
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4270
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4271
-		$hookListener->expects($this->never())->method('post');
4272
-
4273
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4274
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4275
-		$hookListener2->expects($this->never())->method('post');
4276
-
4277
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4278
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4279
-		$hookListener3->expects($this->never())->method('post');
4280
-
4281
-		$manager->updateShare($share);
4282
-	}
4283
-
4284
-
4285
-	public function testUpdateShareMailEnableSendPasswordByTalkWithPreviousPassword(): void {
4286
-		$this->expectException(\InvalidArgumentException::class);
4287
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk without setting a new password');
4288
-
4289
-		$manager = $this->createManagerMock()
4290
-			->onlyMethods([
4291
-				'canShare',
4292
-				'getShareById',
4293
-				'generalCreateChecks',
4294
-				'verifyPassword',
4295
-				'pathCreateChecks',
4296
-				'linkCreateChecks',
4297
-				'validateExpirationDateLink',
4298
-			])
4299
-			->getMock();
4300
-
4301
-		$originalShare = $this->manager->newShare();
4302
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4303
-			->setPermissions(Constants::PERMISSION_ALL)
4304
-			->setPassword('password')
4305
-			->setSendPasswordByTalk(false);
4306
-
4307
-		$tomorrow = new \DateTime();
4308
-		$tomorrow->setTime(0, 0, 0);
4309
-		$tomorrow->add(new \DateInterval('P1D'));
4310
-
4311
-		$file = $this->createMock(File::class);
4312
-		$file->method('getId')->willReturn(100);
4313
-
4314
-		$share = $this->manager->newShare();
4315
-		$share->setProviderId('foo')
4316
-			->setId('42')
4317
-			->setShareType(IShare::TYPE_EMAIL)
4318
-			->setToken('token')
4319
-			->setSharedBy('owner')
4320
-			->setShareOwner('owner')
4321
-			->setPassword('password')
4322
-			->setSendPasswordByTalk(true)
4323
-			->setExpirationDate($tomorrow)
4324
-			->setNode($file)
4325
-			->setPermissions(Constants::PERMISSION_ALL);
4326
-
4327
-		$manager->expects($this->once())->method('canShare');
4328
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4329
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4330
-		$manager->expects($this->never())->method('verifyPassword');
4331
-		$manager->expects($this->never())->method('pathCreateChecks');
4332
-		$manager->expects($this->once())->method('linkCreateChecks');
4333
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4334
-
4335
-		// If the old & new passwords are the same, we don't do anything
4336
-		$this->hasher->expects($this->never())
4337
-			->method('verify');
4338
-		$this->hasher->expects($this->never())
4339
-			->method('hash');
4340
-
4341
-		$this->defaultProvider->expects($this->never())
4342
-			->method('update');
4343
-
4344
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4345
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4346
-		$hookListener->expects($this->never())->method('post');
4347
-
4348
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4349
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4350
-		$hookListener2->expects($this->never())->method('post');
4351
-
4352
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4353
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4354
-		$hookListener3->expects($this->never())->method('post');
4355
-
4356
-		$manager->updateShare($share);
4357
-	}
4358
-
4359
-	public function testUpdateShareMailDisableSendPasswordByTalkWithPreviousPassword(): void {
4360
-		$this->expectException(\InvalidArgumentException::class);
4361
-		$this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4362
-
4363
-		$manager = $this->createManagerMock()
4364
-			->onlyMethods([
4365
-				'canShare',
4366
-				'getShareById',
4367
-				'generalCreateChecks',
4368
-				'verifyPassword',
4369
-				'pathCreateChecks',
4370
-				'linkCreateChecks',
4371
-				'validateExpirationDateLink',
4372
-			])
4373
-			->getMock();
4374
-
4375
-		$originalShare = $this->manager->newShare();
4376
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4377
-			->setPermissions(Constants::PERMISSION_ALL)
4378
-			->setPassword('passwordHash')
4379
-			->setSendPasswordByTalk(true);
4380
-
4381
-		$tomorrow = new \DateTime();
4382
-		$tomorrow->setTime(0, 0, 0);
4383
-		$tomorrow->add(new \DateInterval('P1D'));
4384
-
4385
-		$file = $this->createMock(File::class);
4386
-		$file->method('getId')->willReturn(100);
4387
-
4388
-		$share = $this->manager->newShare();
4389
-		$share->setProviderId('foo')
4390
-			->setId('42')
4391
-			->setShareType(IShare::TYPE_EMAIL)
4392
-			->setToken('token')
4393
-			->setSharedBy('owner')
4394
-			->setShareOwner('owner')
4395
-			->setPassword('passwordHash')
4396
-			->setSendPasswordByTalk(false)
4397
-			->setExpirationDate($tomorrow)
4398
-			->setNode($file)
4399
-			->setPermissions(Constants::PERMISSION_ALL);
4400
-
4401
-		$manager->expects($this->once())->method('canShare');
4402
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4403
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4404
-		$manager->expects($this->never())->method('verifyPassword');
4405
-		$manager->expects($this->never())->method('pathCreateChecks');
4406
-		$manager->expects($this->once())->method('linkCreateChecks');
4407
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4408
-
4409
-		// If the old & new passwords are the same, we don't do anything
4410
-		$this->hasher->expects($this->never())
4411
-			->method('verify');
4412
-		$this->hasher->expects($this->never())
4413
-			->method('hash');
4414
-
4415
-		$this->defaultProvider->expects($this->never())
4416
-			->method('update');
4417
-
4418
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4419
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4420
-		$hookListener->expects($this->never())->method('post');
4421
-
4422
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4423
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4424
-		$hookListener2->expects($this->never())->method('post');
4425
-
4426
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4427
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4428
-		$hookListener3->expects($this->never())->method('post');
4429
-
4430
-		$manager->updateShare($share);
4431
-	}
4432
-
4433
-	public function testUpdateShareMailDisableSendPasswordByTalkWithoutChangingPassword(): void {
4434
-		$this->expectException(\InvalidArgumentException::class);
4435
-		$this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4436
-
4437
-		$manager = $this->createManagerMock()
4438
-			->onlyMethods([
4439
-				'canShare',
4440
-				'getShareById',
4441
-				'generalCreateChecks',
4442
-				'verifyPassword',
4443
-				'pathCreateChecks',
4444
-				'linkCreateChecks',
4445
-				'validateExpirationDateLink',
4446
-			])
4447
-			->getMock();
4448
-
4449
-		$originalShare = $this->manager->newShare();
4450
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4451
-			->setPermissions(Constants::PERMISSION_ALL)
4452
-			->setPassword('passwordHash')
4453
-			->setSendPasswordByTalk(true);
4454
-
4455
-		$tomorrow = new \DateTime();
4456
-		$tomorrow->setTime(0, 0, 0);
4457
-		$tomorrow->add(new \DateInterval('P1D'));
4458
-
4459
-		$file = $this->createMock(File::class);
4460
-		$file->method('getId')->willReturn(100);
4461
-
4462
-		$share = $this->manager->newShare();
4463
-		$share->setProviderId('foo')
4464
-			->setId('42')
4465
-			->setShareType(IShare::TYPE_EMAIL)
4466
-			->setToken('token')
4467
-			->setSharedBy('owner')
4468
-			->setShareOwner('owner')
4469
-			->setPassword('passwordHash')
4470
-			->setSendPasswordByTalk(false)
4471
-			->setExpirationDate($tomorrow)
4472
-			->setNode($file)
4473
-			->setPermissions(Constants::PERMISSION_ALL);
4474
-
4475
-		$manager->expects($this->once())->method('canShare');
4476
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4477
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4478
-		$manager->expects($this->never())->method('verifyPassword');
4479
-		$manager->expects($this->never())->method('pathCreateChecks');
4480
-		$manager->expects($this->once())->method('linkCreateChecks');
4481
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4482
-
4483
-		// If the old & new passwords are the same, we don't do anything
4484
-		$this->hasher->expects($this->never())
4485
-			->method('verify');
4486
-		$this->hasher->expects($this->never())
4487
-			->method('hash');
4488
-
4489
-		$this->defaultProvider->expects($this->never())
4490
-			->method('update');
4491
-
4492
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4493
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4494
-		$hookListener->expects($this->never())->method('post');
3042
+        $manager->method('deleteShare')
3043
+            ->willReturnCallback(function ($share) use (&$shares2): void {
3044
+                for ($i = 0; $i < count($shares2); $i++) {
3045
+                    if ($shares2[$i]->getId() === $share->getId()) {
3046
+                        array_splice($shares2, $i, 1);
3047
+                        break;
3048
+                    }
3049
+                }
3050
+            });
3051
+
3052
+        $res = $manager->getSharesBy('user', IShare::TYPE_LINK, $node, true, 3, 0);
3053
+
3054
+        $this->assertCount(3, $res);
3055
+        $this->assertEquals($shares[0]->getId(), $res[0]->getId());
3056
+        $this->assertEquals($shares[1]->getId(), $res[1]->getId());
3057
+        $this->assertEquals($shares[6]->getId(), $res[2]->getId());
3058
+
3059
+        $this->assertCount(4, $shares2);
3060
+        $this->assertEquals(0, $shares2[0]->getId());
3061
+        $this->assertEquals(1, $shares2[1]->getId());
3062
+        $this->assertEquals(6, $shares2[2]->getId());
3063
+        $this->assertEquals(7, $shares2[3]->getId());
3064
+        $this->assertSame($today, $shares[3]->getExpirationDate());
3065
+    }
3066
+
3067
+    public function testGetShareByToken(): void {
3068
+        $this->config
3069
+            ->expects($this->exactly(2))
3070
+            ->method('getAppValue')
3071
+            ->willReturnMap([
3072
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3073
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3074
+            ]);
3075
+
3076
+        $factory = $this->createMock(IProviderFactory::class);
3077
+
3078
+        $manager = $this->createManager($factory);
3079
+
3080
+        $share = $this->createMock(IShare::class);
3081
+
3082
+        $factory->expects($this->once())
3083
+            ->method('getProviderForType')
3084
+            ->with(IShare::TYPE_LINK)
3085
+            ->willReturn($this->defaultProvider);
3086
+
3087
+        $this->defaultProvider->expects($this->once())
3088
+            ->method('getShareByToken')
3089
+            ->with('token')
3090
+            ->willReturn($share);
3091
+
3092
+        $ret = $manager->getShareByToken('token');
3093
+        $this->assertSame($share, $ret);
3094
+    }
3095
+
3096
+    public function testGetShareByTokenRoom(): void {
3097
+        $this->config
3098
+            ->expects($this->exactly(2))
3099
+            ->method('getAppValue')
3100
+            ->willReturnMap([
3101
+                ['core', 'shareapi_allow_links', 'yes', 'no'],
3102
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3103
+            ]);
3104
+
3105
+        $factory = $this->createMock(IProviderFactory::class);
3106
+
3107
+        $manager = $this->createManager($factory);
3108
+
3109
+        $share = $this->createMock(IShare::class);
3110
+
3111
+        $roomShareProvider = $this->createMock(IShareProvider::class);
3112
+
3113
+        $factory->expects($this->any())
3114
+            ->method('getProviderForType')
3115
+            ->willReturnCallback(function ($shareType) use ($roomShareProvider) {
3116
+                if ($shareType !== IShare::TYPE_ROOM) {
3117
+                    throw new ProviderException();
3118
+                }
3119
+
3120
+                return $roomShareProvider;
3121
+            });
3122
+
3123
+        $roomShareProvider->expects($this->once())
3124
+            ->method('getShareByToken')
3125
+            ->with('token')
3126
+            ->willReturn($share);
3127
+
3128
+        $ret = $manager->getShareByToken('token');
3129
+        $this->assertSame($share, $ret);
3130
+    }
3131
+
3132
+    public function testGetShareByTokenWithException(): void {
3133
+        $this->config
3134
+            ->expects($this->exactly(2))
3135
+            ->method('getAppValue')
3136
+            ->willReturnMap([
3137
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3138
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3139
+            ]);
3140
+
3141
+        $factory = $this->createMock(IProviderFactory::class);
3142
+
3143
+        $manager = $this->createManager($factory);
3144
+
3145
+        $share = $this->createMock(IShare::class);
3146
+
3147
+        $calls = [
3148
+            [IShare::TYPE_LINK],
3149
+            [IShare::TYPE_REMOTE],
3150
+        ];
3151
+        $factory->expects($this->exactly(2))
3152
+            ->method('getProviderForType')
3153
+            ->willReturnCallback(function () use (&$calls) {
3154
+                $expected = array_shift($calls);
3155
+                $this->assertEquals($expected, func_get_args());
3156
+                return $this->defaultProvider;
3157
+            });
3158
+
3159
+        $this->defaultProvider->expects($this->exactly(2))
3160
+            ->method('getShareByToken')
3161
+            ->with('token')
3162
+            ->willReturnOnConsecutiveCalls(
3163
+                $this->throwException(new ShareNotFound()),
3164
+                $share
3165
+            );
3166
+
3167
+        $ret = $manager->getShareByToken('token');
3168
+        $this->assertSame($share, $ret);
3169
+    }
3170
+
3171
+
3172
+    public function testGetShareByTokenHideDisabledUser(): void {
3173
+        $this->expectException(ShareNotFound::class);
3174
+        $this->expectExceptionMessage('The requested share comes from a disabled user');
3175
+
3176
+        $this->config
3177
+            ->expects($this->exactly(2))
3178
+            ->method('getAppValue')
3179
+            ->willReturnMap([
3180
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3181
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'yes'],
3182
+            ]);
3183
+
3184
+        $this->l->expects($this->once())
3185
+            ->method('t')
3186
+            ->willReturnArgument(0);
3187
+
3188
+        $manager = $this->createManagerMock()
3189
+            ->onlyMethods(['deleteShare'])
3190
+            ->getMock();
3191
+
3192
+        $date = new \DateTime();
3193
+        $date->setTime(0, 0, 0);
3194
+        $date->add(new \DateInterval('P2D'));
3195
+        $share = $this->manager->newShare();
3196
+        $share->setExpirationDate($date);
3197
+        $share->setShareOwner('owner');
3198
+        $share->setSharedBy('sharedBy');
3199
+
3200
+        $sharedBy = $this->createMock(IUser::class);
3201
+        $owner = $this->createMock(IUser::class);
3202
+
3203
+        $this->userManager->method('get')->willReturnMap([
3204
+            ['sharedBy', $sharedBy],
3205
+            ['owner', $owner],
3206
+        ]);
3207
+
3208
+        $owner->expects($this->once())
3209
+            ->method('isEnabled')
3210
+            ->willReturn(true);
3211
+        $sharedBy->expects($this->once())
3212
+            ->method('isEnabled')
3213
+            ->willReturn(false);
3214
+
3215
+        $this->defaultProvider->expects($this->once())
3216
+            ->method('getShareByToken')
3217
+            ->with('expiredToken')
3218
+            ->willReturn($share);
3219
+
3220
+        $manager->expects($this->never())
3221
+            ->method('deleteShare');
3222
+
3223
+        $manager->getShareByToken('expiredToken');
3224
+    }
3225
+
3226
+
3227
+    public function testGetShareByTokenExpired(): void {
3228
+        $this->expectException(ShareNotFound::class);
3229
+        $this->expectExceptionMessage('The requested share does not exist anymore');
3230
+
3231
+        $this->config
3232
+            ->expects($this->once())
3233
+            ->method('getAppValue')
3234
+            ->with('core', 'shareapi_allow_links', 'yes')
3235
+            ->willReturn('yes');
3236
+
3237
+        $this->l->expects($this->once())
3238
+            ->method('t')
3239
+            ->willReturnArgument(0);
3240
+
3241
+        $manager = $this->createManagerMock()
3242
+            ->onlyMethods(['deleteShare'])
3243
+            ->getMock();
3244
+
3245
+        $date = new \DateTime();
3246
+        $date->setTime(0, 0, 0);
3247
+        $share = $this->manager->newShare();
3248
+        $share->setExpirationDate($date);
3249
+
3250
+        $this->defaultProvider->expects($this->once())
3251
+            ->method('getShareByToken')
3252
+            ->with('expiredToken')
3253
+            ->willReturn($share);
3254
+
3255
+        $manager->expects($this->once())
3256
+            ->method('deleteShare')
3257
+            ->with($this->equalTo($share));
3258
+
3259
+        $manager->getShareByToken('expiredToken');
3260
+    }
3261
+
3262
+    public function testGetShareByTokenNotExpired(): void {
3263
+        $this->config
3264
+            ->expects($this->exactly(2))
3265
+            ->method('getAppValue')
3266
+            ->willReturnMap([
3267
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3268
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3269
+            ]);
3270
+
3271
+        $date = new \DateTime();
3272
+        $date->setTime(0, 0, 0);
3273
+        $date->add(new \DateInterval('P2D'));
3274
+        $share = $this->manager->newShare();
3275
+        $share->setExpirationDate($date);
3276
+
3277
+        $this->defaultProvider->expects($this->once())
3278
+            ->method('getShareByToken')
3279
+            ->with('expiredToken')
3280
+            ->willReturn($share);
3281
+
3282
+        $res = $this->manager->getShareByToken('expiredToken');
3283
+
3284
+        $this->assertSame($share, $res);
3285
+    }
3286
+
3287
+
3288
+    public function testGetShareByTokenWithPublicLinksDisabled(): void {
3289
+        $this->expectException(ShareNotFound::class);
3290
+
3291
+        $this->config
3292
+            ->expects($this->once())
3293
+            ->method('getAppValue')
3294
+            ->with('core', 'shareapi_allow_links', 'yes')
3295
+            ->willReturn('no');
3296
+        $this->manager->getShareByToken('validToken');
3297
+    }
3298
+
3299
+    public function testGetShareByTokenPublicUploadDisabled(): void {
3300
+        $this->config
3301
+            ->expects($this->exactly(5))
3302
+            ->method('getAppValue')
3303
+            ->willReturnMap([
3304
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3305
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no'],
3306
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3307
+                ['core', 'shareapi_allow_links_exclude_groups', '[]', '[]'],
3308
+            ]);
3309
+
3310
+        $share = $this->manager->newShare();
3311
+        $share->setShareType(IShare::TYPE_LINK)
3312
+            ->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
3313
+        $share->setSharedWith('sharedWith');
3314
+        $share->setShareOwner('shareOwner');
3315
+        $folder = $this->createMock(\OC\Files\Node\Folder::class);
3316
+        $share->setNode($folder);
3317
+
3318
+        $shareOwner = $this->createMock(IUser::class);
3319
+        $this->userManager->expects($this->once())
3320
+            ->method('get')
3321
+            ->with('shareOwner')
3322
+            ->willReturn($shareOwner);
3323
+
3324
+        $this->defaultProvider->expects($this->once())
3325
+            ->method('getShareByToken')
3326
+            ->willReturn('validToken')
3327
+            ->willReturn($share);
3328
+
3329
+        $res = $this->manager->getShareByToken('validToken');
3330
+
3331
+        $this->assertSame(Constants::PERMISSION_READ, $res->getPermissions());
3332
+    }
3333
+
3334
+    public function testGetShareByTokenShareOwnerExcludedFromLinkShares(): void {
3335
+        $this->expectException(ShareNotFound::class);
3336
+        $this->expectExceptionMessage('The requested share does not exist anymore');
3337
+
3338
+        $this->config
3339
+            ->expects($this->exactly(4))
3340
+            ->method('getAppValue')
3341
+            ->willReturnMap([
3342
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3343
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3344
+                ['core', 'shareapi_allow_links_exclude_groups', '[]', '["excludedGroup"]'],
3345
+            ]);
3346
+
3347
+        $this->l->expects($this->once())
3348
+            ->method('t')
3349
+            ->willReturnArgument(0);
3350
+
3351
+        $share = $this->manager->newShare();
3352
+        $share->setShareType(IShare::TYPE_LINK)
3353
+            ->setPermissions(Constants::PERMISSION_READ);
3354
+        $share->setShareOwner('shareOwner');
3355
+        $file = $this->createMock(File::class);
3356
+        $share->setNode($file);
3357
+
3358
+        $shareOwner = $this->createMock(IUser::class);
3359
+        $this->userManager->expects($this->once())
3360
+            ->method('get')
3361
+            ->with('shareOwner')
3362
+            ->willReturn($shareOwner);
3363
+
3364
+        $this->groupManager->expects($this->once())
3365
+            ->method('getUserGroupIds')
3366
+            ->with($shareOwner)
3367
+            ->willReturn(['excludedGroup', 'otherGroup']);
3368
+
3369
+        $this->defaultProvider->expects($this->once())
3370
+            ->method('getShareByToken')
3371
+            ->with('token')
3372
+            ->willReturn($share);
3373
+
3374
+        $this->manager->getShareByToken('token');
3375
+    }
3376
+
3377
+    public function testGetShareByTokenShareOwnerNotExcludedFromLinkShares(): void {
3378
+        $this->config
3379
+            ->expects($this->exactly(4))
3380
+            ->method('getAppValue')
3381
+            ->willReturnMap([
3382
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3383
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3384
+                ['core', 'shareapi_allow_links_exclude_groups', '[]', '["excludedGroup"]'],
3385
+            ]);
3386
+
3387
+        $share = $this->manager->newShare();
3388
+        $share->setShareType(IShare::TYPE_LINK)
3389
+            ->setPermissions(Constants::PERMISSION_READ);
3390
+        $share->setShareOwner('shareOwner');
3391
+        $file = $this->createMock(File::class);
3392
+        $share->setNode($file);
3393
+
3394
+        $shareOwner = $this->createMock(IUser::class);
3395
+        $this->userManager->expects($this->once())
3396
+            ->method('get')
3397
+            ->with('shareOwner')
3398
+            ->willReturn($shareOwner);
3399
+
3400
+        $this->groupManager->expects($this->once())
3401
+            ->method('getUserGroupIds')
3402
+            ->with($shareOwner)
3403
+            ->willReturn(['allowedGroup', 'otherGroup']);
3404
+
3405
+        $this->defaultProvider->expects($this->once())
3406
+            ->method('getShareByToken')
3407
+            ->with('token')
3408
+            ->willReturn($share);
3409
+
3410
+        $res = $this->manager->getShareByToken('token');
3411
+
3412
+        $this->assertSame($share, $res);
3413
+    }
3414
+
3415
+    public function testCheckPasswordNoLinkShare(): void {
3416
+        $share = $this->createMock(IShare::class);
3417
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
3418
+        $this->assertFalse($this->manager->checkPassword($share, 'password'));
3419
+    }
3420
+
3421
+    public function testCheckPasswordNoPassword(): void {
3422
+        $share = $this->createMock(IShare::class);
3423
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3424
+        $this->assertFalse($this->manager->checkPassword($share, 'password'));
3425
+
3426
+        $share->method('getPassword')->willReturn('password');
3427
+        $this->assertFalse($this->manager->checkPassword($share, null));
3428
+    }
3429
+
3430
+    public function testCheckPasswordInvalidPassword(): void {
3431
+        $share = $this->createMock(IShare::class);
3432
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3433
+        $share->method('getPassword')->willReturn('password');
3434
+
3435
+        $this->hasher->method('verify')->with('invalidpassword', 'password', '')->willReturn(false);
3436
+
3437
+        $this->assertFalse($this->manager->checkPassword($share, 'invalidpassword'));
3438
+    }
3439
+
3440
+    public function testCheckPasswordValidPassword(): void {
3441
+        $share = $this->createMock(IShare::class);
3442
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3443
+        $share->method('getPassword')->willReturn('passwordHash');
3444
+
3445
+        $this->hasher->method('verify')->with('password', 'passwordHash', '')->willReturn(true);
3446
+
3447
+        $this->assertTrue($this->manager->checkPassword($share, 'password'));
3448
+    }
3449
+
3450
+    public function testCheckPasswordUpdateShare(): void {
3451
+        $share = $this->manager->newShare();
3452
+        $share->setShareType(IShare::TYPE_LINK)
3453
+            ->setPassword('passwordHash');
3454
+
3455
+        $this->hasher->method('verify')->with('password', 'passwordHash', '')
3456
+            ->willReturnCallback(function ($pass, $hash, &$newHash) {
3457
+                $newHash = 'newHash';
3458
+
3459
+                return true;
3460
+            });
3461
+
3462
+        $this->defaultProvider->expects($this->once())
3463
+            ->method('update')
3464
+            ->with($this->callback(function (IShare $share) {
3465
+                return $share->getPassword() === 'newHash';
3466
+            }));
3467
+
3468
+        $this->assertTrue($this->manager->checkPassword($share, 'password'));
3469
+    }
3470
+
3471
+
3472
+    public function testUpdateShareCantChangeShareType(): void {
3473
+        $this->expectException(\Exception::class);
3474
+        $this->expectExceptionMessage('Cannot change share type');
3475
+
3476
+        $manager = $this->createManagerMock()
3477
+            ->onlyMethods([
3478
+                'canShare',
3479
+                'getShareById'
3480
+            ])
3481
+            ->getMock();
3482
+
3483
+        $originalShare = $this->manager->newShare();
3484
+        $originalShare->setShareType(IShare::TYPE_GROUP);
3485
+
3486
+        $manager->expects($this->once())->method('canShare');
3487
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3488
+
3489
+        $share = $this->manager->newShare();
3490
+        $attrs = $this->manager->newShare()->newAttributes();
3491
+        $attrs->setAttribute('app1', 'perm1', true);
3492
+        $share->setProviderId('foo')
3493
+            ->setId('42')
3494
+            ->setShareType(IShare::TYPE_USER);
3495
+
3496
+        $manager->updateShare($share);
3497
+    }
3498
+
3499
+
3500
+    public function testUpdateShareCantChangeRecipientForGroupShare(): void {
3501
+        $this->expectException(\Exception::class);
3502
+        $this->expectExceptionMessage('Can only update recipient on user shares');
3503
+
3504
+        $manager = $this->createManagerMock()
3505
+            ->onlyMethods([
3506
+                'canShare',
3507
+                'getShareById'
3508
+            ])
3509
+            ->getMock();
3510
+
3511
+        $originalShare = $this->manager->newShare();
3512
+        $originalShare->setShareType(IShare::TYPE_GROUP)
3513
+            ->setSharedWith('origGroup');
3514
+
3515
+        $manager->expects($this->once())->method('canShare');
3516
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3517
+
3518
+        $share = $this->manager->newShare();
3519
+        $share->setProviderId('foo')
3520
+            ->setId('42')
3521
+            ->setShareType(IShare::TYPE_GROUP)
3522
+            ->setSharedWith('newGroup');
3523
+
3524
+        $manager->updateShare($share);
3525
+    }
3526
+
3527
+
3528
+    public function testUpdateShareCantShareWithOwner(): void {
3529
+        $this->expectException(\Exception::class);
3530
+        $this->expectExceptionMessage('Cannot share with the share owner');
3531
+
3532
+        $manager = $this->createManagerMock()
3533
+            ->onlyMethods([
3534
+                'canShare',
3535
+                'getShareById'
3536
+            ])
3537
+            ->getMock();
3538
+
3539
+        $originalShare = $this->manager->newShare();
3540
+        $originalShare->setShareType(IShare::TYPE_USER)
3541
+            ->setSharedWith('sharedWith');
3542
+
3543
+        $manager->expects($this->once())->method('canShare');
3544
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3545
+
3546
+        $share = $this->manager->newShare();
3547
+        $share->setProviderId('foo')
3548
+            ->setId('42')
3549
+            ->setShareType(IShare::TYPE_USER)
3550
+            ->setSharedWith('newUser')
3551
+            ->setShareOwner('newUser');
3552
+
3553
+        $manager->updateShare($share);
3554
+    }
3555
+
3556
+    public function testUpdateShareUser(): void {
3557
+        $this->userManager->expects($this->any())->method('userExists')->willReturn(true);
3558
+
3559
+        $manager = $this->createManagerMock()
3560
+            ->onlyMethods([
3561
+                'canShare',
3562
+                'getShareById',
3563
+                'generalCreateChecks',
3564
+                'userCreateChecks',
3565
+                'pathCreateChecks',
3566
+            ])
3567
+            ->getMock();
3568
+
3569
+        $originalShare = $this->manager->newShare();
3570
+        $originalShare->setShareType(IShare::TYPE_USER)
3571
+            ->setSharedWith('origUser')
3572
+            ->setPermissions(1);
3573
+
3574
+        $node = $this->createMock(File::class);
3575
+        $node->method('getId')->willReturn(100);
3576
+        $node->method('getPath')->willReturn('/newUser/files/myPath');
3577
+
3578
+        $manager->expects($this->once())->method('canShare');
3579
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3580
+
3581
+        $share = $this->manager->newShare();
3582
+        $attrs = $this->manager->newShare()->newAttributes();
3583
+        $attrs->setAttribute('app1', 'perm1', true);
3584
+        $share->setProviderId('foo')
3585
+            ->setId('42')
3586
+            ->setShareType(IShare::TYPE_USER)
3587
+            ->setSharedWith('origUser')
3588
+            ->setShareOwner('newUser')
3589
+            ->setSharedBy('sharer')
3590
+            ->setPermissions(31)
3591
+            ->setAttributes($attrs)
3592
+            ->setNode($node);
3593
+
3594
+        $this->defaultProvider->expects($this->once())
3595
+            ->method('update')
3596
+            ->with($share)
3597
+            ->willReturn($share);
3598
+
3599
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3600
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3601
+        $hookListener->expects($this->never())->method('post');
3602
+
3603
+        $this->rootFolder->method('getUserFolder')->with('newUser')->willReturnSelf();
3604
+        $this->rootFolder->method('getRelativePath')->with('/newUser/files/myPath')->willReturn('/myPath');
3605
+
3606
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3607
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3608
+        $hookListener2->expects($this->once())->method('post')->with([
3609
+            'itemType' => 'file',
3610
+            'itemSource' => 100,
3611
+            'shareType' => IShare::TYPE_USER,
3612
+            'shareWith' => 'origUser',
3613
+            'uidOwner' => 'sharer',
3614
+            'permissions' => 31,
3615
+            'path' => '/myPath',
3616
+            'attributes' => $attrs->toArray(),
3617
+        ]);
3618
+
3619
+        $manager->updateShare($share);
3620
+    }
3621
+
3622
+    public function testUpdateShareGroup(): void {
3623
+        $manager = $this->createManagerMock()
3624
+            ->onlyMethods([
3625
+                'canShare',
3626
+                'getShareById',
3627
+                'generalCreateChecks',
3628
+                'groupCreateChecks',
3629
+                'pathCreateChecks',
3630
+            ])
3631
+            ->getMock();
3632
+
3633
+        $originalShare = $this->manager->newShare();
3634
+        $originalShare->setShareType(IShare::TYPE_GROUP)
3635
+            ->setSharedWith('origUser')
3636
+            ->setPermissions(31);
3637
+
3638
+        $manager->expects($this->once())->method('canShare');
3639
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3640
+
3641
+        $node = $this->createMock(File::class);
3642
+
3643
+        $share = $this->manager->newShare();
3644
+        $share->setProviderId('foo')
3645
+            ->setId('42')
3646
+            ->setShareType(IShare::TYPE_GROUP)
3647
+            ->setSharedWith('origUser')
3648
+            ->setShareOwner('owner')
3649
+            ->setNode($node)
3650
+            ->setPermissions(31);
3651
+
3652
+        $this->defaultProvider->expects($this->once())
3653
+            ->method('update')
3654
+            ->with($share)
3655
+            ->willReturn($share);
3656
+
3657
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3658
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3659
+        $hookListener->expects($this->never())->method('post');
3660
+
3661
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3662
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3663
+        $hookListener2->expects($this->never())->method('post');
3664
+
3665
+        $manager->updateShare($share);
3666
+    }
3667
+
3668
+    public function testUpdateShareLink(): void {
3669
+        $manager = $this->createManagerMock()
3670
+            ->onlyMethods([
3671
+                'canShare',
3672
+                'getShareById',
3673
+                'generalCreateChecks',
3674
+                'linkCreateChecks',
3675
+                'pathCreateChecks',
3676
+                'verifyPassword',
3677
+                'validateExpirationDateLink',
3678
+            ])
3679
+            ->getMock();
3680
+
3681
+        $originalShare = $this->manager->newShare();
3682
+        $originalShare->setShareType(IShare::TYPE_LINK)
3683
+            ->setPermissions(15);
3684
+
3685
+        $tomorrow = new \DateTime();
3686
+        $tomorrow->setTime(0, 0, 0);
3687
+        $tomorrow->add(new \DateInterval('P1D'));
3688
+
3689
+        $file = $this->createMock(File::class);
3690
+        $file->method('getId')->willReturn(100);
3691
+
3692
+        $share = $this->manager->newShare();
3693
+        $share->setProviderId('foo')
3694
+            ->setId('42')
3695
+            ->setShareType(IShare::TYPE_LINK)
3696
+            ->setToken('token')
3697
+            ->setSharedBy('owner')
3698
+            ->setShareOwner('owner')
3699
+            ->setPassword('password')
3700
+            ->setExpirationDate($tomorrow)
3701
+            ->setNode($file)
3702
+            ->setPermissions(15);
3703
+
3704
+        $manager->expects($this->once())->method('canShare');
3705
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3706
+        $manager->expects($this->once())->method('validateExpirationDateLink')->with($share);
3707
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3708
+
3709
+        $this->hasher->expects($this->once())
3710
+            ->method('hash')
3711
+            ->with('password')
3712
+            ->willReturn('hashed');
3713
+
3714
+        $this->defaultProvider->expects($this->once())
3715
+            ->method('update')
3716
+            ->with($share)
3717
+            ->willReturn($share);
3718
+
3719
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3720
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3721
+        $hookListener->expects($this->once())->method('post')->with([
3722
+            'itemType' => 'file',
3723
+            'itemSource' => 100,
3724
+            'date' => $tomorrow,
3725
+            'uidOwner' => 'owner',
3726
+        ]);
3727
+
3728
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3729
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3730
+        $hookListener2->expects($this->once())->method('post')->with([
3731
+            'itemType' => 'file',
3732
+            'itemSource' => 100,
3733
+            'uidOwner' => 'owner',
3734
+            'token' => 'token',
3735
+            'disabled' => false,
3736
+        ]);
3737
+
3738
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3739
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3740
+        $hookListener3->expects($this->never())->method('post');
3741
+
3742
+
3743
+        $manager->updateShare($share);
3744
+    }
3745
+
3746
+    public function testUpdateShareLinkEnableSendPasswordByTalkWithNoPassword(): void {
3747
+        $this->expectException(\InvalidArgumentException::class);
3748
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3749
+
3750
+        $manager = $this->createManagerMock()
3751
+            ->onlyMethods([
3752
+                'canShare',
3753
+                'getShareById',
3754
+                'generalCreateChecks',
3755
+                'linkCreateChecks',
3756
+                'pathCreateChecks',
3757
+                'verifyPassword',
3758
+                'validateExpirationDateLink',
3759
+            ])
3760
+            ->getMock();
3761
+
3762
+        $originalShare = $this->manager->newShare();
3763
+        $originalShare->setShareType(IShare::TYPE_LINK)
3764
+            ->setPermissions(15);
3765
+
3766
+        $tomorrow = new \DateTime();
3767
+        $tomorrow->setTime(0, 0, 0);
3768
+        $tomorrow->add(new \DateInterval('P1D'));
3769
+
3770
+        $file = $this->createMock(File::class);
3771
+        $file->method('getId')->willReturn(100);
3772
+
3773
+        $share = $this->manager->newShare();
3774
+        $share->setProviderId('foo')
3775
+            ->setId('42')
3776
+            ->setShareType(IShare::TYPE_LINK)
3777
+            ->setToken('token')
3778
+            ->setSharedBy('owner')
3779
+            ->setShareOwner('owner')
3780
+            ->setPassword(null)
3781
+            ->setSendPasswordByTalk(true)
3782
+            ->setExpirationDate($tomorrow)
3783
+            ->setNode($file)
3784
+            ->setPermissions(15);
3785
+
3786
+        $manager->expects($this->once())->method('canShare');
3787
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3788
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3789
+        $manager->expects($this->once())->method('linkCreateChecks')->with($share);
3790
+        $manager->expects($this->never())->method('verifyPassword');
3791
+        $manager->expects($this->never())->method('pathCreateChecks');
3792
+        $manager->expects($this->never())->method('validateExpirationDateLink');
3793
+
3794
+        $this->hasher->expects($this->never())
3795
+            ->method('hash');
3796
+
3797
+        $this->defaultProvider->expects($this->never())
3798
+            ->method('update');
3799
+
3800
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3801
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3802
+        $hookListener->expects($this->never())->method('post');
3803
+
3804
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3805
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3806
+        $hookListener2->expects($this->never())->method('post');
3807
+
3808
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3809
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3810
+        $hookListener3->expects($this->never())->method('post');
3811
+
3812
+        $manager->updateShare($share);
3813
+    }
3814
+
3815
+    public function testUpdateShareMail(): void {
3816
+        $manager = $this->createManagerMock()
3817
+            ->onlyMethods([
3818
+                'canShare',
3819
+                'getShareById',
3820
+                'generalCreateChecks',
3821
+                'verifyPassword',
3822
+                'pathCreateChecks',
3823
+                'linkCreateChecks',
3824
+                'validateExpirationDateLink',
3825
+            ])
3826
+            ->getMock();
3827
+
3828
+        $originalShare = $this->manager->newShare();
3829
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3830
+            ->setPermissions(Constants::PERMISSION_ALL);
3831
+
3832
+        $tomorrow = new \DateTime();
3833
+        $tomorrow->setTime(0, 0, 0);
3834
+        $tomorrow->add(new \DateInterval('P1D'));
3835
+
3836
+        $file = $this->createMock(File::class);
3837
+        $file->method('getId')->willReturn(100);
3838
+
3839
+        $share = $this->manager->newShare();
3840
+        $share->setProviderId('foo')
3841
+            ->setId('42')
3842
+            ->setShareType(IShare::TYPE_EMAIL)
3843
+            ->setToken('token')
3844
+            ->setSharedBy('owner')
3845
+            ->setShareOwner('owner')
3846
+            ->setPassword('password')
3847
+            ->setExpirationDate($tomorrow)
3848
+            ->setNode($file)
3849
+            ->setPermissions(Constants::PERMISSION_ALL);
3850
+
3851
+        $manager->expects($this->once())->method('canShare');
3852
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3853
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3854
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3855
+        $manager->expects($this->once())->method('pathCreateChecks')->with($file);
3856
+        $manager->expects($this->once())->method('linkCreateChecks');
3857
+        $manager->expects($this->once())->method('validateExpirationDateLink');
3858
+
3859
+        $this->hasher->expects($this->once())
3860
+            ->method('hash')
3861
+            ->with('password')
3862
+            ->willReturn('hashed');
3863
+
3864
+        $this->defaultProvider->expects($this->once())
3865
+            ->method('update')
3866
+            ->with($share, 'password')
3867
+            ->willReturn($share);
3868
+
3869
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3870
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3871
+        $hookListener->expects($this->once())->method('post')->with([
3872
+            'itemType' => 'file',
3873
+            'itemSource' => 100,
3874
+            'date' => $tomorrow,
3875
+            'uidOwner' => 'owner',
3876
+        ]);
3877
+
3878
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3879
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3880
+        $hookListener2->expects($this->once())->method('post')->with([
3881
+            'itemType' => 'file',
3882
+            'itemSource' => 100,
3883
+            'uidOwner' => 'owner',
3884
+            'token' => 'token',
3885
+            'disabled' => false,
3886
+        ]);
3887
+
3888
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3889
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3890
+        $hookListener3->expects($this->never())->method('post');
3891
+
3892
+        $manager->updateShare($share);
3893
+    }
3894
+
3895
+    public function testUpdateShareMailEnableSendPasswordByTalk(): void {
3896
+        $manager = $this->createManagerMock()
3897
+            ->onlyMethods([
3898
+                'canShare',
3899
+                'getShareById',
3900
+                'generalCreateChecks',
3901
+                'verifyPassword',
3902
+                'pathCreateChecks',
3903
+                'linkCreateChecks',
3904
+                'validateExpirationDateLink',
3905
+            ])
3906
+            ->getMock();
3907
+
3908
+        $originalShare = $this->manager->newShare();
3909
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3910
+            ->setPermissions(Constants::PERMISSION_ALL)
3911
+            ->setPassword(null)
3912
+            ->setSendPasswordByTalk(false);
3913
+
3914
+        $tomorrow = new \DateTime();
3915
+        $tomorrow->setTime(0, 0, 0);
3916
+        $tomorrow->add(new \DateInterval('P1D'));
3917
+
3918
+        $file = $this->createMock(File::class);
3919
+        $file->method('getId')->willReturn(100);
3920
+
3921
+        $share = $this->manager->newShare();
3922
+        $share->setProviderId('foo')
3923
+            ->setId('42')
3924
+            ->setShareType(IShare::TYPE_EMAIL)
3925
+            ->setToken('token')
3926
+            ->setSharedBy('owner')
3927
+            ->setShareOwner('owner')
3928
+            ->setPassword('password')
3929
+            ->setSendPasswordByTalk(true)
3930
+            ->setExpirationDate($tomorrow)
3931
+            ->setNode($file)
3932
+            ->setPermissions(Constants::PERMISSION_ALL);
3933
+
3934
+        $manager->expects($this->once())->method('canShare');
3935
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3936
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3937
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3938
+        $manager->expects($this->once())->method('pathCreateChecks')->with($file);
3939
+        $manager->expects($this->once())->method('linkCreateChecks');
3940
+        $manager->expects($this->once())->method('validateExpirationDateLink');
3941
+
3942
+        $this->hasher->expects($this->once())
3943
+            ->method('hash')
3944
+            ->with('password')
3945
+            ->willReturn('hashed');
3946
+
3947
+        $this->defaultProvider->expects($this->once())
3948
+            ->method('update')
3949
+            ->with($share, 'password')
3950
+            ->willReturn($share);
3951
+
3952
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3953
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3954
+        $hookListener->expects($this->once())->method('post')->with([
3955
+            'itemType' => 'file',
3956
+            'itemSource' => 100,
3957
+            'date' => $tomorrow,
3958
+            'uidOwner' => 'owner',
3959
+        ]);
3960
+
3961
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3962
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3963
+        $hookListener2->expects($this->once())->method('post')->with([
3964
+            'itemType' => 'file',
3965
+            'itemSource' => 100,
3966
+            'uidOwner' => 'owner',
3967
+            'token' => 'token',
3968
+            'disabled' => false,
3969
+        ]);
3970
+
3971
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3972
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3973
+        $hookListener3->expects($this->never())->method('post');
3974
+
3975
+        $manager->updateShare($share);
3976
+    }
3977
+
3978
+    public function testUpdateShareMailEnableSendPasswordByTalkWithDifferentPassword(): void {
3979
+        $manager = $this->createManagerMock()
3980
+            ->onlyMethods([
3981
+                'canShare',
3982
+                'getShareById',
3983
+                'generalCreateChecks',
3984
+                'verifyPassword',
3985
+                'pathCreateChecks',
3986
+                'linkCreateChecks',
3987
+                'validateExpirationDateLink',
3988
+            ])
3989
+            ->getMock();
3990
+
3991
+        $originalShare = $this->manager->newShare();
3992
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3993
+            ->setPermissions(Constants::PERMISSION_ALL)
3994
+            ->setPassword('anotherPasswordHash')
3995
+            ->setSendPasswordByTalk(false);
3996
+
3997
+        $tomorrow = new \DateTime();
3998
+        $tomorrow->setTime(0, 0, 0);
3999
+        $tomorrow->add(new \DateInterval('P1D'));
4000
+
4001
+        $file = $this->createMock(File::class);
4002
+        $file->method('getId')->willReturn(100);
4003
+
4004
+        $share = $this->manager->newShare();
4005
+        $share->setProviderId('foo')
4006
+            ->setId('42')
4007
+            ->setShareType(IShare::TYPE_EMAIL)
4008
+            ->setToken('token')
4009
+            ->setSharedBy('owner')
4010
+            ->setShareOwner('owner')
4011
+            ->setPassword('password')
4012
+            ->setSendPasswordByTalk(true)
4013
+            ->setExpirationDate($tomorrow)
4014
+            ->setNode($file)
4015
+            ->setPermissions(Constants::PERMISSION_ALL);
4016
+
4017
+        $manager->expects($this->once())->method('canShare');
4018
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4019
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4020
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
4021
+        $manager->expects($this->once())->method('pathCreateChecks')->with($file);
4022
+        $manager->expects($this->once())->method('linkCreateChecks');
4023
+        $manager->expects($this->once())->method('validateExpirationDateLink');
4024
+
4025
+        $this->hasher->expects($this->once())
4026
+            ->method('verify')
4027
+            ->with('password', 'anotherPasswordHash')
4028
+            ->willReturn(false);
4029
+
4030
+        $this->hasher->expects($this->once())
4031
+            ->method('hash')
4032
+            ->with('password')
4033
+            ->willReturn('hashed');
4034
+
4035
+        $this->defaultProvider->expects($this->once())
4036
+            ->method('update')
4037
+            ->with($share, 'password')
4038
+            ->willReturn($share);
4039
+
4040
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4041
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4042
+        $hookListener->expects($this->once())->method('post')->with([
4043
+            'itemType' => 'file',
4044
+            'itemSource' => 100,
4045
+            'date' => $tomorrow,
4046
+            'uidOwner' => 'owner',
4047
+        ]);
4048
+
4049
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4050
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4051
+        $hookListener2->expects($this->once())->method('post')->with([
4052
+            'itemType' => 'file',
4053
+            'itemSource' => 100,
4054
+            'uidOwner' => 'owner',
4055
+            'token' => 'token',
4056
+            'disabled' => false,
4057
+        ]);
4058
+
4059
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4060
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4061
+        $hookListener3->expects($this->never())->method('post');
4062
+
4063
+        $manager->updateShare($share);
4064
+    }
4065
+
4066
+    public function testUpdateShareMailEnableSendPasswordByTalkWithNoPassword(): void {
4067
+        $this->expectException(\InvalidArgumentException::class);
4068
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4069
+
4070
+        $manager = $this->createManagerMock()
4071
+            ->onlyMethods([
4072
+                'canShare',
4073
+                'getShareById',
4074
+                'generalCreateChecks',
4075
+                'verifyPassword',
4076
+                'pathCreateChecks',
4077
+                'linkCreateChecks',
4078
+                'validateExpirationDateLink',
4079
+            ])
4080
+            ->getMock();
4081
+
4082
+        $originalShare = $this->manager->newShare();
4083
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4084
+            ->setPermissions(Constants::PERMISSION_ALL)
4085
+            ->setPassword(null)
4086
+            ->setSendPasswordByTalk(false);
4087
+
4088
+        $tomorrow = new \DateTime();
4089
+        $tomorrow->setTime(0, 0, 0);
4090
+        $tomorrow->add(new \DateInterval('P1D'));
4091
+
4092
+        $file = $this->createMock(File::class);
4093
+        $file->method('getId')->willReturn(100);
4094
+
4095
+        $share = $this->manager->newShare();
4096
+        $share->setProviderId('foo')
4097
+            ->setId('42')
4098
+            ->setShareType(IShare::TYPE_EMAIL)
4099
+            ->setToken('token')
4100
+            ->setSharedBy('owner')
4101
+            ->setShareOwner('owner')
4102
+            ->setPassword(null)
4103
+            ->setSendPasswordByTalk(true)
4104
+            ->setExpirationDate($tomorrow)
4105
+            ->setNode($file)
4106
+            ->setPermissions(Constants::PERMISSION_ALL);
4107
+
4108
+        $manager->expects($this->once())->method('canShare');
4109
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4110
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4111
+        $manager->expects($this->never())->method('verifyPassword');
4112
+        $manager->expects($this->never())->method('pathCreateChecks');
4113
+        $manager->expects($this->once())->method('linkCreateChecks');
4114
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4115
+
4116
+        // If the password is empty, we have nothing to hash
4117
+        $this->hasher->expects($this->never())
4118
+            ->method('hash');
4119
+
4120
+        $this->defaultProvider->expects($this->never())
4121
+            ->method('update');
4122
+
4123
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4124
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4125
+        $hookListener->expects($this->never())->method('post');
4126
+
4127
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4128
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4129
+        $hookListener2->expects($this->never())->method('post');
4130
+
4131
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4132
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4133
+        $hookListener3->expects($this->never())->method('post');
4134
+
4135
+        $manager->updateShare($share);
4136
+    }
4137
+
4138
+
4139
+    public function testUpdateShareMailEnableSendPasswordByTalkRemovingPassword(): void {
4140
+        $this->expectException(\InvalidArgumentException::class);
4141
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4142
+
4143
+        $manager = $this->createManagerMock()
4144
+            ->onlyMethods([
4145
+                'canShare',
4146
+                'getShareById',
4147
+                'generalCreateChecks',
4148
+                'verifyPassword',
4149
+                'pathCreateChecks',
4150
+                'linkCreateChecks',
4151
+                'validateExpirationDateLink',
4152
+            ])
4153
+            ->getMock();
4154
+
4155
+        $originalShare = $this->manager->newShare();
4156
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4157
+            ->setPermissions(Constants::PERMISSION_ALL)
4158
+            ->setPassword('passwordHash')
4159
+            ->setSendPasswordByTalk(false);
4160
+
4161
+        $tomorrow = new \DateTime();
4162
+        $tomorrow->setTime(0, 0, 0);
4163
+        $tomorrow->add(new \DateInterval('P1D'));
4164
+
4165
+        $file = $this->createMock(File::class);
4166
+        $file->method('getId')->willReturn(100);
4167
+
4168
+        $share = $this->manager->newShare();
4169
+        $share->setProviderId('foo')
4170
+            ->setId('42')
4171
+            ->setShareType(IShare::TYPE_EMAIL)
4172
+            ->setToken('token')
4173
+            ->setSharedBy('owner')
4174
+            ->setShareOwner('owner')
4175
+            ->setPassword(null)
4176
+            ->setSendPasswordByTalk(true)
4177
+            ->setExpirationDate($tomorrow)
4178
+            ->setNode($file)
4179
+            ->setPermissions(Constants::PERMISSION_ALL);
4180
+
4181
+        $manager->expects($this->once())->method('canShare');
4182
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4183
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4184
+        $manager->expects($this->once())->method('verifyPassword');
4185
+        $manager->expects($this->never())->method('pathCreateChecks');
4186
+        $manager->expects($this->once())->method('linkCreateChecks');
4187
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4188
+
4189
+        // If the password is empty, we have nothing to hash
4190
+        $this->hasher->expects($this->never())
4191
+            ->method('hash');
4192
+
4193
+        $this->defaultProvider->expects($this->never())
4194
+            ->method('update');
4195
+
4196
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4197
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4198
+        $hookListener->expects($this->never())->method('post');
4199
+
4200
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4201
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4202
+        $hookListener2->expects($this->never())->method('post');
4203
+
4204
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4205
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4206
+        $hookListener3->expects($this->never())->method('post');
4207
+
4208
+        $manager->updateShare($share);
4209
+    }
4210
+
4211
+
4212
+    public function testUpdateShareMailEnableSendPasswordByTalkRemovingPasswordWithEmptyString(): void {
4213
+        $this->expectException(\InvalidArgumentException::class);
4214
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4215
+
4216
+        $manager = $this->createManagerMock()
4217
+            ->onlyMethods([
4218
+                'canShare',
4219
+                'getShareById',
4220
+                'generalCreateChecks',
4221
+                'verifyPassword',
4222
+                'pathCreateChecks',
4223
+                'linkCreateChecks',
4224
+                'validateExpirationDateLink',
4225
+            ])
4226
+            ->getMock();
4227
+
4228
+        $originalShare = $this->manager->newShare();
4229
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4230
+            ->setPermissions(Constants::PERMISSION_ALL)
4231
+            ->setPassword('passwordHash')
4232
+            ->setSendPasswordByTalk(false);
4233
+
4234
+        $tomorrow = new \DateTime();
4235
+        $tomorrow->setTime(0, 0, 0);
4236
+        $tomorrow->add(new \DateInterval('P1D'));
4237
+
4238
+        $file = $this->createMock(File::class);
4239
+        $file->method('getId')->willReturn(100);
4240
+
4241
+        $share = $this->manager->newShare();
4242
+        $share->setProviderId('foo')
4243
+            ->setId('42')
4244
+            ->setShareType(IShare::TYPE_EMAIL)
4245
+            ->setToken('token')
4246
+            ->setSharedBy('owner')
4247
+            ->setShareOwner('owner')
4248
+            ->setPassword('')
4249
+            ->setSendPasswordByTalk(true)
4250
+            ->setExpirationDate($tomorrow)
4251
+            ->setNode($file)
4252
+            ->setPermissions(Constants::PERMISSION_ALL);
4253
+
4254
+        $manager->expects($this->once())->method('canShare');
4255
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4256
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4257
+        $manager->expects($this->once())->method('verifyPassword');
4258
+        $manager->expects($this->never())->method('pathCreateChecks');
4259
+        $manager->expects($this->once())->method('linkCreateChecks');
4260
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4261
+
4262
+        // If the password is empty, we have nothing to hash
4263
+        $this->hasher->expects($this->never())
4264
+            ->method('hash');
4265
+
4266
+        $this->defaultProvider->expects($this->never())
4267
+            ->method('update');
4268
+
4269
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4270
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4271
+        $hookListener->expects($this->never())->method('post');
4272
+
4273
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4274
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4275
+        $hookListener2->expects($this->never())->method('post');
4276
+
4277
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4278
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4279
+        $hookListener3->expects($this->never())->method('post');
4280
+
4281
+        $manager->updateShare($share);
4282
+    }
4283
+
4284
+
4285
+    public function testUpdateShareMailEnableSendPasswordByTalkWithPreviousPassword(): void {
4286
+        $this->expectException(\InvalidArgumentException::class);
4287
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk without setting a new password');
4288
+
4289
+        $manager = $this->createManagerMock()
4290
+            ->onlyMethods([
4291
+                'canShare',
4292
+                'getShareById',
4293
+                'generalCreateChecks',
4294
+                'verifyPassword',
4295
+                'pathCreateChecks',
4296
+                'linkCreateChecks',
4297
+                'validateExpirationDateLink',
4298
+            ])
4299
+            ->getMock();
4300
+
4301
+        $originalShare = $this->manager->newShare();
4302
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4303
+            ->setPermissions(Constants::PERMISSION_ALL)
4304
+            ->setPassword('password')
4305
+            ->setSendPasswordByTalk(false);
4306
+
4307
+        $tomorrow = new \DateTime();
4308
+        $tomorrow->setTime(0, 0, 0);
4309
+        $tomorrow->add(new \DateInterval('P1D'));
4310
+
4311
+        $file = $this->createMock(File::class);
4312
+        $file->method('getId')->willReturn(100);
4313
+
4314
+        $share = $this->manager->newShare();
4315
+        $share->setProviderId('foo')
4316
+            ->setId('42')
4317
+            ->setShareType(IShare::TYPE_EMAIL)
4318
+            ->setToken('token')
4319
+            ->setSharedBy('owner')
4320
+            ->setShareOwner('owner')
4321
+            ->setPassword('password')
4322
+            ->setSendPasswordByTalk(true)
4323
+            ->setExpirationDate($tomorrow)
4324
+            ->setNode($file)
4325
+            ->setPermissions(Constants::PERMISSION_ALL);
4326
+
4327
+        $manager->expects($this->once())->method('canShare');
4328
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4329
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4330
+        $manager->expects($this->never())->method('verifyPassword');
4331
+        $manager->expects($this->never())->method('pathCreateChecks');
4332
+        $manager->expects($this->once())->method('linkCreateChecks');
4333
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4334
+
4335
+        // If the old & new passwords are the same, we don't do anything
4336
+        $this->hasher->expects($this->never())
4337
+            ->method('verify');
4338
+        $this->hasher->expects($this->never())
4339
+            ->method('hash');
4340
+
4341
+        $this->defaultProvider->expects($this->never())
4342
+            ->method('update');
4343
+
4344
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4345
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4346
+        $hookListener->expects($this->never())->method('post');
4347
+
4348
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4349
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4350
+        $hookListener2->expects($this->never())->method('post');
4351
+
4352
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4353
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4354
+        $hookListener3->expects($this->never())->method('post');
4355
+
4356
+        $manager->updateShare($share);
4357
+    }
4358
+
4359
+    public function testUpdateShareMailDisableSendPasswordByTalkWithPreviousPassword(): void {
4360
+        $this->expectException(\InvalidArgumentException::class);
4361
+        $this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4362
+
4363
+        $manager = $this->createManagerMock()
4364
+            ->onlyMethods([
4365
+                'canShare',
4366
+                'getShareById',
4367
+                'generalCreateChecks',
4368
+                'verifyPassword',
4369
+                'pathCreateChecks',
4370
+                'linkCreateChecks',
4371
+                'validateExpirationDateLink',
4372
+            ])
4373
+            ->getMock();
4374
+
4375
+        $originalShare = $this->manager->newShare();
4376
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4377
+            ->setPermissions(Constants::PERMISSION_ALL)
4378
+            ->setPassword('passwordHash')
4379
+            ->setSendPasswordByTalk(true);
4380
+
4381
+        $tomorrow = new \DateTime();
4382
+        $tomorrow->setTime(0, 0, 0);
4383
+        $tomorrow->add(new \DateInterval('P1D'));
4384
+
4385
+        $file = $this->createMock(File::class);
4386
+        $file->method('getId')->willReturn(100);
4387
+
4388
+        $share = $this->manager->newShare();
4389
+        $share->setProviderId('foo')
4390
+            ->setId('42')
4391
+            ->setShareType(IShare::TYPE_EMAIL)
4392
+            ->setToken('token')
4393
+            ->setSharedBy('owner')
4394
+            ->setShareOwner('owner')
4395
+            ->setPassword('passwordHash')
4396
+            ->setSendPasswordByTalk(false)
4397
+            ->setExpirationDate($tomorrow)
4398
+            ->setNode($file)
4399
+            ->setPermissions(Constants::PERMISSION_ALL);
4400
+
4401
+        $manager->expects($this->once())->method('canShare');
4402
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4403
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4404
+        $manager->expects($this->never())->method('verifyPassword');
4405
+        $manager->expects($this->never())->method('pathCreateChecks');
4406
+        $manager->expects($this->once())->method('linkCreateChecks');
4407
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4408
+
4409
+        // If the old & new passwords are the same, we don't do anything
4410
+        $this->hasher->expects($this->never())
4411
+            ->method('verify');
4412
+        $this->hasher->expects($this->never())
4413
+            ->method('hash');
4414
+
4415
+        $this->defaultProvider->expects($this->never())
4416
+            ->method('update');
4417
+
4418
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4419
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4420
+        $hookListener->expects($this->never())->method('post');
4421
+
4422
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4423
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4424
+        $hookListener2->expects($this->never())->method('post');
4425
+
4426
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4427
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4428
+        $hookListener3->expects($this->never())->method('post');
4429
+
4430
+        $manager->updateShare($share);
4431
+    }
4432
+
4433
+    public function testUpdateShareMailDisableSendPasswordByTalkWithoutChangingPassword(): void {
4434
+        $this->expectException(\InvalidArgumentException::class);
4435
+        $this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4436
+
4437
+        $manager = $this->createManagerMock()
4438
+            ->onlyMethods([
4439
+                'canShare',
4440
+                'getShareById',
4441
+                'generalCreateChecks',
4442
+                'verifyPassword',
4443
+                'pathCreateChecks',
4444
+                'linkCreateChecks',
4445
+                'validateExpirationDateLink',
4446
+            ])
4447
+            ->getMock();
4448
+
4449
+        $originalShare = $this->manager->newShare();
4450
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4451
+            ->setPermissions(Constants::PERMISSION_ALL)
4452
+            ->setPassword('passwordHash')
4453
+            ->setSendPasswordByTalk(true);
4454
+
4455
+        $tomorrow = new \DateTime();
4456
+        $tomorrow->setTime(0, 0, 0);
4457
+        $tomorrow->add(new \DateInterval('P1D'));
4458
+
4459
+        $file = $this->createMock(File::class);
4460
+        $file->method('getId')->willReturn(100);
4461
+
4462
+        $share = $this->manager->newShare();
4463
+        $share->setProviderId('foo')
4464
+            ->setId('42')
4465
+            ->setShareType(IShare::TYPE_EMAIL)
4466
+            ->setToken('token')
4467
+            ->setSharedBy('owner')
4468
+            ->setShareOwner('owner')
4469
+            ->setPassword('passwordHash')
4470
+            ->setSendPasswordByTalk(false)
4471
+            ->setExpirationDate($tomorrow)
4472
+            ->setNode($file)
4473
+            ->setPermissions(Constants::PERMISSION_ALL);
4474
+
4475
+        $manager->expects($this->once())->method('canShare');
4476
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4477
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4478
+        $manager->expects($this->never())->method('verifyPassword');
4479
+        $manager->expects($this->never())->method('pathCreateChecks');
4480
+        $manager->expects($this->once())->method('linkCreateChecks');
4481
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4482
+
4483
+        // If the old & new passwords are the same, we don't do anything
4484
+        $this->hasher->expects($this->never())
4485
+            ->method('verify');
4486
+        $this->hasher->expects($this->never())
4487
+            ->method('hash');
4488
+
4489
+        $this->defaultProvider->expects($this->never())
4490
+            ->method('update');
4491
+
4492
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4493
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4494
+        $hookListener->expects($this->never())->method('post');
4495 4495
 
4496
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4497
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4498
-		$hookListener2->expects($this->never())->method('post');
4496
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4497
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4498
+        $hookListener2->expects($this->never())->method('post');
4499 4499
 
4500
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4501
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4502
-		$hookListener3->expects($this->never())->method('post');
4500
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4501
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4502
+        $hookListener3->expects($this->never())->method('post');
4503 4503
 
4504
-		$manager->updateShare($share);
4505
-	}
4504
+        $manager->updateShare($share);
4505
+    }
4506 4506
 
4507
-	public function testMoveShareLink(): void {
4508
-		$this->expectException(\InvalidArgumentException::class);
4509
-		$this->expectExceptionMessage('Cannot change target of link share');
4507
+    public function testMoveShareLink(): void {
4508
+        $this->expectException(\InvalidArgumentException::class);
4509
+        $this->expectExceptionMessage('Cannot change target of link share');
4510 4510
 
4511
-		$share = $this->manager->newShare();
4512
-		$share->setShareType(IShare::TYPE_LINK);
4511
+        $share = $this->manager->newShare();
4512
+        $share->setShareType(IShare::TYPE_LINK);
4513 4513
 
4514
-		$this->manager->moveShare($share, 'recipient');
4515
-	}
4514
+        $this->manager->moveShare($share, 'recipient');
4515
+    }
4516 4516
 
4517 4517
 
4518
-	public function testMoveShareUserNotRecipient(): void {
4519
-		$this->expectException(\InvalidArgumentException::class);
4520
-		$this->expectExceptionMessage('Invalid share recipient');
4518
+    public function testMoveShareUserNotRecipient(): void {
4519
+        $this->expectException(\InvalidArgumentException::class);
4520
+        $this->expectExceptionMessage('Invalid share recipient');
4521 4521
 
4522
-		$share = $this->manager->newShare();
4523
-		$share->setShareType(IShare::TYPE_USER);
4524
-
4525
-		$share->setSharedWith('sharedWith');
4526
-
4527
-		$this->manager->moveShare($share, 'recipient');
4528
-	}
4522
+        $share = $this->manager->newShare();
4523
+        $share->setShareType(IShare::TYPE_USER);
4524
+
4525
+        $share->setSharedWith('sharedWith');
4526
+
4527
+        $this->manager->moveShare($share, 'recipient');
4528
+    }
4529 4529
 
4530
-	public function testMoveShareUser(): void {
4531
-		$share = $this->manager->newShare();
4532
-		$share->setShareType(IShare::TYPE_USER)
4533
-			->setId('42')
4534
-			->setProviderId('foo');
4530
+    public function testMoveShareUser(): void {
4531
+        $share = $this->manager->newShare();
4532
+        $share->setShareType(IShare::TYPE_USER)
4533
+            ->setId('42')
4534
+            ->setProviderId('foo');
4535 4535
 
4536
-		$share->setSharedWith('recipient');
4537
-
4538
-		$this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4536
+        $share->setSharedWith('recipient');
4537
+
4538
+        $this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4539 4539
 
4540
-		$this->manager->moveShare($share, 'recipient');
4541
-		$this->addToAssertionCount(1);
4542
-	}
4540
+        $this->manager->moveShare($share, 'recipient');
4541
+        $this->addToAssertionCount(1);
4542
+    }
4543 4543
 
4544 4544
 
4545
-	public function testMoveShareGroupNotRecipient(): void {
4546
-		$this->expectException(\InvalidArgumentException::class);
4547
-		$this->expectExceptionMessage('Invalid share recipient');
4545
+    public function testMoveShareGroupNotRecipient(): void {
4546
+        $this->expectException(\InvalidArgumentException::class);
4547
+        $this->expectExceptionMessage('Invalid share recipient');
4548 4548
 
4549
-		$share = $this->manager->newShare();
4550
-		$share->setShareType(IShare::TYPE_GROUP);
4549
+        $share = $this->manager->newShare();
4550
+        $share->setShareType(IShare::TYPE_GROUP);
4551 4551
 
4552
-		$sharedWith = $this->createMock(IGroup::class);
4553
-		$share->setSharedWith('shareWith');
4552
+        $sharedWith = $this->createMock(IGroup::class);
4553
+        $share->setSharedWith('shareWith');
4554 4554
 
4555
-		$recipient = $this->createMock(IUser::class);
4556
-		$sharedWith->method('inGroup')->with($recipient)->willReturn(false);
4555
+        $recipient = $this->createMock(IUser::class);
4556
+        $sharedWith->method('inGroup')->with($recipient)->willReturn(false);
4557 4557
 
4558
-		$this->groupManager->method('get')->with('shareWith')->willReturn($sharedWith);
4559
-		$this->userManager->method('get')->with('recipient')->willReturn($recipient);
4560
-
4561
-		$this->manager->moveShare($share, 'recipient');
4562
-	}
4558
+        $this->groupManager->method('get')->with('shareWith')->willReturn($sharedWith);
4559
+        $this->userManager->method('get')->with('recipient')->willReturn($recipient);
4560
+
4561
+        $this->manager->moveShare($share, 'recipient');
4562
+    }
4563 4563
 
4564 4564
 
4565
-	public function testMoveShareGroupNull(): void {
4566
-		$this->expectException(\InvalidArgumentException::class);
4567
-		$this->expectExceptionMessage('Group "shareWith" does not exist');
4565
+    public function testMoveShareGroupNull(): void {
4566
+        $this->expectException(\InvalidArgumentException::class);
4567
+        $this->expectExceptionMessage('Group "shareWith" does not exist');
4568 4568
 
4569
-		$share = $this->manager->newShare();
4570
-		$share->setShareType(IShare::TYPE_GROUP);
4571
-		$share->setSharedWith('shareWith');
4569
+        $share = $this->manager->newShare();
4570
+        $share->setShareType(IShare::TYPE_GROUP);
4571
+        $share->setSharedWith('shareWith');
4572 4572
 
4573
-		$recipient = $this->createMock(IUser::class);
4573
+        $recipient = $this->createMock(IUser::class);
4574 4574
 
4575
-		$this->groupManager->method('get')->with('shareWith')->willReturn(null);
4576
-		$this->userManager->method('get')->with('recipient')->willReturn($recipient);
4575
+        $this->groupManager->method('get')->with('shareWith')->willReturn(null);
4576
+        $this->userManager->method('get')->with('recipient')->willReturn($recipient);
4577 4577
 
4578
-		$this->manager->moveShare($share, 'recipient');
4579
-	}
4578
+        $this->manager->moveShare($share, 'recipient');
4579
+    }
4580 4580
 
4581
-	public function testMoveShareGroup(): void {
4582
-		$share = $this->manager->newShare();
4583
-		$share->setShareType(IShare::TYPE_GROUP)
4584
-			->setId('42')
4585
-			->setProviderId('foo');
4581
+    public function testMoveShareGroup(): void {
4582
+        $share = $this->manager->newShare();
4583
+        $share->setShareType(IShare::TYPE_GROUP)
4584
+            ->setId('42')
4585
+            ->setProviderId('foo');
4586 4586
 
4587
-		$group = $this->createMock(IGroup::class);
4588
-		$share->setSharedWith('group');
4587
+        $group = $this->createMock(IGroup::class);
4588
+        $share->setSharedWith('group');
4589 4589
 
4590
-		$recipient = $this->createMock(IUser::class);
4591
-		$group->method('inGroup')->with($recipient)->willReturn(true);
4590
+        $recipient = $this->createMock(IUser::class);
4591
+        $group->method('inGroup')->with($recipient)->willReturn(true);
4592 4592
 
4593
-		$this->groupManager->method('get')->with('group')->willReturn($group);
4594
-		$this->userManager->method('get')->with('recipient')->willReturn($recipient);
4593
+        $this->groupManager->method('get')->with('group')->willReturn($group);
4594
+        $this->userManager->method('get')->with('recipient')->willReturn($recipient);
4595 4595
 
4596
-		$this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4596
+        $this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4597 4597
 
4598
-		$this->manager->moveShare($share, 'recipient');
4599
-		$this->addToAssertionCount(1);
4600
-	}
4598
+        $this->manager->moveShare($share, 'recipient');
4599
+        $this->addToAssertionCount(1);
4600
+    }
4601 4601
 
4602
-	#[DataProvider('dataTestShareProviderExists')]
4603
-	public function testShareProviderExists($shareType, $expected): void {
4604
-		$factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock();
4605
-		$factory->expects($this->any())->method('getProviderForType')
4606
-			->willReturnCallback(function ($id) {
4607
-				if ($id === IShare::TYPE_USER) {
4608
-					return true;
4609
-				}
4610
-				throw new ProviderException();
4611
-			});
4602
+    #[DataProvider('dataTestShareProviderExists')]
4603
+    public function testShareProviderExists($shareType, $expected): void {
4604
+        $factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock();
4605
+        $factory->expects($this->any())->method('getProviderForType')
4606
+            ->willReturnCallback(function ($id) {
4607
+                if ($id === IShare::TYPE_USER) {
4608
+                    return true;
4609
+                }
4610
+                throw new ProviderException();
4611
+            });
4612 4612
 
4613
-		$manager = $this->createManager($factory);
4614
-		$this->assertSame($expected,
4615
-			$manager->shareProviderExists($shareType)
4616
-		);
4617
-	}
4613
+        $manager = $this->createManager($factory);
4614
+        $this->assertSame($expected,
4615
+            $manager->shareProviderExists($shareType)
4616
+        );
4617
+    }
4618 4618
 
4619
-	public static function dataTestShareProviderExists() {
4620
-		return [
4621
-			[IShare::TYPE_USER, true],
4622
-			[42, false],
4623
-		];
4624
-	}
4619
+    public static function dataTestShareProviderExists() {
4620
+        return [
4621
+            [IShare::TYPE_USER, true],
4622
+            [42, false],
4623
+        ];
4624
+    }
4625 4625
 
4626
-	public function testGetSharesInFolder(): void {
4627
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4626
+    public function testGetSharesInFolder(): void {
4627
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4628 4628
 
4629
-		$manager = $this->createManager($factory);
4629
+        $manager = $this->createManager($factory);
4630 4630
 
4631
-		$factory->setProvider($this->defaultProvider);
4632
-		$extraProvider = $this->createMock(IShareProvider::class);
4633
-		$factory->setSecondProvider($extraProvider);
4631
+        $factory->setProvider($this->defaultProvider);
4632
+        $extraProvider = $this->createMock(IShareProvider::class);
4633
+        $factory->setSecondProvider($extraProvider);
4634 4634
 
4635
-		$share1 = $this->createMock(IShare::class);
4636
-		$share2 = $this->createMock(IShare::class);
4637
-		$share3 = $this->createMock(IShare::class);
4638
-		$share4 = $this->createMock(IShare::class);
4635
+        $share1 = $this->createMock(IShare::class);
4636
+        $share2 = $this->createMock(IShare::class);
4637
+        $share3 = $this->createMock(IShare::class);
4638
+        $share4 = $this->createMock(IShare::class);
4639 4639
 
4640
-		$folder = $this->createMock(Folder::class);
4640
+        $folder = $this->createMock(Folder::class);
4641 4641
 
4642
-		$this->defaultProvider->method('getSharesInFolder')
4643
-			->with(
4644
-				$this->equalTo('user'),
4645
-				$this->equalTo($folder),
4646
-				$this->equalTo(false)
4647
-			)->willReturn([
4648
-				1 => [$share1],
4649
-				2 => [$share2],
4650
-			]);
4651
-
4652
-		$extraProvider->method('getSharesInFolder')
4653
-			->with(
4654
-				$this->equalTo('user'),
4655
-				$this->equalTo($folder),
4656
-				$this->equalTo(false)
4657
-			)->willReturn([
4658
-				2 => [$share3],
4659
-				3 => [$share4],
4660
-			]);
4661
-
4662
-		$result = $manager->getSharesInFolder('user', $folder, false);
4663
-
4664
-		$expects = [
4665
-			1 => [$share1],
4666
-			2 => [$share2, $share3],
4667
-			3 => [$share4],
4668
-		];
4669
-
4670
-		$this->assertSame($expects, $result);
4671
-	}
4672
-
4673
-	public function testGetSharesInFolderOwnerless(): void {
4674
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4675
-
4676
-		$manager = $this->createManager($factory);
4677
-
4678
-		$factory->setProvider($this->defaultProvider);
4679
-		$extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class);
4680
-		$factory->setSecondProvider($extraProvider);
4681
-
4682
-		$share1 = $this->createMock(IShare::class);
4683
-		$share2 = $this->createMock(IShare::class);
4684
-
4685
-		$mount = $this->createMock(IShareOwnerlessMount::class);
4686
-
4687
-		$folder = $this->createMock(Folder::class);
4688
-		$folder
4689
-			->method('getMountPoint')
4690
-			->willReturn($mount);
4691
-
4692
-		$this->defaultProvider
4693
-			->method('getAllSharesInFolder')
4694
-			->with($folder)
4695
-			->willReturn([1 => [$share1]]);
4696
-
4697
-		$extraProvider
4698
-			->method('getAllSharesInFolder')
4699
-			->with($folder)
4700
-			->willReturn([1 => [$share2]]);
4701
-
4702
-		$this->assertSame([
4703
-			1 => [$share1, $share2],
4704
-		], $manager->getSharesInFolder('user', $folder));
4705
-	}
4706
-
4707
-
4708
-	public function testGetAccessList(): void {
4709
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4710
-
4711
-		$manager = $this->createManager($factory);
4712
-
4713
-		$factory->setProvider($this->defaultProvider);
4714
-		$extraProvider = $this->createMock(IShareProvider::class);
4715
-		$factory->setSecondProvider($extraProvider);
4716
-
4717
-		$nodeOwner = $this->createMock(IUser::class);
4718
-		$nodeOwner->expects($this->once())
4719
-			->method('getUID')
4720
-			->willReturn('user1');
4721
-
4722
-		$node = $this->createMock(Node::class);
4723
-		$node->expects($this->once())
4724
-			->method('getOwner')
4725
-			->willReturn($nodeOwner);
4726
-		$node->method('getId')
4727
-			->willReturn(42);
4728
-
4729
-		$userFolder = $this->createMock(Folder::class);
4730
-		$file = $this->createMock(File::class);
4731
-		$folder = $this->createMock(Folder::class);
4732
-
4733
-		$owner = $this->createMock(IUser::class);
4734
-		$owner->expects($this->once())
4735
-			->method('getUID')
4736
-			->willReturn('owner');
4737
-
4738
-		$file->method('getParent')
4739
-			->willReturn($folder);
4740
-		$file->method('getPath')
4741
-			->willReturn('/owner/files/folder/file');
4742
-		$file->method('getOwner')
4743
-			->willReturn($owner);
4744
-		$file->method('getId')
4745
-			->willReturn(23);
4746
-		$folder->method('getParent')
4747
-			->willReturn($userFolder);
4748
-		$folder->method('getPath')
4749
-			->willReturn('/owner/files/folder');
4750
-		$userFolder->method('getFirstNodeById')
4751
-			->with($this->equalTo(42))
4752
-			->willReturn($file);
4753
-		$userFolder->method('getPath')
4754
-			->willReturn('/user1/files');
4755
-
4756
-		$this->userManager->method('userExists')
4757
-			->with($this->equalTo('user1'))
4758
-			->willReturn(true);
4759
-
4760
-		$this->defaultProvider->method('getAccessList')
4761
-			->with(
4762
-				$this->equalTo([$file, $folder]),
4763
-				false
4764
-			)
4765
-			->willReturn([
4766
-				'users' => [
4767
-					'user1',
4768
-					'user2',
4769
-					'user3',
4770
-					'123456',
4771
-				],
4772
-				'public' => true,
4773
-			]);
4774
-
4775
-		$extraProvider->method('getAccessList')
4776
-			->with(
4777
-				$this->equalTo([$file, $folder]),
4778
-				false
4779
-			)
4780
-			->willReturn([
4781
-				'users' => [
4782
-					'user3',
4783
-					'user4',
4784
-					'user5',
4785
-					'234567',
4786
-				],
4787
-				'remote' => true,
4788
-			]);
4789
-
4790
-		$this->rootFolder->method('getUserFolder')
4791
-			->with($this->equalTo('user1'))
4792
-			->willReturn($userFolder);
4793
-
4794
-		$expected = [
4795
-			'users' => ['owner', 'user1', 'user2', 'user3', '123456','user4', 'user5', '234567'],
4796
-			'remote' => true,
4797
-			'public' => true,
4798
-		];
4799
-
4800
-		$result = $manager->getAccessList($node, true, false);
4801
-
4802
-		$this->assertSame($expected['public'], $result['public']);
4803
-		$this->assertSame($expected['remote'], $result['remote']);
4804
-		$this->assertSame($expected['users'], $result['users']);
4805
-	}
4806
-
4807
-	public function testGetAccessListWithCurrentAccess(): void {
4808
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4809
-
4810
-		$manager = $this->createManager($factory);
4811
-
4812
-		$factory->setProvider($this->defaultProvider);
4813
-		$extraProvider = $this->createMock(IShareProvider::class);
4814
-		$factory->setSecondProvider($extraProvider);
4815
-
4816
-		$nodeOwner = $this->createMock(IUser::class);
4817
-		$nodeOwner->expects($this->once())
4818
-			->method('getUID')
4819
-			->willReturn('user1');
4820
-
4821
-		$node = $this->createMock(Node::class);
4822
-		$node->expects($this->once())
4823
-			->method('getOwner')
4824
-			->willReturn($nodeOwner);
4825
-		$node->method('getId')
4826
-			->willReturn(42);
4827
-
4828
-		$userFolder = $this->createMock(Folder::class);
4829
-		$file = $this->createMock(File::class);
4830
-
4831
-		$owner = $this->createMock(IUser::class);
4832
-		$owner->expects($this->once())
4833
-			->method('getUID')
4834
-			->willReturn('owner');
4835
-		$folder = $this->createMock(Folder::class);
4836
-
4837
-		$file->method('getParent')
4838
-			->willReturn($folder);
4839
-		$file->method('getPath')
4840
-			->willReturn('/owner/files/folder/file');
4841
-		$file->method('getOwner')
4842
-			->willReturn($owner);
4843
-		$file->method('getId')
4844
-			->willReturn(23);
4845
-		$folder->method('getParent')
4846
-			->willReturn($userFolder);
4847
-		$folder->method('getPath')
4848
-			->willReturn('/owner/files/folder');
4849
-		$userFolder->method('getFirstNodeById')
4850
-			->with($this->equalTo(42))
4851
-			->willReturn($file);
4852
-		$userFolder->method('getPath')
4853
-			->willReturn('/user1/files');
4854
-
4855
-		$this->userManager->method('userExists')
4856
-			->with($this->equalTo('user1'))
4857
-			->willReturn(true);
4858
-
4859
-		$this->defaultProvider->method('getAccessList')
4860
-			->with(
4861
-				$this->equalTo([$file, $folder]),
4862
-				true
4863
-			)
4864
-			->willReturn([
4865
-				'users' => [
4866
-					'user1' => [],
4867
-					'user2' => [],
4868
-					'user3' => [],
4869
-					'123456' => [],
4870
-				],
4871
-				'public' => true,
4872
-			]);
4873
-
4874
-		$extraProvider->method('getAccessList')
4875
-			->with(
4876
-				$this->equalTo([$file, $folder]),
4877
-				true
4878
-			)
4879
-			->willReturn([
4880
-				'users' => [
4881
-					'user3' => [],
4882
-					'user4' => [],
4883
-					'user5' => [],
4884
-					'234567' => [],
4885
-				],
4886
-				'remote' => [
4887
-					'remote1',
4888
-				],
4889
-			]);
4890
-
4891
-		$this->rootFolder->method('getUserFolder')
4892
-			->with($this->equalTo('user1'))
4893
-			->willReturn($userFolder);
4894
-
4895
-		$expected = [
4896
-			'users' => [
4897
-				'owner' => [
4898
-					'node_id' => 23,
4899
-					'node_path' => '/folder/file'
4900
-				]
4901
-				, 'user1' => [], 'user2' => [], 'user3' => [], '123456' => [], 'user4' => [], 'user5' => [], '234567' => []],
4902
-			'remote' => [
4903
-				'remote1',
4904
-			],
4905
-			'public' => true,
4906
-		];
4907
-
4908
-		$result = $manager->getAccessList($node, true, true);
4909
-
4910
-		$this->assertSame($expected['public'], $result['public']);
4911
-		$this->assertSame($expected['remote'], $result['remote']);
4912
-		$this->assertSame($expected['users'], $result['users']);
4913
-	}
4914
-
4915
-	public function testGetAllShares(): void {
4916
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4917
-
4918
-		$manager = $this->createManager($factory);
4919
-
4920
-		$factory->setProvider($this->defaultProvider);
4921
-		$extraProvider = $this->createMock(IShareProvider::class);
4922
-		$factory->setSecondProvider($extraProvider);
4923
-
4924
-		$share1 = $this->createMock(IShare::class);
4925
-		$share2 = $this->createMock(IShare::class);
4926
-		$share3 = $this->createMock(IShare::class);
4927
-		$share4 = $this->createMock(IShare::class);
4928
-
4929
-		$this->defaultProvider->method('getAllShares')
4930
-			->willReturnCallback(function () use ($share1, $share2) {
4931
-				yield $share1;
4932
-				yield $share2;
4933
-			});
4934
-		$extraProvider->method('getAllShares')
4935
-			->willReturnCallback(function () use ($share3, $share4) {
4936
-				yield $share3;
4937
-				yield $share4;
4938
-			});
4939
-
4940
-		// "yield from", used in "getAllShares()", does not reset the keys, so
4941
-		// "use_keys" has to be disabled to collect all the values while
4942
-		// ignoring the keys returned by the generator.
4943
-		$result = iterator_to_array($manager->getAllShares(), $use_keys = false);
4944
-
4945
-		$expects = [$share1, $share2, $share3, $share4];
4946
-
4947
-		$this->assertSame($expects, $result);
4948
-	}
4949
-
4950
-	public static function dataCurrentUserCanEnumerateTargetUser(): array {
4951
-		return [
4952
-			'Full match guest' => [true, true, false, false, false, false, false, true],
4953
-			'Full match user' => [false, true, false, false, false, false, false, true],
4954
-			'Enumeration off guest' => [true, false, false, false, false, false, false, false],
4955
-			'Enumeration off user' => [false, false, false, false, false, false, false, false],
4956
-			'Enumeration guest' => [true, false, true, false, false, false, false, true],
4957
-			'Enumeration user' => [false, false, true, false, false, false, false, true],
4958
-
4959
-			// Restricted enumerations guests never works
4960
-			'Guest phone' => [true, false, true, true, false, false, false, false],
4961
-			'Guest group' => [true, false, true, false, true, false, false, false],
4962
-			'Guest both' => [true, false, true, true, true, false, false, false],
4963
-
4964
-			// Restricted enumerations users
4965
-			'User phone but not known' => [false, false, true, true, false, false, false, false],
4966
-			'User phone known' => [false, false, true, true, false, true, false, true],
4967
-			'User group but no match' => [false, false, true, false, true, false, false, false],
4968
-			'User group with match' => [false, false, true, false, true, false, true, true],
4969
-		];
4970
-	}
4971
-
4972
-	/**
4973
-	 * @param bool $expected
4974
-	 */
4975
-	#[DataProvider('dataCurrentUserCanEnumerateTargetUser')]
4976
-	public function testCurrentUserCanEnumerateTargetUser(bool $currentUserIsGuest, bool $allowEnumerationFullMatch, bool $allowEnumeration, bool $limitEnumerationToPhone, bool $limitEnumerationToGroups, bool $isKnownToUser, bool $haveCommonGroup, bool $expected): void {
4977
-		/** @var IManager|MockObject $manager */
4978
-		$manager = $this->createManagerMock()
4979
-			->onlyMethods([
4980
-				'allowEnumerationFullMatch',
4981
-				'allowEnumeration',
4982
-				'limitEnumerationToPhone',
4983
-				'limitEnumerationToGroups',
4984
-			])
4985
-			->getMock();
4986
-
4987
-		$manager->method('allowEnumerationFullMatch')
4988
-			->willReturn($allowEnumerationFullMatch);
4989
-		$manager->method('allowEnumeration')
4990
-			->willReturn($allowEnumeration);
4991
-		$manager->method('limitEnumerationToPhone')
4992
-			->willReturn($limitEnumerationToPhone);
4993
-		$manager->method('limitEnumerationToGroups')
4994
-			->willReturn($limitEnumerationToGroups);
4995
-
4996
-		$this->knownUserService->method('isKnownToUser')
4997
-			->with('current', 'target')
4998
-			->willReturn($isKnownToUser);
4999
-
5000
-		$currentUser = null;
5001
-		if (!$currentUserIsGuest) {
5002
-			$currentUser = $this->createMock(IUser::class);
5003
-			$currentUser->method('getUID')
5004
-				->willReturn('current');
5005
-		}
5006
-		$targetUser = $this->createMock(IUser::class);
5007
-		$targetUser->method('getUID')
5008
-			->willReturn('target');
5009
-
5010
-		if ($haveCommonGroup) {
5011
-			$this->groupManager->method('getUserGroupIds')
5012
-				->willReturnMap([
5013
-					[$targetUser, ['gid1', 'gid2']],
5014
-					[$currentUser, ['gid2', 'gid3']],
5015
-				]);
5016
-		} else {
5017
-			$this->groupManager->method('getUserGroupIds')
5018
-				->willReturnMap([
5019
-					[$targetUser, ['gid1', 'gid2']],
5020
-					[$currentUser, ['gid3', 'gid4']],
5021
-				]);
5022
-		}
5023
-
5024
-		$this->assertSame($expected, $manager->currentUserCanEnumerateTargetUser($currentUser, $targetUser));
5025
-	}
4642
+        $this->defaultProvider->method('getSharesInFolder')
4643
+            ->with(
4644
+                $this->equalTo('user'),
4645
+                $this->equalTo($folder),
4646
+                $this->equalTo(false)
4647
+            )->willReturn([
4648
+                1 => [$share1],
4649
+                2 => [$share2],
4650
+            ]);
4651
+
4652
+        $extraProvider->method('getSharesInFolder')
4653
+            ->with(
4654
+                $this->equalTo('user'),
4655
+                $this->equalTo($folder),
4656
+                $this->equalTo(false)
4657
+            )->willReturn([
4658
+                2 => [$share3],
4659
+                3 => [$share4],
4660
+            ]);
4661
+
4662
+        $result = $manager->getSharesInFolder('user', $folder, false);
4663
+
4664
+        $expects = [
4665
+            1 => [$share1],
4666
+            2 => [$share2, $share3],
4667
+            3 => [$share4],
4668
+        ];
4669
+
4670
+        $this->assertSame($expects, $result);
4671
+    }
4672
+
4673
+    public function testGetSharesInFolderOwnerless(): void {
4674
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4675
+
4676
+        $manager = $this->createManager($factory);
4677
+
4678
+        $factory->setProvider($this->defaultProvider);
4679
+        $extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class);
4680
+        $factory->setSecondProvider($extraProvider);
4681
+
4682
+        $share1 = $this->createMock(IShare::class);
4683
+        $share2 = $this->createMock(IShare::class);
4684
+
4685
+        $mount = $this->createMock(IShareOwnerlessMount::class);
4686
+
4687
+        $folder = $this->createMock(Folder::class);
4688
+        $folder
4689
+            ->method('getMountPoint')
4690
+            ->willReturn($mount);
4691
+
4692
+        $this->defaultProvider
4693
+            ->method('getAllSharesInFolder')
4694
+            ->with($folder)
4695
+            ->willReturn([1 => [$share1]]);
4696
+
4697
+        $extraProvider
4698
+            ->method('getAllSharesInFolder')
4699
+            ->with($folder)
4700
+            ->willReturn([1 => [$share2]]);
4701
+
4702
+        $this->assertSame([
4703
+            1 => [$share1, $share2],
4704
+        ], $manager->getSharesInFolder('user', $folder));
4705
+    }
4706
+
4707
+
4708
+    public function testGetAccessList(): void {
4709
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4710
+
4711
+        $manager = $this->createManager($factory);
4712
+
4713
+        $factory->setProvider($this->defaultProvider);
4714
+        $extraProvider = $this->createMock(IShareProvider::class);
4715
+        $factory->setSecondProvider($extraProvider);
4716
+
4717
+        $nodeOwner = $this->createMock(IUser::class);
4718
+        $nodeOwner->expects($this->once())
4719
+            ->method('getUID')
4720
+            ->willReturn('user1');
4721
+
4722
+        $node = $this->createMock(Node::class);
4723
+        $node->expects($this->once())
4724
+            ->method('getOwner')
4725
+            ->willReturn($nodeOwner);
4726
+        $node->method('getId')
4727
+            ->willReturn(42);
4728
+
4729
+        $userFolder = $this->createMock(Folder::class);
4730
+        $file = $this->createMock(File::class);
4731
+        $folder = $this->createMock(Folder::class);
4732
+
4733
+        $owner = $this->createMock(IUser::class);
4734
+        $owner->expects($this->once())
4735
+            ->method('getUID')
4736
+            ->willReturn('owner');
4737
+
4738
+        $file->method('getParent')
4739
+            ->willReturn($folder);
4740
+        $file->method('getPath')
4741
+            ->willReturn('/owner/files/folder/file');
4742
+        $file->method('getOwner')
4743
+            ->willReturn($owner);
4744
+        $file->method('getId')
4745
+            ->willReturn(23);
4746
+        $folder->method('getParent')
4747
+            ->willReturn($userFolder);
4748
+        $folder->method('getPath')
4749
+            ->willReturn('/owner/files/folder');
4750
+        $userFolder->method('getFirstNodeById')
4751
+            ->with($this->equalTo(42))
4752
+            ->willReturn($file);
4753
+        $userFolder->method('getPath')
4754
+            ->willReturn('/user1/files');
4755
+
4756
+        $this->userManager->method('userExists')
4757
+            ->with($this->equalTo('user1'))
4758
+            ->willReturn(true);
4759
+
4760
+        $this->defaultProvider->method('getAccessList')
4761
+            ->with(
4762
+                $this->equalTo([$file, $folder]),
4763
+                false
4764
+            )
4765
+            ->willReturn([
4766
+                'users' => [
4767
+                    'user1',
4768
+                    'user2',
4769
+                    'user3',
4770
+                    '123456',
4771
+                ],
4772
+                'public' => true,
4773
+            ]);
4774
+
4775
+        $extraProvider->method('getAccessList')
4776
+            ->with(
4777
+                $this->equalTo([$file, $folder]),
4778
+                false
4779
+            )
4780
+            ->willReturn([
4781
+                'users' => [
4782
+                    'user3',
4783
+                    'user4',
4784
+                    'user5',
4785
+                    '234567',
4786
+                ],
4787
+                'remote' => true,
4788
+            ]);
4789
+
4790
+        $this->rootFolder->method('getUserFolder')
4791
+            ->with($this->equalTo('user1'))
4792
+            ->willReturn($userFolder);
4793
+
4794
+        $expected = [
4795
+            'users' => ['owner', 'user1', 'user2', 'user3', '123456','user4', 'user5', '234567'],
4796
+            'remote' => true,
4797
+            'public' => true,
4798
+        ];
4799
+
4800
+        $result = $manager->getAccessList($node, true, false);
4801
+
4802
+        $this->assertSame($expected['public'], $result['public']);
4803
+        $this->assertSame($expected['remote'], $result['remote']);
4804
+        $this->assertSame($expected['users'], $result['users']);
4805
+    }
4806
+
4807
+    public function testGetAccessListWithCurrentAccess(): void {
4808
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4809
+
4810
+        $manager = $this->createManager($factory);
4811
+
4812
+        $factory->setProvider($this->defaultProvider);
4813
+        $extraProvider = $this->createMock(IShareProvider::class);
4814
+        $factory->setSecondProvider($extraProvider);
4815
+
4816
+        $nodeOwner = $this->createMock(IUser::class);
4817
+        $nodeOwner->expects($this->once())
4818
+            ->method('getUID')
4819
+            ->willReturn('user1');
4820
+
4821
+        $node = $this->createMock(Node::class);
4822
+        $node->expects($this->once())
4823
+            ->method('getOwner')
4824
+            ->willReturn($nodeOwner);
4825
+        $node->method('getId')
4826
+            ->willReturn(42);
4827
+
4828
+        $userFolder = $this->createMock(Folder::class);
4829
+        $file = $this->createMock(File::class);
4830
+
4831
+        $owner = $this->createMock(IUser::class);
4832
+        $owner->expects($this->once())
4833
+            ->method('getUID')
4834
+            ->willReturn('owner');
4835
+        $folder = $this->createMock(Folder::class);
4836
+
4837
+        $file->method('getParent')
4838
+            ->willReturn($folder);
4839
+        $file->method('getPath')
4840
+            ->willReturn('/owner/files/folder/file');
4841
+        $file->method('getOwner')
4842
+            ->willReturn($owner);
4843
+        $file->method('getId')
4844
+            ->willReturn(23);
4845
+        $folder->method('getParent')
4846
+            ->willReturn($userFolder);
4847
+        $folder->method('getPath')
4848
+            ->willReturn('/owner/files/folder');
4849
+        $userFolder->method('getFirstNodeById')
4850
+            ->with($this->equalTo(42))
4851
+            ->willReturn($file);
4852
+        $userFolder->method('getPath')
4853
+            ->willReturn('/user1/files');
4854
+
4855
+        $this->userManager->method('userExists')
4856
+            ->with($this->equalTo('user1'))
4857
+            ->willReturn(true);
4858
+
4859
+        $this->defaultProvider->method('getAccessList')
4860
+            ->with(
4861
+                $this->equalTo([$file, $folder]),
4862
+                true
4863
+            )
4864
+            ->willReturn([
4865
+                'users' => [
4866
+                    'user1' => [],
4867
+                    'user2' => [],
4868
+                    'user3' => [],
4869
+                    '123456' => [],
4870
+                ],
4871
+                'public' => true,
4872
+            ]);
4873
+
4874
+        $extraProvider->method('getAccessList')
4875
+            ->with(
4876
+                $this->equalTo([$file, $folder]),
4877
+                true
4878
+            )
4879
+            ->willReturn([
4880
+                'users' => [
4881
+                    'user3' => [],
4882
+                    'user4' => [],
4883
+                    'user5' => [],
4884
+                    '234567' => [],
4885
+                ],
4886
+                'remote' => [
4887
+                    'remote1',
4888
+                ],
4889
+            ]);
4890
+
4891
+        $this->rootFolder->method('getUserFolder')
4892
+            ->with($this->equalTo('user1'))
4893
+            ->willReturn($userFolder);
4894
+
4895
+        $expected = [
4896
+            'users' => [
4897
+                'owner' => [
4898
+                    'node_id' => 23,
4899
+                    'node_path' => '/folder/file'
4900
+                ]
4901
+                , 'user1' => [], 'user2' => [], 'user3' => [], '123456' => [], 'user4' => [], 'user5' => [], '234567' => []],
4902
+            'remote' => [
4903
+                'remote1',
4904
+            ],
4905
+            'public' => true,
4906
+        ];
4907
+
4908
+        $result = $manager->getAccessList($node, true, true);
4909
+
4910
+        $this->assertSame($expected['public'], $result['public']);
4911
+        $this->assertSame($expected['remote'], $result['remote']);
4912
+        $this->assertSame($expected['users'], $result['users']);
4913
+    }
4914
+
4915
+    public function testGetAllShares(): void {
4916
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4917
+
4918
+        $manager = $this->createManager($factory);
4919
+
4920
+        $factory->setProvider($this->defaultProvider);
4921
+        $extraProvider = $this->createMock(IShareProvider::class);
4922
+        $factory->setSecondProvider($extraProvider);
4923
+
4924
+        $share1 = $this->createMock(IShare::class);
4925
+        $share2 = $this->createMock(IShare::class);
4926
+        $share3 = $this->createMock(IShare::class);
4927
+        $share4 = $this->createMock(IShare::class);
4928
+
4929
+        $this->defaultProvider->method('getAllShares')
4930
+            ->willReturnCallback(function () use ($share1, $share2) {
4931
+                yield $share1;
4932
+                yield $share2;
4933
+            });
4934
+        $extraProvider->method('getAllShares')
4935
+            ->willReturnCallback(function () use ($share3, $share4) {
4936
+                yield $share3;
4937
+                yield $share4;
4938
+            });
4939
+
4940
+        // "yield from", used in "getAllShares()", does not reset the keys, so
4941
+        // "use_keys" has to be disabled to collect all the values while
4942
+        // ignoring the keys returned by the generator.
4943
+        $result = iterator_to_array($manager->getAllShares(), $use_keys = false);
4944
+
4945
+        $expects = [$share1, $share2, $share3, $share4];
4946
+
4947
+        $this->assertSame($expects, $result);
4948
+    }
4949
+
4950
+    public static function dataCurrentUserCanEnumerateTargetUser(): array {
4951
+        return [
4952
+            'Full match guest' => [true, true, false, false, false, false, false, true],
4953
+            'Full match user' => [false, true, false, false, false, false, false, true],
4954
+            'Enumeration off guest' => [true, false, false, false, false, false, false, false],
4955
+            'Enumeration off user' => [false, false, false, false, false, false, false, false],
4956
+            'Enumeration guest' => [true, false, true, false, false, false, false, true],
4957
+            'Enumeration user' => [false, false, true, false, false, false, false, true],
4958
+
4959
+            // Restricted enumerations guests never works
4960
+            'Guest phone' => [true, false, true, true, false, false, false, false],
4961
+            'Guest group' => [true, false, true, false, true, false, false, false],
4962
+            'Guest both' => [true, false, true, true, true, false, false, false],
4963
+
4964
+            // Restricted enumerations users
4965
+            'User phone but not known' => [false, false, true, true, false, false, false, false],
4966
+            'User phone known' => [false, false, true, true, false, true, false, true],
4967
+            'User group but no match' => [false, false, true, false, true, false, false, false],
4968
+            'User group with match' => [false, false, true, false, true, false, true, true],
4969
+        ];
4970
+    }
4971
+
4972
+    /**
4973
+     * @param bool $expected
4974
+     */
4975
+    #[DataProvider('dataCurrentUserCanEnumerateTargetUser')]
4976
+    public function testCurrentUserCanEnumerateTargetUser(bool $currentUserIsGuest, bool $allowEnumerationFullMatch, bool $allowEnumeration, bool $limitEnumerationToPhone, bool $limitEnumerationToGroups, bool $isKnownToUser, bool $haveCommonGroup, bool $expected): void {
4977
+        /** @var IManager|MockObject $manager */
4978
+        $manager = $this->createManagerMock()
4979
+            ->onlyMethods([
4980
+                'allowEnumerationFullMatch',
4981
+                'allowEnumeration',
4982
+                'limitEnumerationToPhone',
4983
+                'limitEnumerationToGroups',
4984
+            ])
4985
+            ->getMock();
4986
+
4987
+        $manager->method('allowEnumerationFullMatch')
4988
+            ->willReturn($allowEnumerationFullMatch);
4989
+        $manager->method('allowEnumeration')
4990
+            ->willReturn($allowEnumeration);
4991
+        $manager->method('limitEnumerationToPhone')
4992
+            ->willReturn($limitEnumerationToPhone);
4993
+        $manager->method('limitEnumerationToGroups')
4994
+            ->willReturn($limitEnumerationToGroups);
4995
+
4996
+        $this->knownUserService->method('isKnownToUser')
4997
+            ->with('current', 'target')
4998
+            ->willReturn($isKnownToUser);
4999
+
5000
+        $currentUser = null;
5001
+        if (!$currentUserIsGuest) {
5002
+            $currentUser = $this->createMock(IUser::class);
5003
+            $currentUser->method('getUID')
5004
+                ->willReturn('current');
5005
+        }
5006
+        $targetUser = $this->createMock(IUser::class);
5007
+        $targetUser->method('getUID')
5008
+            ->willReturn('target');
5009
+
5010
+        if ($haveCommonGroup) {
5011
+            $this->groupManager->method('getUserGroupIds')
5012
+                ->willReturnMap([
5013
+                    [$targetUser, ['gid1', 'gid2']],
5014
+                    [$currentUser, ['gid2', 'gid3']],
5015
+                ]);
5016
+        } else {
5017
+            $this->groupManager->method('getUserGroupIds')
5018
+                ->willReturnMap([
5019
+                    [$targetUser, ['gid1', 'gid2']],
5020
+                    [$currentUser, ['gid3', 'gid4']],
5021
+                ]);
5022
+        }
5023
+
5024
+        $this->assertSame($expected, $manager->currentUserCanEnumerateTargetUser($currentUser, $targetUser));
5025
+    }
5026 5026
 }
5027 5027
 
5028 5028
 class DummyFactory implements IProviderFactory {
5029
-	/** @var IShareProvider */
5030
-	protected $provider;
5031
-
5032
-	public function __construct(IServerContainer $serverContainer) {
5033
-	}
5034
-
5035
-	/**
5036
-	 * @param IShareProvider $provider
5037
-	 */
5038
-	public function setProvider($provider) {
5039
-		$this->provider = $provider;
5040
-	}
5041
-
5042
-	/**
5043
-	 * @param string $id
5044
-	 * @return IShareProvider
5045
-	 */
5046
-	public function getProvider($id) {
5047
-		return $this->provider;
5048
-	}
5049
-
5050
-	/**
5051
-	 * @param int $shareType
5052
-	 * @return IShareProvider
5053
-	 */
5054
-	public function getProviderForType($shareType) {
5055
-		return $this->provider;
5056
-	}
5057
-
5058
-	/**
5059
-	 * @return IShareProvider[]
5060
-	 */
5061
-	public function getAllProviders() {
5062
-		return [$this->provider];
5063
-	}
5064
-
5065
-	public function registerProvider(string $shareProvier): void {
5066
-	}
5029
+    /** @var IShareProvider */
5030
+    protected $provider;
5031
+
5032
+    public function __construct(IServerContainer $serverContainer) {
5033
+    }
5034
+
5035
+    /**
5036
+     * @param IShareProvider $provider
5037
+     */
5038
+    public function setProvider($provider) {
5039
+        $this->provider = $provider;
5040
+    }
5041
+
5042
+    /**
5043
+     * @param string $id
5044
+     * @return IShareProvider
5045
+     */
5046
+    public function getProvider($id) {
5047
+        return $this->provider;
5048
+    }
5049
+
5050
+    /**
5051
+     * @param int $shareType
5052
+     * @return IShareProvider
5053
+     */
5054
+    public function getProviderForType($shareType) {
5055
+        return $this->provider;
5056
+    }
5057
+
5058
+    /**
5059
+     * @return IShareProvider[]
5060
+     */
5061
+    public function getAllProviders() {
5062
+        return [$this->provider];
5063
+    }
5064
+
5065
+    public function registerProvider(string $shareProvier): void {
5066
+    }
5067 5067
 }
5068 5068
 
5069 5069
 class DummyFactory2 extends DummyFactory {
5070
-	/** @var IShareProvider */
5071
-	private $provider2;
5072
-
5073
-	/**
5074
-	 * @param IShareProvider $provider
5075
-	 */
5076
-	public function setSecondProvider($provider) {
5077
-		$this->provider2 = $provider;
5078
-	}
5079
-
5080
-	public function getAllProviders() {
5081
-		return [$this->provider, $this->provider2];
5082
-	}
5083
-
5084
-	public function registerProvider(string $shareProvier): void {
5085
-	}
5070
+    /** @var IShareProvider */
5071
+    private $provider2;
5072
+
5073
+    /**
5074
+     * @param IShareProvider $provider
5075
+     */
5076
+    public function setSecondProvider($provider) {
5077
+        $this->provider2 = $provider;
5078
+    }
5079
+
5080
+    public function getAllProviders() {
5081
+        return [$this->provider, $this->provider2];
5082
+    }
5083
+
5084
+    public function registerProvider(string $shareProvier): void {
5085
+    }
5086 5086
 }
Please login to merge, or discard this patch.
Spacing   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -121,11 +121,11 @@  discard block
 block discarded – undo
121 121
 		$this->l10nFactory = $this->createMock(IFactory::class);
122 122
 		$this->l = $this->createMock(IL10N::class);
123 123
 		$this->l->method('t')
124
-			->willReturnCallback(function ($text, $parameters = []) {
124
+			->willReturnCallback(function($text, $parameters = []) {
125 125
 				return vsprintf($text, $parameters);
126 126
 			});
127 127
 		$this->l->method('n')
128
-			->willReturnCallback(function ($singular, $plural, $count, $parameters = []) {
128
+			->willReturnCallback(function($singular, $plural, $count, $parameters = []) {
129 129
 				return vsprintf(str_replace('%n', $count, ($count === 1) ? $singular : $plural), $parameters);
130 130
 			});
131 131
 		$this->l10nFactory->method('get')->willReturn($this->l);
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
 		];
246 246
 		$this->dispatcher->expects($this->exactly(2))
247 247
 			->method('dispatchTyped')
248
-			->willReturnCallback(function ($event) use (&$calls, $share): void {
248
+			->willReturnCallback(function($event) use (&$calls, $share): void {
249 249
 				$expected = array_shift($calls);
250 250
 				$this->assertInstanceOf($expected, $event);
251 251
 				$this->assertEquals($share, $event->getShare());
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
 		];
289 289
 		$this->dispatcher->expects($this->exactly(2))
290 290
 			->method('dispatchTyped')
291
-			->willReturnCallback(function ($event) use (&$calls, $share): void {
291
+			->willReturnCallback(function($event) use (&$calls, $share): void {
292 292
 				$expected = array_shift($calls);
293 293
 				$this->assertInstanceOf($expected, $event);
294 294
 				$this->assertEquals($share, $event->getShare());
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
 		];
349 349
 		$this->defaultProvider->expects($this->exactly(3))
350 350
 			->method('delete')
351
-			->willReturnCallback(function ($share) use (&$deleteCalls): void {
351
+			->willReturnCallback(function($share) use (&$deleteCalls): void {
352 352
 				$expected = array_shift($deleteCalls);
353 353
 				$this->assertEquals($expected, $share);
354 354
 			});
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
 		];
364 364
 		$this->dispatcher->expects($this->exactly(6))
365 365
 			->method('dispatchTyped')
366
-			->willReturnCallback(function ($event) use (&$dispatchCalls): void {
366
+			->willReturnCallback(function($event) use (&$dispatchCalls): void {
367 367
 				$expected = array_shift($dispatchCalls);
368 368
 				$this->assertInstanceOf($expected[0], $event);
369 369
 				$this->assertEquals($expected[1]->getId(), $event->getShare()->getId());
@@ -397,7 +397,7 @@  discard block
 block discarded – undo
397 397
 		$this->dispatcher->expects($this->once())
398 398
 			->method('dispatchTyped')
399 399
 			->with(
400
-				$this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) {
400
+				$this->callBack(function(ShareDeletedFromSelfEvent $e) use ($share) {
401 401
 					return $e->getShare() === $share;
402 402
 				})
403 403
 			);
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
 		$this->defaultProvider
430 430
 			->expects($this->exactly(4))
431 431
 			->method('getChildren')
432
-			->willReturnCallback(function ($_share) use ($share, $shares) {
432
+			->willReturnCallback(function($_share) use ($share, $shares) {
433 433
 				if ($_share === $share) {
434 434
 					return $shares;
435 435
 				}
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
 		];
444 444
 		$this->defaultProvider->expects($this->exactly(3))
445 445
 			->method('delete')
446
-			->willReturnCallback(function ($share) use (&$calls): void {
446
+			->willReturnCallback(function($share) use (&$calls): void {
447 447
 				$expected = array_shift($calls);
448 448
 				$this->assertEquals($expected, $share);
449 449
 			});
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
 		$reShare->method('getNode')->willReturn($file);
473 473
 
474 474
 		$this->defaultProvider->method('getSharesBy')
475
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) {
475
+			->willReturnCallback(function($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) {
476 476
 				$this->assertEquals($file, $node);
477 477
 				if ($shareType === IShare::TYPE_USER) {
478 478
 					return match($userId) {
@@ -523,10 +523,10 @@  discard block
 block discarded – undo
523 523
 		$reShareInOtherFolder->method('getNode')->willReturn($otherFolder);
524 524
 
525 525
 		$this->defaultProvider->method('getSharesBy')
526
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) {
526
+			->willReturnCallback(function($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) {
527 527
 				if ($shareType === IShare::TYPE_USER) {
528 528
 					return match($userId) {
529
-						'userB' => [$reShare,$reShareInSubFolder,$reShareInOtherFolder],
529
+						'userB' => [$reShare, $reShareInSubFolder, $reShareInOtherFolder],
530 530
 					};
531 531
 				} else {
532 532
 					return [];
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
 		];
541 541
 		$manager->expects($this->exactly(2))
542 542
 			->method('updateShare')
543
-			->willReturnCallback(function ($share) use (&$calls): IShare {
543
+			->willReturnCallback(function($share) use (&$calls): IShare {
544 544
 				$expected = array_shift($calls);
545 545
 				$this->assertEquals($expected, $share);
546 546
 				return $expected;
@@ -615,7 +615,7 @@  discard block
 block discarded – undo
615 615
 		$this->groupManager->method('get')->with('Group')->willReturn($group);
616 616
 
617 617
 		$this->defaultProvider->method('getSharesBy')
618
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) {
618
+			->willReturnCallback(function($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) {
619 619
 				if ($shareType === IShare::TYPE_USER) {
620 620
 					return match($userId) {
621 621
 						'userB' => [$reShare1],
@@ -635,7 +635,7 @@  discard block
 block discarded – undo
635 635
 		];
636 636
 		$manager->expects($this->exactly(2))
637 637
 			->method('updateShare')
638
-			->willReturnCallback(function ($share) use (&$calls): IShare {
638
+			->willReturnCallback(function($share) use (&$calls): IShare {
639 639
 				$expected = array_shift($calls);
640 640
 				$this->assertEquals($expected, $share);
641 641
 				return $expected;
@@ -746,7 +746,7 @@  discard block
 block discarded – undo
746 746
 		]);
747 747
 
748 748
 		$this->dispatcher->expects($this->once())->method('dispatchTyped')
749
-			->willReturnCallback(function (Event $event): void {
749
+			->willReturnCallback(function(Event $event): void {
750 750
 				$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
751 751
 				/** @var ValidatePasswordPolicyEvent $event */
752 752
 				$this->assertSame('password', $event->getPassword());
@@ -768,7 +768,7 @@  discard block
 block discarded – undo
768 768
 		]);
769 769
 
770 770
 		$this->dispatcher->expects($this->once())->method('dispatchTyped')
771
-			->willReturnCallback(function (Event $event): void {
771
+			->willReturnCallback(function(Event $event): void {
772 772
 				$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
773 773
 				/** @var ValidatePasswordPolicyEvent $event */
774 774
 				$this->assertSame('password', $event->getPassword());
@@ -793,7 +793,7 @@  discard block
 block discarded – undo
793 793
 				$share->method('getNodeId')->willReturn($node->getId());
794 794
 			}
795 795
 		} else {
796
-			$share->method('getNode')->willReturnCallback(function (): never {
796
+			$share->method('getNode')->willReturnCallback(function(): never {
797 797
 				throw new NotFoundException();
798 798
 			});
799 799
 		}
@@ -1018,7 +1018,7 @@  discard block
 block discarded – undo
1018 1018
 					->willReturn(true);
1019 1019
 				break;
1020 1020
 			default:
1021
-				throw new \Exception('Unknown storage type ' . $storageType);
1021
+				throw new \Exception('Unknown storage type '.$storageType);
1022 1022
 		}
1023 1023
 		if ($storage === false) {
1024 1024
 			$mock->expects(self::never())->method('getStorage');
@@ -1303,7 +1303,7 @@  discard block
 block discarded – undo
1303 1303
 
1304 1304
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1305 1305
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1306
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1306
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($future) {
1307 1307
 			return $data['expirationDate'] == $future;
1308 1308
 		}));
1309 1309
 
@@ -1327,7 +1327,7 @@  discard block
 block discarded – undo
1327 1327
 
1328 1328
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1329 1329
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1330
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1330
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1331 1331
 			return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1332 1332
 		}));
1333 1333
 
@@ -1340,7 +1340,7 @@  discard block
 block discarded – undo
1340 1340
 	public function testValidateExpirationDateInternalNoDateNoDefault($shareType): void {
1341 1341
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1342 1342
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1343
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1343
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) {
1344 1344
 			return $data['expirationDate'] === null && $data['passwordSet'] === true;
1345 1345
 		}));
1346 1346
 
@@ -1381,7 +1381,7 @@  discard block
 block discarded – undo
1381 1381
 
1382 1382
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1383 1383
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1384
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1384
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1385 1385
 			return $data['expirationDate'] == $expected;
1386 1386
 		}));
1387 1387
 
@@ -1421,7 +1421,7 @@  discard block
 block discarded – undo
1421 1421
 
1422 1422
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1423 1423
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1424
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1424
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1425 1425
 			return $data['expirationDate'] == $expected;
1426 1426
 		}));
1427 1427
 
@@ -1440,7 +1440,7 @@  discard block
 block discarded – undo
1440 1440
 
1441 1441
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1442 1442
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1443
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1443
+		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function($data): void {
1444 1444
 			$data['expirationDate']->sub(new \DateInterval('P2D'));
1445 1445
 		});
1446 1446
 
@@ -1469,7 +1469,7 @@  discard block
 block discarded – undo
1469 1469
 
1470 1470
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1471 1471
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1472
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1472
+		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function($data): void {
1473 1473
 			$data['accepted'] = false;
1474 1474
 			$data['message'] = 'Invalid date!';
1475 1475
 		});
@@ -1644,7 +1644,7 @@  discard block
 block discarded – undo
1644 1644
 
1645 1645
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1646 1646
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1647
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1647
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($future) {
1648 1648
 			return $data['expirationDate'] == $future;
1649 1649
 		}));
1650 1650
 
@@ -1667,7 +1667,7 @@  discard block
 block discarded – undo
1667 1667
 
1668 1668
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1669 1669
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1670
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1670
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1671 1671
 			return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1672 1672
 		}));
1673 1673
 
@@ -1679,7 +1679,7 @@  discard block
 block discarded – undo
1679 1679
 	public function testValidateExpirationDateNoDateNoDefault(): void {
1680 1680
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1681 1681
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1682
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1682
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) {
1683 1683
 			return $data['expirationDate'] === null && $data['passwordSet'] === true;
1684 1684
 		}));
1685 1685
 
@@ -1713,7 +1713,7 @@  discard block
 block discarded – undo
1713 1713
 
1714 1714
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1715 1715
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1716
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1716
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1717 1717
 			return $data['expirationDate'] == $expected;
1718 1718
 		}));
1719 1719
 
@@ -1748,7 +1748,7 @@  discard block
 block discarded – undo
1748 1748
 
1749 1749
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1750 1750
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1751
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1751
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1752 1752
 			return $data['expirationDate'] == $expected;
1753 1753
 		}));
1754 1754
 
@@ -1784,7 +1784,7 @@  discard block
 block discarded – undo
1784 1784
 
1785 1785
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1786 1786
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1787
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1787
+		$hookListener->expects($this->once())->method('listener')->with($this->callback(function($data) use ($expected) {
1788 1788
 			return $data['expirationDate'] == $expected;
1789 1789
 		}));
1790 1790
 
@@ -1804,7 +1804,7 @@  discard block
 block discarded – undo
1804 1804
 
1805 1805
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1806 1806
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1807
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1807
+		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function($data): void {
1808 1808
 			$data['expirationDate']->sub(new \DateInterval('P2D'));
1809 1809
 		});
1810 1810
 
@@ -1829,7 +1829,7 @@  discard block
 block discarded – undo
1829 1829
 
1830 1830
 		$hookListener = $this->createMock(DummyShareManagerListener::class);
1831 1831
 		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1832
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1832
+		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function($data): void {
1833 1833
 			$data['accepted'] = false;
1834 1834
 			$data['message'] = 'Invalid date!';
1835 1835
 		});
@@ -2662,7 +2662,7 @@  discard block
 block discarded – undo
2662 2662
 			->expects($this->once())
2663 2663
 			->method('create')
2664 2664
 			->with($share)
2665
-			->willReturnCallback(function (Share $share) {
2665
+			->willReturnCallback(function(Share $share) {
2666 2666
 				return $share->setId(42);
2667 2667
 			});
2668 2668
 
@@ -2672,7 +2672,7 @@  discard block
 block discarded – undo
2672 2672
 		];
2673 2673
 		$this->dispatcher->expects($this->exactly(2))
2674 2674
 			->method('dispatchTyped')
2675
-			->willReturnCallback(function ($event) use (&$calls, $date, $path): void {
2675
+			->willReturnCallback(function($event) use (&$calls, $date, $path): void {
2676 2676
 				$expected = array_shift($calls);
2677 2677
 				$this->assertInstanceOf($expected, $event);
2678 2678
 				$share = $event->getShare();
@@ -2758,7 +2758,7 @@  discard block
 block discarded – undo
2758 2758
 			->expects($this->once())
2759 2759
 			->method('create')
2760 2760
 			->with($share)
2761
-			->willReturnCallback(function (Share $share) {
2761
+			->willReturnCallback(function(Share $share) {
2762 2762
 				return $share->setId(42);
2763 2763
 			});
2764 2764
 
@@ -2768,7 +2768,7 @@  discard block
 block discarded – undo
2768 2768
 		];
2769 2769
 		$this->dispatcher->expects($this->exactly(2))
2770 2770
 			->method('dispatchTyped')
2771
-			->willReturnCallback(function ($event) use (&$calls, $path): void {
2771
+			->willReturnCallback(function($event) use (&$calls, $path): void {
2772 2772
 				$expected = array_shift($calls);
2773 2773
 				$this->assertInstanceOf($expected, $event);
2774 2774
 				$share = $event->getShare();
@@ -2854,7 +2854,7 @@  discard block
 block discarded – undo
2854 2854
 			->method('dispatchTyped')
2855 2855
 			->with(
2856 2856
 				$this->isInstanceOf(BeforeShareCreatedEvent::class)
2857
-			)->willReturnCallback(function (BeforeShareCreatedEvent $e): void {
2857
+			)->willReturnCallback(function(BeforeShareCreatedEvent $e): void {
2858 2858
 				$e->setError('I won\'t let you share!');
2859 2859
 				$e->stopPropagation();
2860 2860
 			}
@@ -3032,7 +3032,7 @@  discard block
 block discarded – undo
3032 3032
 		 */
3033 3033
 		$this->defaultProvider
3034 3034
 			->method('getSharesBy')
3035
-			->willReturnCallback(function ($uid, $type, $node, $reshares, $limit, $offset) use (&$shares2) {
3035
+			->willReturnCallback(function($uid, $type, $node, $reshares, $limit, $offset) use (&$shares2) {
3036 3036
 				return array_slice($shares2, $offset, $limit);
3037 3037
 			});
3038 3038
 
@@ -3040,7 +3040,7 @@  discard block
 block discarded – undo
3040 3040
 		 * Simulate the deleteShare call.
3041 3041
 		 */
3042 3042
 		$manager->method('deleteShare')
3043
-			->willReturnCallback(function ($share) use (&$shares2): void {
3043
+			->willReturnCallback(function($share) use (&$shares2): void {
3044 3044
 				for ($i = 0; $i < count($shares2); $i++) {
3045 3045
 					if ($shares2[$i]->getId() === $share->getId()) {
3046 3046
 						array_splice($shares2, $i, 1);
@@ -3112,7 +3112,7 @@  discard block
 block discarded – undo
3112 3112
 
3113 3113
 		$factory->expects($this->any())
3114 3114
 			->method('getProviderForType')
3115
-			->willReturnCallback(function ($shareType) use ($roomShareProvider) {
3115
+			->willReturnCallback(function($shareType) use ($roomShareProvider) {
3116 3116
 				if ($shareType !== IShare::TYPE_ROOM) {
3117 3117
 					throw new ProviderException();
3118 3118
 				}
@@ -3150,7 +3150,7 @@  discard block
 block discarded – undo
3150 3150
 		];
3151 3151
 		$factory->expects($this->exactly(2))
3152 3152
 			->method('getProviderForType')
3153
-			->willReturnCallback(function () use (&$calls) {
3153
+			->willReturnCallback(function() use (&$calls) {
3154 3154
 				$expected = array_shift($calls);
3155 3155
 				$this->assertEquals($expected, func_get_args());
3156 3156
 				return $this->defaultProvider;
@@ -3453,7 +3453,7 @@  discard block
 block discarded – undo
3453 3453
 			->setPassword('passwordHash');
3454 3454
 
3455 3455
 		$this->hasher->method('verify')->with('password', 'passwordHash', '')
3456
-			->willReturnCallback(function ($pass, $hash, &$newHash) {
3456
+			->willReturnCallback(function($pass, $hash, &$newHash) {
3457 3457
 				$newHash = 'newHash';
3458 3458
 
3459 3459
 				return true;
@@ -3461,7 +3461,7 @@  discard block
 block discarded – undo
3461 3461
 
3462 3462
 		$this->defaultProvider->expects($this->once())
3463 3463
 			->method('update')
3464
-			->with($this->callback(function (IShare $share) {
3464
+			->with($this->callback(function(IShare $share) {
3465 3465
 				return $share->getPassword() === 'newHash';
3466 3466
 			}));
3467 3467
 
@@ -4603,7 +4603,7 @@  discard block
 block discarded – undo
4603 4603
 	public function testShareProviderExists($shareType, $expected): void {
4604 4604
 		$factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock();
4605 4605
 		$factory->expects($this->any())->method('getProviderForType')
4606
-			->willReturnCallback(function ($id) {
4606
+			->willReturnCallback(function($id) {
4607 4607
 				if ($id === IShare::TYPE_USER) {
4608 4608
 					return true;
4609 4609
 				}
@@ -4792,7 +4792,7 @@  discard block
 block discarded – undo
4792 4792
 			->willReturn($userFolder);
4793 4793
 
4794 4794
 		$expected = [
4795
-			'users' => ['owner', 'user1', 'user2', 'user3', '123456','user4', 'user5', '234567'],
4795
+			'users' => ['owner', 'user1', 'user2', 'user3', '123456', 'user4', 'user5', '234567'],
4796 4796
 			'remote' => true,
4797 4797
 			'public' => true,
4798 4798
 		];
@@ -4927,12 +4927,12 @@  discard block
 block discarded – undo
4927 4927
 		$share4 = $this->createMock(IShare::class);
4928 4928
 
4929 4929
 		$this->defaultProvider->method('getAllShares')
4930
-			->willReturnCallback(function () use ($share1, $share2) {
4930
+			->willReturnCallback(function() use ($share1, $share2) {
4931 4931
 				yield $share1;
4932 4932
 				yield $share2;
4933 4933
 			});
4934 4934
 		$extraProvider->method('getAllShares')
4935
-			->willReturnCallback(function () use ($share3, $share4) {
4935
+			->willReturnCallback(function() use ($share3, $share4) {
4936 4936
 				yield $share3;
4937 4937
 				yield $share4;
4938 4938
 			});
Please login to merge, or discard this patch.
apps/sharebymail/tests/ShareByMailProviderTest.php 2 patches
Indentation   +1808 added lines, -1808 removed lines patch added patch discarded remove patch
@@ -50,1859 +50,1859 @@
 block discarded – undo
50 50
  */
51 51
 #[\PHPUnit\Framework\Attributes\Group(name: 'DB')]
52 52
 class ShareByMailProviderTest extends TestCase {
53
-	use EmailValidatorTrait;
54
-
55
-	private IDBConnection $connection;
56
-
57
-	private IL10N&MockObject $l;
58
-	private IShare&MockObject $share;
59
-	private IConfig&MockObject $config;
60
-	private IMailer&MockObject $mailer;
61
-	private IHasher&MockObject $hasher;
62
-	private Defaults&MockObject $defaults;
63
-	private IManager&MockObject $shareManager;
64
-	private LoggerInterface&MockObject $logger;
65
-	private IRootFolder&MockObject $rootFolder;
66
-	private IUserManager&MockObject $userManager;
67
-	private ISecureRandom&MockObject $secureRandom;
68
-	private IURLGenerator&MockObject $urlGenerator;
69
-	private SettingsManager&MockObject $settingsManager;
70
-	private IActivityManager&MockObject $activityManager;
71
-	private IEventDispatcher&MockObject $eventDispatcher;
72
-
73
-	protected function setUp(): void {
74
-		parent::setUp();
75
-
76
-		$this->connection = Server::get(IDBConnection::class);
77
-
78
-		$this->l = $this->createMock(IL10N::class);
79
-		$this->l->method('t')
80
-			->willReturnCallback(function ($text, $parameters = []) {
81
-				return vsprintf($text, $parameters);
82
-			});
83
-		$this->config = $this->createMock(IConfig::class);
84
-		$this->logger = $this->createMock(LoggerInterface::class);
85
-		$this->rootFolder = $this->createMock('OCP\Files\IRootFolder');
86
-		$this->userManager = $this->createMock(IUserManager::class);
87
-		$this->secureRandom = $this->createMock('\OCP\Security\ISecureRandom');
88
-		$this->mailer = $this->createMock('\OCP\Mail\IMailer');
89
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
90
-		$this->share = $this->createMock(IShare::class);
91
-		$this->activityManager = $this->createMock('OCP\Activity\IManager');
92
-		$this->settingsManager = $this->createMock(SettingsManager::class);
93
-		$this->defaults = $this->createMock(Defaults::class);
94
-		$this->hasher = $this->createMock(IHasher::class);
95
-		$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
96
-		$this->shareManager = $this->createMock(IManager::class);
97
-
98
-		$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
99
-		$this->config->expects($this->any())->method('getAppValue')->with('core', 'enforce_strict_email_check')->willReturn('yes');
100
-	}
101
-
102
-	/**
103
-	 * get instance of Mocked ShareByMailProvider
104
-	 *
105
-	 * @param array $mockedMethods internal methods which should be mocked
106
-	 * @return \PHPUnit\Framework\MockObject\MockObject | ShareByMailProvider
107
-	 */
108
-	private function getInstance(array $mockedMethods = []) {
109
-		if (!empty($mockedMethods)) {
110
-			return $this->getMockBuilder(ShareByMailProvider::class)
111
-				->setConstructorArgs([
112
-					$this->config,
113
-					$this->connection,
114
-					$this->secureRandom,
115
-					$this->userManager,
116
-					$this->rootFolder,
117
-					$this->l,
118
-					$this->logger,
119
-					$this->mailer,
120
-					$this->urlGenerator,
121
-					$this->activityManager,
122
-					$this->settingsManager,
123
-					$this->defaults,
124
-					$this->hasher,
125
-					$this->eventDispatcher,
126
-					$this->shareManager,
127
-					$this->getEmailValidatorWithStrictEmailCheck(),
128
-				])
129
-				->onlyMethods($mockedMethods)
130
-				->getMock();
131
-		}
132
-
133
-		return new ShareByMailProvider(
134
-			$this->config,
135
-			$this->connection,
136
-			$this->secureRandom,
137
-			$this->userManager,
138
-			$this->rootFolder,
139
-			$this->l,
140
-			$this->logger,
141
-			$this->mailer,
142
-			$this->urlGenerator,
143
-			$this->activityManager,
144
-			$this->settingsManager,
145
-			$this->defaults,
146
-			$this->hasher,
147
-			$this->eventDispatcher,
148
-			$this->shareManager,
149
-			$this->getEmailValidatorWithStrictEmailCheck(),
150
-		);
151
-	}
152
-
153
-	protected function tearDown(): void {
154
-		$this->connection
155
-			->getQueryBuilder()
156
-			->delete('share')
157
-			->executeStatement();
158
-
159
-		parent::tearDown();
160
-	}
161
-
162
-	public function testCreate(): void {
163
-		$expectedShare = $this->createMock(IShare::class);
164
-
165
-		$share = $this->createMock(IShare::class);
166
-		$share->expects($this->any())->method('getSharedWith')->willReturn('user1');
167
-
168
-		$node = $this->createMock(File::class);
169
-		$node->expects($this->any())->method('getName')->willReturn('filename');
170
-
171
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'sendEmail', 'sendPassword']);
172
-
173
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
174
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
175
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
176
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare']);
177
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
178
-		$share->expects($this->any())->method('getNode')->willReturn($node);
179
-
180
-		// As share api link password is not enforced, the password will not be generated.
181
-		$this->shareManager->expects($this->once())->method('shareApiLinkEnforcePassword')->willReturn(false);
182
-		$this->settingsManager->expects($this->never())->method('sendPasswordByMail');
183
-
184
-		// Mail notification is triggered by the share manager.
185
-		$instance->expects($this->never())->method('sendEmail');
186
-		$instance->expects($this->never())->method('sendPassword');
187
-
188
-		$this->assertSame($expectedShare, $instance->create($share));
189
-	}
190
-
191
-	public function testCreateSendPasswordByMailWithoutEnforcedPasswordProtection(): void {
192
-		$expectedShare = $this->createMock(IShare::class);
193
-
194
-		$node = $this->createMock(File::class);
195
-		$node->expects($this->any())->method('getName')->willReturn('filename');
196
-
197
-		$share = $this->createMock(IShare::class);
198
-		$share->expects($this->any())->method('getSharedWith')->willReturn('receiver@examplelölöl.com');
199
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
200
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
201
-		$share->expects($this->any())->method('getNode')->willReturn($node);
202
-		$share->expects($this->any())->method('getId')->willReturn('42');
203
-		$share->expects($this->any())->method('getNote')->willReturn('');
204
-		$share->expects($this->any())->method('getToken')->willReturn('token');
205
-
206
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
207
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
208
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
209
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
210
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare']);
211
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
212
-		$share->expects($this->any())->method('getNode')->willReturn($node);
213
-
214
-		// The autogenerated password should not be mailed.
215
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
216
-		$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
217
-		$instance->expects($this->never())->method('autoGeneratePassword');
218
-
219
-		// No password is set and no password sent via talk is requested
220
-		$instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@examplelölöl.com']);
221
-		$instance->expects($this->never())->method('sendPassword');
222
-		$instance->expects($this->never())->method('sendPasswordToOwner');
223
-
224
-		// The manager sends the mail notification.
225
-		// For the sake of testing simplicity, we will handle it ourselves.
226
-		$this->assertSame($expectedShare, $instance->create($share));
227
-		$instance->sendMailNotification($share);
228
-	}
229
-
230
-	public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithPermanentPassword(): void {
231
-		$expectedShare = $this->createMock(IShare::class);
232
-
233
-		$node = $this->createMock(File::class);
234
-		$node->expects($this->any())->method('getName')->willReturn('filename');
235
-
236
-		$share = $this->createMock(IShare::class);
237
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
238
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
239
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
240
-		$share->expects($this->any())->method('getNode')->willReturn($node);
241
-		$share->expects($this->any())->method('getId')->willReturn('42');
242
-		$share->expects($this->any())->method('getNote')->willReturn('');
243
-		$share->expects($this->any())->method('getToken')->willReturn('token');
244
-
245
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
246
-
247
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
248
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
249
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
250
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
251
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
252
-		$share->expects($this->any())->method('getNode')->willReturn($node);
253
-
254
-		$share->expects($this->any())->method('getPassword')->willReturn('password');
255
-		$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
256
-		$share->expects($this->once())->method('setPassword')->with('passwordHashed');
257
-
258
-		// The given password (but not the autogenerated password) should not be
259
-		// mailed to the receiver of the share because permanent passwords are not enforced.
260
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
261
-		$this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
262
-		$instance->expects($this->never())->method('autoGeneratePassword');
263
-
264
-		// A password is set but no password sent via talk has been requested
265
-		$instance->expects($this->once())->method('sendEmail')->with($share, ['[email protected]']);
266
-		$instance->expects($this->once())->method('sendPassword')->with($share, 'password');
267
-		$instance->expects($this->never())->method('sendPasswordToOwner');
268
-
269
-		$this->assertSame($expectedShare, $instance->create($share));
270
-		$instance->sendMailNotification($share);
271
-	}
272
-
273
-	public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithoutPermanentPassword(): void {
274
-		$expectedShare = $this->createMock(IShare::class);
275
-
276
-		$node = $this->createMock(File::class);
277
-		$node->expects($this->any())->method('getName')->willReturn('filename');
278
-
279
-		$share = $this->createMock(IShare::class);
280
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
281
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
282
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
283
-		$share->expects($this->any())->method('getNode')->willReturn($node);
284
-		$share->expects($this->any())->method('getId')->willReturn('42');
285
-		$share->expects($this->any())->method('getNote')->willReturn('');
286
-		$share->expects($this->any())->method('getToken')->willReturn('token');
287
-
288
-		$instance = $this->getInstance([
289
-			'getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject',
290
-			'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity',
291
-			'sendEmail', 'sendPassword', 'sendPasswordToOwner',
292
-		]);
293
-
294
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
295
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
296
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
297
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
298
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
299
-		$share->expects($this->any())->method('getNode')->willReturn($node);
300
-
301
-		$share->expects($this->any())->method('getPassword')->willReturn('password');
302
-		$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
303
-		$share->expects($this->once())->method('setPassword')->with('passwordHashed');
304
-
305
-		// No password is generated, so no emails need to be sent
306
-		// aside from the main email notification.
307
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
308
-		$instance->expects($this->never())->method('autoGeneratePassword');
309
-		$this->config->expects($this->once())->method('getSystemValue')
310
-			->with('sharing.enable_mail_link_password_expiration')
311
-			->willReturn(true);
312
-
313
-		// No password has been set and no password sent via talk has been requested,
314
-		// but password has been enforced for the whole instance and will be generated.
315
-		$instance->expects($this->once())->method('sendEmail')->with($share, ['[email protected]']);
316
-		$instance->expects($this->never())->method('sendPassword');
317
-		$instance->expects($this->never())->method('sendPasswordToOwner');
318
-
319
-		$this->assertSame($expectedShare, $instance->create($share));
320
-		$instance->sendMailNotification($share);
321
-	}
322
-
323
-	public function testCreateSendPasswordByMailWithEnforcedPasswordProtectionWithPermanentPassword(): void {
324
-		$expectedShare = $this->createMock(IShare::class);
325
-
326
-		$node = $this->createMock(File::class);
327
-		$node->expects($this->any())->method('getName')->willReturn('filename');
328
-
329
-		$share = $this->createMock(IShare::class);
330
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
331
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
332
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
333
-		$share->expects($this->any())->method('getNode')->willReturn($node);
334
-		$share->expects($this->any())->method('getId')->willReturn('42');
335
-		$share->expects($this->any())->method('getNote')->willReturn('');
336
-		$share->expects($this->any())->method('getToken')->willReturn('token');
337
-
338
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
339
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
340
-			->willReturn('https://example.com/file.txt');
341
-
342
-		$this->secureRandom->expects($this->once())
343
-			->method('generate')
344
-			->with(8, ISecureRandom::CHAR_HUMAN_READABLE)
345
-			->willReturn('autogeneratedPassword');
346
-		$this->eventDispatcher->expects($this->once())
347
-			->method('dispatchTyped')
348
-			->with(new GenerateSecurePasswordEvent(PasswordContext::SHARING));
349
-
350
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'createPasswordSendActivity', 'sendPasswordToOwner']);
351
-
352
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
353
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
354
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
355
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'autogeneratedPassword']);
356
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare);
357
-
358
-		// Initially not set, but will be set by the autoGeneratePassword method.
359
-		$share->expects($this->exactly(3))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword');
360
-		$this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed');
361
-		$share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed');
362
-
363
-		// The autogenerated password should be mailed to the receiver of the share because permanent passwords are enforced.
364
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
365
-		$this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
366
-		$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
367
-
368
-		$message = $this->createMock(IMessage::class);
369
-		$message->expects($this->exactly(2))->method('setTo')->with(['[email protected]']);
370
-		$this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
371
-		$calls = [
372
-			[
373
-				'sharebymail.RecipientNotification',
374
-				[
375
-					'filename' => 'filename',
376
-					'link' => 'https://example.com/file.txt',
377
-					'initiator' => 'owner',
378
-					'expiration' => null,
379
-					'shareWith' => '[email protected]',
380
-					'note' => '',
381
-				],
382
-			],
383
-			[
384
-				'sharebymail.RecipientPasswordNotification',
385
-				[
386
-					'filename' => 'filename',
387
-					'password' => 'autogeneratedPassword',
388
-					'initiator' => 'owner',
389
-					'initiatorEmail' => null,
390
-					'shareWith' => '[email protected]',
391
-				],
392
-			],
393
-		];
394
-		$this->mailer->expects($this->exactly(2))
395
-			->method('createEMailTemplate')
396
-			->willReturnCallback(function () use (&$calls) {
397
-				$expected = array_shift($calls);
398
-				$this->assertEquals($expected, func_get_args());
399
-				return $this->createMock(IEMailTemplate::class);
400
-			});
401
-
402
-		// Main email notification is sent as well as the password
403
-		// to the recipient because shareApiLinkEnforcePassword is enabled.
404
-		$this->mailer->expects($this->exactly(2))->method('send');
405
-		$instance->expects($this->never())->method('sendPasswordToOwner');
406
-
407
-		$this->assertSame($expectedShare, $instance->create($share));
408
-		$instance->sendMailNotification($share);
409
-	}
410
-
411
-	public function testCreateSendPasswordByMailWithPasswordAndWithEnforcedPasswordProtectionWithPermanentPassword(): void {
412
-		$expectedShare = $this->createMock(IShare::class);
413
-
414
-		$node = $this->createMock(File::class);
415
-		$node->expects($this->any())->method('getName')->willReturn('filename');
416
-
417
-		$share = $this->createMock(IShare::class);
418
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
419
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
420
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
421
-		$share->expects($this->any())->method('getNode')->willReturn($node);
422
-		$share->expects($this->any())->method('getId')->willReturn('42');
423
-		$share->expects($this->any())->method('getNote')->willReturn('');
424
-		$share->expects($this->any())->method('getToken')->willReturn('token');
425
-
426
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
427
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
428
-			->willReturn('https://example.com/file.txt');
429
-
430
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendPasswordToOwner']);
431
-
432
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
433
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
434
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
435
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
436
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
437
-
438
-		$share->expects($this->exactly(3))->method('getPassword')->willReturn('password');
439
-		$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
440
-		$share->expects($this->once())->method('setPassword')->with('passwordHashed');
441
-
442
-		// The given password (but not the autogenerated password) should be
443
-		// mailed to the receiver of the share.
444
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
445
-		$this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
446
-		$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
447
-		$instance->expects($this->never())->method('autoGeneratePassword');
448
-
449
-		$message = $this->createMock(IMessage::class);
450
-		$message->expects($this->exactly(2))->method('setTo')->with(['[email protected]']);
451
-		$this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
452
-
453
-		$calls = [
454
-			[
455
-				'sharebymail.RecipientNotification',
456
-				[
457
-					'filename' => 'filename',
458
-					'link' => 'https://example.com/file.txt',
459
-					'initiator' => 'owner',
460
-					'expiration' => null,
461
-					'shareWith' => '[email protected]',
462
-					'note' => '',
463
-				],
464
-			],
465
-			[
466
-				'sharebymail.RecipientPasswordNotification',
467
-				[
468
-					'filename' => 'filename',
469
-					'password' => 'password',
470
-					'initiator' => 'owner',
471
-					'initiatorEmail' => null,
472
-					'shareWith' => '[email protected]',
473
-				],
474
-			],
475
-		];
476
-		$this->mailer->expects($this->exactly(2))
477
-			->method('createEMailTemplate')
478
-			->willReturnCallback(function () use (&$calls) {
479
-				$expected = array_shift($calls);
480
-				$this->assertEquals($expected, func_get_args());
481
-				return $this->createMock(IEMailTemplate::class);
482
-			});
483
-
484
-		// Main email notification is sent as well as the password
485
-		// to the recipient because the password is set.
486
-		$this->mailer->expects($this->exactly(2))->method('send');
487
-		$instance->expects($this->never())->method('sendPasswordToOwner');
488
-
489
-		$this->assertSame($expectedShare, $instance->create($share));
490
-		$instance->sendMailNotification($share);
491
-	}
492
-
493
-	public function testCreateSendPasswordByTalkWithEnforcedPasswordProtectionWithPermanentPassword(): void {
494
-		$expectedShare = $this->createMock(IShare::class);
495
-
496
-		// The owner of the share.
497
-		$owner = $this->createMock(IUser::class);
498
-		$this->userManager->expects($this->any())->method('get')->with('owner')->willReturn($owner);
499
-		$owner->expects($this->any())->method('getEMailAddress')->willReturn('[email protected]');
500
-		$owner->expects($this->any())->method('getDisplayName')->willReturn('owner');
501
-
502
-		$node = $this->createMock(File::class);
503
-		$node->expects($this->any())->method('getName')->willReturn('filename');
504
-
505
-		$share = $this->createMock(IShare::class);
506
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
507
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(true);
508
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
509
-		$share->expects($this->any())->method('getNode')->willReturn($node);
510
-		$share->expects($this->any())->method('getId')->willReturn('42');
511
-		$share->expects($this->any())->method('getNote')->willReturn('');
512
-		$share->expects($this->any())->method('getToken')->willReturn('token');
513
-
514
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
515
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
516
-			->willReturn('https://example.com/file.txt');
517
-
518
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
519
-
520
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
521
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
522
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
523
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'autogeneratedPassword']);
524
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare);
525
-
526
-		$share->expects($this->exactly(4))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword', 'autogeneratedPassword');
527
-		$this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed');
528
-		$share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed');
529
-
530
-		// The autogenerated password should be mailed to the owner of the share.
531
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
532
-		$this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
533
-		$this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
534
-		$instance->expects($this->once())->method('autoGeneratePassword')->with($share)->willReturn('autogeneratedPassword');
535
-
536
-		$message = $this->createMock(IMessage::class);
537
-		$setToCalls = [
538
-			[['[email protected]']],
539
-			[['[email protected]' => 'owner']],
540
-		];
541
-		$message->expects($this->exactly(2))
542
-			->method('setTo')
543
-			->willReturnCallback(function () use (&$setToCalls, $message) {
544
-				$expected = array_shift($setToCalls);
545
-				$this->assertEquals($expected, func_get_args());
546
-				return $message;
547
-			});
548
-		$this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
549
-
550
-		$calls = [
551
-			[
552
-				'sharebymail.RecipientNotification',
553
-				[
554
-					'filename' => 'filename',
555
-					'link' => 'https://example.com/file.txt',
556
-					'initiator' => 'owner',
557
-					'expiration' => null,
558
-					'shareWith' => '[email protected]',
559
-					'note' => '',
560
-				],
561
-			],
562
-			[
563
-				'sharebymail.OwnerPasswordNotification',
564
-				[
565
-					'filename' => 'filename',
566
-					'password' => 'autogeneratedPassword',
567
-					'initiator' => 'owner',
568
-					'initiatorEmail' => '[email protected]',
569
-					'shareWith' => '[email protected]',
570
-				],
571
-			],
572
-		];
573
-		$this->mailer->expects($this->exactly(2))
574
-			->method('createEMailTemplate')
575
-			->willReturnCallback(function () use (&$calls) {
576
-				$expected = array_shift($calls);
577
-				$this->assertEquals($expected, func_get_args());
578
-				return $this->createMock(IEMailTemplate::class);
579
-			});
580
-
581
-		// Main email notification is sent as well as the password to owner
582
-		// because the password is set and SendPasswordByTalk is enabled.
583
-		$this->mailer->expects($this->exactly(2))->method('send');
584
-
585
-		$this->assertSame($expectedShare, $instance->create($share));
586
-		$instance->sendMailNotification($share);
587
-	}
588
-
589
-	// If attributes is set to multiple emails, use them as BCC
590
-	public function sendNotificationToMultipleEmails() {
591
-		$expectedShare = $this->createMock(IShare::class);
592
-
593
-		$node = $this->createMock(File::class);
594
-		$node->expects($this->any())->method('getName')->willReturn('filename');
595
-
596
-		$share = $this->createMock(IShare::class);
597
-		$share->expects($this->any())->method('getSharedWith')->willReturn('');
598
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
599
-		$share->expects($this->any())->method('getSharedBy')->willReturn('owner');
600
-		$share->expects($this->any())->method('getNode')->willReturn($node);
601
-		$share->expects($this->any())->method('getId')->willReturn('42');
602
-		$share->expects($this->any())->method('getNote')->willReturn('');
603
-		$share->expects($this->any())->method('getToken')->willReturn('token');
604
-
605
-		$attributes = $this->createMock(IAttributes::class);
606
-		$share->expects($this->any())->method('getAttributes')->willReturn($attributes);
607
-		$attributes->expects($this->any())->method('getAttribute')->with('shareWith', 'emails')->willReturn([
608
-			'[email protected]',
609
-			'[email protected]',
610
-			'[email protected]',
611
-		]);
612
-
613
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
614
-
615
-		$instance->expects($this->once())->method('getSharedWith')->willReturn([]);
616
-		$instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
617
-		$instance->expects($this->once())->method('createShareActivity')->with($share);
618
-		$instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
619
-		$instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
620
-		$share->expects($this->any())->method('getNode')->willReturn($node);
621
-
622
-		$share->expects($this->any())->method('getPassword')->willReturn('password');
623
-		$this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
624
-		$share->expects($this->once())->method('setPassword')->with('passwordHashed');
625
-
626
-		// The given password (but not the autogenerated password) should not be
627
-		// mailed to the receiver of the share because permanent passwords are not enforced.
628
-		$this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
629
-		$this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
630
-		$instance->expects($this->never())->method('autoGeneratePassword');
631
-
632
-		// A password is set but no password sent via talk has been requested
633
-		$instance->expects($this->once())->method('sendEmail')
634
-			->with($share, ['[email protected]', '[email protected]', '[email protected]']);
635
-		$instance->expects($this->once())->method('sendPassword')->with($share, 'password');
636
-		$instance->expects($this->never())->method('sendPasswordToOwner');
637
-
638
-
639
-		$message = $this->createMock(IMessage::class);
640
-		$message->expects($this->never())->method('setTo');
641
-		$message->expects($this->exactly(2))->method('setBcc')->with(['[email protected]', '[email protected]', '[email protected]']);
642
-		$this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
643
-
644
-		// Main email notification is sent as well as the password
645
-		// to recipients because the password is set.
646
-		$this->mailer->expects($this->exactly(2))->method('send');
647
-
648
-		$this->assertSame($expectedShare, $instance->create($share));
649
-		$instance->sendMailNotification($share);
650
-	}
651
-
652
-	public function testCreateFailed(): void {
653
-		$this->expectException(\Exception::class);
654
-
655
-		$this->share->expects($this->once())->method('getSharedWith')->willReturn('user1');
656
-		$node = $this->createMock('OCP\Files\Node');
657
-		$node->expects($this->any())->method('getName')->willReturn('fileName');
658
-		$this->share->expects($this->any())->method('getNode')->willReturn($node);
659
-
660
-		$instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject']);
661
-
662
-		$instance->expects($this->once())->method('getSharedWith')->willReturn(['found']);
663
-		$instance->expects($this->never())->method('createMailShare');
664
-		$instance->expects($this->never())->method('getRawShare');
665
-		$instance->expects($this->never())->method('createShareObject');
666
-
667
-		$this->assertSame('shareObject',
668
-			$instance->create($this->share)
669
-		);
670
-	}
671
-
672
-	public function testCreateMailShare(): void {
673
-		$this->share->expects($this->any())->method('getToken')->willReturn('token');
674
-		$this->share->expects($this->once())->method('setToken')->with('token');
675
-		$this->share->expects($this->any())->method('getSharedBy')->willReturn('[email protected]');
676
-		$this->share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
677
-		$this->share->expects($this->any())->method('getNote')->willReturn('Check this!');
678
-		$this->share->expects($this->any())->method('getMailSend')->willReturn(true);
679
-
680
-		$node = $this->createMock('OCP\Files\Node');
681
-		$node->expects($this->any())->method('getName')->willReturn('fileName');
682
-		$this->share->expects($this->any())->method('getNode')->willReturn($node);
683
-
684
-		$instance = $this->getInstance(['generateToken', 'addShareToDB', 'sendMailNotification']);
685
-
686
-		$instance->expects($this->once())->method('generateToken')->willReturn('token');
687
-		$instance->expects($this->once())->method('addShareToDB')->willReturn('42');
688
-
689
-		// The manager handle the mail sending
690
-		$instance->expects($this->never())->method('sendMailNotification');
691
-
692
-		$this->assertSame('42',
693
-			$this->invokePrivate($instance, 'createMailShare', [$this->share])
694
-		);
695
-	}
696
-
697
-	public function testGenerateToken(): void {
698
-		$instance = $this->getInstance();
699
-
700
-		$this->secureRandom->expects($this->once())->method('generate')->willReturn('token');
701
-
702
-		$this->assertSame('token',
703
-			$this->invokePrivate($instance, 'generateToken')
704
-		);
705
-	}
706
-
707
-	public function testAddShareToDB(): void {
708
-		$itemSource = 11;
709
-		$itemType = 'file';
710
-		$shareWith = '[email protected]';
711
-		$sharedBy = 'user1';
712
-		$uidOwner = 'user2';
713
-		$permissions = 1;
714
-		$token = 'token';
715
-		$password = 'password';
716
-		$sendPasswordByTalk = true;
717
-		$hideDownload = true;
718
-		$label = 'label';
719
-		$expiration = new \DateTime();
720
-		$passwordExpirationTime = new \DateTime();
721
-
722
-
723
-		$instance = $this->getInstance();
724
-		$id = $this->invokePrivate(
725
-			$instance,
726
-			'addShareToDB',
727
-			[
728
-				$itemSource,
729
-				$itemType,
730
-				$shareWith,
731
-				$sharedBy,
732
-				$uidOwner,
733
-				$permissions,
734
-				$token,
735
-				$password,
736
-				$passwordExpirationTime,
737
-				$sendPasswordByTalk,
738
-				$hideDownload,
739
-				$label,
740
-				$expiration
741
-			]
742
-		);
743
-
744
-		$qb = $this->connection->getQueryBuilder();
745
-		$qb->select('*')
746
-			->from('share')
747
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
748
-
749
-		$qResult = $qb->executeQuery();
750
-		$result = $qResult->fetchAllAssociative();
751
-		$qResult->closeCursor();
752
-
753
-		$this->assertSame(1, count($result));
754
-
755
-		$this->assertSame($itemSource, (int)$result[0]['item_source']);
756
-		$this->assertSame($itemType, $result[0]['item_type']);
757
-		$this->assertSame($shareWith, $result[0]['share_with']);
758
-		$this->assertSame($sharedBy, $result[0]['uid_initiator']);
759
-		$this->assertSame($uidOwner, $result[0]['uid_owner']);
760
-		$this->assertSame($permissions, (int)$result[0]['permissions']);
761
-		$this->assertSame($token, $result[0]['token']);
762
-		$this->assertSame($password, $result[0]['password']);
763
-		$this->assertSame($passwordExpirationTime->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['password_expiration_time'])->getTimestamp());
764
-		$this->assertSame($sendPasswordByTalk, (bool)$result[0]['password_by_talk']);
765
-		$this->assertSame($hideDownload, (bool)$result[0]['hide_download']);
766
-		$this->assertSame($label, $result[0]['label']);
767
-		$this->assertSame($expiration->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['expiration'])->getTimestamp());
768
-	}
769
-
770
-	public function testUpdate(): void {
771
-		$itemSource = 11;
772
-		$itemType = 'file';
773
-		$shareWith = '[email protected]';
774
-		$sharedBy = 'user1';
775
-		$uidOwner = 'user2';
776
-		$permissions = 1;
777
-		$token = 'token';
778
-		$note = 'personal note';
779
-
780
-
781
-		$instance = $this->getInstance();
782
-
783
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note);
784
-
785
-		$this->share->expects($this->once())->method('getPermissions')->willReturn($permissions + 1);
786
-		$this->share->expects($this->once())->method('getShareOwner')->willReturn($uidOwner);
787
-		$this->share->expects($this->once())->method('getSharedBy')->willReturn($sharedBy);
788
-		$this->share->expects($this->any())->method('getNote')->willReturn($note);
789
-		$this->share->expects($this->atLeastOnce())->method('getId')->willReturn($id);
790
-		$this->share->expects($this->atLeastOnce())->method('getNodeId')->willReturn($itemSource);
791
-		$this->share->expects($this->once())->method('getSharedWith')->willReturn($shareWith);
792
-
793
-		$this->assertSame($this->share,
794
-			$instance->update($this->share)
795
-		);
796
-
797
-		$qb = $this->connection->getQueryBuilder();
798
-		$qb->select('*')
799
-			->from('share')
800
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
801
-
802
-		$qResult = $qb->executeQuery();
803
-		$result = $qResult->fetchAllAssociative();
804
-		$qResult->closeCursor();
805
-
806
-		$this->assertSame(1, count($result));
807
-
808
-		$this->assertSame($itemSource, (int)$result[0]['item_source']);
809
-		$this->assertSame($itemType, $result[0]['item_type']);
810
-		$this->assertSame($shareWith, $result[0]['share_with']);
811
-		$this->assertSame($sharedBy, $result[0]['uid_initiator']);
812
-		$this->assertSame($uidOwner, $result[0]['uid_owner']);
813
-		$this->assertSame($permissions + 1, (int)$result[0]['permissions']);
814
-		$this->assertSame($token, $result[0]['token']);
815
-		$this->assertSame($note, $result[0]['note']);
816
-	}
817
-
818
-	public static function dataUpdateSendPassword(): array {
819
-		return [
820
-			['password', 'hashed', 'hashed new', false, false, true],
821
-			['', 'hashed', 'hashed new', false, false, false],
822
-			[null, 'hashed', 'hashed new', false, false, false],
823
-			['password', 'hashed', 'hashed', false, false, false],
824
-			['password', 'hashed', 'hashed new', false, true, false],
825
-			['password', 'hashed', 'hashed new', true, false, true],
826
-			['password', 'hashed', 'hashed', true, false, true],
827
-		];
828
-	}
829
-
830
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataUpdateSendPassword')]
831
-	public function testUpdateSendPassword(?string $plainTextPassword, string $originalPassword, string $newPassword, bool $originalSendPasswordByTalk, bool $newSendPasswordByTalk, bool $sendMail): void {
832
-		$node = $this->createMock(File::class);
833
-		$node->expects($this->any())->method('getName')->willReturn('filename');
834
-
835
-		$this->settingsManager->method('sendPasswordByMail')->willReturn(true);
836
-
837
-		$originalShare = $this->createMock(IShare::class);
838
-		$originalShare->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
839
-		$originalShare->expects($this->any())->method('getNode')->willReturn($node);
840
-		$originalShare->expects($this->any())->method('getId')->willReturn('42');
841
-		$originalShare->expects($this->any())->method('getPassword')->willReturn($originalPassword);
842
-		$originalShare->expects($this->any())->method('getSendPasswordByTalk')->willReturn($originalSendPasswordByTalk);
843
-
844
-		$share = $this->createMock(IShare::class);
845
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
846
-		$share->expects($this->any())->method('getNode')->willReturn($node);
847
-		$share->expects($this->any())->method('getId')->willReturn('42');
848
-		$share->expects($this->any())->method('getPassword')->willReturn($newPassword);
849
-		$share->expects($this->any())->method('getSendPasswordByTalk')->willReturn($newSendPasswordByTalk);
850
-
851
-		if ($sendMail) {
852
-			$this->mailer->expects($this->once())->method('createEMailTemplate')->with('sharebymail.RecipientPasswordNotification', [
853
-				'filename' => 'filename',
854
-				'password' => $plainTextPassword,
855
-				'initiator' => null,
856
-				'initiatorEmail' => null,
857
-				'shareWith' => '[email protected]',
858
-			]);
859
-			$this->mailer->expects($this->once())->method('send');
860
-		} else {
861
-			$this->mailer->expects($this->never())->method('send');
862
-		}
863
-
864
-		$instance = $this->getInstance(['getShareById', 'createPasswordSendActivity']);
865
-		$instance->expects($this->once())->method('getShareById')->willReturn($originalShare);
866
-
867
-		$this->assertSame($share,
868
-			$instance->update($share, $plainTextPassword)
869
-		);
870
-	}
871
-
872
-	public function testDelete(): void {
873
-		$instance = $this->getInstance(['removeShareFromTable', 'createShareActivity']);
874
-		$this->share->expects($this->once())->method('getId')->willReturn('42');
875
-		$instance->expects($this->once())->method('removeShareFromTable')->with('42');
876
-		$instance->expects($this->once())->method('createShareActivity')->with($this->share, 'unshare');
877
-		$instance->delete($this->share);
878
-	}
879
-
880
-	public function testGetShareById(): void {
881
-		$instance = $this->getInstance(['createShareObject']);
882
-
883
-		$itemSource = 11;
884
-		$itemType = 'file';
885
-		$shareWith = '[email protected]';
886
-		$sharedBy = 'user1';
887
-		$uidOwner = 'user2';
888
-		$permissions = 1;
889
-		$token = 'token';
890
-
891
-		$this->createDummyShare($itemType, $itemSource, $shareWith, 'user1wrong', 'user2wrong', $permissions, $token);
892
-		$id2 = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
893
-
894
-		$instance->expects($this->once())->method('createShareObject')
895
-			->willReturnCallback(
896
-				function ($data) use ($uidOwner, $sharedBy, $id2) {
897
-					$this->assertSame($uidOwner, $data['uid_owner']);
898
-					$this->assertSame($sharedBy, $data['uid_initiator']);
899
-					$this->assertSame($id2, (string)$data['id']);
900
-					return $this->share;
901
-				}
902
-			);
903
-
904
-		$result = $instance->getShareById($id2);
905
-
906
-		$this->assertInstanceOf('OCP\Share\IShare', $result);
907
-	}
908
-
909
-
910
-	public function testGetShareByIdFailed(): void {
911
-		$this->expectException(ShareNotFound::class);
912
-
913
-		$instance = $this->getInstance(['createShareObject']);
914
-
915
-		$itemSource = 11;
916
-		$itemType = 'file';
917
-		$shareWith = '[email protected]';
918
-		$sharedBy = 'user1';
919
-		$uidOwner = 'user2';
920
-		$permissions = 1;
921
-		$token = 'token';
922
-
923
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
924
-
925
-		$instance->getShareById($id + 1);
926
-	}
927
-
928
-	public function testGetShareByPath(): void {
929
-		$itemSource = 11;
930
-		$itemType = 'file';
931
-		$shareWith = '[email protected]';
932
-		$sharedBy = 'user1';
933
-		$uidOwner = 'user2';
934
-		$permissions = 1;
935
-		$token = 'token';
936
-
937
-		$node = $this->createMock(Node::class);
938
-		$node->expects($this->once())->method('getId')->willReturn($itemSource);
939
-
940
-
941
-		$instance = $this->getInstance(['createShareObject']);
942
-
943
-		$this->createDummyShare($itemType, 111, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
944
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
945
-
946
-		$instance->expects($this->once())->method('createShareObject')
947
-			->willReturnCallback(
948
-				function ($data) use ($uidOwner, $sharedBy, $id) {
949
-					$this->assertSame($uidOwner, $data['uid_owner']);
950
-					$this->assertSame($sharedBy, $data['uid_initiator']);
951
-					$this->assertSame($id, $data['id']);
952
-					return $this->share;
953
-				}
954
-			);
955
-
956
-		$result = $instance->getSharesByPath($node);
957
-
958
-		$this->assertTrue(is_array($result));
959
-		$this->assertSame(1, count($result));
960
-		$this->assertInstanceOf('OCP\Share\IShare', $result[0]);
961
-	}
962
-
963
-	public function testGetShareByToken(): void {
964
-		$itemSource = 11;
965
-		$itemType = 'file';
966
-		$shareWith = '[email protected]';
967
-		$sharedBy = 'user1';
968
-		$uidOwner = 'user2';
969
-		$permissions = 1;
970
-		$token = 'token';
53
+    use EmailValidatorTrait;
54
+
55
+    private IDBConnection $connection;
56
+
57
+    private IL10N&MockObject $l;
58
+    private IShare&MockObject $share;
59
+    private IConfig&MockObject $config;
60
+    private IMailer&MockObject $mailer;
61
+    private IHasher&MockObject $hasher;
62
+    private Defaults&MockObject $defaults;
63
+    private IManager&MockObject $shareManager;
64
+    private LoggerInterface&MockObject $logger;
65
+    private IRootFolder&MockObject $rootFolder;
66
+    private IUserManager&MockObject $userManager;
67
+    private ISecureRandom&MockObject $secureRandom;
68
+    private IURLGenerator&MockObject $urlGenerator;
69
+    private SettingsManager&MockObject $settingsManager;
70
+    private IActivityManager&MockObject $activityManager;
71
+    private IEventDispatcher&MockObject $eventDispatcher;
72
+
73
+    protected function setUp(): void {
74
+        parent::setUp();
75
+
76
+        $this->connection = Server::get(IDBConnection::class);
77
+
78
+        $this->l = $this->createMock(IL10N::class);
79
+        $this->l->method('t')
80
+            ->willReturnCallback(function ($text, $parameters = []) {
81
+                return vsprintf($text, $parameters);
82
+            });
83
+        $this->config = $this->createMock(IConfig::class);
84
+        $this->logger = $this->createMock(LoggerInterface::class);
85
+        $this->rootFolder = $this->createMock('OCP\Files\IRootFolder');
86
+        $this->userManager = $this->createMock(IUserManager::class);
87
+        $this->secureRandom = $this->createMock('\OCP\Security\ISecureRandom');
88
+        $this->mailer = $this->createMock('\OCP\Mail\IMailer');
89
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
90
+        $this->share = $this->createMock(IShare::class);
91
+        $this->activityManager = $this->createMock('OCP\Activity\IManager');
92
+        $this->settingsManager = $this->createMock(SettingsManager::class);
93
+        $this->defaults = $this->createMock(Defaults::class);
94
+        $this->hasher = $this->createMock(IHasher::class);
95
+        $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
96
+        $this->shareManager = $this->createMock(IManager::class);
97
+
98
+        $this->userManager->expects($this->any())->method('userExists')->willReturn(true);
99
+        $this->config->expects($this->any())->method('getAppValue')->with('core', 'enforce_strict_email_check')->willReturn('yes');
100
+    }
101
+
102
+    /**
103
+     * get instance of Mocked ShareByMailProvider
104
+     *
105
+     * @param array $mockedMethods internal methods which should be mocked
106
+     * @return \PHPUnit\Framework\MockObject\MockObject | ShareByMailProvider
107
+     */
108
+    private function getInstance(array $mockedMethods = []) {
109
+        if (!empty($mockedMethods)) {
110
+            return $this->getMockBuilder(ShareByMailProvider::class)
111
+                ->setConstructorArgs([
112
+                    $this->config,
113
+                    $this->connection,
114
+                    $this->secureRandom,
115
+                    $this->userManager,
116
+                    $this->rootFolder,
117
+                    $this->l,
118
+                    $this->logger,
119
+                    $this->mailer,
120
+                    $this->urlGenerator,
121
+                    $this->activityManager,
122
+                    $this->settingsManager,
123
+                    $this->defaults,
124
+                    $this->hasher,
125
+                    $this->eventDispatcher,
126
+                    $this->shareManager,
127
+                    $this->getEmailValidatorWithStrictEmailCheck(),
128
+                ])
129
+                ->onlyMethods($mockedMethods)
130
+                ->getMock();
131
+        }
132
+
133
+        return new ShareByMailProvider(
134
+            $this->config,
135
+            $this->connection,
136
+            $this->secureRandom,
137
+            $this->userManager,
138
+            $this->rootFolder,
139
+            $this->l,
140
+            $this->logger,
141
+            $this->mailer,
142
+            $this->urlGenerator,
143
+            $this->activityManager,
144
+            $this->settingsManager,
145
+            $this->defaults,
146
+            $this->hasher,
147
+            $this->eventDispatcher,
148
+            $this->shareManager,
149
+            $this->getEmailValidatorWithStrictEmailCheck(),
150
+        );
151
+    }
152
+
153
+    protected function tearDown(): void {
154
+        $this->connection
155
+            ->getQueryBuilder()
156
+            ->delete('share')
157
+            ->executeStatement();
158
+
159
+        parent::tearDown();
160
+    }
161
+
162
+    public function testCreate(): void {
163
+        $expectedShare = $this->createMock(IShare::class);
164
+
165
+        $share = $this->createMock(IShare::class);
166
+        $share->expects($this->any())->method('getSharedWith')->willReturn('user1');
167
+
168
+        $node = $this->createMock(File::class);
169
+        $node->expects($this->any())->method('getName')->willReturn('filename');
170
+
171
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'sendEmail', 'sendPassword']);
172
+
173
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
174
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
175
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
176
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare']);
177
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
178
+        $share->expects($this->any())->method('getNode')->willReturn($node);
179
+
180
+        // As share api link password is not enforced, the password will not be generated.
181
+        $this->shareManager->expects($this->once())->method('shareApiLinkEnforcePassword')->willReturn(false);
182
+        $this->settingsManager->expects($this->never())->method('sendPasswordByMail');
183
+
184
+        // Mail notification is triggered by the share manager.
185
+        $instance->expects($this->never())->method('sendEmail');
186
+        $instance->expects($this->never())->method('sendPassword');
187
+
188
+        $this->assertSame($expectedShare, $instance->create($share));
189
+    }
190
+
191
+    public function testCreateSendPasswordByMailWithoutEnforcedPasswordProtection(): void {
192
+        $expectedShare = $this->createMock(IShare::class);
193
+
194
+        $node = $this->createMock(File::class);
195
+        $node->expects($this->any())->method('getName')->willReturn('filename');
196
+
197
+        $share = $this->createMock(IShare::class);
198
+        $share->expects($this->any())->method('getSharedWith')->willReturn('receiver@examplelölöl.com');
199
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
200
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
201
+        $share->expects($this->any())->method('getNode')->willReturn($node);
202
+        $share->expects($this->any())->method('getId')->willReturn('42');
203
+        $share->expects($this->any())->method('getNote')->willReturn('');
204
+        $share->expects($this->any())->method('getToken')->willReturn('token');
205
+
206
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
207
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
208
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
209
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
210
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare']);
211
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare'])->willReturn($expectedShare);
212
+        $share->expects($this->any())->method('getNode')->willReturn($node);
213
+
214
+        // The autogenerated password should not be mailed.
215
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
216
+        $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
217
+        $instance->expects($this->never())->method('autoGeneratePassword');
218
+
219
+        // No password is set and no password sent via talk is requested
220
+        $instance->expects($this->once())->method('sendEmail')->with($share, ['receiver@examplelölöl.com']);
221
+        $instance->expects($this->never())->method('sendPassword');
222
+        $instance->expects($this->never())->method('sendPasswordToOwner');
223
+
224
+        // The manager sends the mail notification.
225
+        // For the sake of testing simplicity, we will handle it ourselves.
226
+        $this->assertSame($expectedShare, $instance->create($share));
227
+        $instance->sendMailNotification($share);
228
+    }
229
+
230
+    public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithPermanentPassword(): void {
231
+        $expectedShare = $this->createMock(IShare::class);
232
+
233
+        $node = $this->createMock(File::class);
234
+        $node->expects($this->any())->method('getName')->willReturn('filename');
235
+
236
+        $share = $this->createMock(IShare::class);
237
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
238
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
239
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
240
+        $share->expects($this->any())->method('getNode')->willReturn($node);
241
+        $share->expects($this->any())->method('getId')->willReturn('42');
242
+        $share->expects($this->any())->method('getNote')->willReturn('');
243
+        $share->expects($this->any())->method('getToken')->willReturn('token');
244
+
245
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
246
+
247
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
248
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
249
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
250
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
251
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
252
+        $share->expects($this->any())->method('getNode')->willReturn($node);
253
+
254
+        $share->expects($this->any())->method('getPassword')->willReturn('password');
255
+        $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
256
+        $share->expects($this->once())->method('setPassword')->with('passwordHashed');
257
+
258
+        // The given password (but not the autogenerated password) should not be
259
+        // mailed to the receiver of the share because permanent passwords are not enforced.
260
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
261
+        $this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
262
+        $instance->expects($this->never())->method('autoGeneratePassword');
263
+
264
+        // A password is set but no password sent via talk has been requested
265
+        $instance->expects($this->once())->method('sendEmail')->with($share, ['[email protected]']);
266
+        $instance->expects($this->once())->method('sendPassword')->with($share, 'password');
267
+        $instance->expects($this->never())->method('sendPasswordToOwner');
268
+
269
+        $this->assertSame($expectedShare, $instance->create($share));
270
+        $instance->sendMailNotification($share);
271
+    }
272
+
273
+    public function testCreateSendPasswordByMailWithPasswordAndWithoutEnforcedPasswordProtectionWithoutPermanentPassword(): void {
274
+        $expectedShare = $this->createMock(IShare::class);
275
+
276
+        $node = $this->createMock(File::class);
277
+        $node->expects($this->any())->method('getName')->willReturn('filename');
278
+
279
+        $share = $this->createMock(IShare::class);
280
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
281
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
282
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
283
+        $share->expects($this->any())->method('getNode')->willReturn($node);
284
+        $share->expects($this->any())->method('getId')->willReturn('42');
285
+        $share->expects($this->any())->method('getNote')->willReturn('');
286
+        $share->expects($this->any())->method('getToken')->willReturn('token');
287
+
288
+        $instance = $this->getInstance([
289
+            'getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject',
290
+            'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity',
291
+            'sendEmail', 'sendPassword', 'sendPasswordToOwner',
292
+        ]);
293
+
294
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
295
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
296
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
297
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
298
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
299
+        $share->expects($this->any())->method('getNode')->willReturn($node);
300
+
301
+        $share->expects($this->any())->method('getPassword')->willReturn('password');
302
+        $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
303
+        $share->expects($this->once())->method('setPassword')->with('passwordHashed');
304
+
305
+        // No password is generated, so no emails need to be sent
306
+        // aside from the main email notification.
307
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
308
+        $instance->expects($this->never())->method('autoGeneratePassword');
309
+        $this->config->expects($this->once())->method('getSystemValue')
310
+            ->with('sharing.enable_mail_link_password_expiration')
311
+            ->willReturn(true);
312
+
313
+        // No password has been set and no password sent via talk has been requested,
314
+        // but password has been enforced for the whole instance and will be generated.
315
+        $instance->expects($this->once())->method('sendEmail')->with($share, ['[email protected]']);
316
+        $instance->expects($this->never())->method('sendPassword');
317
+        $instance->expects($this->never())->method('sendPasswordToOwner');
318
+
319
+        $this->assertSame($expectedShare, $instance->create($share));
320
+        $instance->sendMailNotification($share);
321
+    }
322
+
323
+    public function testCreateSendPasswordByMailWithEnforcedPasswordProtectionWithPermanentPassword(): void {
324
+        $expectedShare = $this->createMock(IShare::class);
325
+
326
+        $node = $this->createMock(File::class);
327
+        $node->expects($this->any())->method('getName')->willReturn('filename');
328
+
329
+        $share = $this->createMock(IShare::class);
330
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
331
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
332
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
333
+        $share->expects($this->any())->method('getNode')->willReturn($node);
334
+        $share->expects($this->any())->method('getId')->willReturn('42');
335
+        $share->expects($this->any())->method('getNote')->willReturn('');
336
+        $share->expects($this->any())->method('getToken')->willReturn('token');
337
+
338
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
339
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
340
+            ->willReturn('https://example.com/file.txt');
341
+
342
+        $this->secureRandom->expects($this->once())
343
+            ->method('generate')
344
+            ->with(8, ISecureRandom::CHAR_HUMAN_READABLE)
345
+            ->willReturn('autogeneratedPassword');
346
+        $this->eventDispatcher->expects($this->once())
347
+            ->method('dispatchTyped')
348
+            ->with(new GenerateSecurePasswordEvent(PasswordContext::SHARING));
349
+
350
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'createPasswordSendActivity', 'sendPasswordToOwner']);
351
+
352
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
353
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
354
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
355
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'autogeneratedPassword']);
356
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare);
357
+
358
+        // Initially not set, but will be set by the autoGeneratePassword method.
359
+        $share->expects($this->exactly(3))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword');
360
+        $this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed');
361
+        $share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed');
362
+
363
+        // The autogenerated password should be mailed to the receiver of the share because permanent passwords are enforced.
364
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
365
+        $this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
366
+        $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
367
+
368
+        $message = $this->createMock(IMessage::class);
369
+        $message->expects($this->exactly(2))->method('setTo')->with(['[email protected]']);
370
+        $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
371
+        $calls = [
372
+            [
373
+                'sharebymail.RecipientNotification',
374
+                [
375
+                    'filename' => 'filename',
376
+                    'link' => 'https://example.com/file.txt',
377
+                    'initiator' => 'owner',
378
+                    'expiration' => null,
379
+                    'shareWith' => '[email protected]',
380
+                    'note' => '',
381
+                ],
382
+            ],
383
+            [
384
+                'sharebymail.RecipientPasswordNotification',
385
+                [
386
+                    'filename' => 'filename',
387
+                    'password' => 'autogeneratedPassword',
388
+                    'initiator' => 'owner',
389
+                    'initiatorEmail' => null,
390
+                    'shareWith' => '[email protected]',
391
+                ],
392
+            ],
393
+        ];
394
+        $this->mailer->expects($this->exactly(2))
395
+            ->method('createEMailTemplate')
396
+            ->willReturnCallback(function () use (&$calls) {
397
+                $expected = array_shift($calls);
398
+                $this->assertEquals($expected, func_get_args());
399
+                return $this->createMock(IEMailTemplate::class);
400
+            });
401
+
402
+        // Main email notification is sent as well as the password
403
+        // to the recipient because shareApiLinkEnforcePassword is enabled.
404
+        $this->mailer->expects($this->exactly(2))->method('send');
405
+        $instance->expects($this->never())->method('sendPasswordToOwner');
406
+
407
+        $this->assertSame($expectedShare, $instance->create($share));
408
+        $instance->sendMailNotification($share);
409
+    }
410
+
411
+    public function testCreateSendPasswordByMailWithPasswordAndWithEnforcedPasswordProtectionWithPermanentPassword(): void {
412
+        $expectedShare = $this->createMock(IShare::class);
413
+
414
+        $node = $this->createMock(File::class);
415
+        $node->expects($this->any())->method('getName')->willReturn('filename');
416
+
417
+        $share = $this->createMock(IShare::class);
418
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
419
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
420
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
421
+        $share->expects($this->any())->method('getNode')->willReturn($node);
422
+        $share->expects($this->any())->method('getId')->willReturn('42');
423
+        $share->expects($this->any())->method('getNote')->willReturn('');
424
+        $share->expects($this->any())->method('getToken')->willReturn('token');
425
+
426
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
427
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
428
+            ->willReturn('https://example.com/file.txt');
429
+
430
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendPasswordToOwner']);
431
+
432
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
433
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
434
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
435
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
436
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
437
+
438
+        $share->expects($this->exactly(3))->method('getPassword')->willReturn('password');
439
+        $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
440
+        $share->expects($this->once())->method('setPassword')->with('passwordHashed');
441
+
442
+        // The given password (but not the autogenerated password) should be
443
+        // mailed to the receiver of the share.
444
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
445
+        $this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
446
+        $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
447
+        $instance->expects($this->never())->method('autoGeneratePassword');
448
+
449
+        $message = $this->createMock(IMessage::class);
450
+        $message->expects($this->exactly(2))->method('setTo')->with(['[email protected]']);
451
+        $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
452
+
453
+        $calls = [
454
+            [
455
+                'sharebymail.RecipientNotification',
456
+                [
457
+                    'filename' => 'filename',
458
+                    'link' => 'https://example.com/file.txt',
459
+                    'initiator' => 'owner',
460
+                    'expiration' => null,
461
+                    'shareWith' => '[email protected]',
462
+                    'note' => '',
463
+                ],
464
+            ],
465
+            [
466
+                'sharebymail.RecipientPasswordNotification',
467
+                [
468
+                    'filename' => 'filename',
469
+                    'password' => 'password',
470
+                    'initiator' => 'owner',
471
+                    'initiatorEmail' => null,
472
+                    'shareWith' => '[email protected]',
473
+                ],
474
+            ],
475
+        ];
476
+        $this->mailer->expects($this->exactly(2))
477
+            ->method('createEMailTemplate')
478
+            ->willReturnCallback(function () use (&$calls) {
479
+                $expected = array_shift($calls);
480
+                $this->assertEquals($expected, func_get_args());
481
+                return $this->createMock(IEMailTemplate::class);
482
+            });
483
+
484
+        // Main email notification is sent as well as the password
485
+        // to the recipient because the password is set.
486
+        $this->mailer->expects($this->exactly(2))->method('send');
487
+        $instance->expects($this->never())->method('sendPasswordToOwner');
488
+
489
+        $this->assertSame($expectedShare, $instance->create($share));
490
+        $instance->sendMailNotification($share);
491
+    }
492
+
493
+    public function testCreateSendPasswordByTalkWithEnforcedPasswordProtectionWithPermanentPassword(): void {
494
+        $expectedShare = $this->createMock(IShare::class);
495
+
496
+        // The owner of the share.
497
+        $owner = $this->createMock(IUser::class);
498
+        $this->userManager->expects($this->any())->method('get')->with('owner')->willReturn($owner);
499
+        $owner->expects($this->any())->method('getEMailAddress')->willReturn('[email protected]');
500
+        $owner->expects($this->any())->method('getDisplayName')->willReturn('owner');
501
+
502
+        $node = $this->createMock(File::class);
503
+        $node->expects($this->any())->method('getName')->willReturn('filename');
504
+
505
+        $share = $this->createMock(IShare::class);
506
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
507
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(true);
508
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
509
+        $share->expects($this->any())->method('getNode')->willReturn($node);
510
+        $share->expects($this->any())->method('getId')->willReturn('42');
511
+        $share->expects($this->any())->method('getNote')->willReturn('');
512
+        $share->expects($this->any())->method('getToken')->willReturn('token');
513
+
514
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
515
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
516
+            ->willReturn('https://example.com/file.txt');
517
+
518
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity']);
519
+
520
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
521
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
522
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
523
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'autogeneratedPassword']);
524
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'autogeneratedPassword'])->willReturn($expectedShare);
525
+
526
+        $share->expects($this->exactly(4))->method('getPassword')->willReturnOnConsecutiveCalls(null, 'autogeneratedPassword', 'autogeneratedPassword', 'autogeneratedPassword');
527
+        $this->hasher->expects($this->once())->method('hash')->with('autogeneratedPassword')->willReturn('autogeneratedPasswordHashed');
528
+        $share->expects($this->once())->method('setPassword')->with('autogeneratedPasswordHashed');
529
+
530
+        // The autogenerated password should be mailed to the owner of the share.
531
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(true);
532
+        $this->config->expects($this->any())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
533
+        $this->settingsManager->expects($this->any())->method('sendPasswordByMail')->willReturn(true);
534
+        $instance->expects($this->once())->method('autoGeneratePassword')->with($share)->willReturn('autogeneratedPassword');
535
+
536
+        $message = $this->createMock(IMessage::class);
537
+        $setToCalls = [
538
+            [['[email protected]']],
539
+            [['[email protected]' => 'owner']],
540
+        ];
541
+        $message->expects($this->exactly(2))
542
+            ->method('setTo')
543
+            ->willReturnCallback(function () use (&$setToCalls, $message) {
544
+                $expected = array_shift($setToCalls);
545
+                $this->assertEquals($expected, func_get_args());
546
+                return $message;
547
+            });
548
+        $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
549
+
550
+        $calls = [
551
+            [
552
+                'sharebymail.RecipientNotification',
553
+                [
554
+                    'filename' => 'filename',
555
+                    'link' => 'https://example.com/file.txt',
556
+                    'initiator' => 'owner',
557
+                    'expiration' => null,
558
+                    'shareWith' => '[email protected]',
559
+                    'note' => '',
560
+                ],
561
+            ],
562
+            [
563
+                'sharebymail.OwnerPasswordNotification',
564
+                [
565
+                    'filename' => 'filename',
566
+                    'password' => 'autogeneratedPassword',
567
+                    'initiator' => 'owner',
568
+                    'initiatorEmail' => '[email protected]',
569
+                    'shareWith' => '[email protected]',
570
+                ],
571
+            ],
572
+        ];
573
+        $this->mailer->expects($this->exactly(2))
574
+            ->method('createEMailTemplate')
575
+            ->willReturnCallback(function () use (&$calls) {
576
+                $expected = array_shift($calls);
577
+                $this->assertEquals($expected, func_get_args());
578
+                return $this->createMock(IEMailTemplate::class);
579
+            });
580
+
581
+        // Main email notification is sent as well as the password to owner
582
+        // because the password is set and SendPasswordByTalk is enabled.
583
+        $this->mailer->expects($this->exactly(2))->method('send');
584
+
585
+        $this->assertSame($expectedShare, $instance->create($share));
586
+        $instance->sendMailNotification($share);
587
+    }
588
+
589
+    // If attributes is set to multiple emails, use them as BCC
590
+    public function sendNotificationToMultipleEmails() {
591
+        $expectedShare = $this->createMock(IShare::class);
592
+
593
+        $node = $this->createMock(File::class);
594
+        $node->expects($this->any())->method('getName')->willReturn('filename');
595
+
596
+        $share = $this->createMock(IShare::class);
597
+        $share->expects($this->any())->method('getSharedWith')->willReturn('');
598
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn(false);
599
+        $share->expects($this->any())->method('getSharedBy')->willReturn('owner');
600
+        $share->expects($this->any())->method('getNode')->willReturn($node);
601
+        $share->expects($this->any())->method('getId')->willReturn('42');
602
+        $share->expects($this->any())->method('getNote')->willReturn('');
603
+        $share->expects($this->any())->method('getToken')->willReturn('token');
604
+
605
+        $attributes = $this->createMock(IAttributes::class);
606
+        $share->expects($this->any())->method('getAttributes')->willReturn($attributes);
607
+        $attributes->expects($this->any())->method('getAttribute')->with('shareWith', 'emails')->willReturn([
608
+            '[email protected]',
609
+            '[email protected]',
610
+            '[email protected]',
611
+        ]);
612
+
613
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject', 'createShareActivity', 'autoGeneratePassword', 'createPasswordSendActivity', 'sendEmail', 'sendPassword', 'sendPasswordToOwner']);
614
+
615
+        $instance->expects($this->once())->method('getSharedWith')->willReturn([]);
616
+        $instance->expects($this->once())->method('createMailShare')->with($share)->willReturn('42');
617
+        $instance->expects($this->once())->method('createShareActivity')->with($share);
618
+        $instance->expects($this->once())->method('getRawShare')->with('42')->willReturn(['rawShare', 'password' => 'password']);
619
+        $instance->expects($this->once())->method('createShareObject')->with(['rawShare', 'password' => 'password'])->willReturn($expectedShare);
620
+        $share->expects($this->any())->method('getNode')->willReturn($node);
621
+
622
+        $share->expects($this->any())->method('getPassword')->willReturn('password');
623
+        $this->hasher->expects($this->once())->method('hash')->with('password')->willReturn('passwordHashed');
624
+        $share->expects($this->once())->method('setPassword')->with('passwordHashed');
625
+
626
+        // The given password (but not the autogenerated password) should not be
627
+        // mailed to the receiver of the share because permanent passwords are not enforced.
628
+        $this->shareManager->expects($this->any())->method('shareApiLinkEnforcePassword')->willReturn(false);
629
+        $this->config->expects($this->once())->method('getSystemValue')->with('sharing.enable_mail_link_password_expiration')->willReturn(false);
630
+        $instance->expects($this->never())->method('autoGeneratePassword');
631
+
632
+        // A password is set but no password sent via talk has been requested
633
+        $instance->expects($this->once())->method('sendEmail')
634
+            ->with($share, ['[email protected]', '[email protected]', '[email protected]']);
635
+        $instance->expects($this->once())->method('sendPassword')->with($share, 'password');
636
+        $instance->expects($this->never())->method('sendPasswordToOwner');
637
+
638
+
639
+        $message = $this->createMock(IMessage::class);
640
+        $message->expects($this->never())->method('setTo');
641
+        $message->expects($this->exactly(2))->method('setBcc')->with(['[email protected]', '[email protected]', '[email protected]']);
642
+        $this->mailer->expects($this->exactly(2))->method('createMessage')->willReturn($message);
643
+
644
+        // Main email notification is sent as well as the password
645
+        // to recipients because the password is set.
646
+        $this->mailer->expects($this->exactly(2))->method('send');
647
+
648
+        $this->assertSame($expectedShare, $instance->create($share));
649
+        $instance->sendMailNotification($share);
650
+    }
651
+
652
+    public function testCreateFailed(): void {
653
+        $this->expectException(\Exception::class);
654
+
655
+        $this->share->expects($this->once())->method('getSharedWith')->willReturn('user1');
656
+        $node = $this->createMock('OCP\Files\Node');
657
+        $node->expects($this->any())->method('getName')->willReturn('fileName');
658
+        $this->share->expects($this->any())->method('getNode')->willReturn($node);
659
+
660
+        $instance = $this->getInstance(['getSharedWith', 'createMailShare', 'getRawShare', 'createShareObject']);
661
+
662
+        $instance->expects($this->once())->method('getSharedWith')->willReturn(['found']);
663
+        $instance->expects($this->never())->method('createMailShare');
664
+        $instance->expects($this->never())->method('getRawShare');
665
+        $instance->expects($this->never())->method('createShareObject');
666
+
667
+        $this->assertSame('shareObject',
668
+            $instance->create($this->share)
669
+        );
670
+    }
671
+
672
+    public function testCreateMailShare(): void {
673
+        $this->share->expects($this->any())->method('getToken')->willReturn('token');
674
+        $this->share->expects($this->once())->method('setToken')->with('token');
675
+        $this->share->expects($this->any())->method('getSharedBy')->willReturn('[email protected]');
676
+        $this->share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
677
+        $this->share->expects($this->any())->method('getNote')->willReturn('Check this!');
678
+        $this->share->expects($this->any())->method('getMailSend')->willReturn(true);
679
+
680
+        $node = $this->createMock('OCP\Files\Node');
681
+        $node->expects($this->any())->method('getName')->willReturn('fileName');
682
+        $this->share->expects($this->any())->method('getNode')->willReturn($node);
683
+
684
+        $instance = $this->getInstance(['generateToken', 'addShareToDB', 'sendMailNotification']);
685
+
686
+        $instance->expects($this->once())->method('generateToken')->willReturn('token');
687
+        $instance->expects($this->once())->method('addShareToDB')->willReturn('42');
688
+
689
+        // The manager handle the mail sending
690
+        $instance->expects($this->never())->method('sendMailNotification');
691
+
692
+        $this->assertSame('42',
693
+            $this->invokePrivate($instance, 'createMailShare', [$this->share])
694
+        );
695
+    }
696
+
697
+    public function testGenerateToken(): void {
698
+        $instance = $this->getInstance();
699
+
700
+        $this->secureRandom->expects($this->once())->method('generate')->willReturn('token');
701
+
702
+        $this->assertSame('token',
703
+            $this->invokePrivate($instance, 'generateToken')
704
+        );
705
+    }
706
+
707
+    public function testAddShareToDB(): void {
708
+        $itemSource = 11;
709
+        $itemType = 'file';
710
+        $shareWith = '[email protected]';
711
+        $sharedBy = 'user1';
712
+        $uidOwner = 'user2';
713
+        $permissions = 1;
714
+        $token = 'token';
715
+        $password = 'password';
716
+        $sendPasswordByTalk = true;
717
+        $hideDownload = true;
718
+        $label = 'label';
719
+        $expiration = new \DateTime();
720
+        $passwordExpirationTime = new \DateTime();
721
+
722
+
723
+        $instance = $this->getInstance();
724
+        $id = $this->invokePrivate(
725
+            $instance,
726
+            'addShareToDB',
727
+            [
728
+                $itemSource,
729
+                $itemType,
730
+                $shareWith,
731
+                $sharedBy,
732
+                $uidOwner,
733
+                $permissions,
734
+                $token,
735
+                $password,
736
+                $passwordExpirationTime,
737
+                $sendPasswordByTalk,
738
+                $hideDownload,
739
+                $label,
740
+                $expiration
741
+            ]
742
+        );
743
+
744
+        $qb = $this->connection->getQueryBuilder();
745
+        $qb->select('*')
746
+            ->from('share')
747
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
748
+
749
+        $qResult = $qb->executeQuery();
750
+        $result = $qResult->fetchAllAssociative();
751
+        $qResult->closeCursor();
752
+
753
+        $this->assertSame(1, count($result));
754
+
755
+        $this->assertSame($itemSource, (int)$result[0]['item_source']);
756
+        $this->assertSame($itemType, $result[0]['item_type']);
757
+        $this->assertSame($shareWith, $result[0]['share_with']);
758
+        $this->assertSame($sharedBy, $result[0]['uid_initiator']);
759
+        $this->assertSame($uidOwner, $result[0]['uid_owner']);
760
+        $this->assertSame($permissions, (int)$result[0]['permissions']);
761
+        $this->assertSame($token, $result[0]['token']);
762
+        $this->assertSame($password, $result[0]['password']);
763
+        $this->assertSame($passwordExpirationTime->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['password_expiration_time'])->getTimestamp());
764
+        $this->assertSame($sendPasswordByTalk, (bool)$result[0]['password_by_talk']);
765
+        $this->assertSame($hideDownload, (bool)$result[0]['hide_download']);
766
+        $this->assertSame($label, $result[0]['label']);
767
+        $this->assertSame($expiration->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['expiration'])->getTimestamp());
768
+    }
769
+
770
+    public function testUpdate(): void {
771
+        $itemSource = 11;
772
+        $itemType = 'file';
773
+        $shareWith = '[email protected]';
774
+        $sharedBy = 'user1';
775
+        $uidOwner = 'user2';
776
+        $permissions = 1;
777
+        $token = 'token';
778
+        $note = 'personal note';
779
+
780
+
781
+        $instance = $this->getInstance();
782
+
783
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note);
784
+
785
+        $this->share->expects($this->once())->method('getPermissions')->willReturn($permissions + 1);
786
+        $this->share->expects($this->once())->method('getShareOwner')->willReturn($uidOwner);
787
+        $this->share->expects($this->once())->method('getSharedBy')->willReturn($sharedBy);
788
+        $this->share->expects($this->any())->method('getNote')->willReturn($note);
789
+        $this->share->expects($this->atLeastOnce())->method('getId')->willReturn($id);
790
+        $this->share->expects($this->atLeastOnce())->method('getNodeId')->willReturn($itemSource);
791
+        $this->share->expects($this->once())->method('getSharedWith')->willReturn($shareWith);
792
+
793
+        $this->assertSame($this->share,
794
+            $instance->update($this->share)
795
+        );
796
+
797
+        $qb = $this->connection->getQueryBuilder();
798
+        $qb->select('*')
799
+            ->from('share')
800
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
801
+
802
+        $qResult = $qb->executeQuery();
803
+        $result = $qResult->fetchAllAssociative();
804
+        $qResult->closeCursor();
805
+
806
+        $this->assertSame(1, count($result));
807
+
808
+        $this->assertSame($itemSource, (int)$result[0]['item_source']);
809
+        $this->assertSame($itemType, $result[0]['item_type']);
810
+        $this->assertSame($shareWith, $result[0]['share_with']);
811
+        $this->assertSame($sharedBy, $result[0]['uid_initiator']);
812
+        $this->assertSame($uidOwner, $result[0]['uid_owner']);
813
+        $this->assertSame($permissions + 1, (int)$result[0]['permissions']);
814
+        $this->assertSame($token, $result[0]['token']);
815
+        $this->assertSame($note, $result[0]['note']);
816
+    }
817
+
818
+    public static function dataUpdateSendPassword(): array {
819
+        return [
820
+            ['password', 'hashed', 'hashed new', false, false, true],
821
+            ['', 'hashed', 'hashed new', false, false, false],
822
+            [null, 'hashed', 'hashed new', false, false, false],
823
+            ['password', 'hashed', 'hashed', false, false, false],
824
+            ['password', 'hashed', 'hashed new', false, true, false],
825
+            ['password', 'hashed', 'hashed new', true, false, true],
826
+            ['password', 'hashed', 'hashed', true, false, true],
827
+        ];
828
+    }
829
+
830
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataUpdateSendPassword')]
831
+    public function testUpdateSendPassword(?string $plainTextPassword, string $originalPassword, string $newPassword, bool $originalSendPasswordByTalk, bool $newSendPasswordByTalk, bool $sendMail): void {
832
+        $node = $this->createMock(File::class);
833
+        $node->expects($this->any())->method('getName')->willReturn('filename');
834
+
835
+        $this->settingsManager->method('sendPasswordByMail')->willReturn(true);
836
+
837
+        $originalShare = $this->createMock(IShare::class);
838
+        $originalShare->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
839
+        $originalShare->expects($this->any())->method('getNode')->willReturn($node);
840
+        $originalShare->expects($this->any())->method('getId')->willReturn('42');
841
+        $originalShare->expects($this->any())->method('getPassword')->willReturn($originalPassword);
842
+        $originalShare->expects($this->any())->method('getSendPasswordByTalk')->willReturn($originalSendPasswordByTalk);
843
+
844
+        $share = $this->createMock(IShare::class);
845
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
846
+        $share->expects($this->any())->method('getNode')->willReturn($node);
847
+        $share->expects($this->any())->method('getId')->willReturn('42');
848
+        $share->expects($this->any())->method('getPassword')->willReturn($newPassword);
849
+        $share->expects($this->any())->method('getSendPasswordByTalk')->willReturn($newSendPasswordByTalk);
850
+
851
+        if ($sendMail) {
852
+            $this->mailer->expects($this->once())->method('createEMailTemplate')->with('sharebymail.RecipientPasswordNotification', [
853
+                'filename' => 'filename',
854
+                'password' => $plainTextPassword,
855
+                'initiator' => null,
856
+                'initiatorEmail' => null,
857
+                'shareWith' => '[email protected]',
858
+            ]);
859
+            $this->mailer->expects($this->once())->method('send');
860
+        } else {
861
+            $this->mailer->expects($this->never())->method('send');
862
+        }
863
+
864
+        $instance = $this->getInstance(['getShareById', 'createPasswordSendActivity']);
865
+        $instance->expects($this->once())->method('getShareById')->willReturn($originalShare);
866
+
867
+        $this->assertSame($share,
868
+            $instance->update($share, $plainTextPassword)
869
+        );
870
+    }
871
+
872
+    public function testDelete(): void {
873
+        $instance = $this->getInstance(['removeShareFromTable', 'createShareActivity']);
874
+        $this->share->expects($this->once())->method('getId')->willReturn('42');
875
+        $instance->expects($this->once())->method('removeShareFromTable')->with('42');
876
+        $instance->expects($this->once())->method('createShareActivity')->with($this->share, 'unshare');
877
+        $instance->delete($this->share);
878
+    }
879
+
880
+    public function testGetShareById(): void {
881
+        $instance = $this->getInstance(['createShareObject']);
882
+
883
+        $itemSource = 11;
884
+        $itemType = 'file';
885
+        $shareWith = '[email protected]';
886
+        $sharedBy = 'user1';
887
+        $uidOwner = 'user2';
888
+        $permissions = 1;
889
+        $token = 'token';
890
+
891
+        $this->createDummyShare($itemType, $itemSource, $shareWith, 'user1wrong', 'user2wrong', $permissions, $token);
892
+        $id2 = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
893
+
894
+        $instance->expects($this->once())->method('createShareObject')
895
+            ->willReturnCallback(
896
+                function ($data) use ($uidOwner, $sharedBy, $id2) {
897
+                    $this->assertSame($uidOwner, $data['uid_owner']);
898
+                    $this->assertSame($sharedBy, $data['uid_initiator']);
899
+                    $this->assertSame($id2, (string)$data['id']);
900
+                    return $this->share;
901
+                }
902
+            );
903
+
904
+        $result = $instance->getShareById($id2);
905
+
906
+        $this->assertInstanceOf('OCP\Share\IShare', $result);
907
+    }
908
+
909
+
910
+    public function testGetShareByIdFailed(): void {
911
+        $this->expectException(ShareNotFound::class);
912
+
913
+        $instance = $this->getInstance(['createShareObject']);
914
+
915
+        $itemSource = 11;
916
+        $itemType = 'file';
917
+        $shareWith = '[email protected]';
918
+        $sharedBy = 'user1';
919
+        $uidOwner = 'user2';
920
+        $permissions = 1;
921
+        $token = 'token';
922
+
923
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
924
+
925
+        $instance->getShareById($id + 1);
926
+    }
927
+
928
+    public function testGetShareByPath(): void {
929
+        $itemSource = 11;
930
+        $itemType = 'file';
931
+        $shareWith = '[email protected]';
932
+        $sharedBy = 'user1';
933
+        $uidOwner = 'user2';
934
+        $permissions = 1;
935
+        $token = 'token';
936
+
937
+        $node = $this->createMock(Node::class);
938
+        $node->expects($this->once())->method('getId')->willReturn($itemSource);
939
+
940
+
941
+        $instance = $this->getInstance(['createShareObject']);
942
+
943
+        $this->createDummyShare($itemType, 111, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
944
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
945
+
946
+        $instance->expects($this->once())->method('createShareObject')
947
+            ->willReturnCallback(
948
+                function ($data) use ($uidOwner, $sharedBy, $id) {
949
+                    $this->assertSame($uidOwner, $data['uid_owner']);
950
+                    $this->assertSame($sharedBy, $data['uid_initiator']);
951
+                    $this->assertSame($id, $data['id']);
952
+                    return $this->share;
953
+                }
954
+            );
955
+
956
+        $result = $instance->getSharesByPath($node);
957
+
958
+        $this->assertTrue(is_array($result));
959
+        $this->assertSame(1, count($result));
960
+        $this->assertInstanceOf('OCP\Share\IShare', $result[0]);
961
+    }
962
+
963
+    public function testGetShareByToken(): void {
964
+        $itemSource = 11;
965
+        $itemType = 'file';
966
+        $shareWith = '[email protected]';
967
+        $sharedBy = 'user1';
968
+        $uidOwner = 'user2';
969
+        $permissions = 1;
970
+        $token = 'token';
971 971
 
972
-		$instance = $this->getInstance(['createShareObject']);
972
+        $instance = $this->getInstance(['createShareObject']);
973 973
 
974
-		$idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
975
-		$idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, '', IShare::TYPE_LINK);
974
+        $idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
975
+        $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, '', IShare::TYPE_LINK);
976 976
 
977
-		$this->assertTrue($idMail !== $idPublic);
977
+        $this->assertTrue($idMail !== $idPublic);
978 978
 
979
-		$instance->expects($this->once())->method('createShareObject')
980
-			->willReturnCallback(
981
-				function ($data) use ($idMail) {
982
-					$this->assertSame($idMail, $data['id']);
983
-					return $this->share;
984
-				}
985
-			);
979
+        $instance->expects($this->once())->method('createShareObject')
980
+            ->willReturnCallback(
981
+                function ($data) use ($idMail) {
982
+                    $this->assertSame($idMail, $data['id']);
983
+                    return $this->share;
984
+                }
985
+            );
986 986
 
987
-		$result = $instance->getShareByToken('token');
987
+        $result = $instance->getShareByToken('token');
988 988
 
989
-		$this->assertInstanceOf('OCP\Share\IShare', $result);
990
-	}
989
+        $this->assertInstanceOf('OCP\Share\IShare', $result);
990
+    }
991 991
 
992 992
 
993
-	public function testGetShareByTokenFailed(): void {
994
-		$this->expectException(ShareNotFound::class);
993
+    public function testGetShareByTokenFailed(): void {
994
+        $this->expectException(ShareNotFound::class);
995 995
 
996 996
 
997
-		$itemSource = 11;
998
-		$itemType = 'file';
999
-		$shareWith = '[email protected]';
1000
-		$sharedBy = 'user1';
1001
-		$uidOwner = 'user2';
1002
-		$permissions = 1;
1003
-		$token = 'token';
997
+        $itemSource = 11;
998
+        $itemType = 'file';
999
+        $shareWith = '[email protected]';
1000
+        $sharedBy = 'user1';
1001
+        $uidOwner = 'user2';
1002
+        $permissions = 1;
1003
+        $token = 'token';
1004 1004
 
1005
-		$instance = $this->getInstance(['createShareObject']);
1005
+        $instance = $this->getInstance(['createShareObject']);
1006 1006
 
1007
-		$idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1008
-		$idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, 'token2', '', IShare::TYPE_LINK);
1007
+        $idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1008
+        $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, 'token2', '', IShare::TYPE_LINK);
1009 1009
 
1010
-		$this->assertTrue($idMail !== $idPublic);
1010
+        $this->assertTrue($idMail !== $idPublic);
1011 1011
 
1012
-		$this->assertInstanceOf('OCP\Share\IShare',
1013
-			$instance->getShareByToken('token2')
1014
-		);
1015
-	}
1012
+        $this->assertInstanceOf('OCP\Share\IShare',
1013
+            $instance->getShareByToken('token2')
1014
+        );
1015
+    }
1016 1016
 
1017
-	public function testRemoveShareFromTable(): void {
1018
-		$itemSource = 11;
1019
-		$itemType = 'file';
1020
-		$shareWith = '[email protected]';
1021
-		$sharedBy = 'user1';
1022
-		$uidOwner = 'user2';
1023
-		$permissions = 1;
1024
-		$token = 'token';
1017
+    public function testRemoveShareFromTable(): void {
1018
+        $itemSource = 11;
1019
+        $itemType = 'file';
1020
+        $shareWith = '[email protected]';
1021
+        $sharedBy = 'user1';
1022
+        $uidOwner = 'user2';
1023
+        $permissions = 1;
1024
+        $token = 'token';
1025 1025
 
1026
-		$instance = $this->getInstance();
1026
+        $instance = $this->getInstance();
1027 1027
 
1028
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1028
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1029 1029
 
1030
-		$query = $this->connection->getQueryBuilder();
1031
-		$query->select('*')->from('share')
1032
-			->where($query->expr()->eq('id', $query->createNamedParameter($id)));
1030
+        $query = $this->connection->getQueryBuilder();
1031
+        $query->select('*')->from('share')
1032
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id)));
1033 1033
 
1034
-		$result = $query->executeQuery();
1035
-		$before = $result->fetchAllAssociative();
1036
-		$result->closeCursor();
1034
+        $result = $query->executeQuery();
1035
+        $before = $result->fetchAllAssociative();
1036
+        $result->closeCursor();
1037 1037
 
1038
-		$this->assertTrue(is_array($before));
1039
-		$this->assertSame(1, count($before));
1038
+        $this->assertTrue(is_array($before));
1039
+        $this->assertSame(1, count($before));
1040 1040
 
1041
-		$this->invokePrivate($instance, 'removeShareFromTable', [$id]);
1041
+        $this->invokePrivate($instance, 'removeShareFromTable', [$id]);
1042 1042
 
1043
-		$query = $this->connection->getQueryBuilder();
1044
-		$query->select('*')->from('share')
1045
-			->where($query->expr()->eq('id', $query->createNamedParameter($id)));
1043
+        $query = $this->connection->getQueryBuilder();
1044
+        $query->select('*')->from('share')
1045
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id)));
1046 1046
 
1047
-		$result = $query->executeQuery();
1048
-		$after = $result->fetchAllAssociative();
1049
-		$result->closeCursor();
1047
+        $result = $query->executeQuery();
1048
+        $after = $result->fetchAllAssociative();
1049
+        $result->closeCursor();
1050 1050
 
1051
-		$this->assertTrue(is_array($after));
1052
-		$this->assertEmpty($after);
1053
-	}
1051
+        $this->assertTrue(is_array($after));
1052
+        $this->assertEmpty($after);
1053
+    }
1054 1054
 
1055
-	public function testUserDeleted(): void {
1056
-		$itemSource = 11;
1057
-		$itemType = 'file';
1058
-		$shareWith = '[email protected]';
1059
-		$sharedBy = 'user1';
1060
-		$uidOwner = 'user2';
1061
-		$permissions = 1;
1062
-		$token = 'token';
1055
+    public function testUserDeleted(): void {
1056
+        $itemSource = 11;
1057
+        $itemType = 'file';
1058
+        $shareWith = '[email protected]';
1059
+        $sharedBy = 'user1';
1060
+        $uidOwner = 'user2';
1061
+        $permissions = 1;
1062
+        $token = 'token';
1063 1063
 
1064
-		$this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1065
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, 'user2Wrong', $permissions, $token);
1064
+        $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1065
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, 'user2Wrong', $permissions, $token);
1066 1066
 
1067
-		$query = $this->connection->getQueryBuilder();
1068
-		$query->select('*')->from('share');
1067
+        $query = $this->connection->getQueryBuilder();
1068
+        $query->select('*')->from('share');
1069 1069
 
1070
-		$result = $query->executeQuery();
1071
-		$before = $result->fetchAllAssociative();
1072
-		$result->closeCursor();
1070
+        $result = $query->executeQuery();
1071
+        $before = $result->fetchAllAssociative();
1072
+        $result->closeCursor();
1073 1073
 
1074
-		$this->assertTrue(is_array($before));
1075
-		$this->assertSame(2, count($before));
1074
+        $this->assertTrue(is_array($before));
1075
+        $this->assertSame(2, count($before));
1076 1076
 
1077 1077
 
1078
-		$instance = $this->getInstance();
1078
+        $instance = $this->getInstance();
1079 1079
 
1080
-		$instance->userDeleted($uidOwner, IShare::TYPE_EMAIL);
1080
+        $instance->userDeleted($uidOwner, IShare::TYPE_EMAIL);
1081 1081
 
1082
-		$query = $this->connection->getQueryBuilder();
1083
-		$query->select('*')->from('share');
1082
+        $query = $this->connection->getQueryBuilder();
1083
+        $query->select('*')->from('share');
1084 1084
 
1085
-		$result = $query->executeQuery();
1086
-		$after = $result->fetchAllAssociative();
1087
-		$result->closeCursor();
1085
+        $result = $query->executeQuery();
1086
+        $after = $result->fetchAllAssociative();
1087
+        $result->closeCursor();
1088 1088
 
1089
-		$this->assertTrue(is_array($after));
1090
-		$this->assertSame(1, count($after));
1091
-		$this->assertSame($id, (string)$after[0]['id']);
1092
-	}
1089
+        $this->assertTrue(is_array($after));
1090
+        $this->assertSame(1, count($after));
1091
+        $this->assertSame($id, (string)$after[0]['id']);
1092
+    }
1093 1093
 
1094
-	public function testGetRawShare(): void {
1095
-		$itemSource = 11;
1096
-		$itemType = 'file';
1097
-		$shareWith = '[email protected]';
1098
-		$sharedBy = 'user1';
1099
-		$uidOwner = 'user2';
1100
-		$permissions = 1;
1101
-		$token = 'token';
1094
+    public function testGetRawShare(): void {
1095
+        $itemSource = 11;
1096
+        $itemType = 'file';
1097
+        $shareWith = '[email protected]';
1098
+        $sharedBy = 'user1';
1099
+        $uidOwner = 'user2';
1100
+        $permissions = 1;
1101
+        $token = 'token';
1102 1102
 
1103
-		$instance = $this->getInstance();
1103
+        $instance = $this->getInstance();
1104 1104
 
1105
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1105
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1106 1106
 
1107
-		$result = $this->invokePrivate($instance, 'getRawShare', [$id]);
1108
-
1109
-		$this->assertTrue(is_array($result));
1110
-		$this->assertSame($itemSource, (int)$result['item_source']);
1111
-		$this->assertSame($itemType, $result['item_type']);
1112
-		$this->assertSame($shareWith, $result['share_with']);
1113
-		$this->assertSame($sharedBy, $result['uid_initiator']);
1114
-		$this->assertSame($uidOwner, $result['uid_owner']);
1115
-		$this->assertSame($permissions, (int)$result['permissions']);
1116
-		$this->assertSame($token, $result['token']);
1117
-	}
1107
+        $result = $this->invokePrivate($instance, 'getRawShare', [$id]);
1108
+
1109
+        $this->assertTrue(is_array($result));
1110
+        $this->assertSame($itemSource, (int)$result['item_source']);
1111
+        $this->assertSame($itemType, $result['item_type']);
1112
+        $this->assertSame($shareWith, $result['share_with']);
1113
+        $this->assertSame($sharedBy, $result['uid_initiator']);
1114
+        $this->assertSame($uidOwner, $result['uid_owner']);
1115
+        $this->assertSame($permissions, (int)$result['permissions']);
1116
+        $this->assertSame($token, $result['token']);
1117
+    }
1118 1118
 
1119 1119
 
1120
-	public function testGetRawShareFailed(): void {
1121
-		$this->expectException(ShareNotFound::class);
1120
+    public function testGetRawShareFailed(): void {
1121
+        $this->expectException(ShareNotFound::class);
1122 1122
 
1123
-		$itemSource = 11;
1124
-		$itemType = 'file';
1125
-		$shareWith = '[email protected]';
1126
-		$sharedBy = 'user1';
1127
-		$uidOwner = 'user2';
1128
-		$permissions = 1;
1129
-		$token = 'token';
1130
-
1131
-		$instance = $this->getInstance();
1123
+        $itemSource = 11;
1124
+        $itemType = 'file';
1125
+        $shareWith = '[email protected]';
1126
+        $sharedBy = 'user1';
1127
+        $uidOwner = 'user2';
1128
+        $permissions = 1;
1129
+        $token = 'token';
1130
+
1131
+        $instance = $this->getInstance();
1132 1132
 
1133
-		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1134
-
1135
-		$this->invokePrivate($instance, 'getRawShare', [(string)((int)$id + 1)]);
1136
-	}
1133
+        $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1134
+
1135
+        $this->invokePrivate($instance, 'getRawShare', [(string)((int)$id + 1)]);
1136
+    }
1137 1137
 
1138
-	private function createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note = '', $shareType = IShare::TYPE_EMAIL): string {
1139
-		$qb = $this->connection->getQueryBuilder();
1140
-		$qb->insert('share')
1141
-			->setValue('share_type', $qb->createNamedParameter($shareType))
1142
-			->setValue('item_type', $qb->createNamedParameter($itemType))
1143
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
1144
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
1145
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
1146
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
1147
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
1148
-			->setValue('permissions', $qb->createNamedParameter($permissions))
1149
-			->setValue('token', $qb->createNamedParameter($token))
1150
-			->setValue('note', $qb->createNamedParameter($note))
1151
-			->setValue('stime', $qb->createNamedParameter(time()));
1152
-
1153
-		/*
1138
+    private function createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note = '', $shareType = IShare::TYPE_EMAIL): string {
1139
+        $qb = $this->connection->getQueryBuilder();
1140
+        $qb->insert('share')
1141
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
1142
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
1143
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
1144
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
1145
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
1146
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
1147
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
1148
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
1149
+            ->setValue('token', $qb->createNamedParameter($token))
1150
+            ->setValue('note', $qb->createNamedParameter($note))
1151
+            ->setValue('stime', $qb->createNamedParameter(time()));
1152
+
1153
+        /*
1154 1154
 		 * Added to fix https://github.com/owncloud/core/issues/22215
1155 1155
 		 * Can be removed once we get rid of ajax/share.php
1156 1156
 		 */
1157
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
1158
-
1159
-		$qb->executeStatement();
1160
-		return (string)$qb->getLastInsertId();
1161
-	}
1162
-
1163
-	public function testGetSharesInFolder(): void {
1164
-		$userManager = Server::get(IUserManager::class);
1165
-		$rootFolder = Server::get(IRootFolder::class);
1166
-
1167
-		$this->shareManager->expects($this->any())
1168
-			->method('newShare')
1169
-			->willReturn(new Share($rootFolder, $userManager));
1170
-
1171
-		$provider = $this->getInstance(['sendMailNotification', 'createShareActivity']);
1172
-
1173
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
1174
-		$u2 = $userManager->createUser('testFed2', md5((string)time()));
1175
-
1176
-		$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
1177
-		$file1 = $folder1->newFile('bar1');
1178
-		$file2 = $folder1->newFile('bar2');
1179
-
1180
-		$share1 = $this->shareManager->newShare();
1181
-		$share1->setSharedWith('[email protected]')
1182
-			->setSharedBy($u1->getUID())
1183
-			->setShareOwner($u1->getUID())
1184
-			->setPermissions(Constants::PERMISSION_READ)
1185
-			->setNode($file1);
1186
-		$provider->create($share1);
1187
-
1188
-		$share2 = $this->shareManager->newShare();
1189
-		$share2->setSharedWith('[email protected]')
1190
-			->setSharedBy($u2->getUID())
1191
-			->setShareOwner($u1->getUID())
1192
-			->setPermissions(Constants::PERMISSION_READ)
1193
-			->setNode($file2);
1194
-		$provider->create($share2);
1195
-
1196
-		$result = $provider->getSharesInFolder($u1->getUID(), $folder1, false);
1197
-		$this->assertCount(1, $result);
1198
-		$this->assertCount(1, $result[$file1->getId()]);
1199
-
1200
-		$result = $provider->getSharesInFolder($u1->getUID(), $folder1, true);
1201
-		$this->assertCount(2, $result);
1202
-		$this->assertCount(1, $result[$file1->getId()]);
1203
-		$this->assertCount(1, $result[$file2->getId()]);
1204
-
1205
-		$u1->delete();
1206
-		$u2->delete();
1207
-	}
1208
-
1209
-	public function testGetAccessList(): void {
1210
-		$userManager = Server::get(IUserManager::class);
1211
-		$rootFolder = Server::get(IRootFolder::class);
1212
-
1213
-		$this->shareManager->expects($this->any())
1214
-			->method('newShare')
1215
-			->willReturn(new Share($rootFolder, $userManager));
1216
-
1217
-		$provider = $this->getInstance(['sendMailNotification', 'createShareActivity']);
1218
-
1219
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
1220
-		$u2 = $userManager->createUser('testFed2', md5((string)time()));
1221
-
1222
-		$folder = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
1223
-
1224
-		$accessList = $provider->getAccessList([$folder], true);
1225
-		$this->assertArrayHasKey('public', $accessList);
1226
-		$this->assertFalse($accessList['public']);
1227
-		$accessList = $provider->getAccessList([$folder], false);
1228
-		$this->assertArrayHasKey('public', $accessList);
1229
-		$this->assertFalse($accessList['public']);
1230
-
1231
-		$share1 = $this->shareManager->newShare();
1232
-		$share1->setSharedWith('[email protected]')
1233
-			->setSharedBy($u1->getUID())
1234
-			->setShareOwner($u1->getUID())
1235
-			->setPermissions(Constants::PERMISSION_READ)
1236
-			->setNode($folder);
1237
-		$share1 = $provider->create($share1);
1238
-
1239
-		$share2 = $this->shareManager->newShare();
1240
-		$share2->setSharedWith('[email protected]')
1241
-			->setSharedBy($u2->getUID())
1242
-			->setShareOwner($u1->getUID())
1243
-			->setPermissions(Constants::PERMISSION_READ)
1244
-			->setNode($folder);
1245
-		$share2 = $provider->create($share2);
1246
-
1247
-		$accessList = $provider->getAccessList([$folder], true);
1248
-		$this->assertArrayHasKey('public', $accessList);
1249
-		$this->assertTrue($accessList['public']);
1250
-		$accessList = $provider->getAccessList([$folder], false);
1251
-		$this->assertArrayHasKey('public', $accessList);
1252
-		$this->assertTrue($accessList['public']);
1253
-
1254
-		$provider->delete($share2);
1255
-
1256
-		$accessList = $provider->getAccessList([$folder], true);
1257
-		$this->assertArrayHasKey('public', $accessList);
1258
-		$this->assertTrue($accessList['public']);
1259
-		$accessList = $provider->getAccessList([$folder], false);
1260
-		$this->assertArrayHasKey('public', $accessList);
1261
-		$this->assertTrue($accessList['public']);
1262
-
1263
-		$provider->delete($share1);
1264
-
1265
-		$accessList = $provider->getAccessList([$folder], true);
1266
-		$this->assertArrayHasKey('public', $accessList);
1267
-		$this->assertFalse($accessList['public']);
1268
-		$accessList = $provider->getAccessList([$folder], false);
1269
-		$this->assertArrayHasKey('public', $accessList);
1270
-		$this->assertFalse($accessList['public']);
1271
-
1272
-		$u1->delete();
1273
-		$u2->delete();
1274
-	}
1275
-
1276
-	public function testSendMailNotificationWithSameUserAndUserEmail(): void {
1277
-		$provider = $this->getInstance();
1278
-		$user = $this->createMock(IUser::class);
1279
-		$this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1280
-		$this->userManager
1281
-			->expects($this->once())
1282
-			->method('get')
1283
-			->with('OwnerUser')
1284
-			->willReturn($user);
1285
-		$user
1286
-			->expects($this->once())
1287
-			->method('getDisplayName')
1288
-			->willReturn('Mrs. Owner User');
1289
-		$message = $this->createMock(Message::class);
1290
-		$this->mailer
1291
-			->expects($this->once())
1292
-			->method('createMessage')
1293
-			->willReturn($message);
1294
-		$template = $this->createMock(IEMailTemplate::class);
1295
-		$this->mailer
1296
-			->expects($this->once())
1297
-			->method('createEMailTemplate')
1298
-			->willReturn($template);
1299
-		$template
1300
-			->expects($this->once())
1301
-			->method('addHeader');
1302
-		$template
1303
-			->expects($this->once())
1304
-			->method('addHeading')
1305
-			->with('Mrs. Owner User shared file.txt with you');
1306
-		$template
1307
-			->expects($this->once())
1308
-			->method('addBodyButton')
1309
-			->with(
1310
-				'Open file.txt',
1311
-				'https://example.com/file.txt'
1312
-			);
1313
-		$message
1314
-			->expects($this->once())
1315
-			->method('setTo')
1316
-			->with(['[email protected]']);
1317
-		$this->defaults
1318
-			->expects($this->once())
1319
-			->method('getName')
1320
-			->willReturn('UnitTestCloud');
1321
-		$message
1322
-			->expects($this->once())
1323
-			->method('setFrom')
1324
-			->with([
1325
-				Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud'
1326
-			]);
1327
-		$user
1328
-			->expects($this->once())
1329
-			->method('getEMailAddress')
1330
-			->willReturn('[email protected]');
1331
-		$message
1332
-			->expects($this->once())
1333
-			->method('setReplyTo')
1334
-			->with(['[email protected]' => 'Mrs. Owner User']);
1335
-		$this->defaults
1336
-			->expects($this->exactly(2))
1337
-			->method('getSlogan')
1338
-			->willReturn('Testing like 1990');
1339
-		$template
1340
-			->expects($this->once())
1341
-			->method('addFooter')
1342
-			->with('UnitTestCloud - Testing like 1990');
1343
-		$template
1344
-			->expects($this->once())
1345
-			->method('setSubject')
1346
-			->with('Mrs. Owner User shared file.txt with you');
1347
-		$message
1348
-			->expects($this->once())
1349
-			->method('useTemplate')
1350
-			->with($template);
1351
-
1352
-		$this->mailer
1353
-			->expects($this->once())
1354
-			->method('send')
1355
-			->with($message);
1356
-
1357
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1358
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1359
-			->willReturn('https://example.com/file.txt');
1360
-
1361
-		$node = $this->createMock(File::class);
1362
-		$node->expects($this->any())->method('getName')->willReturn('file.txt');
1363
-
1364
-		$share = $this->createMock(IShare::class);
1365
-		$share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1366
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1367
-		$share->expects($this->any())->method('getNode')->willReturn($node);
1368
-		$share->expects($this->any())->method('getId')->willReturn('42');
1369
-		$share->expects($this->any())->method('getNote')->willReturn('');
1370
-		$share->expects($this->any())->method('getToken')->willReturn('token');
1371
-
1372
-		self::invokePrivate(
1373
-			$provider,
1374
-			'sendMailNotification',
1375
-			[$share]
1376
-		);
1377
-	}
1378
-
1379
-	public function testSendMailNotificationWithSameUserAndUserEmailAndNote(): void {
1380
-		$provider = $this->getInstance();
1381
-		$user = $this->createMock(IUser::class);
1382
-		$this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1383
-		$this->userManager
1384
-			->expects($this->once())
1385
-			->method('get')
1386
-			->with('OwnerUser')
1387
-			->willReturn($user);
1388
-		$user
1389
-			->expects($this->once())
1390
-			->method('getDisplayName')
1391
-			->willReturn('Mrs. Owner User');
1392
-		$message = $this->createMock(Message::class);
1393
-		$this->mailer
1394
-			->expects($this->once())
1395
-			->method('createMessage')
1396
-			->willReturn($message);
1397
-		$template = $this->createMock(IEMailTemplate::class);
1398
-		$this->mailer
1399
-			->expects($this->once())
1400
-			->method('createEMailTemplate')
1401
-			->willReturn($template);
1402
-		$template
1403
-			->expects($this->once())
1404
-			->method('addHeader');
1405
-		$template
1406
-			->expects($this->once())
1407
-			->method('addHeading')
1408
-			->with('Mrs. Owner User shared file.txt with you');
1409
-
1410
-		$this->urlGenerator->expects($this->once())->method('imagePath')
1411
-			->with('core', 'caldav/description.png')
1412
-			->willReturn('core/img/caldav/description.png');
1413
-		$this->urlGenerator->expects($this->once())->method('getAbsoluteURL')
1414
-			->with('core/img/caldav/description.png')
1415
-			->willReturn('https://example.com/core/img/caldav/description.png');
1416
-		$template
1417
-			->expects($this->once())
1418
-			->method('addBodyListItem')
1419
-			->with(
1420
-				'This is a note to the recipient',
1421
-				'Note:',
1422
-				'https://example.com/core/img/caldav/description.png',
1423
-				'This is a note to the recipient'
1424
-			);
1425
-		$template
1426
-			->expects($this->once())
1427
-			->method('addBodyButton')
1428
-			->with(
1429
-				'Open file.txt',
1430
-				'https://example.com/file.txt'
1431
-			);
1432
-		$message
1433
-			->expects($this->once())
1434
-			->method('setTo')
1435
-			->with(['[email protected]']);
1436
-		$this->defaults
1437
-			->expects($this->once())
1438
-			->method('getName')
1439
-			->willReturn('UnitTestCloud');
1440
-		$message
1441
-			->expects($this->once())
1442
-			->method('setFrom')
1443
-			->with([
1444
-				Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud'
1445
-			]);
1446
-		$user
1447
-			->expects($this->once())
1448
-			->method('getEMailAddress')
1449
-			->willReturn('[email protected]');
1450
-		$message
1451
-			->expects($this->once())
1452
-			->method('setReplyTo')
1453
-			->with(['[email protected]' => 'Mrs. Owner User']);
1454
-		$this->defaults
1455
-			->expects($this->exactly(2))
1456
-			->method('getSlogan')
1457
-			->willReturn('Testing like 1990');
1458
-		$template
1459
-			->expects($this->once())
1460
-			->method('addFooter')
1461
-			->with('UnitTestCloud - Testing like 1990');
1462
-		$template
1463
-			->expects($this->once())
1464
-			->method('setSubject')
1465
-			->with('Mrs. Owner User shared file.txt with you');
1466
-		$message
1467
-			->expects($this->once())
1468
-			->method('useTemplate')
1469
-			->with($template);
1470
-
1471
-		$this->mailer
1472
-			->expects($this->once())
1473
-			->method('send')
1474
-			->with($message);
1475
-
1476
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1477
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1478
-			->willReturn('https://example.com/file.txt');
1479
-
1480
-		$node = $this->createMock(File::class);
1481
-		$node->expects($this->any())->method('getName')->willReturn('file.txt');
1482
-
1483
-		$share = $this->createMock(IShare::class);
1484
-		$share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1485
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1486
-		$share->expects($this->any())->method('getNode')->willReturn($node);
1487
-		$share->expects($this->any())->method('getId')->willReturn('42');
1488
-		$share->expects($this->any())->method('getNote')->willReturn('This is a note to the recipient');
1489
-		$share->expects($this->any())->method('getToken')->willReturn('token');
1490
-
1491
-		self::invokePrivate(
1492
-			$provider,
1493
-			'sendMailNotification',
1494
-			[$share]
1495
-		);
1496
-	}
1497
-
1498
-	public function testSendMailNotificationWithSameUserAndUserEmailAndExpiration(): void {
1499
-		$provider = $this->getInstance();
1500
-		$user = $this->createMock(IUser::class);
1501
-		$this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1502
-		$this->userManager
1503
-			->expects($this->once())
1504
-			->method('get')
1505
-			->with('OwnerUser')
1506
-			->willReturn($user);
1507
-		$user
1508
-			->expects($this->once())
1509
-			->method('getDisplayName')
1510
-			->willReturn('Mrs. Owner User');
1511
-		$message = $this->createMock(Message::class);
1512
-		$this->mailer
1513
-			->expects($this->once())
1514
-			->method('createMessage')
1515
-			->willReturn($message);
1516
-		$template = $this->createMock(IEMailTemplate::class);
1517
-		$this->mailer
1518
-			->expects($this->once())
1519
-			->method('createEMailTemplate')
1520
-			->willReturn($template);
1521
-		$template
1522
-			->expects($this->once())
1523
-			->method('addHeader');
1524
-		$template
1525
-			->expects($this->once())
1526
-			->method('addHeading')
1527
-			->with('Mrs. Owner User shared file.txt with you');
1528
-
1529
-		$expiration = new DateTime('2001-01-01');
1530
-		$this->l->expects($this->once())
1531
-			->method('l')
1532
-			->with('date', $expiration, ['width' => 'medium'])
1533
-			->willReturn('2001-01-01');
1534
-		$this->urlGenerator->expects($this->once())->method('imagePath')
1535
-			->with('core', 'caldav/time.png')
1536
-			->willReturn('core/img/caldav/time.png');
1537
-		$this->urlGenerator->expects($this->once())->method('getAbsoluteURL')
1538
-			->with('core/img/caldav/time.png')
1539
-			->willReturn('https://example.com/core/img/caldav/time.png');
1540
-		$template
1541
-			->expects($this->once())
1542
-			->method('addBodyListItem')
1543
-			->with(
1544
-				'This share is valid until 2001-01-01 at midnight',
1545
-				'Expiration:',
1546
-				'https://example.com/core/img/caldav/time.png',
1547
-			);
1548
-
1549
-		$template
1550
-			->expects($this->once())
1551
-			->method('addBodyButton')
1552
-			->with(
1553
-				'Open file.txt',
1554
-				'https://example.com/file.txt'
1555
-			);
1556
-		$message
1557
-			->expects($this->once())
1558
-			->method('setTo')
1559
-			->with(['[email protected]']);
1560
-		$this->defaults
1561
-			->expects($this->once())
1562
-			->method('getName')
1563
-			->willReturn('UnitTestCloud');
1564
-		$message
1565
-			->expects($this->once())
1566
-			->method('setFrom')
1567
-			->with([
1568
-				Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud'
1569
-			]);
1570
-		$user
1571
-			->expects($this->once())
1572
-			->method('getEMailAddress')
1573
-			->willReturn('[email protected]');
1574
-		$message
1575
-			->expects($this->once())
1576
-			->method('setReplyTo')
1577
-			->with(['[email protected]' => 'Mrs. Owner User']);
1578
-		$this->defaults
1579
-			->expects($this->exactly(2))
1580
-			->method('getSlogan')
1581
-			->willReturn('Testing like 1990');
1582
-		$template
1583
-			->expects($this->once())
1584
-			->method('addFooter')
1585
-			->with('UnitTestCloud - Testing like 1990');
1586
-		$template
1587
-			->expects($this->once())
1588
-			->method('setSubject')
1589
-			->with('Mrs. Owner User shared file.txt with you');
1590
-		$message
1591
-			->expects($this->once())
1592
-			->method('useTemplate')
1593
-			->with($template);
1594
-
1595
-		$this->mailer
1596
-			->expects($this->once())
1597
-			->method('send')
1598
-			->with($message);
1599
-
1600
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1601
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1602
-			->willReturn('https://example.com/file.txt');
1603
-
1604
-		$node = $this->createMock(File::class);
1605
-		$node->expects($this->any())->method('getName')->willReturn('file.txt');
1606
-
1607
-		$share = $this->createMock(IShare::class);
1608
-		$share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1609
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1610
-		$share->expects($this->any())->method('getNode')->willReturn($node);
1611
-		$share->expects($this->any())->method('getId')->willReturn('42');
1612
-		$share->expects($this->any())->method('getNote')->willReturn('');
1613
-		$share->expects($this->any())->method('getExpirationDate')->willReturn($expiration);
1614
-		$share->expects($this->any())->method('getToken')->willReturn('token');
1615
-
1616
-		self::invokePrivate(
1617
-			$provider,
1618
-			'sendMailNotification',
1619
-			[$share]
1620
-		);
1621
-	}
1622
-
1623
-	public function testSendMailNotificationWithDifferentUserAndNoUserEmail(): void {
1624
-		$provider = $this->getInstance();
1625
-		$initiatorUser = $this->createMock(IUser::class);
1626
-		$this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1627
-		$this->userManager
1628
-			->expects($this->once())
1629
-			->method('get')
1630
-			->with('InitiatorUser')
1631
-			->willReturn($initiatorUser);
1632
-		$initiatorUser
1633
-			->expects($this->once())
1634
-			->method('getDisplayName')
1635
-			->willReturn('Mr. Initiator User');
1636
-		$message = $this->createMock(Message::class);
1637
-		$this->mailer
1638
-			->expects($this->once())
1639
-			->method('createMessage')
1640
-			->willReturn($message);
1641
-		$template = $this->createMock(IEMailTemplate::class);
1642
-		$this->mailer
1643
-			->expects($this->once())
1644
-			->method('createEMailTemplate')
1645
-			->willReturn($template);
1646
-		$template
1647
-			->expects($this->once())
1648
-			->method('addHeader');
1649
-		$template
1650
-			->expects($this->once())
1651
-			->method('addHeading')
1652
-			->with('Mr. Initiator User shared file.txt with you');
1653
-		$template
1654
-			->expects($this->once())
1655
-			->method('addBodyButton')
1656
-			->with(
1657
-				'Open file.txt',
1658
-				'https://example.com/file.txt'
1659
-			);
1660
-		$message
1661
-			->expects($this->once())
1662
-			->method('setTo')
1663
-			->with(['[email protected]']);
1664
-		$this->defaults
1665
-			->expects($this->once())
1666
-			->method('getName')
1667
-			->willReturn('UnitTestCloud');
1668
-		$message
1669
-			->expects($this->once())
1670
-			->method('setFrom')
1671
-			->with([
1672
-				Util::getDefaultEmailAddress('UnitTestCloud') => 'Mr. Initiator User via UnitTestCloud'
1673
-			]);
1674
-		$message
1675
-			->expects($this->never())
1676
-			->method('setReplyTo');
1677
-		$template
1678
-			->expects($this->once())
1679
-			->method('addFooter')
1680
-			->with('');
1681
-		$template
1682
-			->expects($this->once())
1683
-			->method('setSubject')
1684
-			->with('Mr. Initiator User shared file.txt with you');
1685
-		$message
1686
-			->expects($this->once())
1687
-			->method('useTemplate')
1688
-			->with($template);
1689
-
1690
-		$this->mailer
1691
-			->expects($this->once())
1692
-			->method('send')
1693
-			->with($message);
1694
-
1695
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1696
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1697
-			->willReturn('https://example.com/file.txt');
1698
-
1699
-		$node = $this->createMock(File::class);
1700
-		$node->expects($this->any())->method('getName')->willReturn('file.txt');
1701
-
1702
-		$share = $this->createMock(IShare::class);
1703
-		$share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser');
1704
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1705
-		$share->expects($this->any())->method('getNode')->willReturn($node);
1706
-		$share->expects($this->any())->method('getId')->willReturn('42');
1707
-		$share->expects($this->any())->method('getNote')->willReturn('');
1708
-		$share->expects($this->any())->method('getToken')->willReturn('token');
1709
-
1710
-		self::invokePrivate(
1711
-			$provider,
1712
-			'sendMailNotification',
1713
-			[$share]
1714
-		);
1715
-	}
1716
-
1717
-	public function testSendMailNotificationWithSameUserAndUserEmailAndReplyToDesactivate(): void {
1718
-		$provider = $this->getInstance();
1719
-		$user = $this->createMock(IUser::class);
1720
-		$this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(false);
1721
-		$this->userManager
1722
-			->expects($this->once())
1723
-			->method('get')
1724
-			->with('OwnerUser')
1725
-			->willReturn($user);
1726
-		$user
1727
-			->expects($this->once())
1728
-			->method('getDisplayName')
1729
-			->willReturn('Mrs. Owner User');
1730
-		$message = $this->createMock(Message::class);
1731
-		$this->mailer
1732
-			->expects($this->once())
1733
-			->method('createMessage')
1734
-			->willReturn($message);
1735
-		$template = $this->createMock(IEMailTemplate::class);
1736
-		$this->mailer
1737
-			->expects($this->once())
1738
-			->method('createEMailTemplate')
1739
-			->willReturn($template);
1740
-		$template
1741
-			->expects($this->once())
1742
-			->method('addHeader');
1743
-		$template
1744
-			->expects($this->once())
1745
-			->method('addHeading')
1746
-			->with('Mrs. Owner User shared file.txt with you');
1747
-		$template
1748
-			->expects($this->once())
1749
-			->method('addBodyButton')
1750
-			->with(
1751
-				'Open file.txt',
1752
-				'https://example.com/file.txt'
1753
-			);
1754
-		$message
1755
-			->expects($this->once())
1756
-			->method('setTo')
1757
-			->with(['[email protected]']);
1758
-		$this->defaults
1759
-			->expects($this->once())
1760
-			->method('getName')
1761
-			->willReturn('UnitTestCloud');
1762
-		$message
1763
-			->expects($this->once())
1764
-			->method('setFrom')
1765
-			->with([
1766
-				Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud'
1767
-			]);
1768
-		// Since replyToInitiator is false, we never get the initiator email address
1769
-		$user
1770
-			->expects($this->never())
1771
-			->method('getEMailAddress');
1772
-		$message
1773
-			->expects($this->never())
1774
-			->method('setReplyTo');
1775
-		$template
1776
-			->expects($this->once())
1777
-			->method('addFooter')
1778
-			->with('');
1779
-		$template
1780
-			->expects($this->once())
1781
-			->method('setSubject')
1782
-			->with('Mrs. Owner User shared file.txt with you');
1783
-		$message
1784
-			->expects($this->once())
1785
-			->method('useTemplate')
1786
-			->with($template);
1787
-
1788
-		$this->mailer
1789
-			->expects($this->once())
1790
-			->method('send')
1791
-			->with($message);
1792
-
1793
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1794
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1795
-			->willReturn('https://example.com/file.txt');
1796
-
1797
-		$node = $this->createMock(File::class);
1798
-		$node->expects($this->any())->method('getName')->willReturn('file.txt');
1799
-
1800
-		$share = $this->createMock(IShare::class);
1801
-		$share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1802
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1803
-		$share->expects($this->any())->method('getNode')->willReturn($node);
1804
-		$share->expects($this->any())->method('getId')->willReturn('42');
1805
-		$share->expects($this->any())->method('getNote')->willReturn('');
1806
-		$share->expects($this->any())->method('getToken')->willReturn('token');
1807
-
1808
-		self::invokePrivate(
1809
-			$provider,
1810
-			'sendMailNotification',
1811
-			[$share]
1812
-		);
1813
-	}
1814
-
1815
-	public function testSendMailNotificationWithDifferentUserAndNoUserEmailAndReplyToDesactivate(): void {
1816
-		$provider = $this->getInstance();
1817
-		$initiatorUser = $this->createMock(IUser::class);
1818
-		$this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(false);
1819
-		$this->userManager
1820
-			->expects($this->once())
1821
-			->method('get')
1822
-			->with('InitiatorUser')
1823
-			->willReturn($initiatorUser);
1824
-		$initiatorUser
1825
-			->expects($this->once())
1826
-			->method('getDisplayName')
1827
-			->willReturn('Mr. Initiator User');
1828
-		$message = $this->createMock(Message::class);
1829
-		$this->mailer
1830
-			->expects($this->once())
1831
-			->method('createMessage')
1832
-			->willReturn($message);
1833
-		$template = $this->createMock(IEMailTemplate::class);
1834
-		$this->mailer
1835
-			->expects($this->once())
1836
-			->method('createEMailTemplate')
1837
-			->willReturn($template);
1838
-		$template
1839
-			->expects($this->once())
1840
-			->method('addHeader');
1841
-		$template
1842
-			->expects($this->once())
1843
-			->method('addHeading')
1844
-			->with('Mr. Initiator User shared file.txt with you');
1845
-		$template
1846
-			->expects($this->once())
1847
-			->method('addBodyButton')
1848
-			->with(
1849
-				'Open file.txt',
1850
-				'https://example.com/file.txt'
1851
-			);
1852
-		$message
1853
-			->expects($this->once())
1854
-			->method('setTo')
1855
-			->with(['[email protected]']);
1856
-		$this->defaults
1857
-			->expects($this->once())
1858
-			->method('getName')
1859
-			->willReturn('UnitTestCloud');
1860
-		$message
1861
-			->expects($this->once())
1862
-			->method('setFrom')
1863
-			->with([
1864
-				Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud'
1865
-			]);
1866
-		$message
1867
-			->expects($this->never())
1868
-			->method('setReplyTo');
1869
-		$template
1870
-			->expects($this->once())
1871
-			->method('addFooter')
1872
-			->with('');
1873
-		$template
1874
-			->expects($this->once())
1875
-			->method('setSubject')
1876
-			->with('Mr. Initiator User shared file.txt with you');
1877
-		$message
1878
-			->expects($this->once())
1879
-			->method('useTemplate')
1880
-			->with($template);
1881
-
1882
-		$this->mailer
1883
-			->expects($this->once())
1884
-			->method('send')
1885
-			->with($message);
1886
-
1887
-		$this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1888
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1889
-			->willReturn('https://example.com/file.txt');
1890
-
1891
-		$node = $this->createMock(File::class);
1892
-		$node->expects($this->any())->method('getName')->willReturn('file.txt');
1893
-
1894
-		$share = $this->createMock(IShare::class);
1895
-		$share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser');
1896
-		$share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1897
-		$share->expects($this->any())->method('getNode')->willReturn($node);
1898
-		$share->expects($this->any())->method('getId')->willReturn('42');
1899
-		$share->expects($this->any())->method('getNote')->willReturn('');
1900
-		$share->expects($this->any())->method('getToken')->willReturn('token');
1901
-
1902
-		self::invokePrivate(
1903
-			$provider,
1904
-			'sendMailNotification',
1905
-			[$share]
1906
-		);
1907
-	}
1157
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
1158
+
1159
+        $qb->executeStatement();
1160
+        return (string)$qb->getLastInsertId();
1161
+    }
1162
+
1163
+    public function testGetSharesInFolder(): void {
1164
+        $userManager = Server::get(IUserManager::class);
1165
+        $rootFolder = Server::get(IRootFolder::class);
1166
+
1167
+        $this->shareManager->expects($this->any())
1168
+            ->method('newShare')
1169
+            ->willReturn(new Share($rootFolder, $userManager));
1170
+
1171
+        $provider = $this->getInstance(['sendMailNotification', 'createShareActivity']);
1172
+
1173
+        $u1 = $userManager->createUser('testFed', md5((string)time()));
1174
+        $u2 = $userManager->createUser('testFed2', md5((string)time()));
1175
+
1176
+        $folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
1177
+        $file1 = $folder1->newFile('bar1');
1178
+        $file2 = $folder1->newFile('bar2');
1179
+
1180
+        $share1 = $this->shareManager->newShare();
1181
+        $share1->setSharedWith('[email protected]')
1182
+            ->setSharedBy($u1->getUID())
1183
+            ->setShareOwner($u1->getUID())
1184
+            ->setPermissions(Constants::PERMISSION_READ)
1185
+            ->setNode($file1);
1186
+        $provider->create($share1);
1187
+
1188
+        $share2 = $this->shareManager->newShare();
1189
+        $share2->setSharedWith('[email protected]')
1190
+            ->setSharedBy($u2->getUID())
1191
+            ->setShareOwner($u1->getUID())
1192
+            ->setPermissions(Constants::PERMISSION_READ)
1193
+            ->setNode($file2);
1194
+        $provider->create($share2);
1195
+
1196
+        $result = $provider->getSharesInFolder($u1->getUID(), $folder1, false);
1197
+        $this->assertCount(1, $result);
1198
+        $this->assertCount(1, $result[$file1->getId()]);
1199
+
1200
+        $result = $provider->getSharesInFolder($u1->getUID(), $folder1, true);
1201
+        $this->assertCount(2, $result);
1202
+        $this->assertCount(1, $result[$file1->getId()]);
1203
+        $this->assertCount(1, $result[$file2->getId()]);
1204
+
1205
+        $u1->delete();
1206
+        $u2->delete();
1207
+    }
1208
+
1209
+    public function testGetAccessList(): void {
1210
+        $userManager = Server::get(IUserManager::class);
1211
+        $rootFolder = Server::get(IRootFolder::class);
1212
+
1213
+        $this->shareManager->expects($this->any())
1214
+            ->method('newShare')
1215
+            ->willReturn(new Share($rootFolder, $userManager));
1216
+
1217
+        $provider = $this->getInstance(['sendMailNotification', 'createShareActivity']);
1218
+
1219
+        $u1 = $userManager->createUser('testFed', md5((string)time()));
1220
+        $u2 = $userManager->createUser('testFed2', md5((string)time()));
1221
+
1222
+        $folder = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
1223
+
1224
+        $accessList = $provider->getAccessList([$folder], true);
1225
+        $this->assertArrayHasKey('public', $accessList);
1226
+        $this->assertFalse($accessList['public']);
1227
+        $accessList = $provider->getAccessList([$folder], false);
1228
+        $this->assertArrayHasKey('public', $accessList);
1229
+        $this->assertFalse($accessList['public']);
1230
+
1231
+        $share1 = $this->shareManager->newShare();
1232
+        $share1->setSharedWith('[email protected]')
1233
+            ->setSharedBy($u1->getUID())
1234
+            ->setShareOwner($u1->getUID())
1235
+            ->setPermissions(Constants::PERMISSION_READ)
1236
+            ->setNode($folder);
1237
+        $share1 = $provider->create($share1);
1238
+
1239
+        $share2 = $this->shareManager->newShare();
1240
+        $share2->setSharedWith('[email protected]')
1241
+            ->setSharedBy($u2->getUID())
1242
+            ->setShareOwner($u1->getUID())
1243
+            ->setPermissions(Constants::PERMISSION_READ)
1244
+            ->setNode($folder);
1245
+        $share2 = $provider->create($share2);
1246
+
1247
+        $accessList = $provider->getAccessList([$folder], true);
1248
+        $this->assertArrayHasKey('public', $accessList);
1249
+        $this->assertTrue($accessList['public']);
1250
+        $accessList = $provider->getAccessList([$folder], false);
1251
+        $this->assertArrayHasKey('public', $accessList);
1252
+        $this->assertTrue($accessList['public']);
1253
+
1254
+        $provider->delete($share2);
1255
+
1256
+        $accessList = $provider->getAccessList([$folder], true);
1257
+        $this->assertArrayHasKey('public', $accessList);
1258
+        $this->assertTrue($accessList['public']);
1259
+        $accessList = $provider->getAccessList([$folder], false);
1260
+        $this->assertArrayHasKey('public', $accessList);
1261
+        $this->assertTrue($accessList['public']);
1262
+
1263
+        $provider->delete($share1);
1264
+
1265
+        $accessList = $provider->getAccessList([$folder], true);
1266
+        $this->assertArrayHasKey('public', $accessList);
1267
+        $this->assertFalse($accessList['public']);
1268
+        $accessList = $provider->getAccessList([$folder], false);
1269
+        $this->assertArrayHasKey('public', $accessList);
1270
+        $this->assertFalse($accessList['public']);
1271
+
1272
+        $u1->delete();
1273
+        $u2->delete();
1274
+    }
1275
+
1276
+    public function testSendMailNotificationWithSameUserAndUserEmail(): void {
1277
+        $provider = $this->getInstance();
1278
+        $user = $this->createMock(IUser::class);
1279
+        $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1280
+        $this->userManager
1281
+            ->expects($this->once())
1282
+            ->method('get')
1283
+            ->with('OwnerUser')
1284
+            ->willReturn($user);
1285
+        $user
1286
+            ->expects($this->once())
1287
+            ->method('getDisplayName')
1288
+            ->willReturn('Mrs. Owner User');
1289
+        $message = $this->createMock(Message::class);
1290
+        $this->mailer
1291
+            ->expects($this->once())
1292
+            ->method('createMessage')
1293
+            ->willReturn($message);
1294
+        $template = $this->createMock(IEMailTemplate::class);
1295
+        $this->mailer
1296
+            ->expects($this->once())
1297
+            ->method('createEMailTemplate')
1298
+            ->willReturn($template);
1299
+        $template
1300
+            ->expects($this->once())
1301
+            ->method('addHeader');
1302
+        $template
1303
+            ->expects($this->once())
1304
+            ->method('addHeading')
1305
+            ->with('Mrs. Owner User shared file.txt with you');
1306
+        $template
1307
+            ->expects($this->once())
1308
+            ->method('addBodyButton')
1309
+            ->with(
1310
+                'Open file.txt',
1311
+                'https://example.com/file.txt'
1312
+            );
1313
+        $message
1314
+            ->expects($this->once())
1315
+            ->method('setTo')
1316
+            ->with(['[email protected]']);
1317
+        $this->defaults
1318
+            ->expects($this->once())
1319
+            ->method('getName')
1320
+            ->willReturn('UnitTestCloud');
1321
+        $message
1322
+            ->expects($this->once())
1323
+            ->method('setFrom')
1324
+            ->with([
1325
+                Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud'
1326
+            ]);
1327
+        $user
1328
+            ->expects($this->once())
1329
+            ->method('getEMailAddress')
1330
+            ->willReturn('[email protected]');
1331
+        $message
1332
+            ->expects($this->once())
1333
+            ->method('setReplyTo')
1334
+            ->with(['[email protected]' => 'Mrs. Owner User']);
1335
+        $this->defaults
1336
+            ->expects($this->exactly(2))
1337
+            ->method('getSlogan')
1338
+            ->willReturn('Testing like 1990');
1339
+        $template
1340
+            ->expects($this->once())
1341
+            ->method('addFooter')
1342
+            ->with('UnitTestCloud - Testing like 1990');
1343
+        $template
1344
+            ->expects($this->once())
1345
+            ->method('setSubject')
1346
+            ->with('Mrs. Owner User shared file.txt with you');
1347
+        $message
1348
+            ->expects($this->once())
1349
+            ->method('useTemplate')
1350
+            ->with($template);
1351
+
1352
+        $this->mailer
1353
+            ->expects($this->once())
1354
+            ->method('send')
1355
+            ->with($message);
1356
+
1357
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1358
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1359
+            ->willReturn('https://example.com/file.txt');
1360
+
1361
+        $node = $this->createMock(File::class);
1362
+        $node->expects($this->any())->method('getName')->willReturn('file.txt');
1363
+
1364
+        $share = $this->createMock(IShare::class);
1365
+        $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1366
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1367
+        $share->expects($this->any())->method('getNode')->willReturn($node);
1368
+        $share->expects($this->any())->method('getId')->willReturn('42');
1369
+        $share->expects($this->any())->method('getNote')->willReturn('');
1370
+        $share->expects($this->any())->method('getToken')->willReturn('token');
1371
+
1372
+        self::invokePrivate(
1373
+            $provider,
1374
+            'sendMailNotification',
1375
+            [$share]
1376
+        );
1377
+    }
1378
+
1379
+    public function testSendMailNotificationWithSameUserAndUserEmailAndNote(): void {
1380
+        $provider = $this->getInstance();
1381
+        $user = $this->createMock(IUser::class);
1382
+        $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1383
+        $this->userManager
1384
+            ->expects($this->once())
1385
+            ->method('get')
1386
+            ->with('OwnerUser')
1387
+            ->willReturn($user);
1388
+        $user
1389
+            ->expects($this->once())
1390
+            ->method('getDisplayName')
1391
+            ->willReturn('Mrs. Owner User');
1392
+        $message = $this->createMock(Message::class);
1393
+        $this->mailer
1394
+            ->expects($this->once())
1395
+            ->method('createMessage')
1396
+            ->willReturn($message);
1397
+        $template = $this->createMock(IEMailTemplate::class);
1398
+        $this->mailer
1399
+            ->expects($this->once())
1400
+            ->method('createEMailTemplate')
1401
+            ->willReturn($template);
1402
+        $template
1403
+            ->expects($this->once())
1404
+            ->method('addHeader');
1405
+        $template
1406
+            ->expects($this->once())
1407
+            ->method('addHeading')
1408
+            ->with('Mrs. Owner User shared file.txt with you');
1409
+
1410
+        $this->urlGenerator->expects($this->once())->method('imagePath')
1411
+            ->with('core', 'caldav/description.png')
1412
+            ->willReturn('core/img/caldav/description.png');
1413
+        $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')
1414
+            ->with('core/img/caldav/description.png')
1415
+            ->willReturn('https://example.com/core/img/caldav/description.png');
1416
+        $template
1417
+            ->expects($this->once())
1418
+            ->method('addBodyListItem')
1419
+            ->with(
1420
+                'This is a note to the recipient',
1421
+                'Note:',
1422
+                'https://example.com/core/img/caldav/description.png',
1423
+                'This is a note to the recipient'
1424
+            );
1425
+        $template
1426
+            ->expects($this->once())
1427
+            ->method('addBodyButton')
1428
+            ->with(
1429
+                'Open file.txt',
1430
+                'https://example.com/file.txt'
1431
+            );
1432
+        $message
1433
+            ->expects($this->once())
1434
+            ->method('setTo')
1435
+            ->with(['[email protected]']);
1436
+        $this->defaults
1437
+            ->expects($this->once())
1438
+            ->method('getName')
1439
+            ->willReturn('UnitTestCloud');
1440
+        $message
1441
+            ->expects($this->once())
1442
+            ->method('setFrom')
1443
+            ->with([
1444
+                Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud'
1445
+            ]);
1446
+        $user
1447
+            ->expects($this->once())
1448
+            ->method('getEMailAddress')
1449
+            ->willReturn('[email protected]');
1450
+        $message
1451
+            ->expects($this->once())
1452
+            ->method('setReplyTo')
1453
+            ->with(['[email protected]' => 'Mrs. Owner User']);
1454
+        $this->defaults
1455
+            ->expects($this->exactly(2))
1456
+            ->method('getSlogan')
1457
+            ->willReturn('Testing like 1990');
1458
+        $template
1459
+            ->expects($this->once())
1460
+            ->method('addFooter')
1461
+            ->with('UnitTestCloud - Testing like 1990');
1462
+        $template
1463
+            ->expects($this->once())
1464
+            ->method('setSubject')
1465
+            ->with('Mrs. Owner User shared file.txt with you');
1466
+        $message
1467
+            ->expects($this->once())
1468
+            ->method('useTemplate')
1469
+            ->with($template);
1470
+
1471
+        $this->mailer
1472
+            ->expects($this->once())
1473
+            ->method('send')
1474
+            ->with($message);
1475
+
1476
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1477
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1478
+            ->willReturn('https://example.com/file.txt');
1479
+
1480
+        $node = $this->createMock(File::class);
1481
+        $node->expects($this->any())->method('getName')->willReturn('file.txt');
1482
+
1483
+        $share = $this->createMock(IShare::class);
1484
+        $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1485
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1486
+        $share->expects($this->any())->method('getNode')->willReturn($node);
1487
+        $share->expects($this->any())->method('getId')->willReturn('42');
1488
+        $share->expects($this->any())->method('getNote')->willReturn('This is a note to the recipient');
1489
+        $share->expects($this->any())->method('getToken')->willReturn('token');
1490
+
1491
+        self::invokePrivate(
1492
+            $provider,
1493
+            'sendMailNotification',
1494
+            [$share]
1495
+        );
1496
+    }
1497
+
1498
+    public function testSendMailNotificationWithSameUserAndUserEmailAndExpiration(): void {
1499
+        $provider = $this->getInstance();
1500
+        $user = $this->createMock(IUser::class);
1501
+        $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1502
+        $this->userManager
1503
+            ->expects($this->once())
1504
+            ->method('get')
1505
+            ->with('OwnerUser')
1506
+            ->willReturn($user);
1507
+        $user
1508
+            ->expects($this->once())
1509
+            ->method('getDisplayName')
1510
+            ->willReturn('Mrs. Owner User');
1511
+        $message = $this->createMock(Message::class);
1512
+        $this->mailer
1513
+            ->expects($this->once())
1514
+            ->method('createMessage')
1515
+            ->willReturn($message);
1516
+        $template = $this->createMock(IEMailTemplate::class);
1517
+        $this->mailer
1518
+            ->expects($this->once())
1519
+            ->method('createEMailTemplate')
1520
+            ->willReturn($template);
1521
+        $template
1522
+            ->expects($this->once())
1523
+            ->method('addHeader');
1524
+        $template
1525
+            ->expects($this->once())
1526
+            ->method('addHeading')
1527
+            ->with('Mrs. Owner User shared file.txt with you');
1528
+
1529
+        $expiration = new DateTime('2001-01-01');
1530
+        $this->l->expects($this->once())
1531
+            ->method('l')
1532
+            ->with('date', $expiration, ['width' => 'medium'])
1533
+            ->willReturn('2001-01-01');
1534
+        $this->urlGenerator->expects($this->once())->method('imagePath')
1535
+            ->with('core', 'caldav/time.png')
1536
+            ->willReturn('core/img/caldav/time.png');
1537
+        $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')
1538
+            ->with('core/img/caldav/time.png')
1539
+            ->willReturn('https://example.com/core/img/caldav/time.png');
1540
+        $template
1541
+            ->expects($this->once())
1542
+            ->method('addBodyListItem')
1543
+            ->with(
1544
+                'This share is valid until 2001-01-01 at midnight',
1545
+                'Expiration:',
1546
+                'https://example.com/core/img/caldav/time.png',
1547
+            );
1548
+
1549
+        $template
1550
+            ->expects($this->once())
1551
+            ->method('addBodyButton')
1552
+            ->with(
1553
+                'Open file.txt',
1554
+                'https://example.com/file.txt'
1555
+            );
1556
+        $message
1557
+            ->expects($this->once())
1558
+            ->method('setTo')
1559
+            ->with(['[email protected]']);
1560
+        $this->defaults
1561
+            ->expects($this->once())
1562
+            ->method('getName')
1563
+            ->willReturn('UnitTestCloud');
1564
+        $message
1565
+            ->expects($this->once())
1566
+            ->method('setFrom')
1567
+            ->with([
1568
+                Util::getDefaultEmailAddress('UnitTestCloud') => 'Mrs. Owner User via UnitTestCloud'
1569
+            ]);
1570
+        $user
1571
+            ->expects($this->once())
1572
+            ->method('getEMailAddress')
1573
+            ->willReturn('[email protected]');
1574
+        $message
1575
+            ->expects($this->once())
1576
+            ->method('setReplyTo')
1577
+            ->with(['[email protected]' => 'Mrs. Owner User']);
1578
+        $this->defaults
1579
+            ->expects($this->exactly(2))
1580
+            ->method('getSlogan')
1581
+            ->willReturn('Testing like 1990');
1582
+        $template
1583
+            ->expects($this->once())
1584
+            ->method('addFooter')
1585
+            ->with('UnitTestCloud - Testing like 1990');
1586
+        $template
1587
+            ->expects($this->once())
1588
+            ->method('setSubject')
1589
+            ->with('Mrs. Owner User shared file.txt with you');
1590
+        $message
1591
+            ->expects($this->once())
1592
+            ->method('useTemplate')
1593
+            ->with($template);
1594
+
1595
+        $this->mailer
1596
+            ->expects($this->once())
1597
+            ->method('send')
1598
+            ->with($message);
1599
+
1600
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1601
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1602
+            ->willReturn('https://example.com/file.txt');
1603
+
1604
+        $node = $this->createMock(File::class);
1605
+        $node->expects($this->any())->method('getName')->willReturn('file.txt');
1606
+
1607
+        $share = $this->createMock(IShare::class);
1608
+        $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1609
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1610
+        $share->expects($this->any())->method('getNode')->willReturn($node);
1611
+        $share->expects($this->any())->method('getId')->willReturn('42');
1612
+        $share->expects($this->any())->method('getNote')->willReturn('');
1613
+        $share->expects($this->any())->method('getExpirationDate')->willReturn($expiration);
1614
+        $share->expects($this->any())->method('getToken')->willReturn('token');
1615
+
1616
+        self::invokePrivate(
1617
+            $provider,
1618
+            'sendMailNotification',
1619
+            [$share]
1620
+        );
1621
+    }
1622
+
1623
+    public function testSendMailNotificationWithDifferentUserAndNoUserEmail(): void {
1624
+        $provider = $this->getInstance();
1625
+        $initiatorUser = $this->createMock(IUser::class);
1626
+        $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(true);
1627
+        $this->userManager
1628
+            ->expects($this->once())
1629
+            ->method('get')
1630
+            ->with('InitiatorUser')
1631
+            ->willReturn($initiatorUser);
1632
+        $initiatorUser
1633
+            ->expects($this->once())
1634
+            ->method('getDisplayName')
1635
+            ->willReturn('Mr. Initiator User');
1636
+        $message = $this->createMock(Message::class);
1637
+        $this->mailer
1638
+            ->expects($this->once())
1639
+            ->method('createMessage')
1640
+            ->willReturn($message);
1641
+        $template = $this->createMock(IEMailTemplate::class);
1642
+        $this->mailer
1643
+            ->expects($this->once())
1644
+            ->method('createEMailTemplate')
1645
+            ->willReturn($template);
1646
+        $template
1647
+            ->expects($this->once())
1648
+            ->method('addHeader');
1649
+        $template
1650
+            ->expects($this->once())
1651
+            ->method('addHeading')
1652
+            ->with('Mr. Initiator User shared file.txt with you');
1653
+        $template
1654
+            ->expects($this->once())
1655
+            ->method('addBodyButton')
1656
+            ->with(
1657
+                'Open file.txt',
1658
+                'https://example.com/file.txt'
1659
+            );
1660
+        $message
1661
+            ->expects($this->once())
1662
+            ->method('setTo')
1663
+            ->with(['[email protected]']);
1664
+        $this->defaults
1665
+            ->expects($this->once())
1666
+            ->method('getName')
1667
+            ->willReturn('UnitTestCloud');
1668
+        $message
1669
+            ->expects($this->once())
1670
+            ->method('setFrom')
1671
+            ->with([
1672
+                Util::getDefaultEmailAddress('UnitTestCloud') => 'Mr. Initiator User via UnitTestCloud'
1673
+            ]);
1674
+        $message
1675
+            ->expects($this->never())
1676
+            ->method('setReplyTo');
1677
+        $template
1678
+            ->expects($this->once())
1679
+            ->method('addFooter')
1680
+            ->with('');
1681
+        $template
1682
+            ->expects($this->once())
1683
+            ->method('setSubject')
1684
+            ->with('Mr. Initiator User shared file.txt with you');
1685
+        $message
1686
+            ->expects($this->once())
1687
+            ->method('useTemplate')
1688
+            ->with($template);
1689
+
1690
+        $this->mailer
1691
+            ->expects($this->once())
1692
+            ->method('send')
1693
+            ->with($message);
1694
+
1695
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1696
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1697
+            ->willReturn('https://example.com/file.txt');
1698
+
1699
+        $node = $this->createMock(File::class);
1700
+        $node->expects($this->any())->method('getName')->willReturn('file.txt');
1701
+
1702
+        $share = $this->createMock(IShare::class);
1703
+        $share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser');
1704
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1705
+        $share->expects($this->any())->method('getNode')->willReturn($node);
1706
+        $share->expects($this->any())->method('getId')->willReturn('42');
1707
+        $share->expects($this->any())->method('getNote')->willReturn('');
1708
+        $share->expects($this->any())->method('getToken')->willReturn('token');
1709
+
1710
+        self::invokePrivate(
1711
+            $provider,
1712
+            'sendMailNotification',
1713
+            [$share]
1714
+        );
1715
+    }
1716
+
1717
+    public function testSendMailNotificationWithSameUserAndUserEmailAndReplyToDesactivate(): void {
1718
+        $provider = $this->getInstance();
1719
+        $user = $this->createMock(IUser::class);
1720
+        $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(false);
1721
+        $this->userManager
1722
+            ->expects($this->once())
1723
+            ->method('get')
1724
+            ->with('OwnerUser')
1725
+            ->willReturn($user);
1726
+        $user
1727
+            ->expects($this->once())
1728
+            ->method('getDisplayName')
1729
+            ->willReturn('Mrs. Owner User');
1730
+        $message = $this->createMock(Message::class);
1731
+        $this->mailer
1732
+            ->expects($this->once())
1733
+            ->method('createMessage')
1734
+            ->willReturn($message);
1735
+        $template = $this->createMock(IEMailTemplate::class);
1736
+        $this->mailer
1737
+            ->expects($this->once())
1738
+            ->method('createEMailTemplate')
1739
+            ->willReturn($template);
1740
+        $template
1741
+            ->expects($this->once())
1742
+            ->method('addHeader');
1743
+        $template
1744
+            ->expects($this->once())
1745
+            ->method('addHeading')
1746
+            ->with('Mrs. Owner User shared file.txt with you');
1747
+        $template
1748
+            ->expects($this->once())
1749
+            ->method('addBodyButton')
1750
+            ->with(
1751
+                'Open file.txt',
1752
+                'https://example.com/file.txt'
1753
+            );
1754
+        $message
1755
+            ->expects($this->once())
1756
+            ->method('setTo')
1757
+            ->with(['[email protected]']);
1758
+        $this->defaults
1759
+            ->expects($this->once())
1760
+            ->method('getName')
1761
+            ->willReturn('UnitTestCloud');
1762
+        $message
1763
+            ->expects($this->once())
1764
+            ->method('setFrom')
1765
+            ->with([
1766
+                Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud'
1767
+            ]);
1768
+        // Since replyToInitiator is false, we never get the initiator email address
1769
+        $user
1770
+            ->expects($this->never())
1771
+            ->method('getEMailAddress');
1772
+        $message
1773
+            ->expects($this->never())
1774
+            ->method('setReplyTo');
1775
+        $template
1776
+            ->expects($this->once())
1777
+            ->method('addFooter')
1778
+            ->with('');
1779
+        $template
1780
+            ->expects($this->once())
1781
+            ->method('setSubject')
1782
+            ->with('Mrs. Owner User shared file.txt with you');
1783
+        $message
1784
+            ->expects($this->once())
1785
+            ->method('useTemplate')
1786
+            ->with($template);
1787
+
1788
+        $this->mailer
1789
+            ->expects($this->once())
1790
+            ->method('send')
1791
+            ->with($message);
1792
+
1793
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1794
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1795
+            ->willReturn('https://example.com/file.txt');
1796
+
1797
+        $node = $this->createMock(File::class);
1798
+        $node->expects($this->any())->method('getName')->willReturn('file.txt');
1799
+
1800
+        $share = $this->createMock(IShare::class);
1801
+        $share->expects($this->any())->method('getSharedBy')->willReturn('OwnerUser');
1802
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1803
+        $share->expects($this->any())->method('getNode')->willReturn($node);
1804
+        $share->expects($this->any())->method('getId')->willReturn('42');
1805
+        $share->expects($this->any())->method('getNote')->willReturn('');
1806
+        $share->expects($this->any())->method('getToken')->willReturn('token');
1807
+
1808
+        self::invokePrivate(
1809
+            $provider,
1810
+            'sendMailNotification',
1811
+            [$share]
1812
+        );
1813
+    }
1814
+
1815
+    public function testSendMailNotificationWithDifferentUserAndNoUserEmailAndReplyToDesactivate(): void {
1816
+        $provider = $this->getInstance();
1817
+        $initiatorUser = $this->createMock(IUser::class);
1818
+        $this->settingsManager->expects($this->any())->method('replyToInitiator')->willReturn(false);
1819
+        $this->userManager
1820
+            ->expects($this->once())
1821
+            ->method('get')
1822
+            ->with('InitiatorUser')
1823
+            ->willReturn($initiatorUser);
1824
+        $initiatorUser
1825
+            ->expects($this->once())
1826
+            ->method('getDisplayName')
1827
+            ->willReturn('Mr. Initiator User');
1828
+        $message = $this->createMock(Message::class);
1829
+        $this->mailer
1830
+            ->expects($this->once())
1831
+            ->method('createMessage')
1832
+            ->willReturn($message);
1833
+        $template = $this->createMock(IEMailTemplate::class);
1834
+        $this->mailer
1835
+            ->expects($this->once())
1836
+            ->method('createEMailTemplate')
1837
+            ->willReturn($template);
1838
+        $template
1839
+            ->expects($this->once())
1840
+            ->method('addHeader');
1841
+        $template
1842
+            ->expects($this->once())
1843
+            ->method('addHeading')
1844
+            ->with('Mr. Initiator User shared file.txt with you');
1845
+        $template
1846
+            ->expects($this->once())
1847
+            ->method('addBodyButton')
1848
+            ->with(
1849
+                'Open file.txt',
1850
+                'https://example.com/file.txt'
1851
+            );
1852
+        $message
1853
+            ->expects($this->once())
1854
+            ->method('setTo')
1855
+            ->with(['[email protected]']);
1856
+        $this->defaults
1857
+            ->expects($this->once())
1858
+            ->method('getName')
1859
+            ->willReturn('UnitTestCloud');
1860
+        $message
1861
+            ->expects($this->once())
1862
+            ->method('setFrom')
1863
+            ->with([
1864
+                Util::getDefaultEmailAddress('UnitTestCloud') => 'UnitTestCloud'
1865
+            ]);
1866
+        $message
1867
+            ->expects($this->never())
1868
+            ->method('setReplyTo');
1869
+        $template
1870
+            ->expects($this->once())
1871
+            ->method('addFooter')
1872
+            ->with('');
1873
+        $template
1874
+            ->expects($this->once())
1875
+            ->method('setSubject')
1876
+            ->with('Mr. Initiator User shared file.txt with you');
1877
+        $message
1878
+            ->expects($this->once())
1879
+            ->method('useTemplate')
1880
+            ->with($template);
1881
+
1882
+        $this->mailer
1883
+            ->expects($this->once())
1884
+            ->method('send')
1885
+            ->with($message);
1886
+
1887
+        $this->urlGenerator->expects($this->once())->method('linkToRouteAbsolute')
1888
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'token'])
1889
+            ->willReturn('https://example.com/file.txt');
1890
+
1891
+        $node = $this->createMock(File::class);
1892
+        $node->expects($this->any())->method('getName')->willReturn('file.txt');
1893
+
1894
+        $share = $this->createMock(IShare::class);
1895
+        $share->expects($this->any())->method('getSharedBy')->willReturn('InitiatorUser');
1896
+        $share->expects($this->any())->method('getSharedWith')->willReturn('[email protected]');
1897
+        $share->expects($this->any())->method('getNode')->willReturn($node);
1898
+        $share->expects($this->any())->method('getId')->willReturn('42');
1899
+        $share->expects($this->any())->method('getNote')->willReturn('');
1900
+        $share->expects($this->any())->method('getToken')->willReturn('token');
1901
+
1902
+        self::invokePrivate(
1903
+            $provider,
1904
+            'sendMailNotification',
1905
+            [$share]
1906
+        );
1907
+    }
1908 1908
 }
Please login to merge, or discard this patch.
Spacing   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -77,7 +77,7 @@  discard block
 block discarded – undo
77 77
 
78 78
 		$this->l = $this->createMock(IL10N::class);
79 79
 		$this->l->method('t')
80
-			->willReturnCallback(function ($text, $parameters = []) {
80
+			->willReturnCallback(function($text, $parameters = []) {
81 81
 				return vsprintf($text, $parameters);
82 82
 			});
83 83
 		$this->config = $this->createMock(IConfig::class);
@@ -393,7 +393,7 @@  discard block
 block discarded – undo
393 393
 		];
394 394
 		$this->mailer->expects($this->exactly(2))
395 395
 			->method('createEMailTemplate')
396
-			->willReturnCallback(function () use (&$calls) {
396
+			->willReturnCallback(function() use (&$calls) {
397 397
 				$expected = array_shift($calls);
398 398
 				$this->assertEquals($expected, func_get_args());
399 399
 				return $this->createMock(IEMailTemplate::class);
@@ -475,7 +475,7 @@  discard block
 block discarded – undo
475 475
 		];
476 476
 		$this->mailer->expects($this->exactly(2))
477 477
 			->method('createEMailTemplate')
478
-			->willReturnCallback(function () use (&$calls) {
478
+			->willReturnCallback(function() use (&$calls) {
479 479
 				$expected = array_shift($calls);
480 480
 				$this->assertEquals($expected, func_get_args());
481 481
 				return $this->createMock(IEMailTemplate::class);
@@ -540,7 +540,7 @@  discard block
 block discarded – undo
540 540
 		];
541 541
 		$message->expects($this->exactly(2))
542 542
 			->method('setTo')
543
-			->willReturnCallback(function () use (&$setToCalls, $message) {
543
+			->willReturnCallback(function() use (&$setToCalls, $message) {
544 544
 				$expected = array_shift($setToCalls);
545 545
 				$this->assertEquals($expected, func_get_args());
546 546
 				return $message;
@@ -572,7 +572,7 @@  discard block
 block discarded – undo
572 572
 		];
573 573
 		$this->mailer->expects($this->exactly(2))
574 574
 			->method('createEMailTemplate')
575
-			->willReturnCallback(function () use (&$calls) {
575
+			->willReturnCallback(function() use (&$calls) {
576 576
 				$expected = array_shift($calls);
577 577
 				$this->assertEquals($expected, func_get_args());
578 578
 				return $this->createMock(IEMailTemplate::class);
@@ -752,17 +752,17 @@  discard block
 block discarded – undo
752 752
 
753 753
 		$this->assertSame(1, count($result));
754 754
 
755
-		$this->assertSame($itemSource, (int)$result[0]['item_source']);
755
+		$this->assertSame($itemSource, (int) $result[0]['item_source']);
756 756
 		$this->assertSame($itemType, $result[0]['item_type']);
757 757
 		$this->assertSame($shareWith, $result[0]['share_with']);
758 758
 		$this->assertSame($sharedBy, $result[0]['uid_initiator']);
759 759
 		$this->assertSame($uidOwner, $result[0]['uid_owner']);
760
-		$this->assertSame($permissions, (int)$result[0]['permissions']);
760
+		$this->assertSame($permissions, (int) $result[0]['permissions']);
761 761
 		$this->assertSame($token, $result[0]['token']);
762 762
 		$this->assertSame($password, $result[0]['password']);
763 763
 		$this->assertSame($passwordExpirationTime->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['password_expiration_time'])->getTimestamp());
764
-		$this->assertSame($sendPasswordByTalk, (bool)$result[0]['password_by_talk']);
765
-		$this->assertSame($hideDownload, (bool)$result[0]['hide_download']);
764
+		$this->assertSame($sendPasswordByTalk, (bool) $result[0]['password_by_talk']);
765
+		$this->assertSame($hideDownload, (bool) $result[0]['hide_download']);
766 766
 		$this->assertSame($label, $result[0]['label']);
767 767
 		$this->assertSame($expiration->getTimestamp(), \DateTime::createFromFormat('Y-m-d H:i:s', $result[0]['expiration'])->getTimestamp());
768 768
 	}
@@ -805,12 +805,12 @@  discard block
 block discarded – undo
805 805
 
806 806
 		$this->assertSame(1, count($result));
807 807
 
808
-		$this->assertSame($itemSource, (int)$result[0]['item_source']);
808
+		$this->assertSame($itemSource, (int) $result[0]['item_source']);
809 809
 		$this->assertSame($itemType, $result[0]['item_type']);
810 810
 		$this->assertSame($shareWith, $result[0]['share_with']);
811 811
 		$this->assertSame($sharedBy, $result[0]['uid_initiator']);
812 812
 		$this->assertSame($uidOwner, $result[0]['uid_owner']);
813
-		$this->assertSame($permissions + 1, (int)$result[0]['permissions']);
813
+		$this->assertSame($permissions + 1, (int) $result[0]['permissions']);
814 814
 		$this->assertSame($token, $result[0]['token']);
815 815
 		$this->assertSame($note, $result[0]['note']);
816 816
 	}
@@ -893,10 +893,10 @@  discard block
 block discarded – undo
893 893
 
894 894
 		$instance->expects($this->once())->method('createShareObject')
895 895
 			->willReturnCallback(
896
-				function ($data) use ($uidOwner, $sharedBy, $id2) {
896
+				function($data) use ($uidOwner, $sharedBy, $id2) {
897 897
 					$this->assertSame($uidOwner, $data['uid_owner']);
898 898
 					$this->assertSame($sharedBy, $data['uid_initiator']);
899
-					$this->assertSame($id2, (string)$data['id']);
899
+					$this->assertSame($id2, (string) $data['id']);
900 900
 					return $this->share;
901 901
 				}
902 902
 			);
@@ -945,7 +945,7 @@  discard block
 block discarded – undo
945 945
 
946 946
 		$instance->expects($this->once())->method('createShareObject')
947 947
 			->willReturnCallback(
948
-				function ($data) use ($uidOwner, $sharedBy, $id) {
948
+				function($data) use ($uidOwner, $sharedBy, $id) {
949 949
 					$this->assertSame($uidOwner, $data['uid_owner']);
950 950
 					$this->assertSame($sharedBy, $data['uid_initiator']);
951 951
 					$this->assertSame($id, $data['id']);
@@ -978,7 +978,7 @@  discard block
 block discarded – undo
978 978
 
979 979
 		$instance->expects($this->once())->method('createShareObject')
980 980
 			->willReturnCallback(
981
-				function ($data) use ($idMail) {
981
+				function($data) use ($idMail) {
982 982
 					$this->assertSame($idMail, $data['id']);
983 983
 					return $this->share;
984 984
 				}
@@ -1088,7 +1088,7 @@  discard block
 block discarded – undo
1088 1088
 
1089 1089
 		$this->assertTrue(is_array($after));
1090 1090
 		$this->assertSame(1, count($after));
1091
-		$this->assertSame($id, (string)$after[0]['id']);
1091
+		$this->assertSame($id, (string) $after[0]['id']);
1092 1092
 	}
1093 1093
 
1094 1094
 	public function testGetRawShare(): void {
@@ -1107,12 +1107,12 @@  discard block
 block discarded – undo
1107 1107
 		$result = $this->invokePrivate($instance, 'getRawShare', [$id]);
1108 1108
 
1109 1109
 		$this->assertTrue(is_array($result));
1110
-		$this->assertSame($itemSource, (int)$result['item_source']);
1110
+		$this->assertSame($itemSource, (int) $result['item_source']);
1111 1111
 		$this->assertSame($itemType, $result['item_type']);
1112 1112
 		$this->assertSame($shareWith, $result['share_with']);
1113 1113
 		$this->assertSame($sharedBy, $result['uid_initiator']);
1114 1114
 		$this->assertSame($uidOwner, $result['uid_owner']);
1115
-		$this->assertSame($permissions, (int)$result['permissions']);
1115
+		$this->assertSame($permissions, (int) $result['permissions']);
1116 1116
 		$this->assertSame($token, $result['token']);
1117 1117
 	}
1118 1118
 
@@ -1132,7 +1132,7 @@  discard block
 block discarded – undo
1132 1132
 
1133 1133
 		$id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
1134 1134
 
1135
-		$this->invokePrivate($instance, 'getRawShare', [(string)((int)$id + 1)]);
1135
+		$this->invokePrivate($instance, 'getRawShare', [(string) ((int) $id + 1)]);
1136 1136
 	}
1137 1137
 
1138 1138
 	private function createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note = '', $shareType = IShare::TYPE_EMAIL): string {
@@ -1157,7 +1157,7 @@  discard block
 block discarded – undo
1157 1157
 		$qb->setValue('file_target', $qb->createNamedParameter(''));
1158 1158
 
1159 1159
 		$qb->executeStatement();
1160
-		return (string)$qb->getLastInsertId();
1160
+		return (string) $qb->getLastInsertId();
1161 1161
 	}
1162 1162
 
1163 1163
 	public function testGetSharesInFolder(): void {
@@ -1170,8 +1170,8 @@  discard block
 block discarded – undo
1170 1170
 
1171 1171
 		$provider = $this->getInstance(['sendMailNotification', 'createShareActivity']);
1172 1172
 
1173
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
1174
-		$u2 = $userManager->createUser('testFed2', md5((string)time()));
1173
+		$u1 = $userManager->createUser('testFed', md5((string) time()));
1174
+		$u2 = $userManager->createUser('testFed2', md5((string) time()));
1175 1175
 
1176 1176
 		$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
1177 1177
 		$file1 = $folder1->newFile('bar1');
@@ -1216,8 +1216,8 @@  discard block
 block discarded – undo
1216 1216
 
1217 1217
 		$provider = $this->getInstance(['sendMailNotification', 'createShareActivity']);
1218 1218
 
1219
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
1220
-		$u2 = $userManager->createUser('testFed2', md5((string)time()));
1219
+		$u1 = $userManager->createUser('testFed', md5((string) time()));
1220
+		$u2 = $userManager->createUser('testFed2', md5((string) time()));
1221 1221
 
1222 1222
 		$folder = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
1223 1223
 
Please login to merge, or discard this patch.
apps/sharebymail/lib/ShareByMailProvider.php 2 patches
Indentation   +1199 added lines, -1199 removed lines patch added patch discarded remove patch
@@ -46,1205 +46,1205 @@
 block discarded – undo
46 46
  * @package OCA\ShareByMail
47 47
  */
48 48
 class ShareByMailProvider extends DefaultShareProvider implements IShareProviderWithNotification {
49
-	/**
50
-	 * Return the identifier of this provider.
51
-	 *
52
-	 * @return string Containing only [a-zA-Z0-9]
53
-	 */
54
-	public function identifier(): string {
55
-		return 'ocMailShare';
56
-	}
57
-
58
-	public function __construct(
59
-		private IConfig $config,
60
-		private IDBConnection $dbConnection,
61
-		private ISecureRandom $secureRandom,
62
-		private IUserManager $userManager,
63
-		private IRootFolder $rootFolder,
64
-		private IL10N $l,
65
-		private LoggerInterface $logger,
66
-		private IMailer $mailer,
67
-		private IURLGenerator $urlGenerator,
68
-		private IManager $activityManager,
69
-		private SettingsManager $settingsManager,
70
-		private Defaults $defaults,
71
-		private IHasher $hasher,
72
-		private IEventDispatcher $eventDispatcher,
73
-		private IShareManager $shareManager,
74
-		private IEmailValidator $emailValidator,
75
-	) {
76
-	}
77
-
78
-	/**
79
-	 * Share a path
80
-	 *
81
-	 * @throws ShareNotFound
82
-	 * @throws \Exception
83
-	 */
84
-	public function create(IShare $share): IShare {
85
-		$shareWith = $share->getSharedWith();
86
-		// Check if file is not already shared with the given email,
87
-		// if we have an email at all.
88
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
89
-		if ($shareWith !== '' && !empty($alreadyShared)) {
90
-			$message = 'Sharing %1$s failed, because this item is already shared with the account %2$s';
91
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with the account %2$s', [$share->getNode()->getName(), $shareWith]);
92
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
93
-			throw new \Exception($message_t);
94
-		}
95
-
96
-		// if the admin enforces a password for all mail shares we create a
97
-		// random password and send it to the recipient
98
-		$password = $share->getPassword() ?: '';
99
-		$passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
100
-		if ($passwordEnforced && empty($password)) {
101
-			$password = $this->autoGeneratePassword($share);
102
-		}
103
-
104
-		if (!empty($password)) {
105
-			$share->setPassword($this->hasher->hash($password));
106
-		}
107
-
108
-		$shareId = $this->createMailShare($share);
109
-
110
-		$this->createShareActivity($share);
111
-		$data = $this->getRawShare($shareId);
112
-
113
-		// Temporary set the clear password again to send it by mail
114
-		// This need to be done after the share was created in the database
115
-		// as the password is hashed in between.
116
-		if (!empty($password)) {
117
-			$data['password'] = $password;
118
-		}
119
-
120
-		return $this->createShareObject($data);
121
-	}
122
-
123
-	/**
124
-	 * auto generate password in case of password enforcement on mail shares
125
-	 *
126
-	 * @throws \Exception
127
-	 */
128
-	protected function autoGeneratePassword(IShare $share): string {
129
-		$initiatorUser = $this->userManager->get($share->getSharedBy());
130
-		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
131
-		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
132
-
133
-		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
134
-			throw new \Exception(
135
-				$this->l->t('We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again.')
136
-			);
137
-		}
138
-
139
-		$passwordEvent = new GenerateSecurePasswordEvent(PasswordContext::SHARING);
140
-		$this->eventDispatcher->dispatchTyped($passwordEvent);
141
-
142
-		$password = $passwordEvent->getPassword();
143
-		if ($password === null) {
144
-			$password = $this->secureRandom->generate(8, ISecureRandom::CHAR_HUMAN_READABLE);
145
-		}
146
-
147
-		return $password;
148
-	}
149
-
150
-	/**
151
-	 * create activity if a file/folder was shared by mail
152
-	 */
153
-	protected function createShareActivity(IShare $share, string $type = 'share'): void {
154
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
155
-
156
-		$this->publishActivity(
157
-			$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
158
-			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
159
-			$share->getSharedBy(),
160
-			$share->getNode()->getId(),
161
-			(string)$userFolder->getRelativePath($share->getNode()->getPath())
162
-		);
163
-
164
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
165
-			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
166
-			$fileId = $share->getNode()->getId();
167
-			$nodes = $ownerFolder->getById($fileId);
168
-			$ownerPath = $nodes[0]->getPath();
169
-			$this->publishActivity(
170
-				$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
171
-				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
172
-				$share->getShareOwner(),
173
-				$fileId,
174
-				(string)$ownerFolder->getRelativePath($ownerPath)
175
-			);
176
-		}
177
-	}
178
-
179
-	/**
180
-	 * create activity if a file/folder was shared by mail
181
-	 */
182
-	protected function createPasswordSendActivity(IShare $share, string $sharedWith, bool $sendToSelf): void {
183
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
184
-
185
-		if ($sendToSelf) {
186
-			$this->publishActivity(
187
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
188
-				[$userFolder->getRelativePath($share->getNode()->getPath())],
189
-				$share->getSharedBy(),
190
-				$share->getNode()->getId(),
191
-				(string)$userFolder->getRelativePath($share->getNode()->getPath())
192
-			);
193
-		} else {
194
-			$this->publishActivity(
195
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
196
-				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
197
-				$share->getSharedBy(),
198
-				$share->getNode()->getId(),
199
-				(string)$userFolder->getRelativePath($share->getNode()->getPath())
200
-			);
201
-		}
202
-	}
203
-
204
-
205
-	/**
206
-	 * publish activity if a file/folder was shared by mail
207
-	 */
208
-	protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath): void {
209
-		$event = $this->activityManager->generateEvent();
210
-		$event->setApp('sharebymail')
211
-			->setType('shared')
212
-			->setSubject($subject, $parameters)
213
-			->setAffectedUser($affectedUser)
214
-			->setObject('files', $fileId, $filePath);
215
-		$this->activityManager->publish($event);
216
-	}
217
-
218
-	/**
219
-	 * @throws \Exception
220
-	 */
221
-	protected function createMailShare(IShare $share): string {
222
-		$share->setToken($this->generateToken());
223
-		return $this->addShareToDB(
224
-			$share->getNodeId(),
225
-			$share->getNodeType(),
226
-			$share->getSharedWith(),
227
-			$share->getSharedBy(),
228
-			$share->getShareOwner(),
229
-			$share->getPermissions(),
230
-			$share->getToken(),
231
-			$share->getPassword(),
232
-			$share->getPasswordExpirationTime(),
233
-			$share->getSendPasswordByTalk(),
234
-			$share->getHideDownload(),
235
-			$share->getLabel(),
236
-			$share->getExpirationDate(),
237
-			$share->getNote(),
238
-			$share->getAttributes(),
239
-			$share->getMailSend(),
240
-		);
241
-	}
242
-
243
-	/**
244
-	 * @inheritDoc
245
-	 */
246
-	public function sendMailNotification(IShare $share): bool {
247
-		$shareId = $share->getId();
248
-
249
-		$emails = $this->getSharedWithEmails($share);
250
-		$validEmails = array_filter($emails, function (string $email) {
251
-			return $this->emailValidator->isValid($email);
252
-		});
253
-
254
-		if (count($validEmails) === 0) {
255
-			$this->removeShareFromTable((int)$shareId);
256
-			$e = new HintException('Failed to send share by mail. Could not find a valid email address: ' . join(', ', $emails),
257
-				$this->l->t('Failed to send share by email. Got an invalid email address'));
258
-			$this->logger->error('Failed to send share by mail. Could not find a valid email address ' . join(', ', $emails), [
259
-				'app' => 'sharebymail',
260
-				'exception' => $e,
261
-			]);
262
-		}
263
-
264
-		try {
265
-			$this->sendEmail($share, $validEmails);
266
-
267
-			// If we have a password set, we send it to the recipient
268
-			if ($share->getPassword() !== null) {
269
-				// If share-by-talk password is enabled, we do not send the notification
270
-				// to the recipient. They will have to request it to the owner after opening the link.
271
-				// Secondly, if the password expiration is disabled, we send the notification to the recipient
272
-				// Lastly, if the mail to recipient failed, we send the password to the owner as a fallback.
273
-				// If a password expires, the recipient will still be able to request a new one via talk.
274
-				$passwordExpire = $this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false);
275
-				$passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
276
-				if ($passwordExpire === false || $share->getSendPasswordByTalk()) {
277
-					$send = $this->sendPassword($share, $share->getPassword(), $validEmails);
278
-					if ($passwordEnforced && $send === false) {
279
-						$this->sendPasswordToOwner($share, $share->getPassword());
280
-					}
281
-				}
282
-			}
283
-
284
-			return true;
285
-		} catch (HintException $hintException) {
286
-			$this->logger->error('Failed to send share by mail.', [
287
-				'app' => 'sharebymail',
288
-				'exception' => $hintException,
289
-			]);
290
-			$this->removeShareFromTable((int)$shareId);
291
-			throw $hintException;
292
-		} catch (\Exception $e) {
293
-			$this->logger->error('Failed to send share by mail.', [
294
-				'app' => 'sharebymail',
295
-				'exception' => $e,
296
-			]);
297
-			$this->removeShareFromTable((int)$shareId);
298
-			throw new HintException(
299
-				'Failed to send share by mail',
300
-				$this->l->t('Failed to send share by email'),
301
-				0,
302
-				$e,
303
-			);
304
-		}
305
-		return false;
306
-	}
307
-
308
-	/**
309
-	 * @param IShare $share The share to send the email for
310
-	 * @param array $emails The email addresses to send the email to
311
-	 */
312
-	protected function sendEmail(IShare $share, array $emails): void {
313
-		$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', [
314
-			'token' => $share->getToken()
315
-		]);
316
-
317
-		$expiration = $share->getExpirationDate();
318
-		$filename = $share->getNode()->getName();
319
-		$initiator = $share->getSharedBy();
320
-		$note = $share->getNote();
321
-		$shareWith = $share->getSharedWith();
322
-
323
-		$initiatorUser = $this->userManager->get($initiator);
324
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
325
-		$message = $this->mailer->createMessage();
326
-
327
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
328
-			'filename' => $filename,
329
-			'link' => $link,
330
-			'initiator' => $initiatorDisplayName,
331
-			'expiration' => $expiration,
332
-			'shareWith' => $shareWith,
333
-			'note' => $note
334
-		]);
335
-
336
-		$emailTemplate->setSubject($this->l->t('%1$s shared %2$s with you', [$initiatorDisplayName, $filename]));
337
-		$emailTemplate->addHeader();
338
-		$emailTemplate->addHeading($this->l->t('%1$s shared %2$s with you', [$initiatorDisplayName, $filename]), false);
339
-
340
-		if ($note !== '') {
341
-			$emailTemplate->addBodyListItem(
342
-				htmlspecialchars($note),
343
-				$this->l->t('Note:'),
344
-				$this->getAbsoluteImagePath('caldav/description.png'),
345
-				$note
346
-			);
347
-		}
348
-
349
-		if ($expiration !== null) {
350
-			$dateString = (string)$this->l->l('date', $expiration, ['width' => 'medium']);
351
-			$emailTemplate->addBodyListItem(
352
-				$this->l->t('This share is valid until %s at midnight', [$dateString]),
353
-				$this->l->t('Expiration:'),
354
-				$this->getAbsoluteImagePath('caldav/time.png'),
355
-			);
356
-		}
357
-
358
-		$emailTemplate->addBodyButton(
359
-			$this->l->t('Open %s', [$filename]),
360
-			$link
361
-		);
362
-
363
-		// If multiple recipients are given, we send the mail to all of them
364
-		if (count($emails) > 1) {
365
-			// We do not want to expose the email addresses of the other recipients
366
-			$message->setBcc($emails);
367
-		} else {
368
-			$message->setTo($emails);
369
-		}
370
-
371
-		// The "From" contains the sharers name
372
-		$instanceName = $this->defaults->getName();
373
-		$senderName = $instanceName;
374
-		if ($this->settingsManager->replyToInitiator()) {
375
-			$senderName = $this->l->t(
376
-				'%1$s via %2$s',
377
-				[
378
-					$initiatorDisplayName,
379
-					$instanceName
380
-				]
381
-			);
382
-		}
383
-		$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
384
-
385
-		// The "Reply-To" is set to the sharer if an mail address is configured
386
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
387
-		if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
388
-			$initiatorEmail = $initiatorUser->getEMailAddress();
389
-			if ($initiatorEmail !== null) {
390
-				$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
391
-				$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
392
-			} else {
393
-				$emailTemplate->addFooter();
394
-			}
395
-		} else {
396
-			$emailTemplate->addFooter();
397
-		}
398
-
399
-		$message->useTemplate($emailTemplate);
400
-		$failedRecipients = $this->mailer->send($message);
401
-		if (!empty($failedRecipients)) {
402
-			$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
403
-			return;
404
-		}
405
-	}
406
-
407
-	/**
408
-	 * Send password to recipient of a mail share
409
-	 * Will return false if
410
-	 *  1. the password is empty
411
-	 *  2. the setting to send the password by mail is disabled
412
-	 *  3. the share is set to send the password by talk
413
-	 *
414
-	 * @param IShare $share
415
-	 * @param string $password
416
-	 * @param array $emails
417
-	 * @return bool
418
-	 */
419
-	protected function sendPassword(IShare $share, string $password, array $emails): bool {
420
-		$filename = $share->getNode()->getName();
421
-		$initiator = $share->getSharedBy();
422
-		$shareWith = $share->getSharedWith();
423
-
424
-		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
425
-			return false;
426
-		}
427
-
428
-		$initiatorUser = $this->userManager->get($initiator);
429
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
430
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
431
-
432
-		$plainBodyPart = $this->l->t('%1$s shared %2$s with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
433
-		$htmlBodyPart = $this->l->t('%1$s shared %2$s with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
434
-
435
-		$message = $this->mailer->createMessage();
436
-
437
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
438
-			'filename' => $filename,
439
-			'password' => $password,
440
-			'initiator' => $initiatorDisplayName,
441
-			'initiatorEmail' => $initiatorEmailAddress,
442
-			'shareWith' => $shareWith,
443
-		]);
444
-
445
-		$emailTemplate->setSubject($this->l->t('Password to access %1$s shared to you by %2$s', [$filename, $initiatorDisplayName]));
446
-		$emailTemplate->addHeader();
447
-		$emailTemplate->addHeading($this->l->t('Password to access %s', [$filename]), false);
448
-		$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
449
-		$emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
450
-		$emailTemplate->addBodyText($password);
451
-
452
-		if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
453
-			$expirationTime = new \DateTime();
454
-			$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
455
-			$expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
456
-			$emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
457
-		}
458
-
459
-		// If multiple recipients are given, we send the mail to all of them
460
-		if (count($emails) > 1) {
461
-			// We do not want to expose the email addresses of the other recipients
462
-			$message->setBcc($emails);
463
-		} else {
464
-			$message->setTo($emails);
465
-		}
466
-
467
-		// The "From" contains the sharers name
468
-		$instanceName = $this->defaults->getName();
469
-		$senderName = $instanceName;
470
-		if ($this->settingsManager->replyToInitiator()) {
471
-			$senderName = $this->l->t(
472
-				'%1$s via %2$s',
473
-				[
474
-					$initiatorDisplayName,
475
-					$instanceName
476
-				]
477
-			);
478
-		}
479
-		$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
480
-
481
-		// The "Reply-To" is set to the sharer if an mail address is configured
482
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
483
-		if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
484
-			$initiatorEmail = $initiatorUser->getEMailAddress();
485
-			if ($initiatorEmail !== null) {
486
-				$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
487
-				$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
488
-			} else {
489
-				$emailTemplate->addFooter();
490
-			}
491
-		} else {
492
-			$emailTemplate->addFooter();
493
-		}
494
-
495
-		$message->useTemplate($emailTemplate);
496
-		$failedRecipients = $this->mailer->send($message);
497
-		if (!empty($failedRecipients)) {
498
-			$this->logger->error('Share password mail could not be sent to: ' . implode(', ', $failedRecipients));
499
-			return false;
500
-		}
501
-
502
-		$this->createPasswordSendActivity($share, $shareWith, false);
503
-		return true;
504
-	}
505
-
506
-	protected function sendNote(IShare $share): void {
507
-		$recipient = $share->getSharedWith();
508
-
509
-
510
-		$filename = $share->getNode()->getName();
511
-		$initiator = $share->getSharedBy();
512
-		$note = $share->getNote();
513
-
514
-		$initiatorUser = $this->userManager->get($initiator);
515
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
516
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
517
-
518
-		$plainHeading = $this->l->t('%1$s shared %2$s with you and wants to add:', [$initiatorDisplayName, $filename]);
519
-		$htmlHeading = $this->l->t('%1$s shared %2$s with you and wants to add', [$initiatorDisplayName, $filename]);
520
-
521
-		$message = $this->mailer->createMessage();
522
-
523
-		$emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
524
-
525
-		$emailTemplate->setSubject($this->l->t('%s added a note to a file shared with you', [$initiatorDisplayName]));
526
-		$emailTemplate->addHeader();
527
-		$emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
528
-		$emailTemplate->addBodyText(htmlspecialchars($note), $note);
529
-
530
-		$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
531
-			['token' => $share->getToken()]);
532
-		$emailTemplate->addBodyButton(
533
-			$this->l->t('Open %s', [$filename]),
534
-			$link
535
-		);
536
-
537
-		// The "From" contains the sharers name
538
-		$instanceName = $this->defaults->getName();
539
-		$senderName = $instanceName;
540
-		if ($this->settingsManager->replyToInitiator()) {
541
-			$senderName = $this->l->t(
542
-				'%1$s via %2$s',
543
-				[
544
-					$initiatorDisplayName,
545
-					$instanceName
546
-				]
547
-			);
548
-		}
549
-		$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
550
-		if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
551
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
552
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
553
-		} else {
554
-			$emailTemplate->addFooter();
555
-		}
556
-
557
-		$message->setTo([$recipient]);
558
-		$message->useTemplate($emailTemplate);
559
-		$this->mailer->send($message);
560
-	}
561
-
562
-	/**
563
-	 * send auto generated password to the owner. This happens if the admin enforces
564
-	 * a password for mail shares and forbid to send the password by mail to the recipient
565
-	 *
566
-	 * @throws \Exception
567
-	 */
568
-	protected function sendPasswordToOwner(IShare $share, string $password): bool {
569
-		$filename = $share->getNode()->getName();
570
-		$initiator = $this->userManager->get($share->getSharedBy());
571
-		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
572
-		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
573
-		$shareWith = implode(', ', $this->getSharedWithEmails($share));
574
-
575
-		if ($initiatorEMailAddress === null) {
576
-			throw new \Exception(
577
-				$this->l->t('We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again.')
578
-			);
579
-		}
580
-
581
-		$bodyPart = $this->l->t('You just shared %1$s with %2$s. The share was already sent to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
582
-
583
-		$message = $this->mailer->createMessage();
584
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
585
-			'filename' => $filename,
586
-			'password' => $password,
587
-			'initiator' => $initiatorDisplayName,
588
-			'initiatorEmail' => $initiatorEMailAddress,
589
-			'shareWith' => $shareWith,
590
-		]);
591
-
592
-		$emailTemplate->setSubject($this->l->t('Password to access %1$s shared by you with %2$s', [$filename, $shareWith]));
593
-		$emailTemplate->addHeader();
594
-		$emailTemplate->addHeading($this->l->t('Password to access %s', [$filename]), false);
595
-		$emailTemplate->addBodyText($bodyPart);
596
-		$emailTemplate->addBodyText($this->l->t('This is the password:'));
597
-		$emailTemplate->addBodyText($password);
598
-
599
-		if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
600
-			$expirationTime = new \DateTime();
601
-			$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
602
-			$expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
603
-			$emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
604
-		}
605
-
606
-		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
607
-
608
-		$emailTemplate->addFooter();
609
-
610
-		$instanceName = $this->defaults->getName();
611
-		$senderName = $this->l->t(
612
-			'%1$s via %2$s',
613
-			[
614
-				$initiatorDisplayName,
615
-				$instanceName
616
-			]
617
-		);
618
-		$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
619
-		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
620
-		$message->useTemplate($emailTemplate);
621
-		$this->mailer->send($message);
622
-
623
-		$this->createPasswordSendActivity($share, $shareWith, true);
624
-
625
-		return true;
626
-	}
627
-
628
-	private function getAbsoluteImagePath(string $path):string {
629
-		return $this->urlGenerator->getAbsoluteURL(
630
-			$this->urlGenerator->imagePath('core', $path)
631
-		);
632
-	}
633
-
634
-	/**
635
-	 * generate share token
636
-	 */
637
-	protected function generateToken(int $size = 15): string {
638
-		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
639
-		return $token;
640
-	}
641
-
642
-	public function getChildren(IShare $parent): array {
643
-		$children = [];
644
-
645
-		$qb = $this->dbConnection->getQueryBuilder();
646
-		$qb->select('*')
647
-			->from('share')
648
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
649
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
650
-			->orderBy('id');
651
-
652
-		$cursor = $qb->executeQuery();
653
-		while ($data = $cursor->fetchAssociative()) {
654
-			$children[] = $this->createShareObject($data);
655
-		}
656
-		$cursor->closeCursor();
657
-
658
-		return $children;
659
-	}
660
-
661
-	/**
662
-	 * Add share to the database and return the ID
663
-	 */
664
-	protected function addShareToDB(
665
-		?int $itemSource,
666
-		?string $itemType,
667
-		?string $shareWith,
668
-		?string $sharedBy,
669
-		?string $uidOwner,
670
-		?int $permissions,
671
-		?string $token,
672
-		?string $password,
673
-		?\DateTimeInterface $passwordExpirationTime,
674
-		?bool $sendPasswordByTalk,
675
-		?bool $hideDownload,
676
-		?string $label,
677
-		?\DateTimeInterface $expirationTime,
678
-		?string $note = '',
679
-		?IAttributes $attributes = null,
680
-		?bool $mailSend = true,
681
-	): string {
682
-		$qb = $this->dbConnection->getQueryBuilder();
683
-		$qb->insert('share')
684
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
685
-			->setValue('item_type', $qb->createNamedParameter($itemType))
686
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
687
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
688
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
689
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
690
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
691
-			->setValue('permissions', $qb->createNamedParameter($permissions))
692
-			->setValue('token', $qb->createNamedParameter($token))
693
-			->setValue('password', $qb->createNamedParameter($password))
694
-			->setValue('password_expiration_time', $qb->createNamedParameter($passwordExpirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE))
695
-			->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
696
-			->setValue('stime', $qb->createNamedParameter(time()))
697
-			->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT))
698
-			->setValue('label', $qb->createNamedParameter($label))
699
-			->setValue('note', $qb->createNamedParameter($note))
700
-			->setValue('mail_send', $qb->createNamedParameter((int)$mailSend, IQueryBuilder::PARAM_INT));
701
-
702
-		// set share attributes
703
-		$shareAttributes = $this->formatShareAttributes($attributes);
704
-
705
-		$qb->setValue('attributes', $qb->createNamedParameter($shareAttributes));
706
-		if ($expirationTime !== null) {
707
-			$qb->setValue('expiration', $qb->createNamedParameter($expirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE));
708
-		}
709
-
710
-		$qb->executeStatement();
711
-		return (string)$qb->getLastInsertId();
712
-	}
713
-
714
-	/**
715
-	 * Update a share
716
-	 */
717
-	public function update(IShare $share, ?string $plainTextPassword = null): IShare {
718
-		$originalShare = $this->getShareById($share->getId());
719
-
720
-		// a real password was given
721
-		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
722
-
723
-		if ($validPassword && ($originalShare->getPassword() !== $share->getPassword()
724
-								|| ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
725
-			$emails = $this->getSharedWithEmails($share);
726
-			$validEmails = array_filter($emails, function ($email) {
727
-				return $this->emailValidator->isValid($email);
728
-			});
729
-			$this->sendPassword($share, $plainTextPassword, $validEmails);
730
-		}
731
-
732
-		$shareAttributes = $this->formatShareAttributes($share->getAttributes());
733
-
734
-		/*
49
+    /**
50
+     * Return the identifier of this provider.
51
+     *
52
+     * @return string Containing only [a-zA-Z0-9]
53
+     */
54
+    public function identifier(): string {
55
+        return 'ocMailShare';
56
+    }
57
+
58
+    public function __construct(
59
+        private IConfig $config,
60
+        private IDBConnection $dbConnection,
61
+        private ISecureRandom $secureRandom,
62
+        private IUserManager $userManager,
63
+        private IRootFolder $rootFolder,
64
+        private IL10N $l,
65
+        private LoggerInterface $logger,
66
+        private IMailer $mailer,
67
+        private IURLGenerator $urlGenerator,
68
+        private IManager $activityManager,
69
+        private SettingsManager $settingsManager,
70
+        private Defaults $defaults,
71
+        private IHasher $hasher,
72
+        private IEventDispatcher $eventDispatcher,
73
+        private IShareManager $shareManager,
74
+        private IEmailValidator $emailValidator,
75
+    ) {
76
+    }
77
+
78
+    /**
79
+     * Share a path
80
+     *
81
+     * @throws ShareNotFound
82
+     * @throws \Exception
83
+     */
84
+    public function create(IShare $share): IShare {
85
+        $shareWith = $share->getSharedWith();
86
+        // Check if file is not already shared with the given email,
87
+        // if we have an email at all.
88
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
89
+        if ($shareWith !== '' && !empty($alreadyShared)) {
90
+            $message = 'Sharing %1$s failed, because this item is already shared with the account %2$s';
91
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with the account %2$s', [$share->getNode()->getName(), $shareWith]);
92
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
93
+            throw new \Exception($message_t);
94
+        }
95
+
96
+        // if the admin enforces a password for all mail shares we create a
97
+        // random password and send it to the recipient
98
+        $password = $share->getPassword() ?: '';
99
+        $passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
100
+        if ($passwordEnforced && empty($password)) {
101
+            $password = $this->autoGeneratePassword($share);
102
+        }
103
+
104
+        if (!empty($password)) {
105
+            $share->setPassword($this->hasher->hash($password));
106
+        }
107
+
108
+        $shareId = $this->createMailShare($share);
109
+
110
+        $this->createShareActivity($share);
111
+        $data = $this->getRawShare($shareId);
112
+
113
+        // Temporary set the clear password again to send it by mail
114
+        // This need to be done after the share was created in the database
115
+        // as the password is hashed in between.
116
+        if (!empty($password)) {
117
+            $data['password'] = $password;
118
+        }
119
+
120
+        return $this->createShareObject($data);
121
+    }
122
+
123
+    /**
124
+     * auto generate password in case of password enforcement on mail shares
125
+     *
126
+     * @throws \Exception
127
+     */
128
+    protected function autoGeneratePassword(IShare $share): string {
129
+        $initiatorUser = $this->userManager->get($share->getSharedBy());
130
+        $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
131
+        $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
132
+
133
+        if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
134
+            throw new \Exception(
135
+                $this->l->t('We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again.')
136
+            );
137
+        }
138
+
139
+        $passwordEvent = new GenerateSecurePasswordEvent(PasswordContext::SHARING);
140
+        $this->eventDispatcher->dispatchTyped($passwordEvent);
141
+
142
+        $password = $passwordEvent->getPassword();
143
+        if ($password === null) {
144
+            $password = $this->secureRandom->generate(8, ISecureRandom::CHAR_HUMAN_READABLE);
145
+        }
146
+
147
+        return $password;
148
+    }
149
+
150
+    /**
151
+     * create activity if a file/folder was shared by mail
152
+     */
153
+    protected function createShareActivity(IShare $share, string $type = 'share'): void {
154
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
155
+
156
+        $this->publishActivity(
157
+            $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
158
+            [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
159
+            $share->getSharedBy(),
160
+            $share->getNode()->getId(),
161
+            (string)$userFolder->getRelativePath($share->getNode()->getPath())
162
+        );
163
+
164
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
165
+            $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
166
+            $fileId = $share->getNode()->getId();
167
+            $nodes = $ownerFolder->getById($fileId);
168
+            $ownerPath = $nodes[0]->getPath();
169
+            $this->publishActivity(
170
+                $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
171
+                [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
172
+                $share->getShareOwner(),
173
+                $fileId,
174
+                (string)$ownerFolder->getRelativePath($ownerPath)
175
+            );
176
+        }
177
+    }
178
+
179
+    /**
180
+     * create activity if a file/folder was shared by mail
181
+     */
182
+    protected function createPasswordSendActivity(IShare $share, string $sharedWith, bool $sendToSelf): void {
183
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
184
+
185
+        if ($sendToSelf) {
186
+            $this->publishActivity(
187
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
188
+                [$userFolder->getRelativePath($share->getNode()->getPath())],
189
+                $share->getSharedBy(),
190
+                $share->getNode()->getId(),
191
+                (string)$userFolder->getRelativePath($share->getNode()->getPath())
192
+            );
193
+        } else {
194
+            $this->publishActivity(
195
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
196
+                [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
197
+                $share->getSharedBy(),
198
+                $share->getNode()->getId(),
199
+                (string)$userFolder->getRelativePath($share->getNode()->getPath())
200
+            );
201
+        }
202
+    }
203
+
204
+
205
+    /**
206
+     * publish activity if a file/folder was shared by mail
207
+     */
208
+    protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath): void {
209
+        $event = $this->activityManager->generateEvent();
210
+        $event->setApp('sharebymail')
211
+            ->setType('shared')
212
+            ->setSubject($subject, $parameters)
213
+            ->setAffectedUser($affectedUser)
214
+            ->setObject('files', $fileId, $filePath);
215
+        $this->activityManager->publish($event);
216
+    }
217
+
218
+    /**
219
+     * @throws \Exception
220
+     */
221
+    protected function createMailShare(IShare $share): string {
222
+        $share->setToken($this->generateToken());
223
+        return $this->addShareToDB(
224
+            $share->getNodeId(),
225
+            $share->getNodeType(),
226
+            $share->getSharedWith(),
227
+            $share->getSharedBy(),
228
+            $share->getShareOwner(),
229
+            $share->getPermissions(),
230
+            $share->getToken(),
231
+            $share->getPassword(),
232
+            $share->getPasswordExpirationTime(),
233
+            $share->getSendPasswordByTalk(),
234
+            $share->getHideDownload(),
235
+            $share->getLabel(),
236
+            $share->getExpirationDate(),
237
+            $share->getNote(),
238
+            $share->getAttributes(),
239
+            $share->getMailSend(),
240
+        );
241
+    }
242
+
243
+    /**
244
+     * @inheritDoc
245
+     */
246
+    public function sendMailNotification(IShare $share): bool {
247
+        $shareId = $share->getId();
248
+
249
+        $emails = $this->getSharedWithEmails($share);
250
+        $validEmails = array_filter($emails, function (string $email) {
251
+            return $this->emailValidator->isValid($email);
252
+        });
253
+
254
+        if (count($validEmails) === 0) {
255
+            $this->removeShareFromTable((int)$shareId);
256
+            $e = new HintException('Failed to send share by mail. Could not find a valid email address: ' . join(', ', $emails),
257
+                $this->l->t('Failed to send share by email. Got an invalid email address'));
258
+            $this->logger->error('Failed to send share by mail. Could not find a valid email address ' . join(', ', $emails), [
259
+                'app' => 'sharebymail',
260
+                'exception' => $e,
261
+            ]);
262
+        }
263
+
264
+        try {
265
+            $this->sendEmail($share, $validEmails);
266
+
267
+            // If we have a password set, we send it to the recipient
268
+            if ($share->getPassword() !== null) {
269
+                // If share-by-talk password is enabled, we do not send the notification
270
+                // to the recipient. They will have to request it to the owner after opening the link.
271
+                // Secondly, if the password expiration is disabled, we send the notification to the recipient
272
+                // Lastly, if the mail to recipient failed, we send the password to the owner as a fallback.
273
+                // If a password expires, the recipient will still be able to request a new one via talk.
274
+                $passwordExpire = $this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false);
275
+                $passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword();
276
+                if ($passwordExpire === false || $share->getSendPasswordByTalk()) {
277
+                    $send = $this->sendPassword($share, $share->getPassword(), $validEmails);
278
+                    if ($passwordEnforced && $send === false) {
279
+                        $this->sendPasswordToOwner($share, $share->getPassword());
280
+                    }
281
+                }
282
+            }
283
+
284
+            return true;
285
+        } catch (HintException $hintException) {
286
+            $this->logger->error('Failed to send share by mail.', [
287
+                'app' => 'sharebymail',
288
+                'exception' => $hintException,
289
+            ]);
290
+            $this->removeShareFromTable((int)$shareId);
291
+            throw $hintException;
292
+        } catch (\Exception $e) {
293
+            $this->logger->error('Failed to send share by mail.', [
294
+                'app' => 'sharebymail',
295
+                'exception' => $e,
296
+            ]);
297
+            $this->removeShareFromTable((int)$shareId);
298
+            throw new HintException(
299
+                'Failed to send share by mail',
300
+                $this->l->t('Failed to send share by email'),
301
+                0,
302
+                $e,
303
+            );
304
+        }
305
+        return false;
306
+    }
307
+
308
+    /**
309
+     * @param IShare $share The share to send the email for
310
+     * @param array $emails The email addresses to send the email to
311
+     */
312
+    protected function sendEmail(IShare $share, array $emails): void {
313
+        $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', [
314
+            'token' => $share->getToken()
315
+        ]);
316
+
317
+        $expiration = $share->getExpirationDate();
318
+        $filename = $share->getNode()->getName();
319
+        $initiator = $share->getSharedBy();
320
+        $note = $share->getNote();
321
+        $shareWith = $share->getSharedWith();
322
+
323
+        $initiatorUser = $this->userManager->get($initiator);
324
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
325
+        $message = $this->mailer->createMessage();
326
+
327
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
328
+            'filename' => $filename,
329
+            'link' => $link,
330
+            'initiator' => $initiatorDisplayName,
331
+            'expiration' => $expiration,
332
+            'shareWith' => $shareWith,
333
+            'note' => $note
334
+        ]);
335
+
336
+        $emailTemplate->setSubject($this->l->t('%1$s shared %2$s with you', [$initiatorDisplayName, $filename]));
337
+        $emailTemplate->addHeader();
338
+        $emailTemplate->addHeading($this->l->t('%1$s shared %2$s with you', [$initiatorDisplayName, $filename]), false);
339
+
340
+        if ($note !== '') {
341
+            $emailTemplate->addBodyListItem(
342
+                htmlspecialchars($note),
343
+                $this->l->t('Note:'),
344
+                $this->getAbsoluteImagePath('caldav/description.png'),
345
+                $note
346
+            );
347
+        }
348
+
349
+        if ($expiration !== null) {
350
+            $dateString = (string)$this->l->l('date', $expiration, ['width' => 'medium']);
351
+            $emailTemplate->addBodyListItem(
352
+                $this->l->t('This share is valid until %s at midnight', [$dateString]),
353
+                $this->l->t('Expiration:'),
354
+                $this->getAbsoluteImagePath('caldav/time.png'),
355
+            );
356
+        }
357
+
358
+        $emailTemplate->addBodyButton(
359
+            $this->l->t('Open %s', [$filename]),
360
+            $link
361
+        );
362
+
363
+        // If multiple recipients are given, we send the mail to all of them
364
+        if (count($emails) > 1) {
365
+            // We do not want to expose the email addresses of the other recipients
366
+            $message->setBcc($emails);
367
+        } else {
368
+            $message->setTo($emails);
369
+        }
370
+
371
+        // The "From" contains the sharers name
372
+        $instanceName = $this->defaults->getName();
373
+        $senderName = $instanceName;
374
+        if ($this->settingsManager->replyToInitiator()) {
375
+            $senderName = $this->l->t(
376
+                '%1$s via %2$s',
377
+                [
378
+                    $initiatorDisplayName,
379
+                    $instanceName
380
+                ]
381
+            );
382
+        }
383
+        $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
384
+
385
+        // The "Reply-To" is set to the sharer if an mail address is configured
386
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
387
+        if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
388
+            $initiatorEmail = $initiatorUser->getEMailAddress();
389
+            if ($initiatorEmail !== null) {
390
+                $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
391
+                $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
392
+            } else {
393
+                $emailTemplate->addFooter();
394
+            }
395
+        } else {
396
+            $emailTemplate->addFooter();
397
+        }
398
+
399
+        $message->useTemplate($emailTemplate);
400
+        $failedRecipients = $this->mailer->send($message);
401
+        if (!empty($failedRecipients)) {
402
+            $this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
403
+            return;
404
+        }
405
+    }
406
+
407
+    /**
408
+     * Send password to recipient of a mail share
409
+     * Will return false if
410
+     *  1. the password is empty
411
+     *  2. the setting to send the password by mail is disabled
412
+     *  3. the share is set to send the password by talk
413
+     *
414
+     * @param IShare $share
415
+     * @param string $password
416
+     * @param array $emails
417
+     * @return bool
418
+     */
419
+    protected function sendPassword(IShare $share, string $password, array $emails): bool {
420
+        $filename = $share->getNode()->getName();
421
+        $initiator = $share->getSharedBy();
422
+        $shareWith = $share->getSharedWith();
423
+
424
+        if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
425
+            return false;
426
+        }
427
+
428
+        $initiatorUser = $this->userManager->get($initiator);
429
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
430
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
431
+
432
+        $plainBodyPart = $this->l->t('%1$s shared %2$s with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
433
+        $htmlBodyPart = $this->l->t('%1$s shared %2$s with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
434
+
435
+        $message = $this->mailer->createMessage();
436
+
437
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
438
+            'filename' => $filename,
439
+            'password' => $password,
440
+            'initiator' => $initiatorDisplayName,
441
+            'initiatorEmail' => $initiatorEmailAddress,
442
+            'shareWith' => $shareWith,
443
+        ]);
444
+
445
+        $emailTemplate->setSubject($this->l->t('Password to access %1$s shared to you by %2$s', [$filename, $initiatorDisplayName]));
446
+        $emailTemplate->addHeader();
447
+        $emailTemplate->addHeading($this->l->t('Password to access %s', [$filename]), false);
448
+        $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
449
+        $emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
450
+        $emailTemplate->addBodyText($password);
451
+
452
+        if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
453
+            $expirationTime = new \DateTime();
454
+            $expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
455
+            $expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
456
+            $emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
457
+        }
458
+
459
+        // If multiple recipients are given, we send the mail to all of them
460
+        if (count($emails) > 1) {
461
+            // We do not want to expose the email addresses of the other recipients
462
+            $message->setBcc($emails);
463
+        } else {
464
+            $message->setTo($emails);
465
+        }
466
+
467
+        // The "From" contains the sharers name
468
+        $instanceName = $this->defaults->getName();
469
+        $senderName = $instanceName;
470
+        if ($this->settingsManager->replyToInitiator()) {
471
+            $senderName = $this->l->t(
472
+                '%1$s via %2$s',
473
+                [
474
+                    $initiatorDisplayName,
475
+                    $instanceName
476
+                ]
477
+            );
478
+        }
479
+        $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
480
+
481
+        // The "Reply-To" is set to the sharer if an mail address is configured
482
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
483
+        if ($initiatorUser && $this->settingsManager->replyToInitiator()) {
484
+            $initiatorEmail = $initiatorUser->getEMailAddress();
485
+            if ($initiatorEmail !== null) {
486
+                $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
487
+                $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
488
+            } else {
489
+                $emailTemplate->addFooter();
490
+            }
491
+        } else {
492
+            $emailTemplate->addFooter();
493
+        }
494
+
495
+        $message->useTemplate($emailTemplate);
496
+        $failedRecipients = $this->mailer->send($message);
497
+        if (!empty($failedRecipients)) {
498
+            $this->logger->error('Share password mail could not be sent to: ' . implode(', ', $failedRecipients));
499
+            return false;
500
+        }
501
+
502
+        $this->createPasswordSendActivity($share, $shareWith, false);
503
+        return true;
504
+    }
505
+
506
+    protected function sendNote(IShare $share): void {
507
+        $recipient = $share->getSharedWith();
508
+
509
+
510
+        $filename = $share->getNode()->getName();
511
+        $initiator = $share->getSharedBy();
512
+        $note = $share->getNote();
513
+
514
+        $initiatorUser = $this->userManager->get($initiator);
515
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
516
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
517
+
518
+        $plainHeading = $this->l->t('%1$s shared %2$s with you and wants to add:', [$initiatorDisplayName, $filename]);
519
+        $htmlHeading = $this->l->t('%1$s shared %2$s with you and wants to add', [$initiatorDisplayName, $filename]);
520
+
521
+        $message = $this->mailer->createMessage();
522
+
523
+        $emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
524
+
525
+        $emailTemplate->setSubject($this->l->t('%s added a note to a file shared with you', [$initiatorDisplayName]));
526
+        $emailTemplate->addHeader();
527
+        $emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
528
+        $emailTemplate->addBodyText(htmlspecialchars($note), $note);
529
+
530
+        $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
531
+            ['token' => $share->getToken()]);
532
+        $emailTemplate->addBodyButton(
533
+            $this->l->t('Open %s', [$filename]),
534
+            $link
535
+        );
536
+
537
+        // The "From" contains the sharers name
538
+        $instanceName = $this->defaults->getName();
539
+        $senderName = $instanceName;
540
+        if ($this->settingsManager->replyToInitiator()) {
541
+            $senderName = $this->l->t(
542
+                '%1$s via %2$s',
543
+                [
544
+                    $initiatorDisplayName,
545
+                    $instanceName
546
+                ]
547
+            );
548
+        }
549
+        $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
550
+        if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
551
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
552
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
553
+        } else {
554
+            $emailTemplate->addFooter();
555
+        }
556
+
557
+        $message->setTo([$recipient]);
558
+        $message->useTemplate($emailTemplate);
559
+        $this->mailer->send($message);
560
+    }
561
+
562
+    /**
563
+     * send auto generated password to the owner. This happens if the admin enforces
564
+     * a password for mail shares and forbid to send the password by mail to the recipient
565
+     *
566
+     * @throws \Exception
567
+     */
568
+    protected function sendPasswordToOwner(IShare $share, string $password): bool {
569
+        $filename = $share->getNode()->getName();
570
+        $initiator = $this->userManager->get($share->getSharedBy());
571
+        $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
572
+        $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
573
+        $shareWith = implode(', ', $this->getSharedWithEmails($share));
574
+
575
+        if ($initiatorEMailAddress === null) {
576
+            throw new \Exception(
577
+                $this->l->t('We cannot send you the auto-generated password. Please set a valid email address in your personal settings and try again.')
578
+            );
579
+        }
580
+
581
+        $bodyPart = $this->l->t('You just shared %1$s with %2$s. The share was already sent to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
582
+
583
+        $message = $this->mailer->createMessage();
584
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
585
+            'filename' => $filename,
586
+            'password' => $password,
587
+            'initiator' => $initiatorDisplayName,
588
+            'initiatorEmail' => $initiatorEMailAddress,
589
+            'shareWith' => $shareWith,
590
+        ]);
591
+
592
+        $emailTemplate->setSubject($this->l->t('Password to access %1$s shared by you with %2$s', [$filename, $shareWith]));
593
+        $emailTemplate->addHeader();
594
+        $emailTemplate->addHeading($this->l->t('Password to access %s', [$filename]), false);
595
+        $emailTemplate->addBodyText($bodyPart);
596
+        $emailTemplate->addBodyText($this->l->t('This is the password:'));
597
+        $emailTemplate->addBodyText($password);
598
+
599
+        if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
600
+            $expirationTime = new \DateTime();
601
+            $expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
602
+            $expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
603
+            $emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
604
+        }
605
+
606
+        $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
607
+
608
+        $emailTemplate->addFooter();
609
+
610
+        $instanceName = $this->defaults->getName();
611
+        $senderName = $this->l->t(
612
+            '%1$s via %2$s',
613
+            [
614
+                $initiatorDisplayName,
615
+                $instanceName
616
+            ]
617
+        );
618
+        $message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
619
+        $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
620
+        $message->useTemplate($emailTemplate);
621
+        $this->mailer->send($message);
622
+
623
+        $this->createPasswordSendActivity($share, $shareWith, true);
624
+
625
+        return true;
626
+    }
627
+
628
+    private function getAbsoluteImagePath(string $path):string {
629
+        return $this->urlGenerator->getAbsoluteURL(
630
+            $this->urlGenerator->imagePath('core', $path)
631
+        );
632
+    }
633
+
634
+    /**
635
+     * generate share token
636
+     */
637
+    protected function generateToken(int $size = 15): string {
638
+        $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
639
+        return $token;
640
+    }
641
+
642
+    public function getChildren(IShare $parent): array {
643
+        $children = [];
644
+
645
+        $qb = $this->dbConnection->getQueryBuilder();
646
+        $qb->select('*')
647
+            ->from('share')
648
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
649
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
650
+            ->orderBy('id');
651
+
652
+        $cursor = $qb->executeQuery();
653
+        while ($data = $cursor->fetchAssociative()) {
654
+            $children[] = $this->createShareObject($data);
655
+        }
656
+        $cursor->closeCursor();
657
+
658
+        return $children;
659
+    }
660
+
661
+    /**
662
+     * Add share to the database and return the ID
663
+     */
664
+    protected function addShareToDB(
665
+        ?int $itemSource,
666
+        ?string $itemType,
667
+        ?string $shareWith,
668
+        ?string $sharedBy,
669
+        ?string $uidOwner,
670
+        ?int $permissions,
671
+        ?string $token,
672
+        ?string $password,
673
+        ?\DateTimeInterface $passwordExpirationTime,
674
+        ?bool $sendPasswordByTalk,
675
+        ?bool $hideDownload,
676
+        ?string $label,
677
+        ?\DateTimeInterface $expirationTime,
678
+        ?string $note = '',
679
+        ?IAttributes $attributes = null,
680
+        ?bool $mailSend = true,
681
+    ): string {
682
+        $qb = $this->dbConnection->getQueryBuilder();
683
+        $qb->insert('share')
684
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
685
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
686
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
687
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
688
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
689
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
690
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
691
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
692
+            ->setValue('token', $qb->createNamedParameter($token))
693
+            ->setValue('password', $qb->createNamedParameter($password))
694
+            ->setValue('password_expiration_time', $qb->createNamedParameter($passwordExpirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE))
695
+            ->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
696
+            ->setValue('stime', $qb->createNamedParameter(time()))
697
+            ->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT))
698
+            ->setValue('label', $qb->createNamedParameter($label))
699
+            ->setValue('note', $qb->createNamedParameter($note))
700
+            ->setValue('mail_send', $qb->createNamedParameter((int)$mailSend, IQueryBuilder::PARAM_INT));
701
+
702
+        // set share attributes
703
+        $shareAttributes = $this->formatShareAttributes($attributes);
704
+
705
+        $qb->setValue('attributes', $qb->createNamedParameter($shareAttributes));
706
+        if ($expirationTime !== null) {
707
+            $qb->setValue('expiration', $qb->createNamedParameter($expirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE));
708
+        }
709
+
710
+        $qb->executeStatement();
711
+        return (string)$qb->getLastInsertId();
712
+    }
713
+
714
+    /**
715
+     * Update a share
716
+     */
717
+    public function update(IShare $share, ?string $plainTextPassword = null): IShare {
718
+        $originalShare = $this->getShareById($share->getId());
719
+
720
+        // a real password was given
721
+        $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
722
+
723
+        if ($validPassword && ($originalShare->getPassword() !== $share->getPassword()
724
+                                || ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
725
+            $emails = $this->getSharedWithEmails($share);
726
+            $validEmails = array_filter($emails, function ($email) {
727
+                return $this->emailValidator->isValid($email);
728
+            });
729
+            $this->sendPassword($share, $plainTextPassword, $validEmails);
730
+        }
731
+
732
+        $shareAttributes = $this->formatShareAttributes($share->getAttributes());
733
+
734
+        /*
735 735
 		 * We allow updating mail shares
736 736
 		 */
737
-		$qb = $this->dbConnection->getQueryBuilder();
738
-		$qb->update('share')
739
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
740
-			->set('item_source', $qb->createNamedParameter($share->getNodeId()))
741
-			->set('file_source', $qb->createNamedParameter($share->getNodeId()))
742
-			->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
743
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
744
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
745
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
746
-			->set('password', $qb->createNamedParameter($share->getPassword()))
747
-			->set('password_expiration_time', $qb->createNamedParameter($share->getPasswordExpirationTime(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
748
-			->set('label', $qb->createNamedParameter($share->getLabel()))
749
-			->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
750
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
751
-			->set('note', $qb->createNamedParameter($share->getNote()))
752
-			->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
753
-			->set('attributes', $qb->createNamedParameter($shareAttributes))
754
-			->set('mail_send', $qb->createNamedParameter((int)$share->getMailSend(), IQueryBuilder::PARAM_INT))
755
-			->set('reminder_sent', $qb->createNamedParameter($share->getReminderSent(), IQueryBuilder::PARAM_BOOL))
756
-			->executeStatement();
757
-
758
-		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
759
-			$this->sendNote($share);
760
-		}
761
-
762
-		return $share;
763
-	}
764
-
765
-	/**
766
-	 * @inheritdoc
767
-	 */
768
-	public function move(IShare $share, $recipient): IShare {
769
-		/**
770
-		 * nothing to do here, mail shares are only outgoing shares
771
-		 */
772
-		return $share;
773
-	}
774
-
775
-	/**
776
-	 * Delete a share (owner unShares the file)
777
-	 *
778
-	 * @param IShare $share
779
-	 */
780
-	public function delete(IShare $share): void {
781
-		try {
782
-			$this->createShareActivity($share, 'unshare');
783
-		} catch (\Exception $e) {
784
-		}
785
-
786
-		$this->removeShareFromTable((int)$share->getId());
787
-	}
788
-
789
-	/**
790
-	 * @inheritdoc
791
-	 */
792
-	public function deleteFromSelf(IShare $share, $recipient): void {
793
-		// nothing to do here, mail shares are only outgoing shares
794
-	}
795
-
796
-	public function restore(IShare $share, string $recipient): IShare {
797
-		throw new GenericShareException('not implemented');
798
-	}
799
-
800
-	/**
801
-	 * @inheritdoc
802
-	 */
803
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset): array {
804
-		$qb = $this->dbConnection->getQueryBuilder();
805
-		$qb->select('*')
806
-			->from('share');
807
-
808
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
809
-
810
-		/**
811
-		 * Reshares for this user are shares where they are the owner.
812
-		 */
813
-		if ($reshares === false) {
814
-			//Special case for old shares created via the web UI
815
-			$or1 = $qb->expr()->andX(
816
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
817
-				$qb->expr()->isNull('uid_initiator')
818
-			);
819
-
820
-			$qb->andWhere(
821
-				$qb->expr()->orX(
822
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
823
-					$or1
824
-				)
825
-			);
826
-		} elseif ($node === null) {
827
-			$qb->andWhere(
828
-				$qb->expr()->orX(
829
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
830
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
831
-				)
832
-			);
833
-		}
834
-
835
-		if ($node !== null) {
836
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
837
-		}
838
-
839
-		if ($limit !== -1) {
840
-			$qb->setMaxResults($limit);
841
-		}
842
-
843
-		$qb->setFirstResult($offset);
844
-		$qb->orderBy('id');
845
-
846
-		$cursor = $qb->executeQuery();
847
-		$shares = [];
848
-		while ($data = $cursor->fetchAssociative()) {
849
-			$shares[] = $this->createShareObject($data);
850
-		}
851
-		$cursor->closeCursor();
852
-
853
-		return $shares;
854
-	}
855
-
856
-	/**
857
-	 * @inheritdoc
858
-	 */
859
-	public function getShareById($id, $recipientId = null): IShare {
860
-		$qb = $this->dbConnection->getQueryBuilder();
861
-
862
-		$qb->select('*')
863
-			->from('share')
864
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
865
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
866
-
867
-		$cursor = $qb->executeQuery();
868
-		$data = $cursor->fetchAssociative();
869
-		$cursor->closeCursor();
870
-
871
-		if ($data === false) {
872
-			throw new ShareNotFound();
873
-		}
874
-
875
-		$data['id'] = (string)$data['id'];
876
-
877
-		try {
878
-			$share = $this->createShareObject($data);
879
-		} catch (InvalidShare $e) {
880
-			throw new ShareNotFound();
881
-		}
882
-
883
-		return $share;
884
-	}
885
-
886
-	/**
887
-	 * Get shares for a given path
888
-	 *
889
-	 * @return IShare[]
890
-	 */
891
-	public function getSharesByPath(Node $path): array {
892
-		$qb = $this->dbConnection->getQueryBuilder();
893
-
894
-		$cursor = $qb->select('*')
895
-			->from('share')
896
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
897
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
898
-			->executeQuery();
899
-
900
-		$shares = [];
901
-		while ($data = $cursor->fetchAssociative()) {
902
-			$data['id'] = (string)$data['id'];
903
-			$shares[] = $this->createShareObject($data);
904
-		}
905
-		$cursor->closeCursor();
906
-
907
-		return $shares;
908
-	}
909
-
910
-	/**
911
-	 * @inheritdoc
912
-	 */
913
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset): array {
914
-		/** @var IShare[] $shares */
915
-		$shares = [];
916
-
917
-		//Get shares directly with this user
918
-		$qb = $this->dbConnection->getQueryBuilder();
919
-		$qb->select('*')
920
-			->from('share');
921
-
922
-		// Order by id
923
-		$qb->orderBy('id');
924
-
925
-		// Set limit and offset
926
-		if ($limit !== -1) {
927
-			$qb->setMaxResults($limit);
928
-		}
929
-		$qb->setFirstResult($offset);
930
-
931
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
932
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
933
-
934
-		// Filter by node if provided
935
-		if ($node !== null) {
936
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
937
-		}
938
-
939
-		$cursor = $qb->executeQuery();
940
-
941
-		while ($data = $cursor->fetchAssociative()) {
942
-			$shares[] = $this->createShareObject($data);
943
-		}
944
-		$cursor->closeCursor();
945
-
946
-
947
-		return $shares;
948
-	}
949
-
950
-	/**
951
-	 * Get a share by token
952
-	 *
953
-	 * @throws ShareNotFound
954
-	 */
955
-	public function getShareByToken($token): IShare {
956
-		$qb = $this->dbConnection->getQueryBuilder();
957
-
958
-		$cursor = $qb->select('*')
959
-			->from('share')
960
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
961
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
962
-			->executeQuery();
963
-
964
-		$data = $cursor->fetchAssociative();
965
-
966
-		if ($data === false) {
967
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
968
-		}
969
-
970
-		$data['id'] = (string)$data['id'];
971
-
972
-		try {
973
-			$share = $this->createShareObject($data);
974
-		} catch (InvalidShare $e) {
975
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
976
-		}
977
-
978
-		return $share;
979
-	}
980
-
981
-	/**
982
-	 * remove share from table
983
-	 */
984
-	protected function removeShareFromTable(int $shareId): void {
985
-		$qb = $this->dbConnection->getQueryBuilder();
986
-		$qb->delete('share')
987
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
988
-		$qb->executeStatement();
989
-	}
990
-
991
-	/**
992
-	 * Create a share object from a database row
993
-	 *
994
-	 * @throws InvalidShare
995
-	 * @throws ShareNotFound
996
-	 */
997
-	protected function createShareObject(array $data): IShare {
998
-		$share = new Share($this->rootFolder, $this->userManager);
999
-		$share->setId($data['id'])
1000
-			->setShareType((int)$data['share_type'])
1001
-			->setPermissions((int)$data['permissions'])
1002
-			->setTarget($data['file_target'])
1003
-			->setMailSend((bool)$data['mail_send'])
1004
-			->setNote($data['note'])
1005
-			->setToken($data['token']);
1006
-
1007
-		$shareTime = new \DateTime();
1008
-		$shareTime->setTimestamp((int)$data['stime']);
1009
-		$share->setShareTime($shareTime);
1010
-		$share->setSharedWith($data['share_with'] ?? '');
1011
-		$share->setPassword($data['password']);
1012
-		$passwordExpirationTime = \DateTime::createFromFormat('Y-m-d H:i:s', $data['password_expiration_time'] ?? '');
1013
-		$share->setPasswordExpirationTime($passwordExpirationTime !== false ? $passwordExpirationTime : null);
1014
-		$share->setLabel($data['label'] ?? '');
1015
-		$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1016
-		$share->setHideDownload((bool)$data['hide_download']);
1017
-		$share->setReminderSent((bool)$data['reminder_sent']);
1018
-
1019
-		if ($data['uid_initiator'] !== null) {
1020
-			$share->setShareOwner($data['uid_owner']);
1021
-			$share->setSharedBy($data['uid_initiator']);
1022
-		} else {
1023
-			//OLD SHARE
1024
-			$share->setSharedBy($data['uid_owner']);
1025
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
1026
-
1027
-			$owner = $path->getOwner();
1028
-			$share->setShareOwner($owner->getUID());
1029
-		}
1030
-
1031
-		if ($data['expiration'] !== null) {
1032
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1033
-			if ($expiration !== false) {
1034
-				$share->setExpirationDate($expiration);
1035
-			}
1036
-		}
1037
-
1038
-		$share = $this->updateShareAttributes($share, $data['attributes']);
1039
-
1040
-		$share->setNodeId((int)$data['file_source']);
1041
-		$share->setNodeType($data['item_type']);
1042
-
1043
-		$share->setProviderId($this->identifier());
1044
-
1045
-		return $share;
1046
-	}
1047
-
1048
-	/**
1049
-	 * Get the node with file $id for $user
1050
-	 *
1051
-	 * @throws InvalidShare
1052
-	 */
1053
-	private function getNode(string $userId, int $id): Node {
1054
-		try {
1055
-			$userFolder = $this->rootFolder->getUserFolder($userId);
1056
-		} catch (NoUserException $e) {
1057
-			throw new InvalidShare();
1058
-		}
1059
-
1060
-		$nodes = $userFolder->getById($id);
1061
-
1062
-		if (empty($nodes)) {
1063
-			throw new InvalidShare();
1064
-		}
1065
-
1066
-		return $nodes[0];
1067
-	}
1068
-
1069
-	/**
1070
-	 * A user is deleted from the system
1071
-	 * So clean up the relevant shares.
1072
-	 */
1073
-	public function userDeleted($uid, $shareType): void {
1074
-		$qb = $this->dbConnection->getQueryBuilder();
1075
-
1076
-		$qb->delete('share')
1077
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1078
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1079
-			->executeStatement();
1080
-	}
1081
-
1082
-	/**
1083
-	 * This provider does not support group shares
1084
-	 */
1085
-	public function groupDeleted($gid): void {
1086
-	}
1087
-
1088
-	/**
1089
-	 * This provider does not support group shares
1090
-	 */
1091
-	public function userDeletedFromGroup($uid, $gid): void {
1092
-	}
1093
-
1094
-	/**
1095
-	 * get database row of a give share
1096
-	 *
1097
-	 * @throws ShareNotFound
1098
-	 */
1099
-	protected function getRawShare(string $id): array {
1100
-		// Now fetch the inserted share and create a complete share object
1101
-		$qb = $this->dbConnection->getQueryBuilder();
1102
-		$qb->select('*')
1103
-			->from('share')
1104
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1105
-
1106
-		$cursor = $qb->executeQuery();
1107
-		$data = $cursor->fetchAssociative();
1108
-		$cursor->closeCursor();
1109
-
1110
-		if ($data === false) {
1111
-			throw new ShareNotFound;
1112
-		}
1113
-
1114
-		return $data;
1115
-	}
1116
-
1117
-	public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true): array {
1118
-		return $this->getSharesInFolderInternal($userId, $node, $reshares);
1119
-	}
1120
-
1121
-	public function getAllSharesInFolder(Folder $node): array {
1122
-		return $this->getSharesInFolderInternal(null, $node, null);
1123
-	}
1124
-
1125
-	/**
1126
-	 * @return array<int, list<IShare>>
1127
-	 */
1128
-	private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
1129
-		$qb = $this->dbConnection->getQueryBuilder();
1130
-		$qb->select('*')
1131
-			->from('share', 's')
1132
-			->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
1133
-			->andWhere(
1134
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1135
-			);
1136
-
1137
-		if ($userId !== null) {
1138
-			/**
1139
-			 * Reshares for this user are shares where they are the owner.
1140
-			 */
1141
-			if ($reshares !== true) {
1142
-				$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1143
-			} else {
1144
-				$qb->andWhere(
1145
-					$qb->expr()->orX(
1146
-						$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1147
-						$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1148
-					)
1149
-				);
1150
-			}
1151
-		}
1152
-
1153
-		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1154
-
1155
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1156
-
1157
-		$qb->orderBy('id');
1158
-
1159
-		$cursor = $qb->executeQuery();
1160
-		$shares = [];
1161
-		while ($data = $cursor->fetchAssociative()) {
1162
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1163
-		}
1164
-		$cursor->closeCursor();
1165
-
1166
-		return $shares;
1167
-	}
1168
-
1169
-	/**
1170
-	 * @inheritdoc
1171
-	 */
1172
-	public function getAccessList($nodes, $currentAccess): array {
1173
-		$ids = [];
1174
-		foreach ($nodes as $node) {
1175
-			$ids[] = $node->getId();
1176
-		}
1177
-
1178
-		$qb = $this->dbConnection->getQueryBuilder();
1179
-		$qb->select('share_with', 'file_source', 'token')
1180
-			->from('share')
1181
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1182
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1183
-			->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
1184
-		$cursor = $qb->executeQuery();
1185
-
1186
-		$public = false;
1187
-		$mail = [];
1188
-		while ($row = $cursor->fetchAssociative()) {
1189
-			$public = true;
1190
-			if ($currentAccess === false) {
1191
-				$mail[] = $row['share_with'];
1192
-			} else {
1193
-				$mail[$row['share_with']] = [
1194
-					'node_id' => $row['file_source'],
1195
-					'token' => $row['token']
1196
-				];
1197
-			}
1198
-		}
1199
-		$cursor->closeCursor();
1200
-
1201
-		return ['public' => $public, 'mail' => $mail];
1202
-	}
1203
-
1204
-	public function getAllShares(): iterable {
1205
-		$qb = $this->dbConnection->getQueryBuilder();
1206
-
1207
-		$qb->select('*')
1208
-			->from('share')
1209
-			->where(
1210
-				$qb->expr()->orX(
1211
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1212
-				)
1213
-			);
1214
-
1215
-		$cursor = $qb->executeQuery();
1216
-		while ($data = $cursor->fetchAssociative()) {
1217
-			try {
1218
-				$share = $this->createShareObject($data);
1219
-			} catch (InvalidShare $e) {
1220
-				continue;
1221
-			} catch (ShareNotFound $e) {
1222
-				continue;
1223
-			}
1224
-
1225
-			yield $share;
1226
-		}
1227
-		$cursor->closeCursor();
1228
-	}
1229
-
1230
-	/**
1231
-	 * Extract the emails from the share
1232
-	 * It can be a single email, from the share_with field
1233
-	 * or a list of emails from the emails attributes field.
1234
-	 * @param IShare $share
1235
-	 * @return string[]
1236
-	 */
1237
-	protected function getSharedWithEmails(IShare $share): array {
1238
-		$attributes = $share->getAttributes();
1239
-
1240
-		if ($attributes === null) {
1241
-			return [$share->getSharedWith()];
1242
-		}
1243
-
1244
-		$emails = $attributes->getAttribute('shareWith', 'emails');
1245
-		if (isset($emails) && is_array($emails) && !empty($emails)) {
1246
-			return $emails;
1247
-		}
1248
-		return [$share->getSharedWith()];
1249
-	}
737
+        $qb = $this->dbConnection->getQueryBuilder();
738
+        $qb->update('share')
739
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
740
+            ->set('item_source', $qb->createNamedParameter($share->getNodeId()))
741
+            ->set('file_source', $qb->createNamedParameter($share->getNodeId()))
742
+            ->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
743
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
744
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
745
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
746
+            ->set('password', $qb->createNamedParameter($share->getPassword()))
747
+            ->set('password_expiration_time', $qb->createNamedParameter($share->getPasswordExpirationTime(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
748
+            ->set('label', $qb->createNamedParameter($share->getLabel()))
749
+            ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
750
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
751
+            ->set('note', $qb->createNamedParameter($share->getNote()))
752
+            ->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
753
+            ->set('attributes', $qb->createNamedParameter($shareAttributes))
754
+            ->set('mail_send', $qb->createNamedParameter((int)$share->getMailSend(), IQueryBuilder::PARAM_INT))
755
+            ->set('reminder_sent', $qb->createNamedParameter($share->getReminderSent(), IQueryBuilder::PARAM_BOOL))
756
+            ->executeStatement();
757
+
758
+        if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
759
+            $this->sendNote($share);
760
+        }
761
+
762
+        return $share;
763
+    }
764
+
765
+    /**
766
+     * @inheritdoc
767
+     */
768
+    public function move(IShare $share, $recipient): IShare {
769
+        /**
770
+         * nothing to do here, mail shares are only outgoing shares
771
+         */
772
+        return $share;
773
+    }
774
+
775
+    /**
776
+     * Delete a share (owner unShares the file)
777
+     *
778
+     * @param IShare $share
779
+     */
780
+    public function delete(IShare $share): void {
781
+        try {
782
+            $this->createShareActivity($share, 'unshare');
783
+        } catch (\Exception $e) {
784
+        }
785
+
786
+        $this->removeShareFromTable((int)$share->getId());
787
+    }
788
+
789
+    /**
790
+     * @inheritdoc
791
+     */
792
+    public function deleteFromSelf(IShare $share, $recipient): void {
793
+        // nothing to do here, mail shares are only outgoing shares
794
+    }
795
+
796
+    public function restore(IShare $share, string $recipient): IShare {
797
+        throw new GenericShareException('not implemented');
798
+    }
799
+
800
+    /**
801
+     * @inheritdoc
802
+     */
803
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset): array {
804
+        $qb = $this->dbConnection->getQueryBuilder();
805
+        $qb->select('*')
806
+            ->from('share');
807
+
808
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
809
+
810
+        /**
811
+         * Reshares for this user are shares where they are the owner.
812
+         */
813
+        if ($reshares === false) {
814
+            //Special case for old shares created via the web UI
815
+            $or1 = $qb->expr()->andX(
816
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
817
+                $qb->expr()->isNull('uid_initiator')
818
+            );
819
+
820
+            $qb->andWhere(
821
+                $qb->expr()->orX(
822
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
823
+                    $or1
824
+                )
825
+            );
826
+        } elseif ($node === null) {
827
+            $qb->andWhere(
828
+                $qb->expr()->orX(
829
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
830
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
831
+                )
832
+            );
833
+        }
834
+
835
+        if ($node !== null) {
836
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
837
+        }
838
+
839
+        if ($limit !== -1) {
840
+            $qb->setMaxResults($limit);
841
+        }
842
+
843
+        $qb->setFirstResult($offset);
844
+        $qb->orderBy('id');
845
+
846
+        $cursor = $qb->executeQuery();
847
+        $shares = [];
848
+        while ($data = $cursor->fetchAssociative()) {
849
+            $shares[] = $this->createShareObject($data);
850
+        }
851
+        $cursor->closeCursor();
852
+
853
+        return $shares;
854
+    }
855
+
856
+    /**
857
+     * @inheritdoc
858
+     */
859
+    public function getShareById($id, $recipientId = null): IShare {
860
+        $qb = $this->dbConnection->getQueryBuilder();
861
+
862
+        $qb->select('*')
863
+            ->from('share')
864
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
865
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
866
+
867
+        $cursor = $qb->executeQuery();
868
+        $data = $cursor->fetchAssociative();
869
+        $cursor->closeCursor();
870
+
871
+        if ($data === false) {
872
+            throw new ShareNotFound();
873
+        }
874
+
875
+        $data['id'] = (string)$data['id'];
876
+
877
+        try {
878
+            $share = $this->createShareObject($data);
879
+        } catch (InvalidShare $e) {
880
+            throw new ShareNotFound();
881
+        }
882
+
883
+        return $share;
884
+    }
885
+
886
+    /**
887
+     * Get shares for a given path
888
+     *
889
+     * @return IShare[]
890
+     */
891
+    public function getSharesByPath(Node $path): array {
892
+        $qb = $this->dbConnection->getQueryBuilder();
893
+
894
+        $cursor = $qb->select('*')
895
+            ->from('share')
896
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
897
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
898
+            ->executeQuery();
899
+
900
+        $shares = [];
901
+        while ($data = $cursor->fetchAssociative()) {
902
+            $data['id'] = (string)$data['id'];
903
+            $shares[] = $this->createShareObject($data);
904
+        }
905
+        $cursor->closeCursor();
906
+
907
+        return $shares;
908
+    }
909
+
910
+    /**
911
+     * @inheritdoc
912
+     */
913
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset): array {
914
+        /** @var IShare[] $shares */
915
+        $shares = [];
916
+
917
+        //Get shares directly with this user
918
+        $qb = $this->dbConnection->getQueryBuilder();
919
+        $qb->select('*')
920
+            ->from('share');
921
+
922
+        // Order by id
923
+        $qb->orderBy('id');
924
+
925
+        // Set limit and offset
926
+        if ($limit !== -1) {
927
+            $qb->setMaxResults($limit);
928
+        }
929
+        $qb->setFirstResult($offset);
930
+
931
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
932
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
933
+
934
+        // Filter by node if provided
935
+        if ($node !== null) {
936
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
937
+        }
938
+
939
+        $cursor = $qb->executeQuery();
940
+
941
+        while ($data = $cursor->fetchAssociative()) {
942
+            $shares[] = $this->createShareObject($data);
943
+        }
944
+        $cursor->closeCursor();
945
+
946
+
947
+        return $shares;
948
+    }
949
+
950
+    /**
951
+     * Get a share by token
952
+     *
953
+     * @throws ShareNotFound
954
+     */
955
+    public function getShareByToken($token): IShare {
956
+        $qb = $this->dbConnection->getQueryBuilder();
957
+
958
+        $cursor = $qb->select('*')
959
+            ->from('share')
960
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
961
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
962
+            ->executeQuery();
963
+
964
+        $data = $cursor->fetchAssociative();
965
+
966
+        if ($data === false) {
967
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
968
+        }
969
+
970
+        $data['id'] = (string)$data['id'];
971
+
972
+        try {
973
+            $share = $this->createShareObject($data);
974
+        } catch (InvalidShare $e) {
975
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
976
+        }
977
+
978
+        return $share;
979
+    }
980
+
981
+    /**
982
+     * remove share from table
983
+     */
984
+    protected function removeShareFromTable(int $shareId): void {
985
+        $qb = $this->dbConnection->getQueryBuilder();
986
+        $qb->delete('share')
987
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
988
+        $qb->executeStatement();
989
+    }
990
+
991
+    /**
992
+     * Create a share object from a database row
993
+     *
994
+     * @throws InvalidShare
995
+     * @throws ShareNotFound
996
+     */
997
+    protected function createShareObject(array $data): IShare {
998
+        $share = new Share($this->rootFolder, $this->userManager);
999
+        $share->setId($data['id'])
1000
+            ->setShareType((int)$data['share_type'])
1001
+            ->setPermissions((int)$data['permissions'])
1002
+            ->setTarget($data['file_target'])
1003
+            ->setMailSend((bool)$data['mail_send'])
1004
+            ->setNote($data['note'])
1005
+            ->setToken($data['token']);
1006
+
1007
+        $shareTime = new \DateTime();
1008
+        $shareTime->setTimestamp((int)$data['stime']);
1009
+        $share->setShareTime($shareTime);
1010
+        $share->setSharedWith($data['share_with'] ?? '');
1011
+        $share->setPassword($data['password']);
1012
+        $passwordExpirationTime = \DateTime::createFromFormat('Y-m-d H:i:s', $data['password_expiration_time'] ?? '');
1013
+        $share->setPasswordExpirationTime($passwordExpirationTime !== false ? $passwordExpirationTime : null);
1014
+        $share->setLabel($data['label'] ?? '');
1015
+        $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1016
+        $share->setHideDownload((bool)$data['hide_download']);
1017
+        $share->setReminderSent((bool)$data['reminder_sent']);
1018
+
1019
+        if ($data['uid_initiator'] !== null) {
1020
+            $share->setShareOwner($data['uid_owner']);
1021
+            $share->setSharedBy($data['uid_initiator']);
1022
+        } else {
1023
+            //OLD SHARE
1024
+            $share->setSharedBy($data['uid_owner']);
1025
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
1026
+
1027
+            $owner = $path->getOwner();
1028
+            $share->setShareOwner($owner->getUID());
1029
+        }
1030
+
1031
+        if ($data['expiration'] !== null) {
1032
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1033
+            if ($expiration !== false) {
1034
+                $share->setExpirationDate($expiration);
1035
+            }
1036
+        }
1037
+
1038
+        $share = $this->updateShareAttributes($share, $data['attributes']);
1039
+
1040
+        $share->setNodeId((int)$data['file_source']);
1041
+        $share->setNodeType($data['item_type']);
1042
+
1043
+        $share->setProviderId($this->identifier());
1044
+
1045
+        return $share;
1046
+    }
1047
+
1048
+    /**
1049
+     * Get the node with file $id for $user
1050
+     *
1051
+     * @throws InvalidShare
1052
+     */
1053
+    private function getNode(string $userId, int $id): Node {
1054
+        try {
1055
+            $userFolder = $this->rootFolder->getUserFolder($userId);
1056
+        } catch (NoUserException $e) {
1057
+            throw new InvalidShare();
1058
+        }
1059
+
1060
+        $nodes = $userFolder->getById($id);
1061
+
1062
+        if (empty($nodes)) {
1063
+            throw new InvalidShare();
1064
+        }
1065
+
1066
+        return $nodes[0];
1067
+    }
1068
+
1069
+    /**
1070
+     * A user is deleted from the system
1071
+     * So clean up the relevant shares.
1072
+     */
1073
+    public function userDeleted($uid, $shareType): void {
1074
+        $qb = $this->dbConnection->getQueryBuilder();
1075
+
1076
+        $qb->delete('share')
1077
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1078
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1079
+            ->executeStatement();
1080
+    }
1081
+
1082
+    /**
1083
+     * This provider does not support group shares
1084
+     */
1085
+    public function groupDeleted($gid): void {
1086
+    }
1087
+
1088
+    /**
1089
+     * This provider does not support group shares
1090
+     */
1091
+    public function userDeletedFromGroup($uid, $gid): void {
1092
+    }
1093
+
1094
+    /**
1095
+     * get database row of a give share
1096
+     *
1097
+     * @throws ShareNotFound
1098
+     */
1099
+    protected function getRawShare(string $id): array {
1100
+        // Now fetch the inserted share and create a complete share object
1101
+        $qb = $this->dbConnection->getQueryBuilder();
1102
+        $qb->select('*')
1103
+            ->from('share')
1104
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1105
+
1106
+        $cursor = $qb->executeQuery();
1107
+        $data = $cursor->fetchAssociative();
1108
+        $cursor->closeCursor();
1109
+
1110
+        if ($data === false) {
1111
+            throw new ShareNotFound;
1112
+        }
1113
+
1114
+        return $data;
1115
+    }
1116
+
1117
+    public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true): array {
1118
+        return $this->getSharesInFolderInternal($userId, $node, $reshares);
1119
+    }
1120
+
1121
+    public function getAllSharesInFolder(Folder $node): array {
1122
+        return $this->getSharesInFolderInternal(null, $node, null);
1123
+    }
1124
+
1125
+    /**
1126
+     * @return array<int, list<IShare>>
1127
+     */
1128
+    private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array {
1129
+        $qb = $this->dbConnection->getQueryBuilder();
1130
+        $qb->select('*')
1131
+            ->from('share', 's')
1132
+            ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)))
1133
+            ->andWhere(
1134
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1135
+            );
1136
+
1137
+        if ($userId !== null) {
1138
+            /**
1139
+             * Reshares for this user are shares where they are the owner.
1140
+             */
1141
+            if ($reshares !== true) {
1142
+                $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1143
+            } else {
1144
+                $qb->andWhere(
1145
+                    $qb->expr()->orX(
1146
+                        $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1147
+                        $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1148
+                    )
1149
+                );
1150
+            }
1151
+        }
1152
+
1153
+        $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1154
+
1155
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1156
+
1157
+        $qb->orderBy('id');
1158
+
1159
+        $cursor = $qb->executeQuery();
1160
+        $shares = [];
1161
+        while ($data = $cursor->fetchAssociative()) {
1162
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1163
+        }
1164
+        $cursor->closeCursor();
1165
+
1166
+        return $shares;
1167
+    }
1168
+
1169
+    /**
1170
+     * @inheritdoc
1171
+     */
1172
+    public function getAccessList($nodes, $currentAccess): array {
1173
+        $ids = [];
1174
+        foreach ($nodes as $node) {
1175
+            $ids[] = $node->getId();
1176
+        }
1177
+
1178
+        $qb = $this->dbConnection->getQueryBuilder();
1179
+        $qb->select('share_with', 'file_source', 'token')
1180
+            ->from('share')
1181
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1182
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1183
+            ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY)));
1184
+        $cursor = $qb->executeQuery();
1185
+
1186
+        $public = false;
1187
+        $mail = [];
1188
+        while ($row = $cursor->fetchAssociative()) {
1189
+            $public = true;
1190
+            if ($currentAccess === false) {
1191
+                $mail[] = $row['share_with'];
1192
+            } else {
1193
+                $mail[$row['share_with']] = [
1194
+                    'node_id' => $row['file_source'],
1195
+                    'token' => $row['token']
1196
+                ];
1197
+            }
1198
+        }
1199
+        $cursor->closeCursor();
1200
+
1201
+        return ['public' => $public, 'mail' => $mail];
1202
+    }
1203
+
1204
+    public function getAllShares(): iterable {
1205
+        $qb = $this->dbConnection->getQueryBuilder();
1206
+
1207
+        $qb->select('*')
1208
+            ->from('share')
1209
+            ->where(
1210
+                $qb->expr()->orX(
1211
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1212
+                )
1213
+            );
1214
+
1215
+        $cursor = $qb->executeQuery();
1216
+        while ($data = $cursor->fetchAssociative()) {
1217
+            try {
1218
+                $share = $this->createShareObject($data);
1219
+            } catch (InvalidShare $e) {
1220
+                continue;
1221
+            } catch (ShareNotFound $e) {
1222
+                continue;
1223
+            }
1224
+
1225
+            yield $share;
1226
+        }
1227
+        $cursor->closeCursor();
1228
+    }
1229
+
1230
+    /**
1231
+     * Extract the emails from the share
1232
+     * It can be a single email, from the share_with field
1233
+     * or a list of emails from the emails attributes field.
1234
+     * @param IShare $share
1235
+     * @return string[]
1236
+     */
1237
+    protected function getSharedWithEmails(IShare $share): array {
1238
+        $attributes = $share->getAttributes();
1239
+
1240
+        if ($attributes === null) {
1241
+            return [$share->getSharedWith()];
1242
+        }
1243
+
1244
+        $emails = $attributes->getAttribute('shareWith', 'emails');
1245
+        if (isset($emails) && is_array($emails) && !empty($emails)) {
1246
+            return $emails;
1247
+        }
1248
+        return [$share->getSharedWith()];
1249
+    }
1250 1250
 }
Please login to merge, or discard this patch.
Spacing   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
159 159
 			$share->getSharedBy(),
160 160
 			$share->getNode()->getId(),
161
-			(string)$userFolder->getRelativePath($share->getNode()->getPath())
161
+			(string) $userFolder->getRelativePath($share->getNode()->getPath())
162 162
 		);
163 163
 
164 164
 		if ($share->getShareOwner() !== $share->getSharedBy()) {
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
172 172
 				$share->getShareOwner(),
173 173
 				$fileId,
174
-				(string)$ownerFolder->getRelativePath($ownerPath)
174
+				(string) $ownerFolder->getRelativePath($ownerPath)
175 175
 			);
176 176
 		}
177 177
 	}
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
 				[$userFolder->getRelativePath($share->getNode()->getPath())],
189 189
 				$share->getSharedBy(),
190 190
 				$share->getNode()->getId(),
191
-				(string)$userFolder->getRelativePath($share->getNode()->getPath())
191
+				(string) $userFolder->getRelativePath($share->getNode()->getPath())
192 192
 			);
193 193
 		} else {
194 194
 			$this->publishActivity(
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
 				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
197 197
 				$share->getSharedBy(),
198 198
 				$share->getNode()->getId(),
199
-				(string)$userFolder->getRelativePath($share->getNode()->getPath())
199
+				(string) $userFolder->getRelativePath($share->getNode()->getPath())
200 200
 			);
201 201
 		}
202 202
 	}
@@ -247,15 +247,15 @@  discard block
 block discarded – undo
247 247
 		$shareId = $share->getId();
248 248
 
249 249
 		$emails = $this->getSharedWithEmails($share);
250
-		$validEmails = array_filter($emails, function (string $email) {
250
+		$validEmails = array_filter($emails, function(string $email) {
251 251
 			return $this->emailValidator->isValid($email);
252 252
 		});
253 253
 
254 254
 		if (count($validEmails) === 0) {
255
-			$this->removeShareFromTable((int)$shareId);
256
-			$e = new HintException('Failed to send share by mail. Could not find a valid email address: ' . join(', ', $emails),
255
+			$this->removeShareFromTable((int) $shareId);
256
+			$e = new HintException('Failed to send share by mail. Could not find a valid email address: '.join(', ', $emails),
257 257
 				$this->l->t('Failed to send share by email. Got an invalid email address'));
258
-			$this->logger->error('Failed to send share by mail. Could not find a valid email address ' . join(', ', $emails), [
258
+			$this->logger->error('Failed to send share by mail. Could not find a valid email address '.join(', ', $emails), [
259 259
 				'app' => 'sharebymail',
260 260
 				'exception' => $e,
261 261
 			]);
@@ -287,14 +287,14 @@  discard block
 block discarded – undo
287 287
 				'app' => 'sharebymail',
288 288
 				'exception' => $hintException,
289 289
 			]);
290
-			$this->removeShareFromTable((int)$shareId);
290
+			$this->removeShareFromTable((int) $shareId);
291 291
 			throw $hintException;
292 292
 		} catch (\Exception $e) {
293 293
 			$this->logger->error('Failed to send share by mail.', [
294 294
 				'app' => 'sharebymail',
295 295
 				'exception' => $e,
296 296
 			]);
297
-			$this->removeShareFromTable((int)$shareId);
297
+			$this->removeShareFromTable((int) $shareId);
298 298
 			throw new HintException(
299 299
 				'Failed to send share by mail',
300 300
 				$this->l->t('Failed to send share by email'),
@@ -347,7 +347,7 @@  discard block
 block discarded – undo
347 347
 		}
348 348
 
349 349
 		if ($expiration !== null) {
350
-			$dateString = (string)$this->l->l('date', $expiration, ['width' => 'medium']);
350
+			$dateString = (string) $this->l->l('date', $expiration, ['width' => 'medium']);
351 351
 			$emailTemplate->addBodyListItem(
352 352
 				$this->l->t('This share is valid until %s at midnight', [$dateString]),
353 353
 				$this->l->t('Expiration:'),
@@ -388,7 +388,7 @@  discard block
 block discarded – undo
388 388
 			$initiatorEmail = $initiatorUser->getEMailAddress();
389 389
 			if ($initiatorEmail !== null) {
390 390
 				$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
391
-				$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
391
+				$emailTemplate->addFooter($instanceName.($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : ''));
392 392
 			} else {
393 393
 				$emailTemplate->addFooter();
394 394
 			}
@@ -399,7 +399,7 @@  discard block
 block discarded – undo
399 399
 		$message->useTemplate($emailTemplate);
400 400
 		$failedRecipients = $this->mailer->send($message);
401 401
 		if (!empty($failedRecipients)) {
402
-			$this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients));
402
+			$this->logger->error('Share notification mail could not be sent to: '.implode(', ', $failedRecipients));
403 403
 			return;
404 404
 		}
405 405
 	}
@@ -452,7 +452,7 @@  discard block
 block discarded – undo
452 452
 		if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
453 453
 			$expirationTime = new \DateTime();
454 454
 			$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
455
-			$expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
455
+			$expirationTime = $expirationTime->add(new \DateInterval('PT'.$expirationInterval.'S'));
456 456
 			$emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
457 457
 		}
458 458
 
@@ -484,7 +484,7 @@  discard block
 block discarded – undo
484 484
 			$initiatorEmail = $initiatorUser->getEMailAddress();
485 485
 			if ($initiatorEmail !== null) {
486 486
 				$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
487
-				$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
487
+				$emailTemplate->addFooter($instanceName.($this->defaults->getSlogan() !== '' ? ' - '.$this->defaults->getSlogan() : ''));
488 488
 			} else {
489 489
 				$emailTemplate->addFooter();
490 490
 			}
@@ -495,7 +495,7 @@  discard block
 block discarded – undo
495 495
 		$message->useTemplate($emailTemplate);
496 496
 		$failedRecipients = $this->mailer->send($message);
497 497
 		if (!empty($failedRecipients)) {
498
-			$this->logger->error('Share password mail could not be sent to: ' . implode(', ', $failedRecipients));
498
+			$this->logger->error('Share password mail could not be sent to: '.implode(', ', $failedRecipients));
499 499
 			return false;
500 500
 		}
501 501
 
@@ -549,7 +549,7 @@  discard block
 block discarded – undo
549 549
 		$message->setFrom([Util::getDefaultEmailAddress($instanceName) => $senderName]);
550 550
 		if ($this->settingsManager->replyToInitiator() && $initiatorEmailAddress !== null) {
551 551
 			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
552
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
552
+			$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
553 553
 		} else {
554 554
 			$emailTemplate->addFooter();
555 555
 		}
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
 		if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === true) {
600 600
 			$expirationTime = new \DateTime();
601 601
 			$expirationInterval = $this->config->getSystemValue('sharing.mail_link_password_expiration_interval', 3600);
602
-			$expirationTime = $expirationTime->add(new \DateInterval('PT' . $expirationInterval . 'S'));
602
+			$expirationTime = $expirationTime->add(new \DateInterval('PT'.$expirationInterval.'S'));
603 603
 			$emailTemplate->addBodyText($this->l->t('This password will expire at %s', [$expirationTime->format('r')]));
604 604
 		}
605 605
 
@@ -694,10 +694,10 @@  discard block
 block discarded – undo
694 694
 			->setValue('password_expiration_time', $qb->createNamedParameter($passwordExpirationTime, IQueryBuilder::PARAM_DATETIME_MUTABLE))
695 695
 			->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
696 696
 			->setValue('stime', $qb->createNamedParameter(time()))
697
-			->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT))
697
+			->setValue('hide_download', $qb->createNamedParameter((int) $hideDownload, IQueryBuilder::PARAM_INT))
698 698
 			->setValue('label', $qb->createNamedParameter($label))
699 699
 			->setValue('note', $qb->createNamedParameter($note))
700
-			->setValue('mail_send', $qb->createNamedParameter((int)$mailSend, IQueryBuilder::PARAM_INT));
700
+			->setValue('mail_send', $qb->createNamedParameter((int) $mailSend, IQueryBuilder::PARAM_INT));
701 701
 
702 702
 		// set share attributes
703 703
 		$shareAttributes = $this->formatShareAttributes($attributes);
@@ -708,7 +708,7 @@  discard block
 block discarded – undo
708 708
 		}
709 709
 
710 710
 		$qb->executeStatement();
711
-		return (string)$qb->getLastInsertId();
711
+		return (string) $qb->getLastInsertId();
712 712
 	}
713 713
 
714 714
 	/**
@@ -723,7 +723,7 @@  discard block
 block discarded – undo
723 723
 		if ($validPassword && ($originalShare->getPassword() !== $share->getPassword()
724 724
 								|| ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
725 725
 			$emails = $this->getSharedWithEmails($share);
726
-			$validEmails = array_filter($emails, function ($email) {
726
+			$validEmails = array_filter($emails, function($email) {
727 727
 				return $this->emailValidator->isValid($email);
728 728
 			});
729 729
 			$this->sendPassword($share, $plainTextPassword, $validEmails);
@@ -749,9 +749,9 @@  discard block
 block discarded – undo
749 749
 			->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
750 750
 			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATETIME_MUTABLE))
751 751
 			->set('note', $qb->createNamedParameter($share->getNote()))
752
-			->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
752
+			->set('hide_download', $qb->createNamedParameter((int) $share->getHideDownload(), IQueryBuilder::PARAM_INT))
753 753
 			->set('attributes', $qb->createNamedParameter($shareAttributes))
754
-			->set('mail_send', $qb->createNamedParameter((int)$share->getMailSend(), IQueryBuilder::PARAM_INT))
754
+			->set('mail_send', $qb->createNamedParameter((int) $share->getMailSend(), IQueryBuilder::PARAM_INT))
755 755
 			->set('reminder_sent', $qb->createNamedParameter($share->getReminderSent(), IQueryBuilder::PARAM_BOOL))
756 756
 			->executeStatement();
757 757
 
@@ -783,7 +783,7 @@  discard block
 block discarded – undo
783 783
 		} catch (\Exception $e) {
784 784
 		}
785 785
 
786
-		$this->removeShareFromTable((int)$share->getId());
786
+		$this->removeShareFromTable((int) $share->getId());
787 787
 	}
788 788
 
789 789
 	/**
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
 			throw new ShareNotFound();
873 873
 		}
874 874
 
875
-		$data['id'] = (string)$data['id'];
875
+		$data['id'] = (string) $data['id'];
876 876
 
877 877
 		try {
878 878
 			$share = $this->createShareObject($data);
@@ -899,7 +899,7 @@  discard block
 block discarded – undo
899 899
 
900 900
 		$shares = [];
901 901
 		while ($data = $cursor->fetchAssociative()) {
902
-			$data['id'] = (string)$data['id'];
902
+			$data['id'] = (string) $data['id'];
903 903
 			$shares[] = $this->createShareObject($data);
904 904
 		}
905 905
 		$cursor->closeCursor();
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
 			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
968 968
 		}
969 969
 
970
-		$data['id'] = (string)$data['id'];
970
+		$data['id'] = (string) $data['id'];
971 971
 
972 972
 		try {
973 973
 			$share = $this->createShareObject($data);
@@ -997,24 +997,24 @@  discard block
 block discarded – undo
997 997
 	protected function createShareObject(array $data): IShare {
998 998
 		$share = new Share($this->rootFolder, $this->userManager);
999 999
 		$share->setId($data['id'])
1000
-			->setShareType((int)$data['share_type'])
1001
-			->setPermissions((int)$data['permissions'])
1000
+			->setShareType((int) $data['share_type'])
1001
+			->setPermissions((int) $data['permissions'])
1002 1002
 			->setTarget($data['file_target'])
1003
-			->setMailSend((bool)$data['mail_send'])
1003
+			->setMailSend((bool) $data['mail_send'])
1004 1004
 			->setNote($data['note'])
1005 1005
 			->setToken($data['token']);
1006 1006
 
1007 1007
 		$shareTime = new \DateTime();
1008
-		$shareTime->setTimestamp((int)$data['stime']);
1008
+		$shareTime->setTimestamp((int) $data['stime']);
1009 1009
 		$share->setShareTime($shareTime);
1010 1010
 		$share->setSharedWith($data['share_with'] ?? '');
1011 1011
 		$share->setPassword($data['password']);
1012 1012
 		$passwordExpirationTime = \DateTime::createFromFormat('Y-m-d H:i:s', $data['password_expiration_time'] ?? '');
1013 1013
 		$share->setPasswordExpirationTime($passwordExpirationTime !== false ? $passwordExpirationTime : null);
1014 1014
 		$share->setLabel($data['label'] ?? '');
1015
-		$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1016
-		$share->setHideDownload((bool)$data['hide_download']);
1017
-		$share->setReminderSent((bool)$data['reminder_sent']);
1015
+		$share->setSendPasswordByTalk((bool) $data['password_by_talk']);
1016
+		$share->setHideDownload((bool) $data['hide_download']);
1017
+		$share->setReminderSent((bool) $data['reminder_sent']);
1018 1018
 
1019 1019
 		if ($data['uid_initiator'] !== null) {
1020 1020
 			$share->setShareOwner($data['uid_owner']);
@@ -1022,7 +1022,7 @@  discard block
 block discarded – undo
1022 1022
 		} else {
1023 1023
 			//OLD SHARE
1024 1024
 			$share->setSharedBy($data['uid_owner']);
1025
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
1025
+			$path = $this->getNode($share->getSharedBy(), (int) $data['file_source']);
1026 1026
 
1027 1027
 			$owner = $path->getOwner();
1028 1028
 			$share->setShareOwner($owner->getUID());
@@ -1037,7 +1037,7 @@  discard block
 block discarded – undo
1037 1037
 
1038 1038
 		$share = $this->updateShareAttributes($share, $data['attributes']);
1039 1039
 
1040
-		$share->setNodeId((int)$data['file_source']);
1040
+		$share->setNodeId((int) $data['file_source']);
1041 1041
 		$share->setNodeType($data['item_type']);
1042 1042
 
1043 1043
 		$share->setProviderId($this->identifier());
Please login to merge, or discard this patch.
federatedfilesharing/tests/Controller/MountPublicLinkControllerTest.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -33,139 +33,139 @@
 block discarded – undo
33 33
 use Psr\Log\LoggerInterface;
34 34
 
35 35
 class MountPublicLinkControllerTest extends \Test\TestCase {
36
-	protected IContactsManager&MockObject $contactsManager;
37
-	private IRequest&MockObject $request;
38
-	private FederatedShareProvider&MockObject $federatedShareProvider;
39
-	private IManager&MockObject $shareManager;
40
-	private AddressHandler&MockObject $addressHandler;
41
-	private IRootFolder&MockObject $rootFolder;
42
-	private IUserManager&MockObject $userManager;
43
-	private ISession&MockObject $session;
44
-	private IL10N&MockObject $l10n;
45
-	private IUserSession&MockObject $userSession;
46
-	private IClientService&MockObject $clientService;
47
-	private IShare $share;
48
-	private ICloudIdManager $cloudIdManager;
49
-	private MountPublicLinkController $controller;
36
+    protected IContactsManager&MockObject $contactsManager;
37
+    private IRequest&MockObject $request;
38
+    private FederatedShareProvider&MockObject $federatedShareProvider;
39
+    private IManager&MockObject $shareManager;
40
+    private AddressHandler&MockObject $addressHandler;
41
+    private IRootFolder&MockObject $rootFolder;
42
+    private IUserManager&MockObject $userManager;
43
+    private ISession&MockObject $session;
44
+    private IL10N&MockObject $l10n;
45
+    private IUserSession&MockObject $userSession;
46
+    private IClientService&MockObject $clientService;
47
+    private IShare $share;
48
+    private ICloudIdManager $cloudIdManager;
49
+    private MountPublicLinkController $controller;
50 50
 
51
-	protected function setUp(): void {
52
-		parent::setUp();
51
+    protected function setUp(): void {
52
+        parent::setUp();
53 53
 
54
-		$this->request = $this->createMock(IRequest::class);
55
-		$this->federatedShareProvider = $this->createMock(FederatedShareProvider::class);
56
-		$this->shareManager = $this->createMock(IManager::class);
57
-		$this->addressHandler = $this->createMock(AddressHandler::class);
58
-		$this->rootFolder = $this->createMock(IRootFolder::class);
59
-		$this->userManager = $this->createMock(IUserManager::class);
60
-		$this->share = new Share($this->rootFolder, $this->userManager);
61
-		$this->share->setId('42');
62
-		$this->session = $this->createMock(ISession::class);
63
-		$this->l10n = $this->createMock(IL10N::class);
64
-		$this->userSession = $this->createMock(IUserSession::class);
65
-		$this->clientService = $this->createMock(IClientService::class);
66
-		$this->contactsManager = $this->createMock(IContactsManager::class);
67
-		$this->cloudIdManager = new CloudIdManager(
68
-			$this->createMock(ICacheFactory::class),
69
-			$this->createMock(IEventDispatcher::class),
70
-			$this->contactsManager,
71
-			$this->createMock(IURLGenerator::class),
72
-			$this->userManager,
73
-		);
54
+        $this->request = $this->createMock(IRequest::class);
55
+        $this->federatedShareProvider = $this->createMock(FederatedShareProvider::class);
56
+        $this->shareManager = $this->createMock(IManager::class);
57
+        $this->addressHandler = $this->createMock(AddressHandler::class);
58
+        $this->rootFolder = $this->createMock(IRootFolder::class);
59
+        $this->userManager = $this->createMock(IUserManager::class);
60
+        $this->share = new Share($this->rootFolder, $this->userManager);
61
+        $this->share->setId('42');
62
+        $this->session = $this->createMock(ISession::class);
63
+        $this->l10n = $this->createMock(IL10N::class);
64
+        $this->userSession = $this->createMock(IUserSession::class);
65
+        $this->clientService = $this->createMock(IClientService::class);
66
+        $this->contactsManager = $this->createMock(IContactsManager::class);
67
+        $this->cloudIdManager = new CloudIdManager(
68
+            $this->createMock(ICacheFactory::class),
69
+            $this->createMock(IEventDispatcher::class),
70
+            $this->contactsManager,
71
+            $this->createMock(IURLGenerator::class),
72
+            $this->userManager,
73
+        );
74 74
 
75
-		$this->controller = new MountPublicLinkController(
76
-			'federatedfilesharing', $this->request,
77
-			$this->federatedShareProvider,
78
-			$this->shareManager,
79
-			$this->addressHandler,
80
-			$this->session,
81
-			$this->l10n,
82
-			$this->userSession,
83
-			$this->clientService,
84
-			$this->cloudIdManager,
85
-			$this->createMock(LoggerInterface::class),
86
-		);
87
-	}
75
+        $this->controller = new MountPublicLinkController(
76
+            'federatedfilesharing', $this->request,
77
+            $this->federatedShareProvider,
78
+            $this->shareManager,
79
+            $this->addressHandler,
80
+            $this->session,
81
+            $this->l10n,
82
+            $this->userSession,
83
+            $this->clientService,
84
+            $this->cloudIdManager,
85
+            $this->createMock(LoggerInterface::class),
86
+        );
87
+    }
88 88
 
89
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestCreateFederatedShare')]
90
-	public function testCreateFederatedShare(
91
-		string $shareWith,
92
-		bool $outgoingSharesAllowed,
93
-		bool $validShareWith,
94
-		string $token,
95
-		bool $validToken,
96
-		bool $createSuccessful,
97
-		string $expectedReturnData,
98
-		int $permissions,
99
-	): void {
100
-		$this->federatedShareProvider->expects($this->any())
101
-			->method('isOutgoingServer2serverShareEnabled')
102
-			->willReturn($outgoingSharesAllowed);
89
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestCreateFederatedShare')]
90
+    public function testCreateFederatedShare(
91
+        string $shareWith,
92
+        bool $outgoingSharesAllowed,
93
+        bool $validShareWith,
94
+        string $token,
95
+        bool $validToken,
96
+        bool $createSuccessful,
97
+        string $expectedReturnData,
98
+        int $permissions,
99
+    ): void {
100
+        $this->federatedShareProvider->expects($this->any())
101
+            ->method('isOutgoingServer2serverShareEnabled')
102
+            ->willReturn($outgoingSharesAllowed);
103 103
 
104
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
105
-			->with($shareWith)
106
-			->willReturnCallback(
107
-				function ($shareWith) use ($validShareWith, $expectedReturnData) {
108
-					if ($validShareWith) {
109
-						return ['user', 'server'];
110
-					}
111
-					throw new HintException($expectedReturnData, $expectedReturnData);
112
-				}
113
-			);
104
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
105
+            ->with($shareWith)
106
+            ->willReturnCallback(
107
+                function ($shareWith) use ($validShareWith, $expectedReturnData) {
108
+                    if ($validShareWith) {
109
+                        return ['user', 'server'];
110
+                    }
111
+                    throw new HintException($expectedReturnData, $expectedReturnData);
112
+                }
113
+            );
114 114
 
115
-		$share = $this->share;
116
-		$share->setPermissions($permissions);
115
+        $share = $this->share;
116
+        $share->setPermissions($permissions);
117 117
 
118
-		$this->shareManager->expects($this->any())->method('getShareByToken')
119
-			->with($token)
120
-			->willReturnCallback(
121
-				function ($token) use ($validToken, $share, $expectedReturnData) {
122
-					if ($validToken) {
123
-						return $share;
124
-					}
125
-					throw new HintException($expectedReturnData, $expectedReturnData);
126
-				}
127
-			);
118
+        $this->shareManager->expects($this->any())->method('getShareByToken')
119
+            ->with($token)
120
+            ->willReturnCallback(
121
+                function ($token) use ($validToken, $share, $expectedReturnData) {
122
+                    if ($validToken) {
123
+                        return $share;
124
+                    }
125
+                    throw new HintException($expectedReturnData, $expectedReturnData);
126
+                }
127
+            );
128 128
 
129
-		$this->federatedShareProvider->expects($this->any())->method('create')
130
-			->with($share)
131
-			->willReturnCallback(
132
-				function (IShare $share) use ($createSuccessful, $shareWith, $expectedReturnData) {
133
-					$this->assertEquals($shareWith, $share->getSharedWith());
134
-					if ($createSuccessful) {
135
-						return $share;
136
-					}
137
-					throw new HintException($expectedReturnData, $expectedReturnData);
138
-				}
139
-			);
129
+        $this->federatedShareProvider->expects($this->any())->method('create')
130
+            ->with($share)
131
+            ->willReturnCallback(
132
+                function (IShare $share) use ($createSuccessful, $shareWith, $expectedReturnData) {
133
+                    $this->assertEquals($shareWith, $share->getSharedWith());
134
+                    if ($createSuccessful) {
135
+                        return $share;
136
+                    }
137
+                    throw new HintException($expectedReturnData, $expectedReturnData);
138
+                }
139
+            );
140 140
 
141
-		$result = $this->controller->createFederatedShare($shareWith, $token);
141
+        $result = $this->controller->createFederatedShare($shareWith, $token);
142 142
 
143
-		$errorCase = !$validShareWith || !$validToken || !$createSuccessful || !$outgoingSharesAllowed;
143
+        $errorCase = !$validShareWith || !$validToken || !$createSuccessful || !$outgoingSharesAllowed;
144 144
 
145
-		if ($errorCase) {
146
-			$this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus());
147
-			$this->assertTrue(isset($result->getData()['message']));
148
-			$this->assertSame($expectedReturnData, $result->getData()['message']);
149
-		} else {
150
-			$this->assertSame(Http::STATUS_OK, $result->getStatus());
151
-			$this->assertTrue(isset($result->getData()['remoteUrl']));
152
-			$this->assertSame($expectedReturnData, $result->getData()['remoteUrl']);
153
-		}
154
-	}
145
+        if ($errorCase) {
146
+            $this->assertSame(Http::STATUS_BAD_REQUEST, $result->getStatus());
147
+            $this->assertTrue(isset($result->getData()['message']));
148
+            $this->assertSame($expectedReturnData, $result->getData()['message']);
149
+        } else {
150
+            $this->assertSame(Http::STATUS_OK, $result->getStatus());
151
+            $this->assertTrue(isset($result->getData()['remoteUrl']));
152
+            $this->assertSame($expectedReturnData, $result->getData()['remoteUrl']);
153
+        }
154
+    }
155 155
 
156
-	public static function dataTestCreateFederatedShare(): array {
157
-		return [
158
-			//shareWith, outgoingSharesAllowed, validShareWith, token, validToken, createSuccessful, expectedReturnData
159
-			['user@server', true, true, 'token', true, true, 'server', 31],
160
-			['user@server', true, true, 'token', false, false, 'server', 4],
161
-			['user@server', true, false, 'token', true, true, 'invalid federated cloud id', 31],
162
-			['user@server', true, false, 'token', false, true, 'invalid federated cloud id', 31],
163
-			['user@server', true, false, 'token', false, false, 'invalid federated cloud id', 31],
164
-			['user@server', true, false, 'token', true, false, 'invalid federated cloud id', 31],
165
-			['user@server', true, true, 'token', false, true, 'invalid token', 31],
166
-			['user@server', true, true, 'token', false, false, 'invalid token', 31],
167
-			['user@server', true, true, 'token', true, false, 'can not create share', 31],
168
-			['user@server', false, true, 'token', true, true, 'This server doesn\'t support outgoing federated shares', 31],
169
-		];
170
-	}
156
+    public static function dataTestCreateFederatedShare(): array {
157
+        return [
158
+            //shareWith, outgoingSharesAllowed, validShareWith, token, validToken, createSuccessful, expectedReturnData
159
+            ['user@server', true, true, 'token', true, true, 'server', 31],
160
+            ['user@server', true, true, 'token', false, false, 'server', 4],
161
+            ['user@server', true, false, 'token', true, true, 'invalid federated cloud id', 31],
162
+            ['user@server', true, false, 'token', false, true, 'invalid federated cloud id', 31],
163
+            ['user@server', true, false, 'token', false, false, 'invalid federated cloud id', 31],
164
+            ['user@server', true, false, 'token', true, false, 'invalid federated cloud id', 31],
165
+            ['user@server', true, true, 'token', false, true, 'invalid token', 31],
166
+            ['user@server', true, true, 'token', false, false, 'invalid token', 31],
167
+            ['user@server', true, true, 'token', true, false, 'can not create share', 31],
168
+            ['user@server', false, true, 'token', true, true, 'This server doesn\'t support outgoing federated shares', 31],
169
+        ];
170
+    }
171 171
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/tests/FederatedShareProviderTest.php 1 patch
Indentation   +888 added lines, -888 removed lines patch added patch discarded remove patch
@@ -40,892 +40,892 @@
 block discarded – undo
40 40
  */
41 41
 #[\PHPUnit\Framework\Attributes\Group(name: 'DB')]
42 42
 class FederatedShareProviderTest extends \Test\TestCase {
43
-	protected IDBConnection $connection;
44
-	protected AddressHandler&MockObject $addressHandler;
45
-	protected Notifications&MockObject $notifications;
46
-	protected TokenHandler&MockObject $tokenHandler;
47
-	protected IL10N $l;
48
-	protected LoggerInterface $logger;
49
-	protected IRootFolder&MockObject $rootFolder;
50
-	protected IConfig&MockObject $config;
51
-	protected IUserManager&MockObject $userManager;
52
-	protected \OCP\GlobalScale\IConfig&MockObject $gsConfig;
53
-	protected IManager $shareManager;
54
-	protected FederatedShareProvider $provider;
55
-	protected IContactsManager&MockObject $contactsManager;
56
-	private ICloudIdManager $cloudIdManager;
57
-	private ICloudFederationProviderManager&MockObject $cloudFederationProviderManager;
58
-
59
-	protected function setUp(): void {
60
-		parent::setUp();
61
-
62
-		$this->connection = Server::get(IDBConnection::class);
63
-		$this->notifications = $this->createMock(Notifications::class);
64
-		$this->tokenHandler = $this->createMock(TokenHandler::class);
65
-		$this->l = $this->createMock(IL10N::class);
66
-		$this->l->method('t')
67
-			->willReturnCallback(function ($text, $parameters = []) {
68
-				return vsprintf($text, $parameters);
69
-			});
70
-		$this->logger = $this->createMock(LoggerInterface::class);
71
-		$this->rootFolder = $this->createMock(IRootFolder::class);
72
-		$this->config = $this->createMock(IConfig::class);
73
-		$this->userManager = $this->createMock(IUserManager::class);
74
-		//$this->addressHandler = new AddressHandler(\OC::$server->getURLGenerator(), $this->l);
75
-		$this->addressHandler = $this->createMock(AddressHandler::class);
76
-		$this->contactsManager = $this->createMock(IContactsManager::class);
77
-		$this->cloudIdManager = new CloudIdManager(
78
-			$this->createMock(ICacheFactory::class),
79
-			$this->createMock(IEventDispatcher::class),
80
-			$this->contactsManager,
81
-			$this->createMock(IURLGenerator::class),
82
-			$this->userManager,
83
-		);
84
-		$this->gsConfig = $this->createMock(\OCP\GlobalScale\IConfig::class);
85
-
86
-		$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
87
-
88
-		$this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
89
-
90
-		$this->provider = new FederatedShareProvider(
91
-			$this->connection,
92
-			$this->addressHandler,
93
-			$this->notifications,
94
-			$this->tokenHandler,
95
-			$this->l,
96
-			$this->rootFolder,
97
-			$this->config,
98
-			$this->userManager,
99
-			$this->cloudIdManager,
100
-			$this->gsConfig,
101
-			$this->cloudFederationProviderManager,
102
-			$this->logger,
103
-		);
104
-
105
-		$this->shareManager = Server::get(IManager::class);
106
-	}
107
-
108
-	protected function tearDown(): void {
109
-		$this->connection->getQueryBuilder()->delete('share')->executeStatement();
110
-
111
-		parent::tearDown();
112
-	}
113
-
114
-	public static function dataTestCreate(): array {
115
-		return [
116
-			[null, null],
117
-			[new \DateTime('2020-03-01T01:02:03'), '2020-03-01 01:02:03'],
118
-		];
119
-	}
120
-
121
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestCreate')]
122
-	public function testCreate(?\DateTime $expirationDate, ?string $expectedDataDate): void {
123
-		$share = $this->shareManager->newShare();
124
-
125
-		/** @var File&MockObject $node */
126
-		$node = $this->createMock(File::class);
127
-		$node->method('getId')->willReturn(42);
128
-		$node->method('getName')->willReturn('myFile');
129
-
130
-		$share->setSharedWith('[email protected]')
131
-			->setSharedBy('sharedBy')
132
-			->setShareOwner('shareOwner')
133
-			->setPermissions(19)
134
-			->setShareType(IShare::TYPE_REMOTE)
135
-			->setExpirationDate($expirationDate)
136
-			->setNode($node);
137
-
138
-		$this->tokenHandler->method('generateToken')->willReturn('token');
139
-
140
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
141
-			->willReturn('http://localhost/');
142
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
143
-			->willReturn(['user', 'server.com']);
144
-
145
-		$this->notifications->expects($this->once())
146
-			->method('sendRemoteShare')
147
-			->with(
148
-				$this->equalTo('token'),
149
-				$this->equalTo('[email protected]'),
150
-				$this->equalTo('myFile'),
151
-				$this->anything(),
152
-				'shareOwner',
153
-				'shareOwner@http://localhost',
154
-				'sharedBy',
155
-				'sharedBy@http://localhost'
156
-			)
157
-			->willReturn(true);
158
-
159
-		$this->rootFolder->expects($this->never())->method($this->anything());
160
-
161
-		$this->contactsManager->expects($this->any())
162
-			->method('search')
163
-			->willReturn([]);
164
-
165
-		$share = $this->provider->create($share);
166
-
167
-		$qb = $this->connection->getQueryBuilder();
168
-		$stmt = $qb->select('*')
169
-			->from('share')
170
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
171
-			->executeQuery();
172
-
173
-		$data = $stmt->fetchAssociative();
174
-		$stmt->closeCursor();
175
-
176
-		$expected = [
177
-			'share_type' => IShare::TYPE_REMOTE,
178
-			'share_with' => '[email protected]',
179
-			'uid_owner' => 'shareOwner',
180
-			'uid_initiator' => 'sharedBy',
181
-			'item_type' => 'file',
182
-			'item_source' => 42,
183
-			'file_source' => 42,
184
-			'permissions' => 19,
185
-			'accepted' => 0,
186
-			'token' => 'token',
187
-			'expiration' => $expectedDataDate,
188
-		];
189
-		foreach (array_keys($expected) as $key) {
190
-			$this->assertEquals($expected[$key], $data[$key], "Assert that value for key '$key' is the same");
191
-		}
192
-
193
-		$this->assertEquals($data['id'], $share->getId());
194
-		$this->assertEquals(IShare::TYPE_REMOTE, $share->getShareType());
195
-		$this->assertEquals('[email protected]', $share->getSharedWith());
196
-		$this->assertEquals('sharedBy', $share->getSharedBy());
197
-		$this->assertEquals('shareOwner', $share->getShareOwner());
198
-		$this->assertEquals('file', $share->getNodeType());
199
-		$this->assertEquals(42, $share->getNodeId());
200
-		$this->assertEquals(19, $share->getPermissions());
201
-		$this->assertEquals('token', $share->getToken());
202
-		$this->assertEquals($expirationDate, $share->getExpirationDate());
203
-	}
204
-
205
-	public function testCreateCouldNotFindServer(): void {
206
-		$this->expectException(LogicException::class);
207
-		$share = $this->shareManager->newShare();
208
-
209
-		$node = $this->createMock(File::class);
210
-		$node->method('getId')->willReturn(42);
211
-		$node->method('getName')->willReturn('myFile');
212
-
213
-		$share->setSharedWith('[email protected]')
214
-			->setSharedBy('sharedBy')
215
-			->setShareOwner('shareOwner')
216
-			->setPermissions(19)
217
-			->setShareType(IShare::TYPE_REMOTE)
218
-			->setNode($node);
219
-
220
-		$this->tokenHandler->method('generateToken')->willReturn('token');
221
-
222
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
223
-			->willReturn('http://localhost/');
224
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
225
-			->willReturn(['user', 'server.com']);
226
-
227
-		$this->notifications->expects($this->once())
228
-			->method('sendRemoteShare')
229
-			->with(
230
-				$this->equalTo('token'),
231
-				$this->equalTo('[email protected]'),
232
-				$this->equalTo('myFile'),
233
-				$this->anything(),
234
-				'shareOwner',
235
-				'shareOwner@http://localhost',
236
-				'sharedBy',
237
-				'sharedBy@http://localhost'
238
-			)->willReturn(false);
239
-
240
-		$this->rootFolder->method('getById')
241
-			->with('42')
242
-			->willReturn([$node]);
243
-
244
-		$this->contactsManager->expects($this->any())
245
-			->method('search')
246
-			->willReturn([]);
247
-
248
-		try {
249
-			$share = $this->provider->create($share);
250
-			$this->fail();
251
-		} catch (\Exception $e) {
252
-			$this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
253
-		}
254
-
255
-		$share->getId();
256
-	}
257
-
258
-	public function testCreateException(): void {
259
-		$this->expectException(LogicException::class);
260
-		$share = $this->shareManager->newShare();
261
-
262
-		$node = $this->createMock(File::class);
263
-		$node->method('getId')->willReturn(42);
264
-		$node->method('getName')->willReturn('myFile');
265
-
266
-		$share->setSharedWith('[email protected]')
267
-			->setSharedBy('sharedBy')
268
-			->setShareOwner('shareOwner')
269
-			->setPermissions(19)
270
-			->setShareType(IShare::TYPE_REMOTE)
271
-			->setNode($node);
272
-
273
-		$this->tokenHandler->method('generateToken')->willReturn('token');
274
-
275
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
276
-			->willReturn('http://localhost/');
277
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
278
-			->willReturn(['user', 'server.com']);
279
-
280
-		$this->notifications->expects($this->once())
281
-			->method('sendRemoteShare')
282
-			->with(
283
-				$this->equalTo('token'),
284
-				$this->equalTo('[email protected]'),
285
-				$this->equalTo('myFile'),
286
-				$this->anything(),
287
-				'shareOwner',
288
-				'shareOwner@http://localhost',
289
-				'sharedBy',
290
-				'sharedBy@http://localhost'
291
-			)->willThrowException(new \Exception('dummy'));
292
-
293
-		$this->rootFolder->method('getById')
294
-			->with('42')
295
-			->willReturn([$node]);
296
-
297
-		$this->contactsManager->expects($this->any())
298
-			->method('search')
299
-			->willReturn([]);
300
-
301
-		try {
302
-			$share = $this->provider->create($share);
303
-			$this->fail();
304
-		} catch (\Exception $e) {
305
-			$this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
306
-		}
307
-
308
-		$share->getId();
309
-	}
310
-
311
-	public function testCreateShareWithSelf(): void {
312
-		$this->expectException(LogicException::class);
313
-		$share = $this->shareManager->newShare();
314
-
315
-		$node = $this->createMock(File::class);
316
-		$node->method('getId')->willReturn(42);
317
-		$node->method('getName')->willReturn('myFile');
318
-
319
-		$this->addressHandler->expects($this->any())->method('compareAddresses')
320
-			->willReturn(true);
321
-
322
-		$shareWith = 'sharedBy@localhost';
323
-
324
-		$share->setSharedWith($shareWith)
325
-			->setSharedBy('sharedBy')
326
-			->setShareOwner('shareOwner')
327
-			->setPermissions(19)
328
-			->setNode($node);
329
-
330
-		$this->contactsManager->expects($this->any())
331
-			->method('search')
332
-			->willReturn([]);
333
-
334
-		$this->rootFolder->expects($this->never())->method($this->anything());
335
-
336
-		try {
337
-			$share = $this->provider->create($share);
338
-			$this->fail();
339
-		} catch (\Exception $e) {
340
-			$this->assertEquals('Not allowed to create a federated share to the same account', $e->getMessage());
341
-		}
342
-
343
-		$share->getId();
344
-	}
345
-
346
-	public function testCreateAlreadyShared(): void {
347
-		$share = $this->shareManager->newShare();
348
-
349
-		$node = $this->createMock(File::class);
350
-		$node->method('getId')->willReturn(42);
351
-		$node->method('getName')->willReturn('myFile');
352
-
353
-
354
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
355
-			->willReturn(['user', 'server.com']);
356
-
357
-		$share->setSharedWith('[email protected]')
358
-			->setSharedBy('sharedBy')
359
-			->setShareOwner('shareOwner')
360
-			->setPermissions(19)
361
-			->setShareType(IShare::TYPE_REMOTE)
362
-			->setNode($node);
363
-
364
-		$this->tokenHandler->method('generateToken')->willReturn('token');
365
-
366
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
367
-			->willReturn('http://localhost/');
368
-
369
-		$this->notifications->expects($this->once())
370
-			->method('sendRemoteShare')
371
-			->with(
372
-				$this->equalTo('token'),
373
-				$this->equalTo('[email protected]'),
374
-				$this->equalTo('myFile'),
375
-				$this->anything(),
376
-				'shareOwner',
377
-				'shareOwner@http://localhost',
378
-				'sharedBy',
379
-				'sharedBy@http://localhost'
380
-			)->willReturn(true);
381
-
382
-		$this->rootFolder->expects($this->never())->method($this->anything());
383
-
384
-		$this->contactsManager->expects($this->any())
385
-			->method('search')
386
-			->willReturn([]);
387
-
388
-		$this->provider->create($share);
389
-
390
-		try {
391
-			$this->provider->create($share);
392
-		} catch (\Exception $e) {
393
-			$this->assertEquals('Sharing myFile failed, because this item is already shared with the account [email protected]', $e->getMessage());
394
-		}
395
-	}
396
-
397
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestUpdate')]
398
-	public function testUpdate(string $owner, string $sharedBy, ?\DateTime $expirationDate): void {
399
-		$this->provider = $this->getMockBuilder(FederatedShareProvider::class)
400
-			->setConstructorArgs(
401
-				[
402
-					$this->connection,
403
-					$this->addressHandler,
404
-					$this->notifications,
405
-					$this->tokenHandler,
406
-					$this->l,
407
-					$this->rootFolder,
408
-					$this->config,
409
-					$this->userManager,
410
-					$this->cloudIdManager,
411
-					$this->gsConfig,
412
-					$this->cloudFederationProviderManager,
413
-					$this->logger,
414
-				]
415
-			)
416
-			->onlyMethods(['sendPermissionUpdate'])
417
-			->getMock();
418
-
419
-		$share = $this->shareManager->newShare();
420
-
421
-		$node = $this->createMock(File::class);
422
-		$node->method('getId')->willReturn(42);
423
-		$node->method('getName')->willReturn('myFile');
424
-
425
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
426
-			->willReturn(['user', 'server.com']);
427
-
428
-		$share->setSharedWith('[email protected]')
429
-			->setSharedBy($sharedBy)
430
-			->setShareOwner($owner)
431
-			->setPermissions(19)
432
-			->setShareType(IShare::TYPE_REMOTE)
433
-			->setExpirationDate(new \DateTime('2019-02-01T01:02:03'))
434
-			->setNode($node);
435
-
436
-		$this->tokenHandler->method('generateToken')->willReturn('token');
437
-		$this->addressHandler->expects($this->any())->method('generateRemoteURL')
438
-			->willReturn('http://localhost/');
439
-
440
-		$this->notifications->expects($this->once())
441
-			->method('sendRemoteShare')
442
-			->with(
443
-				$this->equalTo('token'),
444
-				$this->equalTo('[email protected]'),
445
-				$this->equalTo('myFile'),
446
-				$this->anything(),
447
-				$owner,
448
-				$owner . '@http://localhost',
449
-				$sharedBy,
450
-				$sharedBy . '@http://localhost'
451
-			)->willReturn(true);
452
-
453
-		if ($owner === $sharedBy) {
454
-			$this->provider->expects($this->never())->method('sendPermissionUpdate');
455
-		} else {
456
-			$this->provider->expects($this->once())->method('sendPermissionUpdate');
457
-		}
458
-
459
-		$this->rootFolder->expects($this->never())->method($this->anything());
460
-
461
-		$this->contactsManager->expects($this->any())
462
-			->method('search')
463
-			->willReturn([]);
464
-
465
-		$share = $this->provider->create($share);
466
-
467
-		$share->setPermissions(1);
468
-		$share->setExpirationDate($expirationDate);
469
-		$this->provider->update($share);
470
-
471
-		$share = $this->provider->getShareById($share->getId());
472
-
473
-		$this->assertEquals(1, $share->getPermissions());
474
-		$this->assertEquals($expirationDate, $share->getExpirationDate());
475
-	}
476
-
477
-	public static function dataTestUpdate(): array {
478
-		return [
479
-			['sharedBy', 'shareOwner', new \DateTime('2020-03-01T01:02:03')],
480
-			['shareOwner', 'shareOwner', null],
481
-		];
482
-	}
483
-
484
-	public function testGetSharedBy(): void {
485
-		$node = $this->createMock(File::class);
486
-		$node->method('getId')->willReturn(42);
487
-		$node->method('getName')->willReturn('myFile');
488
-
489
-		$this->addressHandler->expects($this->never())->method('splitUserRemote');
490
-
491
-		$this->addressHandler->method('generateRemoteURL')
492
-			->willReturn('remoteurl.com');
493
-
494
-		$this->tokenHandler->method('generateToken')->willReturn('token');
495
-		$this->notifications
496
-			->method('sendRemoteShare')
497
-			->willReturn(true);
498
-
499
-		$this->rootFolder->expects($this->never())->method($this->anything());
500
-
501
-		$this->contactsManager->expects($this->any())
502
-			->method('search')
503
-			->willReturn([]);
504
-
505
-		$share = $this->shareManager->newShare();
506
-		$share->setSharedWith('[email protected]')
507
-			->setSharedBy('sharedBy')
508
-			->setShareOwner('shareOwner')
509
-			->setPermissions(19)
510
-			->setShareType(IShare::TYPE_REMOTE)
511
-			->setNode($node);
512
-		$this->provider->create($share);
513
-
514
-		$share2 = $this->shareManager->newShare();
515
-		$share2->setSharedWith('[email protected]')
516
-			->setSharedBy('sharedBy2')
517
-			->setShareOwner('shareOwner')
518
-			->setPermissions(19)
519
-			->setShareType(IShare::TYPE_REMOTE)
520
-			->setNode($node);
521
-		$this->provider->create($share2);
522
-
523
-		$shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, null, false, -1, 0);
524
-
525
-		$this->assertCount(1, $shares);
526
-		$this->assertEquals('[email protected]', $shares[0]->getSharedWith());
527
-		$this->assertEquals('sharedBy', $shares[0]->getSharedBy());
528
-	}
529
-
530
-	public function testGetSharedByWithNode(): void {
531
-		$node = $this->createMock(File::class);
532
-		$node->method('getId')->willReturn(42);
533
-		$node->method('getName')->willReturn('myFile');
534
-
535
-		$this->tokenHandler->method('generateToken')->willReturn('token');
536
-		$this->notifications
537
-			->method('sendRemoteShare')
538
-			->willReturn(true);
539
-
540
-		$this->rootFolder->expects($this->never())->method($this->anything());
541
-
542
-		$this->addressHandler->method('generateRemoteURL')
543
-			->willReturn('remoteurl.com');
544
-
545
-		$this->contactsManager->expects($this->any())
546
-			->method('search')
547
-			->willReturn([]);
548
-
549
-		$share = $this->shareManager->newShare();
550
-		$share->setSharedWith('[email protected]')
551
-			->setSharedBy('sharedBy')
552
-			->setShareOwner('shareOwner')
553
-			->setPermissions(19)
554
-			->setShareType(IShare::TYPE_REMOTE)
555
-			->setNode($node);
556
-		$this->provider->create($share);
557
-
558
-		$node2 = $this->getMockBuilder(File::class)->getMock();
559
-		$node2->method('getId')->willReturn(43);
560
-		$node2->method('getName')->willReturn('myOtherFile');
561
-
562
-		$share2 = $this->shareManager->newShare();
563
-		$share2->setSharedWith('[email protected]')
564
-			->setSharedBy('sharedBy')
565
-			->setShareOwner('shareOwner')
566
-			->setPermissions(19)
567
-			->setShareType(IShare::TYPE_REMOTE)
568
-			->setNode($node2);
569
-		$this->provider->create($share2);
570
-
571
-		$shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, $node2, false, -1, 0);
572
-
573
-		$this->assertCount(1, $shares);
574
-		$this->assertEquals(43, $shares[0]->getNodeId());
575
-	}
576
-
577
-	public function testGetSharedByWithReshares(): void {
578
-		$node = $this->createMock(File::class);
579
-		$node->method('getId')->willReturn(42);
580
-		$node->method('getName')->willReturn('myFile');
581
-
582
-		$this->tokenHandler->method('generateToken')->willReturn('token');
583
-		$this->notifications
584
-			->method('sendRemoteShare')
585
-			->willReturn(true);
586
-
587
-		$this->rootFolder->expects($this->never())->method($this->anything());
588
-
589
-		$this->addressHandler->method('generateRemoteURL')
590
-			->willReturn('remoteurl.com');
591
-
592
-		$this->contactsManager->expects($this->any())
593
-			->method('search')
594
-			->willReturn([]);
595
-
596
-		$share = $this->shareManager->newShare();
597
-		$share->setSharedWith('[email protected]')
598
-			->setSharedBy('shareOwner')
599
-			->setShareOwner('shareOwner')
600
-			->setPermissions(19)
601
-			->setShareType(IShare::TYPE_REMOTE)
602
-			->setNode($node);
603
-		$this->provider->create($share);
604
-
605
-		$share2 = $this->shareManager->newShare();
606
-		$share2->setSharedWith('[email protected]')
607
-			->setSharedBy('sharedBy')
608
-			->setShareOwner('shareOwner')
609
-			->setPermissions(19)
610
-			->setShareType(IShare::TYPE_REMOTE)
611
-			->setNode($node);
612
-		$this->provider->create($share2);
613
-
614
-		$shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, -1, 0);
615
-
616
-		$this->assertCount(2, $shares);
617
-	}
618
-
619
-	public function testGetSharedByWithLimit(): void {
620
-		$node = $this->createMock(File::class);
621
-		$node->method('getId')->willReturn(42);
622
-		$node->method('getName')->willReturn('myFile');
623
-
624
-		$this->addressHandler->expects($this->any())->method('splitUserRemote')
625
-			->willReturnCallback(function ($uid) {
626
-				if ($uid === '[email protected]') {
627
-					return ['user', 'server.com'];
628
-				}
629
-				return ['user2', 'server.com'];
630
-			});
631
-
632
-		$this->tokenHandler->method('generateToken')->willReturn('token');
633
-		$this->notifications
634
-			->method('sendRemoteShare')
635
-			->willReturn(true);
636
-
637
-		$this->rootFolder->expects($this->never())->method($this->anything());
638
-
639
-		$this->addressHandler->method('generateRemoteURL')
640
-			->willReturn('remoteurl.com');
641
-
642
-		$this->contactsManager->expects($this->any())
643
-			->method('search')
644
-			->willReturn([]);
645
-
646
-		$share = $this->shareManager->newShare();
647
-		$share->setSharedWith('[email protected]')
648
-			->setSharedBy('sharedBy')
649
-			->setShareOwner('shareOwner')
650
-			->setPermissions(19)
651
-			->setShareType(IShare::TYPE_REMOTE)
652
-			->setNode($node);
653
-		$this->provider->create($share);
654
-
655
-		$share2 = $this->shareManager->newShare();
656
-		$share2->setSharedWith('[email protected]')
657
-			->setSharedBy('sharedBy')
658
-			->setShareOwner('shareOwner')
659
-			->setPermissions(19)
660
-			->setShareType(IShare::TYPE_REMOTE)
661
-			->setNode($node);
662
-		$this->provider->create($share2);
663
-
664
-		$shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, 1, 1);
665
-
666
-		$this->assertCount(1, $shares);
667
-		$this->assertEquals('[email protected]', $shares[0]->getSharedWith());
668
-	}
669
-
670
-	public static function dataDeleteUser(): array {
671
-		return [
672
-			['a', 'b', 'c', 'a', true],
673
-			['a', 'b', 'c', 'b', false],
674
-			// The recipient is non local.
675
-			['a', 'b', 'c', 'c', false],
676
-			['a', 'b', 'c', 'd', false],
677
-		];
678
-	}
679
-
680
-	/**
681
-	 *
682
-	 * @param string $owner The owner of the share (uid)
683
-	 * @param string $initiator The initiator of the share (uid)
684
-	 * @param string $recipient The recipient of the share (uid/gid/pass)
685
-	 * @param string $deletedUser The user that is deleted
686
-	 * @param bool $rowDeleted Is the row deleted in this setup
687
-	 */
688
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataDeleteUser')]
689
-	public function testDeleteUser(string $owner, string $initiator, string $recipient, string $deletedUser, bool $rowDeleted): void {
690
-		$qb = $this->connection->getQueryBuilder();
691
-		$qb->insert('share')
692
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
693
-			->setValue('uid_owner', $qb->createNamedParameter($owner))
694
-			->setValue('uid_initiator', $qb->createNamedParameter($initiator))
695
-			->setValue('share_with', $qb->createNamedParameter($recipient))
696
-			->setValue('item_type', $qb->createNamedParameter('file'))
697
-			->setValue('item_source', $qb->createNamedParameter(42))
698
-			->setValue('file_source', $qb->createNamedParameter(42))
699
-			->executeStatement();
700
-
701
-		$id = $qb->getLastInsertId();
702
-
703
-		$this->provider->userDeleted($deletedUser, IShare::TYPE_REMOTE);
704
-
705
-		$qb = $this->connection->getQueryBuilder();
706
-		$qb->select('*')
707
-			->from('share')
708
-			->where(
709
-				$qb->expr()->eq('id', $qb->createNamedParameter($id))
710
-			);
711
-		$cursor = $qb->executeQuery();
712
-		$data = $cursor->fetchAllAssociative();
713
-		$cursor->closeCursor();
714
-
715
-		$this->assertCount($rowDeleted ? 0 : 1, $data);
716
-	}
717
-
718
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsOutgoingServer2serverShareEnabled')]
719
-	public function testIsOutgoingServer2serverShareEnabled(bool $internalOnly, string $isEnabled, bool $expected): void {
720
-		$this->gsConfig->expects($this->once())->method('onlyInternalFederation')
721
-			->willReturn($internalOnly);
722
-		$this->config->expects($this->any())->method('getAppValue')
723
-			->with('files_sharing', 'outgoing_server2server_share_enabled', 'yes')
724
-			->willReturn($isEnabled);
725
-
726
-		$this->assertSame($expected,
727
-			$this->provider->isOutgoingServer2serverShareEnabled()
728
-		);
729
-	}
730
-
731
-	public static function dataTestIsOutgoingServer2serverShareEnabled(): array {
732
-		return [
733
-			[false, 'yes', true],
734
-			[false, 'no', false],
735
-			[true, 'yes', false],
736
-			[true, 'no', false],
737
-		];
738
-	}
739
-
740
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsIncomingServer2serverShareEnabled')]
741
-	public function testIsIncomingServer2serverShareEnabled(bool $onlyInternal, string $isEnabled, bool $expected): void {
742
-		$this->gsConfig->expects($this->once())->method('onlyInternalFederation')
743
-			->willReturn($onlyInternal);
744
-		$this->config->expects($this->any())->method('getAppValue')
745
-			->with('files_sharing', 'incoming_server2server_share_enabled', 'yes')
746
-			->willReturn($isEnabled);
747
-
748
-		$this->assertSame($expected,
749
-			$this->provider->isIncomingServer2serverShareEnabled()
750
-		);
751
-	}
752
-
753
-	public static function dataTestIsIncomingServer2serverShareEnabled(): array {
754
-		return [
755
-			[false, 'yes', true],
756
-			[false, 'no', false],
757
-			[true, 'yes', false],
758
-			[true, 'no', false],
759
-		];
760
-	}
761
-
762
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsLookupServerQueriesEnabled')]
763
-	public function testIsLookupServerQueriesEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
764
-		$this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
765
-			->willReturn($gsEnabled);
766
-		$this->config->expects($this->any())->method('getAppValue')
767
-			->with('files_sharing', 'lookupServerEnabled', 'no')
768
-			->willReturn($isEnabled);
769
-
770
-		$this->assertSame($expected,
771
-			$this->provider->isLookupServerQueriesEnabled()
772
-		);
773
-	}
774
-
775
-
776
-	public static function dataTestIsLookupServerQueriesEnabled(): array {
777
-		return [
778
-			[true, 'yes', true],
779
-			[true, 'no', true],
780
-			// TODO: reenable if we use the lookup server for non-global scale
781
-			// [false, 'yes', true],
782
-			// [false, 'no', false],
783
-			[false, 'no', false],
784
-			[false, 'yes', false],
785
-		];
786
-	}
787
-
788
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsLookupServerUploadEnabled')]
789
-	public function testIsLookupServerUploadEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
790
-		$this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
791
-			->willReturn($gsEnabled);
792
-		$this->config->expects($this->any())->method('getAppValue')
793
-			->with('files_sharing', 'lookupServerUploadEnabled', 'no')
794
-			->willReturn($isEnabled);
795
-
796
-		$this->assertSame($expected,
797
-			$this->provider->isLookupServerUploadEnabled()
798
-		);
799
-	}
800
-
801
-	public static function dataTestIsLookupServerUploadEnabled(): array {
802
-		return [
803
-			[true, 'yes', false],
804
-			[true, 'no', false],
805
-			// TODO: reenable if we use the lookup server again
806
-			// [false, 'yes', true],
807
-			// [false, 'no', false],
808
-			[false, 'yes', false],
809
-			[false, 'no', false],
810
-		];
811
-	}
812
-
813
-	public function testGetSharesInFolder(): void {
814
-		$userManager = Server::get(IUserManager::class);
815
-		$rootFolder = Server::get(IRootFolder::class);
816
-
817
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
818
-		$u2 = $userManager->createUser('testFed2', md5((string)time()));
819
-
820
-		$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
821
-		$file1 = $folder1->newFile('bar1');
822
-		$file2 = $folder1->newFile('bar2');
823
-
824
-		$this->tokenHandler->method('generateToken')->willReturn('token');
825
-		$this->notifications
826
-			->method('sendRemoteShare')
827
-			->willReturn(true);
828
-
829
-		$this->addressHandler->method('generateRemoteURL')
830
-			->willReturn('remoteurl.com');
831
-
832
-		$this->contactsManager->expects($this->any())
833
-			->method('search')
834
-			->willReturn([]);
835
-
836
-		$share1 = $this->shareManager->newShare();
837
-		$share1->setSharedWith('[email protected]')
838
-			->setSharedBy($u1->getUID())
839
-			->setShareOwner($u1->getUID())
840
-			->setPermissions(Constants::PERMISSION_READ)
841
-			->setShareType(IShare::TYPE_REMOTE)
842
-			->setNode($file1);
843
-		$this->provider->create($share1);
844
-
845
-		$share2 = $this->shareManager->newShare();
846
-		$share2->setSharedWith('[email protected]')
847
-			->setSharedBy($u2->getUID())
848
-			->setShareOwner($u1->getUID())
849
-			->setPermissions(Constants::PERMISSION_READ)
850
-			->setShareType(IShare::TYPE_REMOTE)
851
-			->setNode($file2);
852
-		$this->provider->create($share2);
853
-
854
-		$result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, false);
855
-		$this->assertCount(1, $result);
856
-		$this->assertCount(1, $result[$file1->getId()]);
857
-
858
-		$result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, true);
859
-		$this->assertCount(2, $result);
860
-		$this->assertCount(1, $result[$file1->getId()]);
861
-		$this->assertCount(1, $result[$file2->getId()]);
862
-
863
-		$u1->delete();
864
-		$u2->delete();
865
-	}
866
-
867
-	public function testGetAccessList(): void {
868
-		$userManager = Server::get(IUserManager::class);
869
-		$rootFolder = Server::get(IRootFolder::class);
870
-
871
-		$u1 = $userManager->createUser('testFed', md5((string)time()));
872
-
873
-		$folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
874
-		$file1 = $folder1->newFile('bar1');
875
-
876
-		$this->tokenHandler->expects($this->exactly(2))
877
-			->method('generateToken')
878
-			->willReturnOnConsecutiveCalls('token1', 'token2');
879
-		$this->notifications->expects($this->atLeastOnce())
880
-			->method('sendRemoteShare')
881
-			->willReturn(true);
882
-
883
-		$this->contactsManager->expects($this->any())
884
-			->method('search')
885
-			->willReturn([]);
886
-
887
-		$result = $this->provider->getAccessList([$file1], true);
888
-		$this->assertEquals(['remote' => []], $result);
889
-
890
-		$result = $this->provider->getAccessList([$file1], false);
891
-		$this->assertEquals(['remote' => false], $result);
892
-
893
-		$this->addressHandler->method('generateRemoteURL')
894
-			->willReturn('remoteurl.com');
895
-
896
-		$share1 = $this->shareManager->newShare();
897
-		$share1->setSharedWith('[email protected]')
898
-			->setSharedBy($u1->getUID())
899
-			->setShareOwner($u1->getUID())
900
-			->setPermissions(Constants::PERMISSION_READ)
901
-			->setShareType(IShare::TYPE_REMOTE)
902
-			->setNode($file1);
903
-		$this->provider->create($share1);
904
-
905
-		$share2 = $this->shareManager->newShare();
906
-		$share2->setSharedWith('foobar@localhost')
907
-			->setSharedBy($u1->getUID())
908
-			->setShareOwner($u1->getUID())
909
-			->setPermissions(Constants::PERMISSION_READ)
910
-			->setShareType(IShare::TYPE_REMOTE)
911
-			->setNode($file1);
912
-		$this->provider->create($share2);
913
-
914
-		$result = $this->provider->getAccessList([$file1], true);
915
-		$this->assertEquals(['remote' => [
916
-			'[email protected]' => [
917
-				'token' => 'token1',
918
-				'node_id' => $file1->getId(),
919
-			],
920
-			'foobar@localhost' => [
921
-				'token' => 'token2',
922
-				'node_id' => $file1->getId(),
923
-			],
924
-		]], $result);
925
-
926
-		$result = $this->provider->getAccessList([$file1], false);
927
-		$this->assertEquals(['remote' => true], $result);
928
-
929
-		$u1->delete();
930
-	}
43
+    protected IDBConnection $connection;
44
+    protected AddressHandler&MockObject $addressHandler;
45
+    protected Notifications&MockObject $notifications;
46
+    protected TokenHandler&MockObject $tokenHandler;
47
+    protected IL10N $l;
48
+    protected LoggerInterface $logger;
49
+    protected IRootFolder&MockObject $rootFolder;
50
+    protected IConfig&MockObject $config;
51
+    protected IUserManager&MockObject $userManager;
52
+    protected \OCP\GlobalScale\IConfig&MockObject $gsConfig;
53
+    protected IManager $shareManager;
54
+    protected FederatedShareProvider $provider;
55
+    protected IContactsManager&MockObject $contactsManager;
56
+    private ICloudIdManager $cloudIdManager;
57
+    private ICloudFederationProviderManager&MockObject $cloudFederationProviderManager;
58
+
59
+    protected function setUp(): void {
60
+        parent::setUp();
61
+
62
+        $this->connection = Server::get(IDBConnection::class);
63
+        $this->notifications = $this->createMock(Notifications::class);
64
+        $this->tokenHandler = $this->createMock(TokenHandler::class);
65
+        $this->l = $this->createMock(IL10N::class);
66
+        $this->l->method('t')
67
+            ->willReturnCallback(function ($text, $parameters = []) {
68
+                return vsprintf($text, $parameters);
69
+            });
70
+        $this->logger = $this->createMock(LoggerInterface::class);
71
+        $this->rootFolder = $this->createMock(IRootFolder::class);
72
+        $this->config = $this->createMock(IConfig::class);
73
+        $this->userManager = $this->createMock(IUserManager::class);
74
+        //$this->addressHandler = new AddressHandler(\OC::$server->getURLGenerator(), $this->l);
75
+        $this->addressHandler = $this->createMock(AddressHandler::class);
76
+        $this->contactsManager = $this->createMock(IContactsManager::class);
77
+        $this->cloudIdManager = new CloudIdManager(
78
+            $this->createMock(ICacheFactory::class),
79
+            $this->createMock(IEventDispatcher::class),
80
+            $this->contactsManager,
81
+            $this->createMock(IURLGenerator::class),
82
+            $this->userManager,
83
+        );
84
+        $this->gsConfig = $this->createMock(\OCP\GlobalScale\IConfig::class);
85
+
86
+        $this->userManager->expects($this->any())->method('userExists')->willReturn(true);
87
+
88
+        $this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
89
+
90
+        $this->provider = new FederatedShareProvider(
91
+            $this->connection,
92
+            $this->addressHandler,
93
+            $this->notifications,
94
+            $this->tokenHandler,
95
+            $this->l,
96
+            $this->rootFolder,
97
+            $this->config,
98
+            $this->userManager,
99
+            $this->cloudIdManager,
100
+            $this->gsConfig,
101
+            $this->cloudFederationProviderManager,
102
+            $this->logger,
103
+        );
104
+
105
+        $this->shareManager = Server::get(IManager::class);
106
+    }
107
+
108
+    protected function tearDown(): void {
109
+        $this->connection->getQueryBuilder()->delete('share')->executeStatement();
110
+
111
+        parent::tearDown();
112
+    }
113
+
114
+    public static function dataTestCreate(): array {
115
+        return [
116
+            [null, null],
117
+            [new \DateTime('2020-03-01T01:02:03'), '2020-03-01 01:02:03'],
118
+        ];
119
+    }
120
+
121
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestCreate')]
122
+    public function testCreate(?\DateTime $expirationDate, ?string $expectedDataDate): void {
123
+        $share = $this->shareManager->newShare();
124
+
125
+        /** @var File&MockObject $node */
126
+        $node = $this->createMock(File::class);
127
+        $node->method('getId')->willReturn(42);
128
+        $node->method('getName')->willReturn('myFile');
129
+
130
+        $share->setSharedWith('[email protected]')
131
+            ->setSharedBy('sharedBy')
132
+            ->setShareOwner('shareOwner')
133
+            ->setPermissions(19)
134
+            ->setShareType(IShare::TYPE_REMOTE)
135
+            ->setExpirationDate($expirationDate)
136
+            ->setNode($node);
137
+
138
+        $this->tokenHandler->method('generateToken')->willReturn('token');
139
+
140
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
141
+            ->willReturn('http://localhost/');
142
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
143
+            ->willReturn(['user', 'server.com']);
144
+
145
+        $this->notifications->expects($this->once())
146
+            ->method('sendRemoteShare')
147
+            ->with(
148
+                $this->equalTo('token'),
149
+                $this->equalTo('[email protected]'),
150
+                $this->equalTo('myFile'),
151
+                $this->anything(),
152
+                'shareOwner',
153
+                'shareOwner@http://localhost',
154
+                'sharedBy',
155
+                'sharedBy@http://localhost'
156
+            )
157
+            ->willReturn(true);
158
+
159
+        $this->rootFolder->expects($this->never())->method($this->anything());
160
+
161
+        $this->contactsManager->expects($this->any())
162
+            ->method('search')
163
+            ->willReturn([]);
164
+
165
+        $share = $this->provider->create($share);
166
+
167
+        $qb = $this->connection->getQueryBuilder();
168
+        $stmt = $qb->select('*')
169
+            ->from('share')
170
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
171
+            ->executeQuery();
172
+
173
+        $data = $stmt->fetchAssociative();
174
+        $stmt->closeCursor();
175
+
176
+        $expected = [
177
+            'share_type' => IShare::TYPE_REMOTE,
178
+            'share_with' => '[email protected]',
179
+            'uid_owner' => 'shareOwner',
180
+            'uid_initiator' => 'sharedBy',
181
+            'item_type' => 'file',
182
+            'item_source' => 42,
183
+            'file_source' => 42,
184
+            'permissions' => 19,
185
+            'accepted' => 0,
186
+            'token' => 'token',
187
+            'expiration' => $expectedDataDate,
188
+        ];
189
+        foreach (array_keys($expected) as $key) {
190
+            $this->assertEquals($expected[$key], $data[$key], "Assert that value for key '$key' is the same");
191
+        }
192
+
193
+        $this->assertEquals($data['id'], $share->getId());
194
+        $this->assertEquals(IShare::TYPE_REMOTE, $share->getShareType());
195
+        $this->assertEquals('[email protected]', $share->getSharedWith());
196
+        $this->assertEquals('sharedBy', $share->getSharedBy());
197
+        $this->assertEquals('shareOwner', $share->getShareOwner());
198
+        $this->assertEquals('file', $share->getNodeType());
199
+        $this->assertEquals(42, $share->getNodeId());
200
+        $this->assertEquals(19, $share->getPermissions());
201
+        $this->assertEquals('token', $share->getToken());
202
+        $this->assertEquals($expirationDate, $share->getExpirationDate());
203
+    }
204
+
205
+    public function testCreateCouldNotFindServer(): void {
206
+        $this->expectException(LogicException::class);
207
+        $share = $this->shareManager->newShare();
208
+
209
+        $node = $this->createMock(File::class);
210
+        $node->method('getId')->willReturn(42);
211
+        $node->method('getName')->willReturn('myFile');
212
+
213
+        $share->setSharedWith('[email protected]')
214
+            ->setSharedBy('sharedBy')
215
+            ->setShareOwner('shareOwner')
216
+            ->setPermissions(19)
217
+            ->setShareType(IShare::TYPE_REMOTE)
218
+            ->setNode($node);
219
+
220
+        $this->tokenHandler->method('generateToken')->willReturn('token');
221
+
222
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
223
+            ->willReturn('http://localhost/');
224
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
225
+            ->willReturn(['user', 'server.com']);
226
+
227
+        $this->notifications->expects($this->once())
228
+            ->method('sendRemoteShare')
229
+            ->with(
230
+                $this->equalTo('token'),
231
+                $this->equalTo('[email protected]'),
232
+                $this->equalTo('myFile'),
233
+                $this->anything(),
234
+                'shareOwner',
235
+                'shareOwner@http://localhost',
236
+                'sharedBy',
237
+                'sharedBy@http://localhost'
238
+            )->willReturn(false);
239
+
240
+        $this->rootFolder->method('getById')
241
+            ->with('42')
242
+            ->willReturn([$node]);
243
+
244
+        $this->contactsManager->expects($this->any())
245
+            ->method('search')
246
+            ->willReturn([]);
247
+
248
+        try {
249
+            $share = $this->provider->create($share);
250
+            $this->fail();
251
+        } catch (\Exception $e) {
252
+            $this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
253
+        }
254
+
255
+        $share->getId();
256
+    }
257
+
258
+    public function testCreateException(): void {
259
+        $this->expectException(LogicException::class);
260
+        $share = $this->shareManager->newShare();
261
+
262
+        $node = $this->createMock(File::class);
263
+        $node->method('getId')->willReturn(42);
264
+        $node->method('getName')->willReturn('myFile');
265
+
266
+        $share->setSharedWith('[email protected]')
267
+            ->setSharedBy('sharedBy')
268
+            ->setShareOwner('shareOwner')
269
+            ->setPermissions(19)
270
+            ->setShareType(IShare::TYPE_REMOTE)
271
+            ->setNode($node);
272
+
273
+        $this->tokenHandler->method('generateToken')->willReturn('token');
274
+
275
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
276
+            ->willReturn('http://localhost/');
277
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
278
+            ->willReturn(['user', 'server.com']);
279
+
280
+        $this->notifications->expects($this->once())
281
+            ->method('sendRemoteShare')
282
+            ->with(
283
+                $this->equalTo('token'),
284
+                $this->equalTo('[email protected]'),
285
+                $this->equalTo('myFile'),
286
+                $this->anything(),
287
+                'shareOwner',
288
+                'shareOwner@http://localhost',
289
+                'sharedBy',
290
+                'sharedBy@http://localhost'
291
+            )->willThrowException(new \Exception('dummy'));
292
+
293
+        $this->rootFolder->method('getById')
294
+            ->with('42')
295
+            ->willReturn([$node]);
296
+
297
+        $this->contactsManager->expects($this->any())
298
+            ->method('search')
299
+            ->willReturn([]);
300
+
301
+        try {
302
+            $share = $this->provider->create($share);
303
+            $this->fail();
304
+        } catch (\Exception $e) {
305
+            $this->assertEquals('Sharing myFile failed, could not find [email protected], maybe the server is currently unreachable or uses a self-signed certificate.', $e->getMessage());
306
+        }
307
+
308
+        $share->getId();
309
+    }
310
+
311
+    public function testCreateShareWithSelf(): void {
312
+        $this->expectException(LogicException::class);
313
+        $share = $this->shareManager->newShare();
314
+
315
+        $node = $this->createMock(File::class);
316
+        $node->method('getId')->willReturn(42);
317
+        $node->method('getName')->willReturn('myFile');
318
+
319
+        $this->addressHandler->expects($this->any())->method('compareAddresses')
320
+            ->willReturn(true);
321
+
322
+        $shareWith = 'sharedBy@localhost';
323
+
324
+        $share->setSharedWith($shareWith)
325
+            ->setSharedBy('sharedBy')
326
+            ->setShareOwner('shareOwner')
327
+            ->setPermissions(19)
328
+            ->setNode($node);
329
+
330
+        $this->contactsManager->expects($this->any())
331
+            ->method('search')
332
+            ->willReturn([]);
333
+
334
+        $this->rootFolder->expects($this->never())->method($this->anything());
335
+
336
+        try {
337
+            $share = $this->provider->create($share);
338
+            $this->fail();
339
+        } catch (\Exception $e) {
340
+            $this->assertEquals('Not allowed to create a federated share to the same account', $e->getMessage());
341
+        }
342
+
343
+        $share->getId();
344
+    }
345
+
346
+    public function testCreateAlreadyShared(): void {
347
+        $share = $this->shareManager->newShare();
348
+
349
+        $node = $this->createMock(File::class);
350
+        $node->method('getId')->willReturn(42);
351
+        $node->method('getName')->willReturn('myFile');
352
+
353
+
354
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
355
+            ->willReturn(['user', 'server.com']);
356
+
357
+        $share->setSharedWith('[email protected]')
358
+            ->setSharedBy('sharedBy')
359
+            ->setShareOwner('shareOwner')
360
+            ->setPermissions(19)
361
+            ->setShareType(IShare::TYPE_REMOTE)
362
+            ->setNode($node);
363
+
364
+        $this->tokenHandler->method('generateToken')->willReturn('token');
365
+
366
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
367
+            ->willReturn('http://localhost/');
368
+
369
+        $this->notifications->expects($this->once())
370
+            ->method('sendRemoteShare')
371
+            ->with(
372
+                $this->equalTo('token'),
373
+                $this->equalTo('[email protected]'),
374
+                $this->equalTo('myFile'),
375
+                $this->anything(),
376
+                'shareOwner',
377
+                'shareOwner@http://localhost',
378
+                'sharedBy',
379
+                'sharedBy@http://localhost'
380
+            )->willReturn(true);
381
+
382
+        $this->rootFolder->expects($this->never())->method($this->anything());
383
+
384
+        $this->contactsManager->expects($this->any())
385
+            ->method('search')
386
+            ->willReturn([]);
387
+
388
+        $this->provider->create($share);
389
+
390
+        try {
391
+            $this->provider->create($share);
392
+        } catch (\Exception $e) {
393
+            $this->assertEquals('Sharing myFile failed, because this item is already shared with the account [email protected]', $e->getMessage());
394
+        }
395
+    }
396
+
397
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestUpdate')]
398
+    public function testUpdate(string $owner, string $sharedBy, ?\DateTime $expirationDate): void {
399
+        $this->provider = $this->getMockBuilder(FederatedShareProvider::class)
400
+            ->setConstructorArgs(
401
+                [
402
+                    $this->connection,
403
+                    $this->addressHandler,
404
+                    $this->notifications,
405
+                    $this->tokenHandler,
406
+                    $this->l,
407
+                    $this->rootFolder,
408
+                    $this->config,
409
+                    $this->userManager,
410
+                    $this->cloudIdManager,
411
+                    $this->gsConfig,
412
+                    $this->cloudFederationProviderManager,
413
+                    $this->logger,
414
+                ]
415
+            )
416
+            ->onlyMethods(['sendPermissionUpdate'])
417
+            ->getMock();
418
+
419
+        $share = $this->shareManager->newShare();
420
+
421
+        $node = $this->createMock(File::class);
422
+        $node->method('getId')->willReturn(42);
423
+        $node->method('getName')->willReturn('myFile');
424
+
425
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
426
+            ->willReturn(['user', 'server.com']);
427
+
428
+        $share->setSharedWith('[email protected]')
429
+            ->setSharedBy($sharedBy)
430
+            ->setShareOwner($owner)
431
+            ->setPermissions(19)
432
+            ->setShareType(IShare::TYPE_REMOTE)
433
+            ->setExpirationDate(new \DateTime('2019-02-01T01:02:03'))
434
+            ->setNode($node);
435
+
436
+        $this->tokenHandler->method('generateToken')->willReturn('token');
437
+        $this->addressHandler->expects($this->any())->method('generateRemoteURL')
438
+            ->willReturn('http://localhost/');
439
+
440
+        $this->notifications->expects($this->once())
441
+            ->method('sendRemoteShare')
442
+            ->with(
443
+                $this->equalTo('token'),
444
+                $this->equalTo('[email protected]'),
445
+                $this->equalTo('myFile'),
446
+                $this->anything(),
447
+                $owner,
448
+                $owner . '@http://localhost',
449
+                $sharedBy,
450
+                $sharedBy . '@http://localhost'
451
+            )->willReturn(true);
452
+
453
+        if ($owner === $sharedBy) {
454
+            $this->provider->expects($this->never())->method('sendPermissionUpdate');
455
+        } else {
456
+            $this->provider->expects($this->once())->method('sendPermissionUpdate');
457
+        }
458
+
459
+        $this->rootFolder->expects($this->never())->method($this->anything());
460
+
461
+        $this->contactsManager->expects($this->any())
462
+            ->method('search')
463
+            ->willReturn([]);
464
+
465
+        $share = $this->provider->create($share);
466
+
467
+        $share->setPermissions(1);
468
+        $share->setExpirationDate($expirationDate);
469
+        $this->provider->update($share);
470
+
471
+        $share = $this->provider->getShareById($share->getId());
472
+
473
+        $this->assertEquals(1, $share->getPermissions());
474
+        $this->assertEquals($expirationDate, $share->getExpirationDate());
475
+    }
476
+
477
+    public static function dataTestUpdate(): array {
478
+        return [
479
+            ['sharedBy', 'shareOwner', new \DateTime('2020-03-01T01:02:03')],
480
+            ['shareOwner', 'shareOwner', null],
481
+        ];
482
+    }
483
+
484
+    public function testGetSharedBy(): void {
485
+        $node = $this->createMock(File::class);
486
+        $node->method('getId')->willReturn(42);
487
+        $node->method('getName')->willReturn('myFile');
488
+
489
+        $this->addressHandler->expects($this->never())->method('splitUserRemote');
490
+
491
+        $this->addressHandler->method('generateRemoteURL')
492
+            ->willReturn('remoteurl.com');
493
+
494
+        $this->tokenHandler->method('generateToken')->willReturn('token');
495
+        $this->notifications
496
+            ->method('sendRemoteShare')
497
+            ->willReturn(true);
498
+
499
+        $this->rootFolder->expects($this->never())->method($this->anything());
500
+
501
+        $this->contactsManager->expects($this->any())
502
+            ->method('search')
503
+            ->willReturn([]);
504
+
505
+        $share = $this->shareManager->newShare();
506
+        $share->setSharedWith('[email protected]')
507
+            ->setSharedBy('sharedBy')
508
+            ->setShareOwner('shareOwner')
509
+            ->setPermissions(19)
510
+            ->setShareType(IShare::TYPE_REMOTE)
511
+            ->setNode($node);
512
+        $this->provider->create($share);
513
+
514
+        $share2 = $this->shareManager->newShare();
515
+        $share2->setSharedWith('[email protected]')
516
+            ->setSharedBy('sharedBy2')
517
+            ->setShareOwner('shareOwner')
518
+            ->setPermissions(19)
519
+            ->setShareType(IShare::TYPE_REMOTE)
520
+            ->setNode($node);
521
+        $this->provider->create($share2);
522
+
523
+        $shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, null, false, -1, 0);
524
+
525
+        $this->assertCount(1, $shares);
526
+        $this->assertEquals('[email protected]', $shares[0]->getSharedWith());
527
+        $this->assertEquals('sharedBy', $shares[0]->getSharedBy());
528
+    }
529
+
530
+    public function testGetSharedByWithNode(): void {
531
+        $node = $this->createMock(File::class);
532
+        $node->method('getId')->willReturn(42);
533
+        $node->method('getName')->willReturn('myFile');
534
+
535
+        $this->tokenHandler->method('generateToken')->willReturn('token');
536
+        $this->notifications
537
+            ->method('sendRemoteShare')
538
+            ->willReturn(true);
539
+
540
+        $this->rootFolder->expects($this->never())->method($this->anything());
541
+
542
+        $this->addressHandler->method('generateRemoteURL')
543
+            ->willReturn('remoteurl.com');
544
+
545
+        $this->contactsManager->expects($this->any())
546
+            ->method('search')
547
+            ->willReturn([]);
548
+
549
+        $share = $this->shareManager->newShare();
550
+        $share->setSharedWith('[email protected]')
551
+            ->setSharedBy('sharedBy')
552
+            ->setShareOwner('shareOwner')
553
+            ->setPermissions(19)
554
+            ->setShareType(IShare::TYPE_REMOTE)
555
+            ->setNode($node);
556
+        $this->provider->create($share);
557
+
558
+        $node2 = $this->getMockBuilder(File::class)->getMock();
559
+        $node2->method('getId')->willReturn(43);
560
+        $node2->method('getName')->willReturn('myOtherFile');
561
+
562
+        $share2 = $this->shareManager->newShare();
563
+        $share2->setSharedWith('[email protected]')
564
+            ->setSharedBy('sharedBy')
565
+            ->setShareOwner('shareOwner')
566
+            ->setPermissions(19)
567
+            ->setShareType(IShare::TYPE_REMOTE)
568
+            ->setNode($node2);
569
+        $this->provider->create($share2);
570
+
571
+        $shares = $this->provider->getSharesBy('sharedBy', IShare::TYPE_REMOTE, $node2, false, -1, 0);
572
+
573
+        $this->assertCount(1, $shares);
574
+        $this->assertEquals(43, $shares[0]->getNodeId());
575
+    }
576
+
577
+    public function testGetSharedByWithReshares(): void {
578
+        $node = $this->createMock(File::class);
579
+        $node->method('getId')->willReturn(42);
580
+        $node->method('getName')->willReturn('myFile');
581
+
582
+        $this->tokenHandler->method('generateToken')->willReturn('token');
583
+        $this->notifications
584
+            ->method('sendRemoteShare')
585
+            ->willReturn(true);
586
+
587
+        $this->rootFolder->expects($this->never())->method($this->anything());
588
+
589
+        $this->addressHandler->method('generateRemoteURL')
590
+            ->willReturn('remoteurl.com');
591
+
592
+        $this->contactsManager->expects($this->any())
593
+            ->method('search')
594
+            ->willReturn([]);
595
+
596
+        $share = $this->shareManager->newShare();
597
+        $share->setSharedWith('[email protected]')
598
+            ->setSharedBy('shareOwner')
599
+            ->setShareOwner('shareOwner')
600
+            ->setPermissions(19)
601
+            ->setShareType(IShare::TYPE_REMOTE)
602
+            ->setNode($node);
603
+        $this->provider->create($share);
604
+
605
+        $share2 = $this->shareManager->newShare();
606
+        $share2->setSharedWith('[email protected]')
607
+            ->setSharedBy('sharedBy')
608
+            ->setShareOwner('shareOwner')
609
+            ->setPermissions(19)
610
+            ->setShareType(IShare::TYPE_REMOTE)
611
+            ->setNode($node);
612
+        $this->provider->create($share2);
613
+
614
+        $shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, -1, 0);
615
+
616
+        $this->assertCount(2, $shares);
617
+    }
618
+
619
+    public function testGetSharedByWithLimit(): void {
620
+        $node = $this->createMock(File::class);
621
+        $node->method('getId')->willReturn(42);
622
+        $node->method('getName')->willReturn('myFile');
623
+
624
+        $this->addressHandler->expects($this->any())->method('splitUserRemote')
625
+            ->willReturnCallback(function ($uid) {
626
+                if ($uid === '[email protected]') {
627
+                    return ['user', 'server.com'];
628
+                }
629
+                return ['user2', 'server.com'];
630
+            });
631
+
632
+        $this->tokenHandler->method('generateToken')->willReturn('token');
633
+        $this->notifications
634
+            ->method('sendRemoteShare')
635
+            ->willReturn(true);
636
+
637
+        $this->rootFolder->expects($this->never())->method($this->anything());
638
+
639
+        $this->addressHandler->method('generateRemoteURL')
640
+            ->willReturn('remoteurl.com');
641
+
642
+        $this->contactsManager->expects($this->any())
643
+            ->method('search')
644
+            ->willReturn([]);
645
+
646
+        $share = $this->shareManager->newShare();
647
+        $share->setSharedWith('[email protected]')
648
+            ->setSharedBy('sharedBy')
649
+            ->setShareOwner('shareOwner')
650
+            ->setPermissions(19)
651
+            ->setShareType(IShare::TYPE_REMOTE)
652
+            ->setNode($node);
653
+        $this->provider->create($share);
654
+
655
+        $share2 = $this->shareManager->newShare();
656
+        $share2->setSharedWith('[email protected]')
657
+            ->setSharedBy('sharedBy')
658
+            ->setShareOwner('shareOwner')
659
+            ->setPermissions(19)
660
+            ->setShareType(IShare::TYPE_REMOTE)
661
+            ->setNode($node);
662
+        $this->provider->create($share2);
663
+
664
+        $shares = $this->provider->getSharesBy('shareOwner', IShare::TYPE_REMOTE, null, true, 1, 1);
665
+
666
+        $this->assertCount(1, $shares);
667
+        $this->assertEquals('[email protected]', $shares[0]->getSharedWith());
668
+    }
669
+
670
+    public static function dataDeleteUser(): array {
671
+        return [
672
+            ['a', 'b', 'c', 'a', true],
673
+            ['a', 'b', 'c', 'b', false],
674
+            // The recipient is non local.
675
+            ['a', 'b', 'c', 'c', false],
676
+            ['a', 'b', 'c', 'd', false],
677
+        ];
678
+    }
679
+
680
+    /**
681
+     *
682
+     * @param string $owner The owner of the share (uid)
683
+     * @param string $initiator The initiator of the share (uid)
684
+     * @param string $recipient The recipient of the share (uid/gid/pass)
685
+     * @param string $deletedUser The user that is deleted
686
+     * @param bool $rowDeleted Is the row deleted in this setup
687
+     */
688
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataDeleteUser')]
689
+    public function testDeleteUser(string $owner, string $initiator, string $recipient, string $deletedUser, bool $rowDeleted): void {
690
+        $qb = $this->connection->getQueryBuilder();
691
+        $qb->insert('share')
692
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
693
+            ->setValue('uid_owner', $qb->createNamedParameter($owner))
694
+            ->setValue('uid_initiator', $qb->createNamedParameter($initiator))
695
+            ->setValue('share_with', $qb->createNamedParameter($recipient))
696
+            ->setValue('item_type', $qb->createNamedParameter('file'))
697
+            ->setValue('item_source', $qb->createNamedParameter(42))
698
+            ->setValue('file_source', $qb->createNamedParameter(42))
699
+            ->executeStatement();
700
+
701
+        $id = $qb->getLastInsertId();
702
+
703
+        $this->provider->userDeleted($deletedUser, IShare::TYPE_REMOTE);
704
+
705
+        $qb = $this->connection->getQueryBuilder();
706
+        $qb->select('*')
707
+            ->from('share')
708
+            ->where(
709
+                $qb->expr()->eq('id', $qb->createNamedParameter($id))
710
+            );
711
+        $cursor = $qb->executeQuery();
712
+        $data = $cursor->fetchAllAssociative();
713
+        $cursor->closeCursor();
714
+
715
+        $this->assertCount($rowDeleted ? 0 : 1, $data);
716
+    }
717
+
718
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsOutgoingServer2serverShareEnabled')]
719
+    public function testIsOutgoingServer2serverShareEnabled(bool $internalOnly, string $isEnabled, bool $expected): void {
720
+        $this->gsConfig->expects($this->once())->method('onlyInternalFederation')
721
+            ->willReturn($internalOnly);
722
+        $this->config->expects($this->any())->method('getAppValue')
723
+            ->with('files_sharing', 'outgoing_server2server_share_enabled', 'yes')
724
+            ->willReturn($isEnabled);
725
+
726
+        $this->assertSame($expected,
727
+            $this->provider->isOutgoingServer2serverShareEnabled()
728
+        );
729
+    }
730
+
731
+    public static function dataTestIsOutgoingServer2serverShareEnabled(): array {
732
+        return [
733
+            [false, 'yes', true],
734
+            [false, 'no', false],
735
+            [true, 'yes', false],
736
+            [true, 'no', false],
737
+        ];
738
+    }
739
+
740
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsIncomingServer2serverShareEnabled')]
741
+    public function testIsIncomingServer2serverShareEnabled(bool $onlyInternal, string $isEnabled, bool $expected): void {
742
+        $this->gsConfig->expects($this->once())->method('onlyInternalFederation')
743
+            ->willReturn($onlyInternal);
744
+        $this->config->expects($this->any())->method('getAppValue')
745
+            ->with('files_sharing', 'incoming_server2server_share_enabled', 'yes')
746
+            ->willReturn($isEnabled);
747
+
748
+        $this->assertSame($expected,
749
+            $this->provider->isIncomingServer2serverShareEnabled()
750
+        );
751
+    }
752
+
753
+    public static function dataTestIsIncomingServer2serverShareEnabled(): array {
754
+        return [
755
+            [false, 'yes', true],
756
+            [false, 'no', false],
757
+            [true, 'yes', false],
758
+            [true, 'no', false],
759
+        ];
760
+    }
761
+
762
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsLookupServerQueriesEnabled')]
763
+    public function testIsLookupServerQueriesEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
764
+        $this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
765
+            ->willReturn($gsEnabled);
766
+        $this->config->expects($this->any())->method('getAppValue')
767
+            ->with('files_sharing', 'lookupServerEnabled', 'no')
768
+            ->willReturn($isEnabled);
769
+
770
+        $this->assertSame($expected,
771
+            $this->provider->isLookupServerQueriesEnabled()
772
+        );
773
+    }
774
+
775
+
776
+    public static function dataTestIsLookupServerQueriesEnabled(): array {
777
+        return [
778
+            [true, 'yes', true],
779
+            [true, 'no', true],
780
+            // TODO: reenable if we use the lookup server for non-global scale
781
+            // [false, 'yes', true],
782
+            // [false, 'no', false],
783
+            [false, 'no', false],
784
+            [false, 'yes', false],
785
+        ];
786
+    }
787
+
788
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataTestIsLookupServerUploadEnabled')]
789
+    public function testIsLookupServerUploadEnabled(bool $gsEnabled, string $isEnabled, bool $expected): void {
790
+        $this->gsConfig->expects($this->once())->method('isGlobalScaleEnabled')
791
+            ->willReturn($gsEnabled);
792
+        $this->config->expects($this->any())->method('getAppValue')
793
+            ->with('files_sharing', 'lookupServerUploadEnabled', 'no')
794
+            ->willReturn($isEnabled);
795
+
796
+        $this->assertSame($expected,
797
+            $this->provider->isLookupServerUploadEnabled()
798
+        );
799
+    }
800
+
801
+    public static function dataTestIsLookupServerUploadEnabled(): array {
802
+        return [
803
+            [true, 'yes', false],
804
+            [true, 'no', false],
805
+            // TODO: reenable if we use the lookup server again
806
+            // [false, 'yes', true],
807
+            // [false, 'no', false],
808
+            [false, 'yes', false],
809
+            [false, 'no', false],
810
+        ];
811
+    }
812
+
813
+    public function testGetSharesInFolder(): void {
814
+        $userManager = Server::get(IUserManager::class);
815
+        $rootFolder = Server::get(IRootFolder::class);
816
+
817
+        $u1 = $userManager->createUser('testFed', md5((string)time()));
818
+        $u2 = $userManager->createUser('testFed2', md5((string)time()));
819
+
820
+        $folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
821
+        $file1 = $folder1->newFile('bar1');
822
+        $file2 = $folder1->newFile('bar2');
823
+
824
+        $this->tokenHandler->method('generateToken')->willReturn('token');
825
+        $this->notifications
826
+            ->method('sendRemoteShare')
827
+            ->willReturn(true);
828
+
829
+        $this->addressHandler->method('generateRemoteURL')
830
+            ->willReturn('remoteurl.com');
831
+
832
+        $this->contactsManager->expects($this->any())
833
+            ->method('search')
834
+            ->willReturn([]);
835
+
836
+        $share1 = $this->shareManager->newShare();
837
+        $share1->setSharedWith('[email protected]')
838
+            ->setSharedBy($u1->getUID())
839
+            ->setShareOwner($u1->getUID())
840
+            ->setPermissions(Constants::PERMISSION_READ)
841
+            ->setShareType(IShare::TYPE_REMOTE)
842
+            ->setNode($file1);
843
+        $this->provider->create($share1);
844
+
845
+        $share2 = $this->shareManager->newShare();
846
+        $share2->setSharedWith('[email protected]')
847
+            ->setSharedBy($u2->getUID())
848
+            ->setShareOwner($u1->getUID())
849
+            ->setPermissions(Constants::PERMISSION_READ)
850
+            ->setShareType(IShare::TYPE_REMOTE)
851
+            ->setNode($file2);
852
+        $this->provider->create($share2);
853
+
854
+        $result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, false);
855
+        $this->assertCount(1, $result);
856
+        $this->assertCount(1, $result[$file1->getId()]);
857
+
858
+        $result = $this->provider->getSharesInFolder($u1->getUID(), $folder1, true);
859
+        $this->assertCount(2, $result);
860
+        $this->assertCount(1, $result[$file1->getId()]);
861
+        $this->assertCount(1, $result[$file2->getId()]);
862
+
863
+        $u1->delete();
864
+        $u2->delete();
865
+    }
866
+
867
+    public function testGetAccessList(): void {
868
+        $userManager = Server::get(IUserManager::class);
869
+        $rootFolder = Server::get(IRootFolder::class);
870
+
871
+        $u1 = $userManager->createUser('testFed', md5((string)time()));
872
+
873
+        $folder1 = $rootFolder->getUserFolder($u1->getUID())->newFolder('foo');
874
+        $file1 = $folder1->newFile('bar1');
875
+
876
+        $this->tokenHandler->expects($this->exactly(2))
877
+            ->method('generateToken')
878
+            ->willReturnOnConsecutiveCalls('token1', 'token2');
879
+        $this->notifications->expects($this->atLeastOnce())
880
+            ->method('sendRemoteShare')
881
+            ->willReturn(true);
882
+
883
+        $this->contactsManager->expects($this->any())
884
+            ->method('search')
885
+            ->willReturn([]);
886
+
887
+        $result = $this->provider->getAccessList([$file1], true);
888
+        $this->assertEquals(['remote' => []], $result);
889
+
890
+        $result = $this->provider->getAccessList([$file1], false);
891
+        $this->assertEquals(['remote' => false], $result);
892
+
893
+        $this->addressHandler->method('generateRemoteURL')
894
+            ->willReturn('remoteurl.com');
895
+
896
+        $share1 = $this->shareManager->newShare();
897
+        $share1->setSharedWith('[email protected]')
898
+            ->setSharedBy($u1->getUID())
899
+            ->setShareOwner($u1->getUID())
900
+            ->setPermissions(Constants::PERMISSION_READ)
901
+            ->setShareType(IShare::TYPE_REMOTE)
902
+            ->setNode($file1);
903
+        $this->provider->create($share1);
904
+
905
+        $share2 = $this->shareManager->newShare();
906
+        $share2->setSharedWith('foobar@localhost')
907
+            ->setSharedBy($u1->getUID())
908
+            ->setShareOwner($u1->getUID())
909
+            ->setPermissions(Constants::PERMISSION_READ)
910
+            ->setShareType(IShare::TYPE_REMOTE)
911
+            ->setNode($file1);
912
+        $this->provider->create($share2);
913
+
914
+        $result = $this->provider->getAccessList([$file1], true);
915
+        $this->assertEquals(['remote' => [
916
+            '[email protected]' => [
917
+                'token' => 'token1',
918
+                'node_id' => $file1->getId(),
919
+            ],
920
+            'foobar@localhost' => [
921
+                'token' => 'token2',
922
+                'node_id' => $file1->getId(),
923
+            ],
924
+        ]], $result);
925
+
926
+        $result = $this->provider->getAccessList([$file1], false);
927
+        $this->assertEquals(['remote' => true], $result);
928
+
929
+        $u1->delete();
930
+    }
931 931
 }
Please login to merge, or discard this patch.
apps/files_sharing/tests/Controller/ShareAPIControllerTest.php 1 patch
Indentation   +5568 added lines, -5568 removed lines patch added patch discarded remove patch
@@ -66,517 +66,517 @@  discard block
 block discarded – undo
66 66
  */
67 67
 #[\PHPUnit\Framework\Attributes\Group(name: 'DB')]
68 68
 class ShareAPIControllerTest extends TestCase {
69
-	use EmailValidatorTrait;
70
-
71
-	private string $appName = 'files_sharing';
72
-	private string $currentUser;
73
-
74
-	private ShareAPIController $ocs;
75
-
76
-	private IManager&MockObject $shareManager;
77
-	private IGroupManager&MockObject $groupManager;
78
-	private IUserManager&MockObject $userManager;
79
-	private IRequest&MockObject $request;
80
-	private IRootFolder&MockObject $rootFolder;
81
-	private IURLGenerator&MockObject $urlGenerator;
82
-	private IL10N&MockObject $l;
83
-	private IConfig&MockObject $config;
84
-	private IAppConfig&MockObject $appConfig;
85
-	private IAppManager&MockObject $appManager;
86
-	private ContainerInterface&MockObject $serverContainer;
87
-	private IUserStatusManager&MockObject $userStatusManager;
88
-	private IPreview&MockObject $previewManager;
89
-	private IDateTimeZone&MockObject $dateTimeZone;
90
-	private LoggerInterface&MockObject $logger;
91
-	private IProviderFactory&MockObject $factory;
92
-	private IMailer&MockObject $mailer;
93
-	private ITagManager&MockObject $tagManager;
94
-	private TrustedServers&MockObject $trustedServers;
95
-
96
-	protected function setUp(): void {
97
-		$this->shareManager = $this->createMock(IManager::class);
98
-		$this->shareManager
99
-			->expects($this->any())
100
-			->method('shareApiEnabled')
101
-			->willReturn(true);
102
-		$this->shareManager
103
-			->expects($this->any())
104
-			->method('shareProviderExists')->willReturn(true);
105
-		$this->groupManager = $this->createMock(IGroupManager::class);
106
-		$this->userManager = $this->createMock(IUserManager::class);
107
-		$this->request = $this->createMock(IRequest::class);
108
-		$this->rootFolder = $this->createMock(IRootFolder::class);
109
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
110
-		$this->currentUser = 'currentUser';
111
-
112
-		$this->l = $this->createMock(IL10N::class);
113
-		$this->l->method('t')
114
-			->willReturnCallback(function ($text, $parameters = []) {
115
-				return vsprintf($text, $parameters);
116
-			});
117
-		$this->config = $this->createMock(IConfig::class);
118
-		$this->appConfig = $this->createMock(IAppConfig::class);
119
-		$this->appManager = $this->createMock(IAppManager::class);
120
-		$this->serverContainer = $this->createMock(ContainerInterface::class);
121
-		$this->userStatusManager = $this->createMock(IUserStatusManager::class);
122
-		$this->previewManager = $this->createMock(IPreview::class);
123
-		$this->previewManager->method('isAvailable')
124
-			->willReturnCallback(function ($fileInfo) {
125
-				return $fileInfo->getMimeType() === 'mimeWithPreview';
126
-			});
127
-		$this->dateTimeZone = $this->createMock(IDateTimeZone::class);
128
-		$this->logger = $this->createMock(LoggerInterface::class);
129
-		$this->factory = $this->createMock(IProviderFactory::class);
130
-		$this->mailer = $this->createMock(IMailer::class);
131
-		$this->tagManager = $this->createMock(ITagManager::class);
132
-		$this->trustedServers = $this->createMock(TrustedServers::class);
133
-
134
-		$this->ocs = new ShareAPIController(
135
-			$this->appName,
136
-			$this->request,
137
-			$this->shareManager,
138
-			$this->groupManager,
139
-			$this->userManager,
140
-			$this->rootFolder,
141
-			$this->urlGenerator,
142
-			$this->l,
143
-			$this->config,
144
-			$this->appConfig,
145
-			$this->appManager,
146
-			$this->serverContainer,
147
-			$this->userStatusManager,
148
-			$this->previewManager,
149
-			$this->dateTimeZone,
150
-			$this->logger,
151
-			$this->factory,
152
-			$this->mailer,
153
-			$this->tagManager,
154
-			$this->getEmailValidatorWithStrictEmailCheck(),
155
-			$this->trustedServers,
156
-			$this->currentUser,
157
-		);
158
-
159
-	}
160
-
161
-	/**
162
-	 * @return ShareAPIController&MockObject
163
-	 */
164
-	private function mockFormatShare() {
165
-		return $this->getMockBuilder(ShareAPIController::class)
166
-			->setConstructorArgs([
167
-				$this->appName,
168
-				$this->request,
169
-				$this->shareManager,
170
-				$this->groupManager,
171
-				$this->userManager,
172
-				$this->rootFolder,
173
-				$this->urlGenerator,
174
-				$this->l,
175
-				$this->config,
176
-				$this->appConfig,
177
-				$this->appManager,
178
-				$this->serverContainer,
179
-				$this->userStatusManager,
180
-				$this->previewManager,
181
-				$this->dateTimeZone,
182
-				$this->logger,
183
-				$this->factory,
184
-				$this->mailer,
185
-				$this->tagManager,
186
-				$this->getEmailValidatorWithStrictEmailCheck(),
187
-				$this->trustedServers,
188
-				$this->currentUser,
189
-			])->onlyMethods(['formatShare'])
190
-			->getMock();
191
-	}
192
-
193
-	private function newShare() {
194
-		return Server::get(IManager::class)->newShare();
195
-	}
196
-
197
-
198
-	private function mockShareAttributes() {
199
-		$formattedShareAttributes = [
200
-			[
201
-				'scope' => 'permissions',
202
-				'key' => 'download',
203
-				'value' => true
204
-			]
205
-		];
206
-
207
-		$shareAttributes = $this->createMock(IShareAttributes::class);
208
-		$shareAttributes->method('toArray')->willReturn($formattedShareAttributes);
209
-		$shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
210
-
211
-		// send both IShare attributes class and expected json string
212
-		return [$shareAttributes, \json_encode($formattedShareAttributes)];
213
-	}
214
-
215
-	public function testDeleteShareShareNotFound(): void {
216
-		$this->expectException(OCSNotFoundException::class);
217
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
218
-
219
-		$this->shareManager
220
-			->expects($this->exactly(6))
221
-			->method('getShareById')
222
-			->willReturnCallback(function ($id): void {
223
-				if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42' || $id === 'deck:42') {
224
-					throw new ShareNotFound();
225
-				} else {
226
-					throw new \Exception();
227
-				}
228
-			});
229
-
230
-		$this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
231
-
232
-		$this->ocs->deleteShare(42);
233
-	}
234
-
235
-	public function testDeleteShare(): void {
236
-		$node = $this->getMockBuilder(File::class)->getMock();
237
-
238
-		$share = $this->newShare();
239
-		$share->setSharedBy($this->currentUser)
240
-			->setNode($node);
241
-		$this->shareManager
242
-			->expects($this->once())
243
-			->method('getShareById')
244
-			->with('ocinternal:42')
245
-			->willReturn($share);
246
-		$this->shareManager
247
-			->expects($this->once())
248
-			->method('deleteShare')
249
-			->with($share);
250
-
251
-		$node->expects($this->once())
252
-			->method('lock')
253
-			->with(ILockingProvider::LOCK_SHARED);
254
-
255
-		$expected = new DataResponse();
256
-		$result = $this->ocs->deleteShare(42);
257
-
258
-		$this->assertInstanceOf(get_class($expected), $result);
259
-		$this->assertEquals($expected->getData(), $result->getData());
260
-	}
261
-
262
-
263
-	public function testDeleteShareLocked(): void {
264
-		$this->expectException(OCSNotFoundException::class);
265
-		$this->expectExceptionMessage('Could not delete share');
266
-
267
-		$node = $this->getMockBuilder(File::class)->getMock();
268
-		$node->method('getId')->willReturn(1);
269
-
270
-		$share = $this->newShare();
271
-		$share->setNode($node);
272
-
273
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
274
-		$this->rootFolder->method('getUserFolder')
275
-			->with($this->currentUser)
276
-			->willReturn($userFolder);
277
-
278
-		$userFolder->method('getById')
279
-			->with($share->getNodeId())
280
-			->willReturn([$node]);
281
-
282
-		$this->shareManager
283
-			->expects($this->once())
284
-			->method('getShareById')
285
-			->with('ocinternal:42')
286
-			->willReturn($share);
287
-
288
-		$this->shareManager
289
-			->expects($this->never())
290
-			->method('deleteShare')
291
-			->with($share);
292
-
293
-		$node->expects($this->once())
294
-			->method('lock')
295
-			->with(ILockingProvider::LOCK_SHARED)
296
-			->willThrowException(new LockedException('mypath'));
297
-
298
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
299
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
300
-
301
-		$this->ocs->deleteShare(42);
302
-	}
303
-
304
-	/**
305
-	 * You can always remove a share that was shared with you
306
-	 */
307
-	public function testDeleteShareWithMe(): void {
308
-		$node = $this->getMockBuilder(File::class)->getMock();
309
-
310
-		$share = $this->newShare();
311
-		$share->setSharedWith($this->currentUser)
312
-			->setShareType(IShare::TYPE_USER)
313
-			->setNode($node);
314
-
315
-		$this->shareManager
316
-			->expects($this->once())
317
-			->method('getShareById')
318
-			->with('ocinternal:42')
319
-			->willReturn($share);
320
-
321
-		$this->shareManager
322
-			->expects($this->once())
323
-			->method('deleteShare')
324
-			->with($share);
325
-
326
-		$node->expects($this->once())
327
-			->method('lock')
328
-			->with(ILockingProvider::LOCK_SHARED);
329
-
330
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
331
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
332
-
333
-		$this->ocs->deleteShare(42);
334
-	}
335
-
336
-	/**
337
-	 * You can always delete a share you own
338
-	 */
339
-	public function testDeleteShareOwner(): void {
340
-		$node = $this->getMockBuilder(File::class)->getMock();
341
-
342
-		$share = $this->newShare();
343
-		$share->setSharedBy($this->currentUser)
344
-			->setNode($node);
345
-
346
-		$this->shareManager
347
-			->expects($this->once())
348
-			->method('getShareById')
349
-			->with('ocinternal:42')
350
-			->willReturn($share);
351
-
352
-		$this->shareManager
353
-			->expects($this->once())
354
-			->method('deleteShare')
355
-			->with($share);
356
-
357
-		$node->expects($this->once())
358
-			->method('lock')
359
-			->with(ILockingProvider::LOCK_SHARED);
360
-
361
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
362
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
363
-
364
-		$this->ocs->deleteShare(42);
365
-	}
366
-
367
-	/**
368
-	 * You can always delete a share when you own
369
-	 * the file path it belong to
370
-	 */
371
-	public function testDeleteShareFileOwner(): void {
372
-		$node = $this->getMockBuilder(File::class)->getMock();
373
-		$node->method('getId')->willReturn(1);
374
-
375
-		$share = $this->newShare();
376
-		$share->setShareOwner($this->currentUser)
377
-			->setNode($node);
378
-
379
-		$this->shareManager
380
-			->expects($this->once())
381
-			->method('getShareById')
382
-			->with('ocinternal:42')
383
-			->willReturn($share);
384
-
385
-		$this->shareManager
386
-			->expects($this->once())
387
-			->method('deleteShare')
388
-			->with($share);
389
-
390
-		$node->expects($this->once())
391
-			->method('lock')
392
-			->with(ILockingProvider::LOCK_SHARED);
393
-
394
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
395
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
396
-
397
-		$this->ocs->deleteShare(42);
398
-	}
399
-
400
-	/**
401
-	 * You can remove (the mountpoint, not the share)
402
-	 * a share if you're in the group the share is shared with
403
-	 */
404
-	public function testDeleteSharedWithMyGroup(): void {
405
-		$node = $this->getMockBuilder(File::class)->getMock();
406
-		$node->method('getId')->willReturn(1);
407
-
408
-		$share = $this->newShare();
409
-		$share->setShareType(IShare::TYPE_GROUP)
410
-			->setSharedWith('group')
411
-			->setNode($node);
412
-
413
-		$this->shareManager
414
-			->expects($this->once())
415
-			->method('getShareById')
416
-			->with('ocinternal:42')
417
-			->willReturn($share);
418
-
419
-		// canDeleteShareFromSelf
420
-		$user = $this->createMock(IUser::class);
421
-		$group = $this->getMockBuilder(IGroup::class)->getMock();
422
-		$this->groupManager
423
-			->method('get')
424
-			->with('group')
425
-			->willReturn($group);
426
-		$this->userManager
427
-			->method('get')
428
-			->with($this->currentUser)
429
-			->willReturn($user);
430
-		$group->method('inGroup')
431
-			->with($user)
432
-			->willReturn(true);
433
-
434
-		$node->expects($this->once())
435
-			->method('lock')
436
-			->with(ILockingProvider::LOCK_SHARED);
437
-
438
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
439
-		$this->rootFolder->method('getUserFolder')
440
-			->with($this->currentUser)
441
-			->willReturn($userFolder);
442
-
443
-		$userFolder->method('getById')
444
-			->with($share->getNodeId())
445
-			->willReturn([$share->getNode()]);
446
-
447
-		$this->shareManager->expects($this->once())
448
-			->method('deleteFromSelf')
449
-			->with($share, $this->currentUser);
450
-
451
-		$this->shareManager->expects($this->never())
452
-			->method('deleteShare');
453
-
454
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
455
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
456
-
457
-		$this->ocs->deleteShare(42);
458
-	}
459
-
460
-	/**
461
-	 * You cannot remove a share if you're not
462
-	 * in the group the share is shared with
463
-	 */
464
-	public function testDeleteSharedWithGroupIDontBelongTo(): void {
465
-		$this->expectException(OCSNotFoundException::class);
466
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
467
-
468
-		$node = $this->getMockBuilder(File::class)->getMock();
469
-		$node->method('getId')->willReturn(42);
470
-
471
-		$share = $this->newShare();
472
-		$share->setShareType(IShare::TYPE_GROUP)
473
-			->setSharedWith('group')
474
-			->setNode($node);
475
-
476
-		$this->shareManager
477
-			->expects($this->once())
478
-			->method('getShareById')
479
-			->with('ocinternal:42')
480
-			->willReturn($share);
481
-
482
-		// canDeleteShareFromSelf
483
-		$user = $this->createMock(IUser::class);
484
-		$group = $this->getMockBuilder(IGroup::class)->getMock();
485
-		$this->groupManager
486
-			->method('get')
487
-			->with('group')
488
-			->willReturn($group);
489
-		$this->userManager
490
-			->method('get')
491
-			->with($this->currentUser)
492
-			->willReturn($user);
493
-		$group->method('inGroup')
494
-			->with($user)
495
-			->willReturn(false);
496
-
497
-		$node->expects($this->once())
498
-			->method('lock')
499
-			->with(ILockingProvider::LOCK_SHARED);
500
-
501
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
502
-		$this->rootFolder->method('getUserFolder')
503
-			->with($this->currentUser)
504
-			->willReturn($userFolder);
505
-
506
-		$userFolder->method('getById')
507
-			->with($share->getNodeId())
508
-			->willReturn([$share->getNode()]);
509
-
510
-		$this->shareManager->expects($this->never())
511
-			->method('deleteFromSelf');
512
-
513
-		$this->shareManager->expects($this->never())
514
-			->method('deleteShare');
515
-
516
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
517
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
518
-
519
-		$this->ocs->deleteShare(42);
520
-	}
521
-
522
-	public function testDeleteShareOwnerless(): void {
523
-		$ocs = $this->mockFormatShare();
524
-
525
-		$mount = $this->createMock(IShareOwnerlessMount::class);
526
-
527
-		$file = $this->createMock(File::class);
528
-		$file
529
-			->expects($this->exactly(2))
530
-			->method('getPermissions')
531
-			->willReturn(Constants::PERMISSION_SHARE);
532
-		$file
533
-			->expects($this->once())
534
-			->method('getMountPoint')
535
-			->willReturn($mount);
536
-
537
-		$userFolder = $this->createMock(Folder::class);
538
-		$userFolder->method('getById')
539
-			->with(2)
540
-			->willReturn([$file]);
541
-		$userFolder->method('getFirstNodeById')
542
-			->with(2)
543
-			->willReturn($file);
544
-
545
-		$this->rootFolder
546
-			->method('getUserFolder')
547
-			->with($this->currentUser)
548
-			->willReturn($userFolder);
549
-
550
-		$share = $this->createMock(IShare::class);
551
-		$share
552
-			->expects($this->once())
553
-			->method('getNode')
554
-			->willReturn($file);
555
-		$share
556
-			->expects($this->exactly(2))
557
-			->method('getNodeId')
558
-			->willReturn(2);
559
-		$share
560
-			->expects($this->exactly(2))
561
-			->method('getPermissions')
562
-			->willReturn(Constants::PERMISSION_SHARE);
563
-
564
-		$this->shareManager
565
-			->expects($this->once())
566
-			->method('getShareById')
567
-			->with('ocinternal:1', $this->currentUser)
568
-			->willReturn($share);
569
-
570
-		$this->shareManager
571
-			->expects($this->once())
572
-			->method('deleteShare')
573
-			->with($share);
574
-
575
-		$result = $ocs->deleteShare(1);
576
-		$this->assertInstanceOf(DataResponse::class, $result);
577
-	}
578
-
579
-	/*
69
+    use EmailValidatorTrait;
70
+
71
+    private string $appName = 'files_sharing';
72
+    private string $currentUser;
73
+
74
+    private ShareAPIController $ocs;
75
+
76
+    private IManager&MockObject $shareManager;
77
+    private IGroupManager&MockObject $groupManager;
78
+    private IUserManager&MockObject $userManager;
79
+    private IRequest&MockObject $request;
80
+    private IRootFolder&MockObject $rootFolder;
81
+    private IURLGenerator&MockObject $urlGenerator;
82
+    private IL10N&MockObject $l;
83
+    private IConfig&MockObject $config;
84
+    private IAppConfig&MockObject $appConfig;
85
+    private IAppManager&MockObject $appManager;
86
+    private ContainerInterface&MockObject $serverContainer;
87
+    private IUserStatusManager&MockObject $userStatusManager;
88
+    private IPreview&MockObject $previewManager;
89
+    private IDateTimeZone&MockObject $dateTimeZone;
90
+    private LoggerInterface&MockObject $logger;
91
+    private IProviderFactory&MockObject $factory;
92
+    private IMailer&MockObject $mailer;
93
+    private ITagManager&MockObject $tagManager;
94
+    private TrustedServers&MockObject $trustedServers;
95
+
96
+    protected function setUp(): void {
97
+        $this->shareManager = $this->createMock(IManager::class);
98
+        $this->shareManager
99
+            ->expects($this->any())
100
+            ->method('shareApiEnabled')
101
+            ->willReturn(true);
102
+        $this->shareManager
103
+            ->expects($this->any())
104
+            ->method('shareProviderExists')->willReturn(true);
105
+        $this->groupManager = $this->createMock(IGroupManager::class);
106
+        $this->userManager = $this->createMock(IUserManager::class);
107
+        $this->request = $this->createMock(IRequest::class);
108
+        $this->rootFolder = $this->createMock(IRootFolder::class);
109
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
110
+        $this->currentUser = 'currentUser';
111
+
112
+        $this->l = $this->createMock(IL10N::class);
113
+        $this->l->method('t')
114
+            ->willReturnCallback(function ($text, $parameters = []) {
115
+                return vsprintf($text, $parameters);
116
+            });
117
+        $this->config = $this->createMock(IConfig::class);
118
+        $this->appConfig = $this->createMock(IAppConfig::class);
119
+        $this->appManager = $this->createMock(IAppManager::class);
120
+        $this->serverContainer = $this->createMock(ContainerInterface::class);
121
+        $this->userStatusManager = $this->createMock(IUserStatusManager::class);
122
+        $this->previewManager = $this->createMock(IPreview::class);
123
+        $this->previewManager->method('isAvailable')
124
+            ->willReturnCallback(function ($fileInfo) {
125
+                return $fileInfo->getMimeType() === 'mimeWithPreview';
126
+            });
127
+        $this->dateTimeZone = $this->createMock(IDateTimeZone::class);
128
+        $this->logger = $this->createMock(LoggerInterface::class);
129
+        $this->factory = $this->createMock(IProviderFactory::class);
130
+        $this->mailer = $this->createMock(IMailer::class);
131
+        $this->tagManager = $this->createMock(ITagManager::class);
132
+        $this->trustedServers = $this->createMock(TrustedServers::class);
133
+
134
+        $this->ocs = new ShareAPIController(
135
+            $this->appName,
136
+            $this->request,
137
+            $this->shareManager,
138
+            $this->groupManager,
139
+            $this->userManager,
140
+            $this->rootFolder,
141
+            $this->urlGenerator,
142
+            $this->l,
143
+            $this->config,
144
+            $this->appConfig,
145
+            $this->appManager,
146
+            $this->serverContainer,
147
+            $this->userStatusManager,
148
+            $this->previewManager,
149
+            $this->dateTimeZone,
150
+            $this->logger,
151
+            $this->factory,
152
+            $this->mailer,
153
+            $this->tagManager,
154
+            $this->getEmailValidatorWithStrictEmailCheck(),
155
+            $this->trustedServers,
156
+            $this->currentUser,
157
+        );
158
+
159
+    }
160
+
161
+    /**
162
+     * @return ShareAPIController&MockObject
163
+     */
164
+    private function mockFormatShare() {
165
+        return $this->getMockBuilder(ShareAPIController::class)
166
+            ->setConstructorArgs([
167
+                $this->appName,
168
+                $this->request,
169
+                $this->shareManager,
170
+                $this->groupManager,
171
+                $this->userManager,
172
+                $this->rootFolder,
173
+                $this->urlGenerator,
174
+                $this->l,
175
+                $this->config,
176
+                $this->appConfig,
177
+                $this->appManager,
178
+                $this->serverContainer,
179
+                $this->userStatusManager,
180
+                $this->previewManager,
181
+                $this->dateTimeZone,
182
+                $this->logger,
183
+                $this->factory,
184
+                $this->mailer,
185
+                $this->tagManager,
186
+                $this->getEmailValidatorWithStrictEmailCheck(),
187
+                $this->trustedServers,
188
+                $this->currentUser,
189
+            ])->onlyMethods(['formatShare'])
190
+            ->getMock();
191
+    }
192
+
193
+    private function newShare() {
194
+        return Server::get(IManager::class)->newShare();
195
+    }
196
+
197
+
198
+    private function mockShareAttributes() {
199
+        $formattedShareAttributes = [
200
+            [
201
+                'scope' => 'permissions',
202
+                'key' => 'download',
203
+                'value' => true
204
+            ]
205
+        ];
206
+
207
+        $shareAttributes = $this->createMock(IShareAttributes::class);
208
+        $shareAttributes->method('toArray')->willReturn($formattedShareAttributes);
209
+        $shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
210
+
211
+        // send both IShare attributes class and expected json string
212
+        return [$shareAttributes, \json_encode($formattedShareAttributes)];
213
+    }
214
+
215
+    public function testDeleteShareShareNotFound(): void {
216
+        $this->expectException(OCSNotFoundException::class);
217
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
218
+
219
+        $this->shareManager
220
+            ->expects($this->exactly(6))
221
+            ->method('getShareById')
222
+            ->willReturnCallback(function ($id): void {
223
+                if ($id === 'ocinternal:42' || $id === 'ocRoomShare:42' || $id === 'ocFederatedSharing:42' || $id === 'ocCircleShare:42' || $id === 'ocMailShare:42' || $id === 'deck:42') {
224
+                    throw new ShareNotFound();
225
+                } else {
226
+                    throw new \Exception();
227
+                }
228
+            });
229
+
230
+        $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
231
+
232
+        $this->ocs->deleteShare(42);
233
+    }
234
+
235
+    public function testDeleteShare(): void {
236
+        $node = $this->getMockBuilder(File::class)->getMock();
237
+
238
+        $share = $this->newShare();
239
+        $share->setSharedBy($this->currentUser)
240
+            ->setNode($node);
241
+        $this->shareManager
242
+            ->expects($this->once())
243
+            ->method('getShareById')
244
+            ->with('ocinternal:42')
245
+            ->willReturn($share);
246
+        $this->shareManager
247
+            ->expects($this->once())
248
+            ->method('deleteShare')
249
+            ->with($share);
250
+
251
+        $node->expects($this->once())
252
+            ->method('lock')
253
+            ->with(ILockingProvider::LOCK_SHARED);
254
+
255
+        $expected = new DataResponse();
256
+        $result = $this->ocs->deleteShare(42);
257
+
258
+        $this->assertInstanceOf(get_class($expected), $result);
259
+        $this->assertEquals($expected->getData(), $result->getData());
260
+    }
261
+
262
+
263
+    public function testDeleteShareLocked(): void {
264
+        $this->expectException(OCSNotFoundException::class);
265
+        $this->expectExceptionMessage('Could not delete share');
266
+
267
+        $node = $this->getMockBuilder(File::class)->getMock();
268
+        $node->method('getId')->willReturn(1);
269
+
270
+        $share = $this->newShare();
271
+        $share->setNode($node);
272
+
273
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
274
+        $this->rootFolder->method('getUserFolder')
275
+            ->with($this->currentUser)
276
+            ->willReturn($userFolder);
277
+
278
+        $userFolder->method('getById')
279
+            ->with($share->getNodeId())
280
+            ->willReturn([$node]);
281
+
282
+        $this->shareManager
283
+            ->expects($this->once())
284
+            ->method('getShareById')
285
+            ->with('ocinternal:42')
286
+            ->willReturn($share);
287
+
288
+        $this->shareManager
289
+            ->expects($this->never())
290
+            ->method('deleteShare')
291
+            ->with($share);
292
+
293
+        $node->expects($this->once())
294
+            ->method('lock')
295
+            ->with(ILockingProvider::LOCK_SHARED)
296
+            ->willThrowException(new LockedException('mypath'));
297
+
298
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
299
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
300
+
301
+        $this->ocs->deleteShare(42);
302
+    }
303
+
304
+    /**
305
+     * You can always remove a share that was shared with you
306
+     */
307
+    public function testDeleteShareWithMe(): void {
308
+        $node = $this->getMockBuilder(File::class)->getMock();
309
+
310
+        $share = $this->newShare();
311
+        $share->setSharedWith($this->currentUser)
312
+            ->setShareType(IShare::TYPE_USER)
313
+            ->setNode($node);
314
+
315
+        $this->shareManager
316
+            ->expects($this->once())
317
+            ->method('getShareById')
318
+            ->with('ocinternal:42')
319
+            ->willReturn($share);
320
+
321
+        $this->shareManager
322
+            ->expects($this->once())
323
+            ->method('deleteShare')
324
+            ->with($share);
325
+
326
+        $node->expects($this->once())
327
+            ->method('lock')
328
+            ->with(ILockingProvider::LOCK_SHARED);
329
+
330
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
331
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
332
+
333
+        $this->ocs->deleteShare(42);
334
+    }
335
+
336
+    /**
337
+     * You can always delete a share you own
338
+     */
339
+    public function testDeleteShareOwner(): void {
340
+        $node = $this->getMockBuilder(File::class)->getMock();
341
+
342
+        $share = $this->newShare();
343
+        $share->setSharedBy($this->currentUser)
344
+            ->setNode($node);
345
+
346
+        $this->shareManager
347
+            ->expects($this->once())
348
+            ->method('getShareById')
349
+            ->with('ocinternal:42')
350
+            ->willReturn($share);
351
+
352
+        $this->shareManager
353
+            ->expects($this->once())
354
+            ->method('deleteShare')
355
+            ->with($share);
356
+
357
+        $node->expects($this->once())
358
+            ->method('lock')
359
+            ->with(ILockingProvider::LOCK_SHARED);
360
+
361
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
362
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
363
+
364
+        $this->ocs->deleteShare(42);
365
+    }
366
+
367
+    /**
368
+     * You can always delete a share when you own
369
+     * the file path it belong to
370
+     */
371
+    public function testDeleteShareFileOwner(): void {
372
+        $node = $this->getMockBuilder(File::class)->getMock();
373
+        $node->method('getId')->willReturn(1);
374
+
375
+        $share = $this->newShare();
376
+        $share->setShareOwner($this->currentUser)
377
+            ->setNode($node);
378
+
379
+        $this->shareManager
380
+            ->expects($this->once())
381
+            ->method('getShareById')
382
+            ->with('ocinternal:42')
383
+            ->willReturn($share);
384
+
385
+        $this->shareManager
386
+            ->expects($this->once())
387
+            ->method('deleteShare')
388
+            ->with($share);
389
+
390
+        $node->expects($this->once())
391
+            ->method('lock')
392
+            ->with(ILockingProvider::LOCK_SHARED);
393
+
394
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteFromSelf', [$share]));
395
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
396
+
397
+        $this->ocs->deleteShare(42);
398
+    }
399
+
400
+    /**
401
+     * You can remove (the mountpoint, not the share)
402
+     * a share if you're in the group the share is shared with
403
+     */
404
+    public function testDeleteSharedWithMyGroup(): void {
405
+        $node = $this->getMockBuilder(File::class)->getMock();
406
+        $node->method('getId')->willReturn(1);
407
+
408
+        $share = $this->newShare();
409
+        $share->setShareType(IShare::TYPE_GROUP)
410
+            ->setSharedWith('group')
411
+            ->setNode($node);
412
+
413
+        $this->shareManager
414
+            ->expects($this->once())
415
+            ->method('getShareById')
416
+            ->with('ocinternal:42')
417
+            ->willReturn($share);
418
+
419
+        // canDeleteShareFromSelf
420
+        $user = $this->createMock(IUser::class);
421
+        $group = $this->getMockBuilder(IGroup::class)->getMock();
422
+        $this->groupManager
423
+            ->method('get')
424
+            ->with('group')
425
+            ->willReturn($group);
426
+        $this->userManager
427
+            ->method('get')
428
+            ->with($this->currentUser)
429
+            ->willReturn($user);
430
+        $group->method('inGroup')
431
+            ->with($user)
432
+            ->willReturn(true);
433
+
434
+        $node->expects($this->once())
435
+            ->method('lock')
436
+            ->with(ILockingProvider::LOCK_SHARED);
437
+
438
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
439
+        $this->rootFolder->method('getUserFolder')
440
+            ->with($this->currentUser)
441
+            ->willReturn($userFolder);
442
+
443
+        $userFolder->method('getById')
444
+            ->with($share->getNodeId())
445
+            ->willReturn([$share->getNode()]);
446
+
447
+        $this->shareManager->expects($this->once())
448
+            ->method('deleteFromSelf')
449
+            ->with($share, $this->currentUser);
450
+
451
+        $this->shareManager->expects($this->never())
452
+            ->method('deleteShare');
453
+
454
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
455
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
456
+
457
+        $this->ocs->deleteShare(42);
458
+    }
459
+
460
+    /**
461
+     * You cannot remove a share if you're not
462
+     * in the group the share is shared with
463
+     */
464
+    public function testDeleteSharedWithGroupIDontBelongTo(): void {
465
+        $this->expectException(OCSNotFoundException::class);
466
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
467
+
468
+        $node = $this->getMockBuilder(File::class)->getMock();
469
+        $node->method('getId')->willReturn(42);
470
+
471
+        $share = $this->newShare();
472
+        $share->setShareType(IShare::TYPE_GROUP)
473
+            ->setSharedWith('group')
474
+            ->setNode($node);
475
+
476
+        $this->shareManager
477
+            ->expects($this->once())
478
+            ->method('getShareById')
479
+            ->with('ocinternal:42')
480
+            ->willReturn($share);
481
+
482
+        // canDeleteShareFromSelf
483
+        $user = $this->createMock(IUser::class);
484
+        $group = $this->getMockBuilder(IGroup::class)->getMock();
485
+        $this->groupManager
486
+            ->method('get')
487
+            ->with('group')
488
+            ->willReturn($group);
489
+        $this->userManager
490
+            ->method('get')
491
+            ->with($this->currentUser)
492
+            ->willReturn($user);
493
+        $group->method('inGroup')
494
+            ->with($user)
495
+            ->willReturn(false);
496
+
497
+        $node->expects($this->once())
498
+            ->method('lock')
499
+            ->with(ILockingProvider::LOCK_SHARED);
500
+
501
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
502
+        $this->rootFolder->method('getUserFolder')
503
+            ->with($this->currentUser)
504
+            ->willReturn($userFolder);
505
+
506
+        $userFolder->method('getById')
507
+            ->with($share->getNodeId())
508
+            ->willReturn([$share->getNode()]);
509
+
510
+        $this->shareManager->expects($this->never())
511
+            ->method('deleteFromSelf');
512
+
513
+        $this->shareManager->expects($this->never())
514
+            ->method('deleteShare');
515
+
516
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShareFromSelf', [$share]));
517
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canDeleteShare', [$share]));
518
+
519
+        $this->ocs->deleteShare(42);
520
+    }
521
+
522
+    public function testDeleteShareOwnerless(): void {
523
+        $ocs = $this->mockFormatShare();
524
+
525
+        $mount = $this->createMock(IShareOwnerlessMount::class);
526
+
527
+        $file = $this->createMock(File::class);
528
+        $file
529
+            ->expects($this->exactly(2))
530
+            ->method('getPermissions')
531
+            ->willReturn(Constants::PERMISSION_SHARE);
532
+        $file
533
+            ->expects($this->once())
534
+            ->method('getMountPoint')
535
+            ->willReturn($mount);
536
+
537
+        $userFolder = $this->createMock(Folder::class);
538
+        $userFolder->method('getById')
539
+            ->with(2)
540
+            ->willReturn([$file]);
541
+        $userFolder->method('getFirstNodeById')
542
+            ->with(2)
543
+            ->willReturn($file);
544
+
545
+        $this->rootFolder
546
+            ->method('getUserFolder')
547
+            ->with($this->currentUser)
548
+            ->willReturn($userFolder);
549
+
550
+        $share = $this->createMock(IShare::class);
551
+        $share
552
+            ->expects($this->once())
553
+            ->method('getNode')
554
+            ->willReturn($file);
555
+        $share
556
+            ->expects($this->exactly(2))
557
+            ->method('getNodeId')
558
+            ->willReturn(2);
559
+        $share
560
+            ->expects($this->exactly(2))
561
+            ->method('getPermissions')
562
+            ->willReturn(Constants::PERMISSION_SHARE);
563
+
564
+        $this->shareManager
565
+            ->expects($this->once())
566
+            ->method('getShareById')
567
+            ->with('ocinternal:1', $this->currentUser)
568
+            ->willReturn($share);
569
+
570
+        $this->shareManager
571
+            ->expects($this->once())
572
+            ->method('deleteShare')
573
+            ->with($share);
574
+
575
+        $result = $ocs->deleteShare(1);
576
+        $this->assertInstanceOf(DataResponse::class, $result);
577
+    }
578
+
579
+    /*
580 580
 	 * FIXME: Enable once we have a federated Share Provider
581 581
 
582 582
 	public function testGetGetShareNotExists() {
@@ -591,5061 +591,5061 @@  discard block
 block discarded – undo
591 591
 	}
592 592
 	*/
593 593
 
594
-	public function createShare(
595
-		string $id,
596
-		int $shareType,
597
-		?string $sharedWith,
598
-		string $sharedBy,
599
-		string $shareOwner,
600
-		File|Folder|null $node,
601
-		int $permissions,
602
-		int $shareTime,
603
-		?\DateTime $expiration,
604
-		int $parent,
605
-		string $target,
606
-		int $mail_send,
607
-		string $note = '',
608
-		?string $token = null,
609
-		?string $password = null,
610
-		string $label = '',
611
-		?IShareAttributes $attributes = null,
612
-	): MockObject {
613
-		$share = $this->createMock(IShare::class);
614
-		$share->method('getId')->willReturn($id);
615
-		$share->method('getShareType')->willReturn($shareType);
616
-		$share->method('getSharedWith')->willReturn($sharedWith);
617
-		$share->method('getSharedBy')->willReturn($sharedBy);
618
-		$share->method('getShareOwner')->willReturn($shareOwner);
619
-		$share->method('getNode')->willReturn($node);
620
-		$share->method('getPermissions')->willReturn($permissions);
621
-		$share->method('getNote')->willReturn($note);
622
-		$share->method('getLabel')->willReturn($label);
623
-		$share->method('getAttributes')->willReturn($attributes);
624
-		$time = new \DateTime();
625
-		$time->setTimestamp($shareTime);
626
-		$share->method('getShareTime')->willReturn($time);
627
-		$share->method('getExpirationDate')->willReturn($expiration);
628
-		$share->method('getTarget')->willReturn($target);
629
-		$share->method('getMailSend')->willReturn($mail_send);
630
-		$share->method('getToken')->willReturn($token);
631
-		$share->method('getPassword')->willReturn($password);
632
-
633
-		if ($shareType === IShare::TYPE_USER
634
-			|| $shareType === IShare::TYPE_GROUP
635
-			|| $shareType === IShare::TYPE_LINK) {
636
-			$share->method('getFullId')->willReturn('ocinternal:' . $id);
637
-		}
638
-
639
-		return $share;
640
-	}
641
-
642
-	public static function dataGetShare(): array {
643
-		$data = [];
644
-
645
-		$file = [
646
-			'class' => File::class,
647
-			'id' => 1,
648
-			'path' => 'file',
649
-			'mimeType' => 'myMimeType',
650
-		];
651
-
652
-		$folder = [
653
-			'class' => Folder::class,
654
-			'id' => 2,
655
-			'path' => 'folder',
656
-			'mimeType' => 'myFolderMimeType',
657
-		];
658
-
659
-		// File shared with user
660
-		$share = [
661
-			'100',
662
-			IShare::TYPE_USER,
663
-			'userId',
664
-			'initiatorId',
665
-			'ownerId',
666
-			$file,
667
-			4,
668
-			5,
669
-			null,
670
-			6,
671
-			'target',
672
-			0,
673
-			'personal note',
674
-			null,
675
-			null,
676
-			'',
677
-			[],
678
-		];
679
-		$expected = [
680
-			'id' => '100',
681
-			'share_type' => IShare::TYPE_USER,
682
-			'share_with' => 'userId',
683
-			'share_with_displayname' => 'userDisplay',
684
-			'share_with_displayname_unique' => '[email protected]',
685
-			'uid_owner' => 'initiatorId',
686
-			'displayname_owner' => 'initiatorDisplay',
687
-			'item_type' => 'file',
688
-			'item_source' => 1,
689
-			'file_source' => 1,
690
-			'file_target' => 'target',
691
-			'file_parent' => 3,
692
-			'token' => null,
693
-			'expiration' => null,
694
-			'permissions' => 4,
695
-			'stime' => 5,
696
-			'parent' => null,
697
-			'storage_id' => 'STORAGE',
698
-			'path' => 'file',
699
-			'storage' => 101,
700
-			'mail_send' => 0,
701
-			'uid_file_owner' => 'ownerId',
702
-			'note' => 'personal note',
703
-			'label' => '',
704
-			'displayname_file_owner' => 'ownerDisplay',
705
-			'mimetype' => 'myMimeType',
706
-			'has_preview' => false,
707
-			'hide_download' => 0,
708
-			'can_edit' => false,
709
-			'can_delete' => false,
710
-			'item_size' => 123465,
711
-			'item_mtime' => 1234567890,
712
-			'item_permissions' => 4,
713
-			'is-mount-root' => false,
714
-			'mount-type' => '',
715
-		];
716
-		$data['File shared with user'] = [$share, $expected, true];
717
-
718
-		// Folder shared with group
719
-		$share = [
720
-			'101',
721
-			IShare::TYPE_GROUP,
722
-			'groupId',
723
-			'initiatorId',
724
-			'ownerId',
725
-			$folder,
726
-			4,
727
-			5,
728
-			null,
729
-			6,
730
-			'target',
731
-			0,
732
-			'personal note',
733
-			null,
734
-			null,
735
-			'',
736
-			[],
737
-		];
738
-		$expected = [
739
-			'id' => '101',
740
-			'share_type' => IShare::TYPE_GROUP,
741
-			'share_with' => 'groupId',
742
-			'share_with_displayname' => 'groupId',
743
-			'uid_owner' => 'initiatorId',
744
-			'displayname_owner' => 'initiatorDisplay',
745
-			'item_type' => 'folder',
746
-			'item_source' => 2,
747
-			'file_source' => 2,
748
-			'file_target' => 'target',
749
-			'file_parent' => 3,
750
-			'token' => null,
751
-			'expiration' => null,
752
-			'permissions' => 4,
753
-			'stime' => 5,
754
-			'parent' => null,
755
-			'storage_id' => 'STORAGE',
756
-			'path' => 'folder',
757
-			'storage' => 101,
758
-			'mail_send' => 0,
759
-			'uid_file_owner' => 'ownerId',
760
-			'note' => 'personal note',
761
-			'label' => '',
762
-			'displayname_file_owner' => 'ownerDisplay',
763
-			'mimetype' => 'myFolderMimeType',
764
-			'has_preview' => false,
765
-			'hide_download' => 0,
766
-			'can_edit' => false,
767
-			'can_delete' => false,
768
-			'item_size' => 123465,
769
-			'item_mtime' => 1234567890,
770
-			'item_permissions' => 4,
771
-			'is-mount-root' => false,
772
-			'mount-type' => '',
773
-		];
774
-		$data['Folder shared with group'] = [$share, $expected, true];
775
-
776
-		// File shared by link with Expire
777
-		$expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03');
778
-		$share = [
779
-			'101',
780
-			IShare::TYPE_LINK,
781
-			null,
782
-			'initiatorId',
783
-			'ownerId',
784
-			$folder,
785
-			4,
786
-			5,
787
-			$expire,
788
-			6,
789
-			'target',
790
-			0,
791
-			'personal note',
792
-			'token',
793
-			'password',
794
-			'first link share'
795
-		];
796
-		$expected = [
797
-			'id' => '101',
798
-			'share_type' => IShare::TYPE_LINK,
799
-			'password' => 'password',
800
-			'share_with' => 'password',
801
-			'share_with_displayname' => '(Shared link)',
802
-			'send_password_by_talk' => false,
803
-			'uid_owner' => 'initiatorId',
804
-			'displayname_owner' => 'initiatorDisplay',
805
-			'item_type' => 'folder',
806
-			'item_source' => 2,
807
-			'file_source' => 2,
808
-			'file_target' => 'target',
809
-			'file_parent' => 3,
810
-			'token' => 'token',
811
-			'expiration' => '2000-01-02 00:00:00',
812
-			'permissions' => 4,
813
-			'attributes' => null,
814
-			'stime' => 5,
815
-			'parent' => null,
816
-			'storage_id' => 'STORAGE',
817
-			'path' => 'folder',
818
-			'storage' => 101,
819
-			'mail_send' => 0,
820
-			'url' => 'url',
821
-			'uid_file_owner' => 'ownerId',
822
-			'note' => 'personal note',
823
-			'label' => 'first link share',
824
-			'displayname_file_owner' => 'ownerDisplay',
825
-			'mimetype' => 'myFolderMimeType',
826
-			'has_preview' => false,
827
-			'hide_download' => 0,
828
-			'can_edit' => false,
829
-			'can_delete' => false,
830
-			'item_size' => 123465,
831
-			'item_mtime' => 1234567890,
832
-			'item_permissions' => 4,
833
-			'is-mount-root' => false,
834
-			'mount-type' => '',
835
-		];
836
-		$data['File shared by link with Expire'] = [$share, $expected, false];
837
-
838
-		return $data;
839
-	}
840
-
841
-	#[DataProvider(methodName: 'dataGetShare')]
842
-	public function testGetShare(array $shareParams, array $result, bool $attributes): void {
843
-
844
-		$cache = $this->createMock(ICache::class);
845
-		$cache->method('getNumericStorageId')->willReturn(101);
846
-
847
-		$storage = $this->createMock(IStorage::class);
848
-		$storage->method('getId')->willReturn('STORAGE');
849
-		$storage->method('getCache')->willReturn($cache);
850
-
851
-		$parentFolder = $this->createMock(Folder::class);
852
-		$parentFolder->method('getId')->willReturn(3);
853
-
854
-		$mountPoint = $this->createMock(IMountPoint::class);
855
-		$mountPoint->method('getMountType')->willReturn('');
856
-
857
-		$nodeParams = $shareParams[5];
858
-		$node = $this->createMock($nodeParams['class']);
859
-		$node->method('getId')->willReturn($nodeParams['id']);
860
-		$node->method('getPath')->willReturn($nodeParams['path']);
861
-		$node->method('getStorage')->willReturn($storage);
862
-		$node->method('getParent')->willReturn($parentFolder);
863
-		$node->method('getSize')->willReturn(123465);
864
-		$node->method('getMTime')->willReturn(1234567890);
865
-		$node->method('getMimeType')->willReturn($nodeParams['mimeType']);
866
-		$node->method('getMountPoint')->willReturn($mountPoint);
867
-
868
-		$shareParams[5] = $node;
869
-
870
-		if ($attributes) {
871
-			[$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
872
-			$result['attributes'] = $shareAttributesReturnJson;
873
-			$shareParams[16] = $shareAttributes;
874
-		}
875
-
876
-		$share = $this->createShare(...$shareParams);
877
-		/** @var ShareAPIController&MockObject $ocs */
878
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
879
-			->setConstructorArgs([
880
-				$this->appName,
881
-				$this->request,
882
-				$this->shareManager,
883
-				$this->groupManager,
884
-				$this->userManager,
885
-				$this->rootFolder,
886
-				$this->urlGenerator,
887
-				$this->l,
888
-				$this->config,
889
-				$this->appConfig,
890
-				$this->appManager,
891
-				$this->serverContainer,
892
-				$this->userStatusManager,
893
-				$this->previewManager,
894
-				$this->dateTimeZone,
895
-				$this->logger,
896
-				$this->factory,
897
-				$this->mailer,
898
-				$this->tagManager,
899
-				$this->getEmailValidatorWithStrictEmailCheck(),
900
-				$this->trustedServers,
901
-				$this->currentUser,
902
-			])
903
-			->onlyMethods(['canAccessShare'])
904
-			->getMock();
905
-
906
-		$ocs->expects($this->any())
907
-			->method('canAccessShare')
908
-			->willReturn(true);
909
-
910
-		$this->shareManager
911
-			->expects($this->any())
912
-			->method('getShareById')
913
-			->with($share->getFullId(), 'currentUser')
914
-			->willReturn($share);
915
-
916
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
917
-		$userFolder
918
-			->method('getRelativePath')
919
-			->willReturnArgument(0);
920
-
921
-		$userFolder->method('getById')
922
-			->with($share->getNodeId())
923
-			->willReturn([$share->getNode()]);
924
-		$userFolder->method('getFirstNodeById')
925
-			->with($share->getNodeId())
926
-			->willReturn($share->getNode());
927
-
928
-		$this->rootFolder->method('getUserFolder')
929
-			->with($this->currentUser)
930
-			->willReturn($userFolder);
931
-
932
-		$this->urlGenerator
933
-			->method('linkToRouteAbsolute')
934
-			->willReturn('url');
935
-
936
-		$initiator = $this->getMockBuilder(IUser::class)->getMock();
937
-		$initiator->method('getUID')->willReturn('initiatorId');
938
-		$initiator->method('getDisplayName')->willReturn('initiatorDisplay');
939
-
940
-		$owner = $this->getMockBuilder(IUser::class)->getMock();
941
-		$owner->method('getUID')->willReturn('ownerId');
942
-		$owner->method('getDisplayName')->willReturn('ownerDisplay');
943
-
944
-		$user = $this->getMockBuilder(IUser::class)->getMock();
945
-		$user->method('getUID')->willReturn('userId');
946
-		$user->method('getDisplayName')->willReturn('userDisplay');
947
-		$user->method('getSystemEMailAddress')->willReturn('[email protected]');
948
-
949
-		$group = $this->getMockBuilder(IGroup::class)->getMock();
950
-		$group->method('getGID')->willReturn('groupId');
951
-
952
-		$this->userManager->method('get')->willReturnMap([
953
-			['userId', $user],
954
-			['initiatorId', $initiator],
955
-			['ownerId', $owner],
956
-		]);
957
-		$this->groupManager->method('get')->willReturnMap([
958
-			['group', $group],
959
-		]);
960
-		$this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
961
-
962
-		$data = $ocs->getShare((string)$share->getId())->getData()[0];
963
-		$this->assertEquals($result, $data);
964
-	}
965
-
966
-
967
-	public function testGetShareInvalidNode(): void {
968
-		$this->expectException(OCSNotFoundException::class);
969
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
970
-
971
-		$share = Server::get(IManager::class)->newShare();
972
-		$share->setSharedBy('initiator')
973
-			->setSharedWith('recipient')
974
-			->setShareOwner('owner');
975
-
976
-		$this->shareManager
977
-			->expects($this->once())
978
-			->method('getShareById')
979
-			->with('ocinternal:42', 'currentUser')
980
-			->willReturn($share);
981
-
982
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
983
-		$this->rootFolder->method('getUserFolder')
984
-			->with($this->currentUser)
985
-			->willReturn($userFolder);
986
-
987
-		$this->ocs->getShare('42');
988
-	}
989
-
990
-	public static function dataGetShares(): array {
991
-		$file1 = [
992
-			'class' => File::class,
993
-			'methods' => [
994
-				'getName' => 'file1',
995
-			]
996
-		];
997
-		$file2 = [
998
-			'class' => File::class,
999
-			'methods' => [
1000
-				'getName' => 'file2',
1001
-			]
1002
-		];
1003
-
1004
-		$folder = [
1005
-			'class' => Folder::class,
1006
-			'methods' => [
1007
-				'getDirectoryListing' => [$file1, $file2]
1008
-			]
1009
-		];
1010
-
1011
-		$file1UserShareOwner = [
1012
-			'type' => IShare::TYPE_USER,
1013
-			'sharedWith' => 'recipient',
1014
-			'sharedBy' => 'initiator',
1015
-			'owner' => 'currentUser',
1016
-			'node' => $file1,
1017
-			'id' => 4,
1018
-		];
1019
-
1020
-		$file1UserShareOwnerExpected = [
1021
-			'id' => 4,
1022
-			'share_type' => IShare::TYPE_USER,
1023
-		];
1024
-
1025
-		$file1UserShareInitiator = [
1026
-			'type' => IShare::TYPE_USER,
1027
-			'sharedWith' => 'recipient',
1028
-			'sharedBy' => 'currentUser',
1029
-			'owner' => 'owner',
1030
-			'node' => $file1,
1031
-			'id' => 8,
1032
-		];
1033
-
1034
-		$file1UserShareInitiatorExpected = [
1035
-			'id' => 8,
1036
-			'share_type' => IShare::TYPE_USER,
1037
-		];
1038
-
1039
-		$file1UserShareRecipient = [
1040
-			'type' => IShare::TYPE_USER,
1041
-			'sharedWith' => 'currentUser',
1042
-			'sharedBy' => 'initiator',
1043
-			'owner' => 'owner',
1044
-			'node' => $file1,
1045
-			'id' => 15,
1046
-		];
1047
-
1048
-		$file1UserShareRecipientExpected = [
1049
-			'id' => 15,
1050
-			'share_type' => IShare::TYPE_USER,
1051
-		];
1052
-
1053
-		$file1UserShareOther = [
1054
-			'type' => IShare::TYPE_USER,
1055
-			'sharedWith' => 'recipient',
1056
-			'sharedBy' => 'initiator',
1057
-			'owner' => 'owner',
1058
-			'node' => $file1,
1059
-			'id' => 16,
1060
-		];
1061
-
1062
-		$file1UserShareOtherExpected = [
1063
-			'id' => 16,
1064
-			'share_type' => IShare::TYPE_USER,
1065
-		];
1066
-
1067
-		$file1GroupShareOwner = [
1068
-			'type' => IShare::TYPE_GROUP,
1069
-			'sharedWith' => 'recipient',
1070
-			'sharedBy' => 'initiator',
1071
-			'owner' => 'currentUser',
1072
-			'node' => $file1,
1073
-			'id' => 23,
1074
-		];
1075
-
1076
-		$file1GroupShareOwnerExpected = [
1077
-			'id' => 23,
1078
-			'share_type' => IShare::TYPE_GROUP,
1079
-		];
1080
-
1081
-		$file1GroupShareRecipient = [
1082
-			'type' => IShare::TYPE_GROUP,
1083
-			'sharedWith' => 'currentUserGroup',
1084
-			'sharedBy' => 'initiator',
1085
-			'owner' => 'owner',
1086
-			'node' => $file1,
1087
-			'id' => 42,
1088
-		];
1089
-
1090
-		$file1GroupShareRecipientExpected = [
1091
-			'id' => 42,
1092
-			'share_type' => IShare::TYPE_GROUP,
1093
-		];
1094
-
1095
-		$file1GroupShareOther = [
1096
-			'type' => IShare::TYPE_GROUP,
1097
-			'sharedWith' => 'recipient',
1098
-			'sharedBy' => 'initiator',
1099
-			'owner' => 'owner',
1100
-			'node' => $file1,
1101
-			'id' => 108,
1102
-		];
1103
-
1104
-		$file1LinkShareOwner = [
1105
-			'type' => IShare::TYPE_LINK,
1106
-			'sharedWith' => 'recipient',
1107
-			'sharedBy' => 'initiator',
1108
-			'owner' => 'currentUser',
1109
-			'node' => $file1,
1110
-			'id' => 415,
1111
-		];
1112
-
1113
-		$file1LinkShareOwnerExpected = [
1114
-			'id' => 415,
1115
-			'share_type' => IShare::TYPE_LINK,
1116
-		];
1117
-
1118
-		$file1EmailShareOwner = [
1119
-			'type' => IShare::TYPE_EMAIL,
1120
-			'sharedWith' => 'recipient',
1121
-			'sharedBy' => 'initiator',
1122
-			'owner' => 'currentUser',
1123
-			'node' => $file1,
1124
-			'id' => 416,
1125
-		];
1126
-
1127
-		$file1EmailShareOwnerExpected = [
1128
-			'id' => 416,
1129
-			'share_type' => IShare::TYPE_EMAIL,
1130
-		];
1131
-
1132
-		$file1CircleShareOwner = [
1133
-			'type' => IShare::TYPE_CIRCLE,
1134
-			'sharedWith' => 'recipient',
1135
-			'sharedBy' => 'initiator',
1136
-			'owner' => 'currentUser',
1137
-			'node' => $file1,
1138
-			'id' => 423,
1139
-		];
1140
-
1141
-		$file1CircleShareOwnerExpected = [
1142
-			'id' => 423,
1143
-			'share_type' => IShare::TYPE_CIRCLE,
1144
-		];
1145
-
1146
-		$file1RoomShareOwner = [
1147
-			'type' => IShare::TYPE_ROOM,
1148
-			'sharedWith' => 'recipient',
1149
-			'sharedBy' => 'initiator',
1150
-			'owner' => 'currentUser',
1151
-			'node' => $file1,
1152
-			'id' => 442,
1153
-		];
1154
-
1155
-		$file1RoomShareOwnerExpected = [
1156
-			'id' => 442,
1157
-			'share_type' => IShare::TYPE_ROOM,
1158
-		];
1159
-
1160
-		$file1RemoteShareOwner = [
1161
-			'type' => IShare::TYPE_REMOTE,
1162
-			'sharedWith' => 'recipient',
1163
-			'sharedBy' => 'initiator',
1164
-			'owner' => 'currentUser',
1165
-			'expirationDate' => new \DateTime('2000-01-01T01:02:03'),
1166
-			'node' => $file1,
1167
-			'id' => 815,
1168
-		];
1169
-
1170
-		$file1RemoteShareOwnerExpected = [
1171
-			'id' => 815,
1172
-			'share_type' => IShare::TYPE_REMOTE,
1173
-		];
1174
-
1175
-		$file1RemoteGroupShareOwner = [
1176
-			'type' => IShare::TYPE_REMOTE_GROUP,
1177
-			'sharedWith' => 'recipient',
1178
-			'sharedBy' => 'initiator',
1179
-			'owner' => 'currentUser',
1180
-			'expirationDate' => new \DateTime('2000-01-01T01:02:03'),
1181
-			'node' => $file1,
1182
-			'id' => 816,
1183
-		];
1184
-
1185
-		$file1RemoteGroupShareOwnerExpected = [
1186
-			'id' => 816,
1187
-			'share_type' => IShare::TYPE_REMOTE_GROUP,
1188
-		];
1189
-
1190
-		$file2UserShareOwner = [
1191
-			'type' => IShare::TYPE_USER,
1192
-			'sharedWith' => 'recipient',
1193
-			'sharedBy' => 'initiator',
1194
-			'owner' => 'currentUser',
1195
-			'node' => $file2,
1196
-			'id' => 823,
1197
-		];
1198
-
1199
-		$file2UserShareOwnerExpected = [
1200
-			'id' => 823,
1201
-			'share_type' => IShare::TYPE_USER,
1202
-		];
1203
-
1204
-		$data = [
1205
-			[
1206
-				[
1207
-					'node' => $file1,
1208
-				],
1209
-				[
1210
-					'file1' => [
1211
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1212
-					],
1213
-				],
1214
-				[
1215
-				],
1216
-				[
1217
-					$file1UserShareOwnerExpected
1218
-				]
1219
-			],
1220
-			[
1221
-				[
1222
-					'node' => $file1,
1223
-				],
1224
-				[
1225
-					'file1' => [
1226
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1227
-					],
1228
-				],
1229
-				[
1230
-				],
1231
-				[
1232
-					$file1UserShareOwnerExpected,
1233
-				]
1234
-			],
1235
-			[
1236
-				[
1237
-					'node' => $file1,
1238
-				],
1239
-				[
1240
-					'file1' => [
1241
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1242
-					],
1243
-				],
1244
-				[
1245
-				],
1246
-				[
1247
-					$file1UserShareOwnerExpected,
1248
-					$file1UserShareInitiatorExpected,
1249
-					$file1UserShareOtherExpected,
1250
-				]
1251
-			],
1252
-			[
1253
-				[
1254
-					'node' => $file1,
1255
-				],
1256
-				[
1257
-					'file1' => [
1258
-						IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1259
-					],
1260
-				],
1261
-				[
1262
-				],
1263
-				[
1264
-					$file1UserShareInitiatorExpected,
1265
-				]
1266
-			],
1267
-			[
1268
-				[
1269
-					'node' => $file1,
1270
-				],
1271
-				[
1272
-					'file1' => [
1273
-						IShare::TYPE_USER => [$file1UserShareOwner],
1274
-						IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1275
-					],
1276
-				],
1277
-				[
1278
-				],
1279
-				[
1280
-					$file1UserShareOwnerExpected,
1281
-					$file1GroupShareRecipientExpected,
1282
-				]
1283
-			],
1284
-			[
1285
-				[
1286
-					'node' => $file1,
1287
-				],
1288
-				[
1289
-					'file1' => [
1290
-						IShare::TYPE_USER => [$file1UserShareOwner],
1291
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1292
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1293
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1294
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1295
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1296
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1297
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1298
-					],
1299
-				],
1300
-				[
1301
-				],
1302
-				[
1303
-					$file1UserShareOwnerExpected,
1304
-					$file1GroupShareOwnerExpected,
1305
-					$file1LinkShareOwnerExpected,
1306
-					$file1EmailShareOwnerExpected,
1307
-					$file1CircleShareOwnerExpected,
1308
-					$file1RoomShareOwnerExpected,
1309
-				]
1310
-			],
1311
-			[
1312
-				[
1313
-					'node' => $file1,
1314
-				],
1315
-				[
1316
-					'file1' => [
1317
-						IShare::TYPE_USER => [$file1UserShareOwner],
1318
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1319
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1320
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1321
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1322
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1323
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1324
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1325
-					],
1326
-				],
1327
-				[
1328
-					IShare::TYPE_REMOTE => true,
1329
-					IShare::TYPE_REMOTE_GROUP => true,
1330
-				],
1331
-				[
1332
-					$file1UserShareOwnerExpected,
1333
-					$file1GroupShareOwnerExpected,
1334
-					$file1LinkShareOwnerExpected,
1335
-					$file1EmailShareOwnerExpected,
1336
-					$file1CircleShareOwnerExpected,
1337
-					$file1RoomShareOwnerExpected,
1338
-					$file1RemoteShareOwnerExpected,
1339
-					$file1RemoteGroupShareOwnerExpected,
1340
-				]
1341
-			],
1342
-			[
1343
-				[
1344
-					'node' => $folder,
1345
-					'subfiles' => 'true',
1346
-				],
1347
-				[
1348
-					'file1' => [
1349
-						IShare::TYPE_USER => [$file1UserShareOwner],
1350
-					],
1351
-					'file2' => [
1352
-						IShare::TYPE_USER => [$file2UserShareOwner],
1353
-					],
1354
-				],
1355
-				[
1356
-				],
1357
-				[
1358
-					$file1UserShareOwnerExpected,
1359
-					$file2UserShareOwnerExpected,
1360
-				]
1361
-			],
1362
-			[
1363
-				[
1364
-					'node' => $folder,
1365
-					'subfiles' => 'true',
1366
-				],
1367
-				[
1368
-					'file1' => [
1369
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1370
-					],
1371
-				],
1372
-				[
1373
-				],
1374
-				[
1375
-					$file1UserShareOwnerExpected,
1376
-				]
1377
-			],
1378
-			[
1379
-				[
1380
-					'node' => $folder,
1381
-					'subfiles' => 'true',
1382
-				],
1383
-				[
1384
-					'file1' => [
1385
-						IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1386
-					],
1387
-				],
1388
-				[
1389
-				],
1390
-				[
1391
-					$file1UserShareOwnerExpected
1392
-				]
1393
-			],
1394
-			[
1395
-				[
1396
-					'node' => $folder,
1397
-					'subfiles' => 'true',
1398
-				],
1399
-				[
1400
-					'file1' => [
1401
-						IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1402
-					],
1403
-					'file2' => [
1404
-						IShare::TYPE_USER => [$file2UserShareOwner],
1405
-					],
1406
-				],
1407
-				[
1408
-				],
1409
-				[
1410
-					$file1UserShareInitiatorExpected,
1411
-					$file1UserShareOtherExpected,
1412
-					$file2UserShareOwnerExpected,
1413
-				]
1414
-			],
1415
-			// This might not happen in a real environment, as the combination
1416
-			// of shares does not seem to be possible on a folder without
1417
-			// resharing rights; if the folder has resharing rights then the
1418
-			// share with others would be included too in the results.
1419
-			[
1420
-				[
1421
-					'node' => $folder,
1422
-					'subfiles' => 'true',
1423
-				],
1424
-				[
1425
-					'file1' => [
1426
-						IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1427
-					],
1428
-				],
1429
-				[
1430
-				],
1431
-				[
1432
-					$file1UserShareInitiatorExpected,
1433
-				]
1434
-			],
1435
-			[
1436
-				[
1437
-					'node' => $folder,
1438
-					'subfiles' => 'true',
1439
-				],
1440
-				[
1441
-					'file1' => [
1442
-						IShare::TYPE_USER => [$file1UserShareOwner],
1443
-						IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1444
-					],
1445
-				],
1446
-				[
1447
-				],
1448
-				[
1449
-					$file1UserShareOwnerExpected,
1450
-					$file1GroupShareRecipientExpected,
1451
-				]
1452
-			],
1453
-			[
1454
-				[
1455
-					'node' => $folder,
1456
-					'subfiles' => 'true',
1457
-				],
1458
-				[
1459
-					'file1' => [
1460
-						IShare::TYPE_USER => [$file1UserShareOwner],
1461
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1462
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1463
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1464
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1465
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1466
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1467
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1468
-					],
1469
-				],
1470
-				[
1471
-				],
1472
-				[
1473
-					$file1UserShareOwnerExpected,
1474
-					$file1GroupShareOwnerExpected,
1475
-					$file1LinkShareOwnerExpected,
1476
-					$file1EmailShareOwnerExpected,
1477
-					$file1CircleShareOwnerExpected,
1478
-					$file1RoomShareOwnerExpected,
1479
-				]
1480
-			],
1481
-			[
1482
-				[
1483
-					'node' => $folder,
1484
-					'subfiles' => 'true',
1485
-				],
1486
-				[
1487
-					'file1' => [
1488
-						IShare::TYPE_USER => [$file1UserShareOwner],
1489
-						IShare::TYPE_GROUP => [$file1GroupShareOwner],
1490
-						IShare::TYPE_LINK => [$file1LinkShareOwner],
1491
-						IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1492
-						IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1493
-						IShare::TYPE_ROOM => [$file1RoomShareOwner],
1494
-						IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1495
-						IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1496
-					],
1497
-				],
1498
-				[
1499
-					IShare::TYPE_REMOTE => true,
1500
-					IShare::TYPE_REMOTE_GROUP => true,
1501
-				],
1502
-				[
1503
-					$file1UserShareOwnerExpected,
1504
-					$file1GroupShareOwnerExpected,
1505
-					$file1LinkShareOwnerExpected,
1506
-					$file1EmailShareOwnerExpected,
1507
-					$file1CircleShareOwnerExpected,
1508
-					$file1RoomShareOwnerExpected,
1509
-					$file1RemoteShareOwnerExpected,
1510
-					$file1RemoteGroupShareOwnerExpected,
1511
-				]
1512
-			],
1513
-		];
1514
-
1515
-		return $data;
1516
-	}
1517
-
1518
-	private function mockSimpleNode(string $class, array $methods): MockObject {
1519
-		$node = $this->createMock($class);
1520
-		foreach ($methods as $method => $return) {
1521
-			if ($method === 'getDirectoryListing') {
1522
-				$return = array_map(
1523
-					fn ($nodeParams) => $this->mockSimpleNode(...$nodeParams),
1524
-					$return
1525
-				);
1526
-			}
1527
-			$node->method($method)->willReturn($return);
1528
-		}
1529
-		return $node;
1530
-	}
1531
-
1532
-	#[DataProvider(methodName: 'dataGetShares')]
1533
-	public function testGetShares(array $getSharesParameters, array $shares, array $extraShareTypes, array $expected): void {
1534
-		$shares = array_map(
1535
-			fn ($sharesByType) => array_map(
1536
-				fn ($shareList) => array_map(
1537
-					function (array $shareParams): IShare {
1538
-						$share = Server::get(IManager::class)->newShare();
1539
-						$share->setShareType($shareParams['type'])
1540
-							->setSharedBy($shareParams['sharedBy'])
1541
-							->setShareOwner($shareParams['owner'])
1542
-							->setPermissions(Constants::PERMISSION_READ)
1543
-							->setId($shareParams['id']);
1544
-						if (isset($shareParams['sharedWith'])) {
1545
-							$share->setSharedWith($shareParams['sharedWith']);
1546
-						}
1547
-						if (isset($shareParams['sharedWithDisplayName'])) {
1548
-							$share->setSharedWithDisplayName($shareParams['sharedWithDisplayName']);
1549
-						}
1550
-						if (isset($shareParams['sharedWithAvatar'])) {
1551
-							$share->setSharedWithAvatar($shareParams['sharedWithAvatar']);
1552
-						}
1553
-						if (isset($shareParams['attributes'])) {
1554
-							$shareAttributes = $this->createMock(IShareAttributes::class);
1555
-							$shareAttributes->method('toArray')->willReturn($shareParams['attributes']);
1556
-							$shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
1557
-							$share->setAttributes($shareAttributes);
1558
-
1559
-							$expects['attributes'] = \json_encode($shareParams['attributes']);
1560
-						}
1561
-						if (isset($shareParams['node'])) {
1562
-							$node = $this->mockSimpleNode(...$shareParams['node']);
1563
-							$share->setNode($node);
1564
-						}
1565
-						if (isset($shareParams['note'])) {
1566
-							$share->setNote($shareParams['note']);
1567
-						}
1568
-						if (isset($shareParams['expirationDate'])) {
1569
-							$share->setExpirationDate($shareParams['expirationDate']);
1570
-						}
1571
-						if (isset($shareParams['token'])) {
1572
-							$share->setToken($shareParams['token']);
1573
-						}
1574
-						if (isset($shareParams['label'])) {
1575
-							$share->setLabel($shareParams['label']);
1576
-						}
1577
-						if (isset($shareParams['password'])) {
1578
-							$share->setPassword($shareParams['password']);
1579
-						}
1580
-						if (isset($shareParams['sendPasswordByTalk'])) {
1581
-							$share->setSendPasswordByTalk($shareParams['sendPasswordByTalk']);
1582
-						}
1583
-						return $share;
1584
-					},
1585
-					$shareList
1586
-				),
1587
-				$sharesByType
1588
-			),
1589
-			$shares
1590
-		);
1591
-
1592
-		/** @var ShareAPIController&MockObject $ocs */
1593
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
1594
-			->setConstructorArgs([
1595
-				$this->appName,
1596
-				$this->request,
1597
-				$this->shareManager,
1598
-				$this->groupManager,
1599
-				$this->userManager,
1600
-				$this->rootFolder,
1601
-				$this->urlGenerator,
1602
-				$this->l,
1603
-				$this->config,
1604
-				$this->appConfig,
1605
-				$this->appManager,
1606
-				$this->serverContainer,
1607
-				$this->userStatusManager,
1608
-				$this->previewManager,
1609
-				$this->dateTimeZone,
1610
-				$this->logger,
1611
-				$this->factory,
1612
-				$this->mailer,
1613
-				$this->tagManager,
1614
-				$this->getEmailValidatorWithStrictEmailCheck(),
1615
-				$this->trustedServers,
1616
-				$this->currentUser,
1617
-			])
1618
-			->onlyMethods(['formatShare'])
1619
-			->getMock();
1620
-
1621
-		$ocs->method('formatShare')
1622
-			->willReturnCallback(
1623
-				function ($share) {
1624
-					return [
1625
-						'id' => $share->getId(),
1626
-						'share_type' => $share->getShareType()
1627
-					];
1628
-				}
1629
-			);
1630
-
1631
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1632
-		$userFolder->method('get')
1633
-			->with('path')
1634
-			->willReturn($this->mockSimpleNode(...$getSharesParameters['node']));
1635
-
1636
-		$this->rootFolder->method('getUserFolder')
1637
-			->with($this->currentUser)
1638
-			->willReturn($userFolder);
1639
-
1640
-		$this->shareManager
1641
-			->method('getSharesBy')
1642
-			->willReturnCallback(
1643
-				function ($user, $shareType, $node) use ($shares) {
1644
-					if (!isset($shares[$node->getName()]) || !isset($shares[$node->getName()][$shareType])) {
1645
-						return [];
1646
-					}
1647
-					return $shares[$node->getName()][$shareType];
1648
-				}
1649
-			);
1650
-
1651
-		$this->shareManager
1652
-			->method('outgoingServer2ServerSharesAllowed')
1653
-			->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE] ?? false);
1654
-
1655
-		$this->shareManager
1656
-			->method('outgoingServer2ServerGroupSharesAllowed')
1657
-			->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE_GROUP] ?? false);
1658
-
1659
-		$this->groupManager
1660
-			->method('isInGroup')
1661
-			->willReturnCallback(
1662
-				function ($user, $group) {
1663
-					return $group === 'currentUserGroup';
1664
-				}
1665
-			);
1666
-
1667
-		$result = $ocs->getShares(
1668
-			$getSharesParameters['sharedWithMe'] ?? 'false',
1669
-			$getSharesParameters['reshares'] ?? 'false',
1670
-			$getSharesParameters['subfiles'] ?? 'false',
1671
-			'path'
1672
-		);
1673
-
1674
-		$this->assertEquals($expected, $result->getData());
1675
-	}
1676
-
1677
-	public function testCanAccessShareAsOwner(): void {
1678
-		$share = $this->createMock(IShare::class);
1679
-		$share->method('getShareOwner')->willReturn($this->currentUser);
1680
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1681
-	}
1682
-
1683
-	public function testCanAccessShareAsSharer(): void {
1684
-		$share = $this->createMock(IShare::class);
1685
-		$share->method('getSharedBy')->willReturn($this->currentUser);
1686
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1687
-	}
1688
-
1689
-	public function testCanAccessShareAsSharee(): void {
1690
-		$share = $this->createMock(IShare::class);
1691
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
1692
-		$share->method('getSharedWith')->willReturn($this->currentUser);
1693
-		$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1694
-	}
1695
-
1696
-	public function testCannotAccessLinkShare(): void {
1697
-		$share = $this->createMock(IShare::class);
1698
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
1699
-		$share->method('getNodeId')->willReturn(42);
1700
-
1701
-		$userFolder = $this->createMock(Folder::class);
1702
-		$this->rootFolder->method('getUserFolder')
1703
-			->with($this->currentUser)
1704
-			->willReturn($userFolder);
1705
-
1706
-		$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1707
-	}
1708
-
1709
-	#[DataProvider(methodName: 'dataCanAccessShareWithPermissions')]
1710
-	public function testCanAccessShareWithPermissions(int $permissions, bool $expected): void {
1711
-		$share = $this->createMock(IShare::class);
1712
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
1713
-		$share->method('getSharedWith')->willReturn($this->createMock(IUser::class));
1714
-		$share->method('getNodeId')->willReturn(42);
1715
-
1716
-		$file = $this->createMock(File::class);
1717
-
1718
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1719
-		$userFolder->method('getFirstNodeById')
1720
-			->with($share->getNodeId())
1721
-			->willReturn($file);
1722
-		$userFolder->method('getById')
1723
-			->with($share->getNodeId())
1724
-			->willReturn([$file]);
1725
-		$this->rootFolder->method('getUserFolder')
1726
-			->with($this->currentUser)
1727
-			->willReturn($userFolder);
1728
-
1729
-		$file->method('getPermissions')
1730
-			->willReturn($permissions);
1731
-
1732
-		if ($expected) {
1733
-			$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1734
-		} else {
1735
-			$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1736
-		}
1737
-	}
1738
-
1739
-	public static function dataCanAccessShareWithPermissions(): array {
1740
-		return [
1741
-			[Constants::PERMISSION_SHARE, true],
1742
-			[Constants::PERMISSION_READ, false],
1743
-			[Constants::PERMISSION_READ | Constants::PERMISSION_SHARE, true],
1744
-		];
1745
-	}
1746
-
1747
-	#[DataProvider(methodName: 'dataCanAccessShareAsGroupMember')]
1748
-	public function testCanAccessShareAsGroupMember(string $group, bool $expected): void {
1749
-		$share = $this->createMock(IShare::class);
1750
-		$share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
1751
-		$share->method('getSharedWith')->willReturn($group);
1752
-		$share->method('getNodeId')->willReturn(42);
1753
-
1754
-		$file = $this->createMock(File::class);
1755
-
1756
-		$userFolder = $this->createMock(Folder::class);
1757
-		$userFolder->method('getFirstNodeById')
1758
-			->with($share->getNodeId())
1759
-			->willReturn($file);
1760
-		$userFolder->method('getById')
1761
-			->with($share->getNodeId())
1762
-			->willReturn([$file]);
1763
-		$this->rootFolder->method('getUserFolder')
1764
-			->with($this->currentUser)
1765
-			->willReturn($userFolder);
1766
-
1767
-		$user = $this->createMock(IUser::class);
1768
-		$this->userManager->method('get')
1769
-			->with($this->currentUser)
1770
-			->willReturn($user);
1771
-
1772
-		$group = $this->createMock(IGroup::class);
1773
-		$group->method('inGroup')->with($user)->willReturn(true);
1774
-		$group2 = $this->createMock(IGroup::class);
1775
-		$group2->method('inGroup')->with($user)->willReturn(false);
1776
-
1777
-		$this->groupManager->method('get')->willReturnMap([
1778
-			['group', $group],
1779
-			['group2', $group2],
1780
-			['group-null', null],
1781
-		]);
1782
-
1783
-		if ($expected) {
1784
-			$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1785
-		} else {
1786
-			$this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1787
-		}
1788
-	}
1789
-
1790
-	public static function dataCanAccessShareAsGroupMember(): array {
1791
-		return [
1792
-			['group', true],
1793
-			['group2', false],
1794
-			['group-null', false],
1795
-		];
1796
-	}
1797
-
1798
-	public static function dataCanAccessRoomShare(): array {
1799
-		return [
1800
-			[false, false, false],
1801
-			[false, false, true],
1802
-			[true, true, true],
1803
-			[false, true, false],
1804
-		];
1805
-	}
1806
-
1807
-	#[DataProvider(methodName: 'dataCanAccessRoomShare')]
1808
-	public function testCanAccessRoomShare(
1809
-		bool $expected,
1810
-		bool $helperAvailable,
1811
-		bool $canAccessShareByHelper,
1812
-	): void {
1813
-		$share = $this->createMock(IShare::class);
1814
-		$share->method('getShareType')->willReturn(IShare::TYPE_ROOM);
1815
-		$share->method('getSharedWith')->willReturn('recipientRoom');
1816
-
1817
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1818
-		$this->rootFolder->method('getUserFolder')
1819
-			->with($this->currentUser)
1820
-			->willReturn($userFolder);
1821
-
1822
-		$userFolder->method('getById')
1823
-			->with($share->getNodeId())
1824
-			->willReturn([$share->getNode()]);
1825
-
1826
-		if (!$helperAvailable) {
1827
-			$this->appManager->method('isEnabledForUser')
1828
-				->with('spreed')
1829
-				->willReturn(false);
1830
-		} else {
1831
-			$this->appManager->method('isEnabledForUser')
1832
-				->with('spreed')
1833
-				->willReturn(true);
1834
-
1835
-			// This is not possible anymore with PHPUnit 10+
1836
-			// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
1837
-			// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
1838
-			$helper = $this->getMockBuilder(\stdClass::class)
1839
-				->addMethods(['canAccessShare'])
1840
-				->getMock();
1841
-			$helper->method('canAccessShare')
1842
-				->with($share, $this->currentUser)
1843
-				->willReturn($canAccessShareByHelper);
1844
-
1845
-			$this->serverContainer->method('get')
1846
-				->with('\OCA\Talk\Share\Helper\ShareAPIController')
1847
-				->willReturn($helper);
1848
-		}
1849
-
1850
-		$this->assertEquals($expected, $this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1851
-	}
1852
-
1853
-
1854
-	public function testCreateShareNoPath(): void {
1855
-		$this->expectException(OCSNotFoundException::class);
1856
-		$this->expectExceptionMessage('Please specify a file or folder path');
1857
-
1858
-		$this->ocs->createShare();
1859
-	}
1860
-
1861
-
1862
-	public function testCreateShareInvalidPath(): void {
1863
-		$this->expectException(OCSNotFoundException::class);
1864
-		$this->expectExceptionMessage('Wrong path, file/folder does not exist');
1865
-
1866
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
1867
-		$this->rootFolder->expects($this->once())
1868
-			->method('getUserFolder')
1869
-			->with('currentUser')
1870
-			->willReturn($userFolder);
1871
-
1872
-		$userFolder->expects($this->once())
1873
-			->method('get')
1874
-			->with('invalid-path')
1875
-			->willThrowException(new NotFoundException());
1876
-
1877
-		$this->ocs->createShare('invalid-path');
1878
-	}
1879
-
1880
-	public function testCreateShareInvalidShareType(): void {
1881
-		$this->expectException(OCSBadRequestException::class);
1882
-		$this->expectExceptionMessage('Unknown share type');
1883
-
1884
-		$share = $this->newShare();
1885
-		$this->shareManager->method('newShare')->willReturn($share);
1886
-
1887
-		[$userFolder, $file] = $this->getNonSharedUserFile();
1888
-		$this->rootFolder->expects($this->atLeastOnce())
1889
-			->method('getUserFolder')
1890
-			->with('currentUser')
1891
-			->willReturn($userFolder);
1892
-
1893
-		$userFolder->expects($this->atLeastOnce())
1894
-			->method('get')
1895
-			->with('valid-path')
1896
-			->willReturn($file);
1897
-		$userFolder->method('getById')
1898
-			->willReturn([]);
1899
-
1900
-		$file->expects($this->once())
1901
-			->method('lock')
1902
-			->with(ILockingProvider::LOCK_SHARED);
1903
-
1904
-		$this->ocs->createShare('valid-path', 31);
1905
-	}
1906
-
1907
-	public function testCreateShareUserNoShareWith(): void {
1908
-		$this->expectException(OCSNotFoundException::class);
1909
-		$this->expectExceptionMessage('Please specify a valid account to share with');
1910
-
1911
-		$share = $this->newShare();
1912
-		$this->shareManager->method('newShare')->willReturn($share);
1913
-
1914
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1915
-		$this->rootFolder->method('getUserFolder')
1916
-			->with('currentUser')
1917
-			->willReturn($userFolder);
1918
-
1919
-		$userFolder->expects($this->once())
1920
-			->method('get')
1921
-			->with('valid-path')
1922
-			->willReturn($path);
1923
-		$userFolder->method('getById')
1924
-			->willReturn([]);
1925
-
1926
-		$path->expects($this->once())
1927
-			->method('lock')
1928
-			->with(ILockingProvider::LOCK_SHARED);
1929
-
1930
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER);
1931
-	}
1932
-
1933
-
1934
-	public function testCreateShareUserNoValidShareWith(): void {
1935
-		$this->expectException(OCSNotFoundException::class);
1936
-		$this->expectExceptionMessage('Please specify a valid account to share with');
1937
-
1938
-		$share = $this->newShare();
1939
-		$this->shareManager->method('newShare')->willReturn($share);
1940
-
1941
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1942
-		$this->rootFolder->method('getUserFolder')
1943
-			->with('currentUser')
1944
-			->willReturn($userFolder);
1945
-
1946
-		$userFolder->expects($this->once())
1947
-			->method('get')
1948
-			->with('valid-path')
1949
-			->willReturn($path);
1950
-		$userFolder->method('getById')
1951
-			->willReturn([]);
1952
-		$path->expects($this->once())
1953
-			->method('lock')
1954
-			->with(ILockingProvider::LOCK_SHARED);
1955
-		$this->userManager->method('userExists')
1956
-			->with('invalidUser')
1957
-			->willReturn(false);
1958
-
1959
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'invalidUser');
1960
-	}
1961
-
1962
-	public function testCreateShareUser(): void {
1963
-		$share = $this->newShare();
1964
-		$this->shareManager->method('newShare')->willReturn($share);
1965
-
1966
-		/** @var ShareAPIController $ocs */
1967
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
1968
-			->setConstructorArgs([
1969
-				$this->appName,
1970
-				$this->request,
1971
-				$this->shareManager,
1972
-				$this->groupManager,
1973
-				$this->userManager,
1974
-				$this->rootFolder,
1975
-				$this->urlGenerator,
1976
-				$this->l,
1977
-				$this->config,
1978
-				$this->appConfig,
1979
-				$this->appManager,
1980
-				$this->serverContainer,
1981
-				$this->userStatusManager,
1982
-				$this->previewManager,
1983
-				$this->dateTimeZone,
1984
-				$this->logger,
1985
-				$this->factory,
1986
-				$this->mailer,
1987
-				$this->tagManager,
1988
-				$this->getEmailValidatorWithStrictEmailCheck(),
1989
-				$this->trustedServers,
1990
-				$this->currentUser,
1991
-			])->onlyMethods(['formatShare'])
1992
-			->getMock();
1993
-
1994
-		[$userFolder, $path] = $this->getNonSharedUserFile();
1995
-		$this->rootFolder->expects($this->exactly(2))
1996
-			->method('getUserFolder')
1997
-			->with('currentUser')
1998
-			->willReturn($userFolder);
1999
-
2000
-		$userFolder->expects($this->once())
2001
-			->method('get')
2002
-			->with('valid-path')
2003
-			->willReturn($path);
2004
-		$userFolder->method('getById')
2005
-			->willReturn([]);
2006
-
2007
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2008
-
2009
-		$path->expects($this->once())
2010
-			->method('lock')
2011
-			->with(ILockingProvider::LOCK_SHARED);
2012
-
2013
-		$this->shareManager->method('createShare')
2014
-			->with($this->callback(function (IShare $share) use ($path) {
2015
-				return $share->getNode() === $path
2016
-					&& $share->getPermissions() === (
2017
-						Constants::PERMISSION_ALL
2018
-						& ~Constants::PERMISSION_DELETE
2019
-						& ~Constants::PERMISSION_CREATE
2020
-					)
2021
-					&& $share->getShareType() === IShare::TYPE_USER
2022
-					&& $share->getSharedWith() === 'validUser'
2023
-					&& $share->getSharedBy() === 'currentUser';
2024
-			}))
2025
-			->willReturnArgument(0);
2026
-
2027
-		$expected = new DataResponse([]);
2028
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
2029
-
2030
-		$this->assertInstanceOf(get_class($expected), $result);
2031
-		$this->assertEquals($expected->getData(), $result->getData());
2032
-	}
2033
-
2034
-
2035
-	public function testCreateShareGroupNoValidShareWith(): void {
2036
-		$this->expectException(OCSNotFoundException::class);
2037
-		$this->expectExceptionMessage('Please specify a valid group');
2038
-
2039
-		$share = $this->newShare();
2040
-		$this->shareManager->method('newShare')->willReturn($share);
2041
-		$this->shareManager->method('createShare')->willReturnArgument(0);
2042
-		$this->shareManager->method('allowGroupSharing')->willReturn(true);
2043
-
2044
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2045
-		$this->rootFolder->method('getUserFolder')
2046
-			->with('currentUser')
2047
-			->willReturn($userFolder);
2048
-
2049
-		$userFolder->expects($this->once())
2050
-			->method('get')
2051
-			->with('valid-path')
2052
-			->willReturn($path);
2053
-		$userFolder->method('getById')
2054
-			->willReturn([]);
2055
-
2056
-		$path->expects($this->once())
2057
-			->method('lock')
2058
-			->with(ILockingProvider::LOCK_SHARED);
2059
-
2060
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
2061
-	}
2062
-
2063
-	public function testCreateShareGroup(): void {
2064
-		$share = $this->newShare();
2065
-		$this->shareManager->method('newShare')->willReturn($share);
2066
-
2067
-		/** @var ShareAPIController&MockObject $ocs */
2068
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2069
-			->setConstructorArgs([
2070
-				$this->appName,
2071
-				$this->request,
2072
-				$this->shareManager,
2073
-				$this->groupManager,
2074
-				$this->userManager,
2075
-				$this->rootFolder,
2076
-				$this->urlGenerator,
2077
-				$this->l,
2078
-				$this->config,
2079
-				$this->appConfig,
2080
-				$this->appManager,
2081
-				$this->serverContainer,
2082
-				$this->userStatusManager,
2083
-				$this->previewManager,
2084
-				$this->dateTimeZone,
2085
-				$this->logger,
2086
-				$this->factory,
2087
-				$this->mailer,
2088
-				$this->tagManager,
2089
-				$this->getEmailValidatorWithStrictEmailCheck(),
2090
-				$this->trustedServers,
2091
-				$this->currentUser,
2092
-			])->onlyMethods(['formatShare'])
2093
-			->getMock();
2094
-
2095
-		$this->request
2096
-			->method('getParam')
2097
-			->willReturnMap([
2098
-				['path', null, 'valid-path'],
2099
-				['permissions', null, Constants::PERMISSION_ALL],
2100
-				['shareType', '-1', IShare::TYPE_GROUP],
2101
-				['shareWith', null, 'validGroup'],
2102
-			]);
2103
-
2104
-		[$userFolder, $path] = $this->getNonSharedUserFolder();
2105
-		$this->rootFolder->expects($this->exactly(2))
2106
-			->method('getUserFolder')
2107
-			->with('currentUser')
2108
-			->willReturn($userFolder);
2109
-
2110
-		$userFolder->expects($this->once())
2111
-			->method('get')
2112
-			->with('valid-path')
2113
-			->willReturn($path);
2114
-		$userFolder->method('getById')
2115
-			->willReturn([]);
2116
-
2117
-		$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2118
-
2119
-		$this->shareManager->expects($this->once())
2120
-			->method('allowGroupSharing')
2121
-			->willReturn(true);
2122
-
2123
-		$path->expects($this->once())
2124
-			->method('lock')
2125
-			->with(ILockingProvider::LOCK_SHARED);
2126
-
2127
-		$this->shareManager->method('createShare')
2128
-			->with($this->callback(function (IShare $share) use ($path) {
2129
-				return $share->getNode() === $path
2130
-				&& $share->getPermissions() === Constants::PERMISSION_ALL
2131
-				&& $share->getShareType() === IShare::TYPE_GROUP
2132
-				&& $share->getSharedWith() === 'validGroup'
2133
-				&& $share->getSharedBy() === 'currentUser';
2134
-			}))
2135
-			->willReturnArgument(0);
2136
-
2137
-		$expected = new DataResponse([]);
2138
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'validGroup');
2139
-
2140
-		$this->assertInstanceOf(get_class($expected), $result);
2141
-		$this->assertEquals($expected->getData(), $result->getData());
2142
-	}
2143
-
2144
-
2145
-	public function testCreateShareGroupNotAllowed(): void {
2146
-		$this->expectException(OCSNotFoundException::class);
2147
-		$this->expectExceptionMessage('Group sharing is disabled by the administrator');
2148
-
2149
-		$share = $this->newShare();
2150
-		$this->shareManager->method('newShare')->willReturn($share);
2151
-
2152
-		[$userFolder, $path] = $this->getNonSharedUserFolder();
2153
-		$this->rootFolder->method('getUserFolder')
2154
-			->with('currentUser')
2155
-			->willReturn($userFolder);
2156
-
2157
-		$userFolder->expects($this->once())
2158
-			->method('get')
2159
-			->with('valid-path')
2160
-			->willReturn($path);
2161
-		$userFolder->method('getById')
2162
-			->willReturn([]);
2163
-
2164
-		$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2165
-
2166
-		$this->shareManager->expects($this->once())
2167
-			->method('allowGroupSharing')
2168
-			->willReturn(false);
2169
-
2170
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
2171
-	}
2172
-
2173
-
2174
-	public function testCreateShareLinkNoLinksAllowed(): void {
2175
-		$this->expectException(OCSNotFoundException::class);
2176
-		$this->expectExceptionMessage('Public link sharing is disabled by the administrator');
2177
-
2178
-		$this->request
2179
-			->method('getParam')
2180
-			->willReturnMap([
2181
-				['path', null, 'valid-path'],
2182
-				['shareType', '-1', IShare::TYPE_LINK],
2183
-			]);
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('shareApiLinkAllowPublicUpload')->willReturn(true);
2201
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(false);
2202
-
2203
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK);
2204
-	}
2205
-
2206
-
2207
-	public function testCreateShareLinkNoPublicUpload(): void {
2208
-		$this->expectException(OCSForbiddenException::class);
2209
-		$this->expectExceptionMessage('Public upload disabled by the administrator');
2210
-
2211
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2212
-		$path->method('getId')->willReturn(42);
2213
-		$storage = $this->createMock(IStorage::class);
2214
-		$storage->method('instanceOfStorage')
2215
-			->willReturnMap([
2216
-				['OCA\Files_Sharing\External\Storage', false],
2217
-				['OCA\Files_Sharing\SharedStorage', false],
2218
-			]);
2219
-		$path->method('getStorage')->willReturn($storage);
2220
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2221
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2222
-		$this->rootFolder->method('getById')
2223
-			->willReturn([]);
2224
-
2225
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2226
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2227
-
2228
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2229
-	}
2230
-
2231
-
2232
-	public function testCreateShareLinkPublicUploadFile(): void {
2233
-		$this->expectException(OCSBadRequestException::class);
2234
-		$this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
2235
-
2236
-		$storage = $this->createMock(IStorage::class);
2237
-		$storage->method('instanceOfStorage')
2238
-			->willReturnMap([
2239
-				['OCA\Files_Sharing\External\Storage', false],
2240
-				['OCA\Files_Sharing\SharedStorage', false],
2241
-			]);
2242
-
2243
-		$file = $this->createMock(File::class);
2244
-		$file->method('getId')->willReturn(42);
2245
-		$file->method('getStorage')->willReturn($storage);
2246
-
2247
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2248
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($file);
2249
-		$this->rootFolder->method('getById')
2250
-			->willReturn([]);
2251
-
2252
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2253
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2254
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2255
-
2256
-		$this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2257
-	}
2258
-
2259
-	public function testCreateShareLinkPublicUploadFolder(): void {
2260
-		$ocs = $this->mockFormatShare();
2261
-
2262
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2263
-		$path->method('getId')->willReturn(1);
2264
-		$storage = $this->createMock(IStorage::class);
2265
-		$storage->method('instanceOfStorage')
2266
-			->willReturnMap([
2267
-				['OCA\Files_Sharing\External\Storage', false],
2268
-				['OCA\Files_Sharing\SharedStorage', false],
2269
-			]);
2270
-		$path->method('getStorage')->willReturn($storage);
2271
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2272
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2273
-		$this->rootFolder->method('getById')
2274
-			->willReturn([]);
2275
-
2276
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2277
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2278
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2279
-
2280
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2281
-			$this->callback(function (IShare $share) use ($path) {
2282
-				return $share->getNode() === $path
2283
-					&& $share->getShareType() === IShare::TYPE_LINK
2284
-					&& $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2285
-					&& $share->getSharedBy() === 'currentUser'
2286
-					&& $share->getPassword() === null
2287
-					&& $share->getExpirationDate() === null;
2288
-			})
2289
-		)->willReturnArgument(0);
2290
-
2291
-		$expected = new DataResponse([]);
2292
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', '', null, '');
2293
-
2294
-		$this->assertInstanceOf(get_class($expected), $result);
2295
-		$this->assertEquals($expected->getData(), $result->getData());
2296
-	}
2297
-
2298
-	public function testCreateShareLinkPassword(): void {
2299
-		$ocs = $this->mockFormatShare();
2300
-
2301
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2302
-		$path->method('getId')->willReturn(42);
2303
-		$storage = $this->createMock(IStorage::class);
2304
-		$storage->method('instanceOfStorage')
2305
-			->willReturnMap([
2306
-				['OCA\Files_Sharing\External\Storage', false],
2307
-				['OCA\Files_Sharing\SharedStorage', false],
2308
-			]);
2309
-		$path->method('getStorage')->willReturn($storage);
2310
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2311
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2312
-		$this->rootFolder->method('getById')
2313
-			->willReturn([]);
2314
-
2315
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2316
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2317
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2318
-
2319
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2320
-			$this->callback(function (IShare $share) use ($path) {
2321
-				return $share->getNode() === $path
2322
-				&& $share->getShareType() === IShare::TYPE_LINK
2323
-				&& $share->getPermissions() === Constants::PERMISSION_READ // publicUpload was set to false
2324
-				&& $share->getSharedBy() === 'currentUser'
2325
-				&& $share->getPassword() === 'password'
2326
-				&& $share->getExpirationDate() === null;
2327
-			})
2328
-		)->willReturnArgument(0);
2329
-
2330
-		$expected = new DataResponse([]);
2331
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_READ, IShare::TYPE_LINK, null, 'false', 'password', null, '');
2332
-
2333
-		$this->assertInstanceOf(get_class($expected), $result);
2334
-		$this->assertEquals($expected->getData(), $result->getData());
2335
-	}
2336
-
2337
-	public function testCreateShareLinkSendPasswordByTalk(): void {
2338
-		$ocs = $this->mockFormatShare();
2339
-
2340
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2341
-		$path->method('getId')->willReturn(42);
2342
-		$storage = $this->createMock(IStorage::class);
2343
-		$storage->method('instanceOfStorage')
2344
-			->willReturnMap([
2345
-				['OCA\Files_Sharing\External\Storage', false],
2346
-				['OCA\Files_Sharing\SharedStorage', false],
2347
-			]);
2348
-		$path->method('getStorage')->willReturn($storage);
2349
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2350
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2351
-		$this->rootFolder->method('getById')
2352
-			->willReturn([]);
2353
-
2354
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2355
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2356
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2357
-
2358
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
2359
-
2360
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2361
-			$this->callback(function (IShare $share) use ($path) {
2362
-				return $share->getNode() === $path
2363
-				&& $share->getShareType() === IShare::TYPE_LINK
2364
-				&& $share->getPermissions() === (Constants::PERMISSION_ALL & ~(Constants::PERMISSION_SHARE))
2365
-				&& $share->getSharedBy() === 'currentUser'
2366
-				&& $share->getPassword() === 'password'
2367
-				&& $share->getSendPasswordByTalk() === true
2368
-				&& $share->getExpirationDate() === null;
2369
-			})
2370
-		)->willReturnArgument(0);
2371
-
2372
-		$expected = new DataResponse([]);
2373
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', 'password', 'true', '');
2374
-
2375
-		$this->assertInstanceOf(get_class($expected), $result);
2376
-		$this->assertEquals($expected->getData(), $result->getData());
2377
-	}
2378
-
2379
-
2380
-	public function testCreateShareLinkSendPasswordByTalkWithTalkDisabled(): void {
2381
-		$this->expectException(OCSForbiddenException::class);
2382
-		$this->expectExceptionMessage('Sharing valid-path sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled');
2383
-
2384
-		$ocs = $this->mockFormatShare();
2385
-
2386
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2387
-		$path->method('getId')->willReturn(42);
2388
-		$storage = $this->createMock(IStorage::class);
2389
-		$storage->method('instanceOfStorage')
2390
-			->willReturnMap([
2391
-				['OCA\Files_Sharing\External\Storage', false],
2392
-				['OCA\Files_Sharing\SharedStorage', false],
2393
-			]);
2394
-		$path->method('getStorage')->willReturn($storage);
2395
-		$path->method('getPath')->willReturn('valid-path');
2396
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2397
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2398
-		$this->rootFolder->method('getById')
2399
-			->willReturn([]);
2400
-
2401
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2402
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2403
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2404
-
2405
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
2406
-
2407
-		$this->shareManager->expects($this->never())->method('createShare');
2408
-
2409
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', 'password', 'true', '');
2410
-	}
2411
-
2412
-	public function testCreateShareValidExpireDate(): void {
2413
-		$ocs = $this->mockFormatShare();
2414
-
2415
-		$this->request
2416
-			->method('getParam')
2417
-			->willReturnMap([
2418
-				['path', null, 'valid-path'],
2419
-				['shareType', '-1', IShare::TYPE_LINK],
2420
-				['publicUpload', null, 'false'],
2421
-				['expireDate', '', '2000-01-01'],
2422
-				['password', '', ''],
2423
-			]);
2424
-
2425
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2426
-		$path->method('getId')->willReturn(42);
2427
-		$storage = $this->createMock(IStorage::class);
2428
-		$storage->method('instanceOfStorage')
2429
-			->willReturnMap([
2430
-				['OCA\Files_Sharing\External\Storage', false],
2431
-				['OCA\Files_Sharing\SharedStorage', false],
2432
-			]);
2433
-		$path->method('getStorage')->willReturn($storage);
2434
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2435
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2436
-		$this->rootFolder->method('getById')
2437
-			->willReturn([]);
2438
-
2439
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2440
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2441
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2442
-
2443
-		$this->shareManager->expects($this->once())->method('createShare')->with(
2444
-			$this->callback(function (IShare $share) use ($path) {
2445
-				$date = new \DateTime('2000-01-01');
2446
-				$date->setTime(0, 0, 0);
2447
-
2448
-				return $share->getNode() === $path
2449
-				&& $share->getShareType() === IShare::TYPE_LINK
2450
-				&& $share->getPermissions() === Constants::PERMISSION_READ | Constants::PERMISSION_SHARE
2451
-				&& $share->getSharedBy() === 'currentUser'
2452
-				&& $share->getPassword() === null
2453
-				&& $share->getExpirationDate() == $date;
2454
-			})
2455
-		)->willReturnArgument(0);
2456
-
2457
-		$expected = new DataResponse([]);
2458
-		$result = $ocs->createShare('valid-path', null, IShare::TYPE_LINK, null, 'false', '', null, '2000-01-01');
2459
-
2460
-		$this->assertInstanceOf(get_class($expected), $result);
2461
-		$this->assertEquals($expected->getData(), $result->getData());
2462
-	}
2463
-
2464
-
2465
-	public function testCreateShareInvalidExpireDate(): void {
2466
-		$this->expectException(OCSNotFoundException::class);
2467
-		$this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
2468
-
2469
-		$ocs = $this->mockFormatShare();
2470
-
2471
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2472
-		$path->method('getId')->willReturn(42);
2473
-		$storage = $this->createMock(IStorage::class);
2474
-		$storage->method('instanceOfStorage')
2475
-			->willReturnMap([
2476
-				['OCA\Files_Sharing\External\Storage', false],
2477
-				['OCA\Files_Sharing\SharedStorage', false],
2478
-			]);
2479
-		$path->method('getStorage')->willReturn($storage);
2480
-		$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2481
-		$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2482
-		$this->rootFolder->method('getById')
2483
-			->willReturn([]);
2484
-
2485
-		$this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2486
-		$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2487
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2488
-
2489
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, 'a1b2d3');
2490
-	}
2491
-
2492
-	public function testCreateShareRemote(): void {
2493
-		$share = $this->newShare();
2494
-		$this->shareManager->method('newShare')->willReturn($share);
2495
-
2496
-		/** @var ShareAPIController $ocs */
2497
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2498
-			->setConstructorArgs([
2499
-				$this->appName,
2500
-				$this->request,
2501
-				$this->shareManager,
2502
-				$this->groupManager,
2503
-				$this->userManager,
2504
-				$this->rootFolder,
2505
-				$this->urlGenerator,
2506
-				$this->l,
2507
-				$this->config,
2508
-				$this->appConfig,
2509
-				$this->appManager,
2510
-				$this->serverContainer,
2511
-				$this->userStatusManager,
2512
-				$this->previewManager,
2513
-				$this->dateTimeZone,
2514
-				$this->logger,
2515
-				$this->factory,
2516
-				$this->mailer,
2517
-				$this->tagManager,
2518
-				$this->getEmailValidatorWithStrictEmailCheck(),
2519
-				$this->trustedServers,
2520
-				$this->currentUser,
2521
-			])->onlyMethods(['formatShare'])
2522
-			->getMock();
2523
-
2524
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2525
-		$this->rootFolder->expects($this->exactly(2))
2526
-			->method('getUserFolder')
2527
-			->with('currentUser')
2528
-			->willReturn($userFolder);
2529
-
2530
-		$userFolder->expects($this->once())
2531
-			->method('get')
2532
-			->with('valid-path')
2533
-			->willReturn($path);
2534
-		$userFolder->method('getById')
2535
-			->willReturn([]);
2536
-
2537
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2538
-
2539
-		$path->expects($this->once())
2540
-			->method('lock')
2541
-			->with(ILockingProvider::LOCK_SHARED);
2542
-
2543
-		$this->shareManager->method('createShare')
2544
-			->with($this->callback(function (IShare $share) use ($path) {
2545
-				return $share->getNode() === $path
2546
-					&& $share->getPermissions() === (
2547
-						Constants::PERMISSION_ALL
2548
-						& ~Constants::PERMISSION_DELETE
2549
-						& ~Constants::PERMISSION_CREATE
2550
-					)
2551
-					&& $share->getShareType() === IShare::TYPE_REMOTE
2552
-					&& $share->getSharedWith() === '[email protected]'
2553
-					&& $share->getSharedBy() === 'currentUser';
2554
-			}))
2555
-			->willReturnArgument(0);
2556
-
2557
-		$this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
2558
-
2559
-		$expected = new DataResponse([]);
2560
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE, '[email protected]');
2561
-
2562
-		$this->assertInstanceOf(get_class($expected), $result);
2563
-		$this->assertEquals($expected->getData(), $result->getData());
2564
-	}
2565
-
2566
-	public function testCreateShareRemoteGroup(): void {
2567
-		$share = $this->newShare();
2568
-		$this->shareManager->method('newShare')->willReturn($share);
2569
-
2570
-		/** @var ShareAPIController $ocs */
2571
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2572
-			->setConstructorArgs([
2573
-				$this->appName,
2574
-				$this->request,
2575
-				$this->shareManager,
2576
-				$this->groupManager,
2577
-				$this->userManager,
2578
-				$this->rootFolder,
2579
-				$this->urlGenerator,
2580
-				$this->l,
2581
-				$this->config,
2582
-				$this->appConfig,
2583
-				$this->appManager,
2584
-				$this->serverContainer,
2585
-				$this->userStatusManager,
2586
-				$this->previewManager,
2587
-				$this->dateTimeZone,
2588
-				$this->logger,
2589
-				$this->factory,
2590
-				$this->mailer,
2591
-				$this->tagManager,
2592
-				$this->getEmailValidatorWithStrictEmailCheck(),
2593
-				$this->trustedServers,
2594
-				$this->currentUser,
2595
-			])->onlyMethods(['formatShare'])
2596
-			->getMock();
2597
-
2598
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2599
-		$this->rootFolder->expects($this->exactly(2))
2600
-			->method('getUserFolder')
2601
-			->with('currentUser')
2602
-			->willReturn($userFolder);
2603
-
2604
-		$userFolder->expects($this->once())
2605
-			->method('get')
2606
-			->with('valid-path')
2607
-			->willReturn($path);
2608
-		$userFolder->method('getById')
2609
-			->willReturn([]);
2610
-
2611
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2612
-
2613
-		$path->expects($this->once())
2614
-			->method('lock')
2615
-			->with(ILockingProvider::LOCK_SHARED);
2616
-
2617
-		$this->shareManager->method('createShare')
2618
-			->with($this->callback(function (IShare $share) use ($path) {
2619
-				return $share->getNode() === $path
2620
-					&& $share->getPermissions() === (
2621
-						Constants::PERMISSION_ALL
2622
-						& ~Constants::PERMISSION_DELETE
2623
-						& ~Constants::PERMISSION_CREATE
2624
-					)
2625
-					&& $share->getShareType() === IShare::TYPE_REMOTE_GROUP
2626
-					&& $share->getSharedWith() === '[email protected]'
2627
-					&& $share->getSharedBy() === 'currentUser';
2628
-			}))
2629
-			->willReturnArgument(0);
2630
-
2631
-		$this->shareManager->method('outgoingServer2ServerGroupSharesAllowed')->willReturn(true);
2632
-
2633
-		$expected = new DataResponse([]);
2634
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE_GROUP, '[email protected]');
2635
-
2636
-		$this->assertInstanceOf(get_class($expected), $result);
2637
-		$this->assertEquals($expected->getData(), $result->getData());
2638
-	}
2639
-
2640
-	public function testCreateShareRoom(): void {
2641
-		$ocs = $this->mockFormatShare();
2642
-
2643
-		$share = $this->newShare();
2644
-		$this->shareManager->method('newShare')->willReturn($share);
2645
-
2646
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2647
-		$this->rootFolder->expects($this->exactly(2))
2648
-			->method('getUserFolder')
2649
-			->with('currentUser')
2650
-			->willReturn($userFolder);
2651
-
2652
-		$userFolder->expects($this->once())
2653
-			->method('get')
2654
-			->with('valid-path')
2655
-			->willReturn($path);
2656
-		$userFolder->method('getById')
2657
-			->willReturn([]);
2658
-
2659
-		$path->expects($this->once())
2660
-			->method('lock')
2661
-			->with(ILockingProvider::LOCK_SHARED);
2662
-
2663
-		$this->appManager->method('isEnabledForUser')
2664
-			->with('spreed')
2665
-			->willReturn(true);
2666
-
2667
-		// This is not possible anymore with PHPUnit 10+
2668
-		// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2669
-		// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2670
-		$helper = $this->getMockBuilder(\stdClass::class)
2671
-			->addMethods(['createShare'])
2672
-			->getMock();
2673
-		$helper->method('createShare')
2674
-			->with(
2675
-				$share,
2676
-				'recipientRoom',
2677
-				Constants::PERMISSION_ALL
2678
-				& ~Constants::PERMISSION_DELETE
2679
-				& ~Constants::PERMISSION_CREATE,
2680
-				''
2681
-			)->willReturnCallback(
2682
-				function ($share): void {
2683
-					$share->setSharedWith('recipientRoom');
2684
-					$share->setPermissions(Constants::PERMISSION_ALL);
2685
-				}
2686
-			);
2687
-
2688
-		$this->serverContainer->method('get')
2689
-			->with('\OCA\Talk\Share\Helper\ShareAPIController')
2690
-			->willReturn($helper);
2691
-
2692
-		$this->shareManager->method('createShare')
2693
-			->with($this->callback(function (IShare $share) use ($path) {
2694
-				return $share->getNode() === $path
2695
-					&& $share->getPermissions() === Constants::PERMISSION_ALL
2696
-					&& $share->getShareType() === IShare::TYPE_ROOM
2697
-					&& $share->getSharedWith() === 'recipientRoom'
2698
-					&& $share->getSharedBy() === 'currentUser';
2699
-			}))
2700
-			->willReturnArgument(0);
2701
-
2702
-		$expected = new DataResponse([]);
2703
-		$result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2704
-
2705
-		$this->assertInstanceOf(get_class($expected), $result);
2706
-		$this->assertEquals($expected->getData(), $result->getData());
2707
-	}
2708
-
2709
-
2710
-	public function testCreateShareRoomHelperNotAvailable(): void {
2711
-		$this->expectException(OCSForbiddenException::class);
2712
-		$this->expectExceptionMessage('Sharing valid-path failed because the back end does not support room shares');
2713
-
2714
-		$ocs = $this->mockFormatShare();
2715
-
2716
-		$share = $this->newShare();
2717
-		$this->shareManager->method('newShare')->willReturn($share);
2718
-
2719
-		[$userFolder, $path] = $this->getNonSharedUserFolder();
2720
-		$this->rootFolder->method('getUserFolder')
2721
-			->with('currentUser')
2722
-			->willReturn($userFolder);
2723
-
2724
-		$path->method('getPath')->willReturn('valid-path');
2725
-		$userFolder->expects($this->once())
2726
-			->method('get')
2727
-			->with('valid-path')
2728
-			->willReturn($path);
2729
-		$userFolder->method('getById')
2730
-			->willReturn([]);
2731
-
2732
-		$path->expects($this->once())
2733
-			->method('lock')
2734
-			->with(ILockingProvider::LOCK_SHARED);
2735
-
2736
-		$this->appManager->method('isEnabledForUser')
2737
-			->with('spreed')
2738
-			->willReturn(false);
2739
-
2740
-		$this->shareManager->expects($this->never())->method('createShare');
2741
-
2742
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2743
-	}
2744
-
2745
-
2746
-	public function testCreateShareRoomHelperThrowException(): void {
2747
-		$this->expectException(OCSNotFoundException::class);
2748
-		$this->expectExceptionMessage('Exception thrown by the helper');
2749
-
2750
-		$ocs = $this->mockFormatShare();
2751
-
2752
-		$share = $this->newShare();
2753
-		$share->setSharedBy('currentUser');
2754
-		$this->shareManager->method('newShare')->willReturn($share);
2755
-
2756
-		[$userFolder, $path] = $this->getNonSharedUserFile();
2757
-		$this->rootFolder->method('getUserFolder')
2758
-			->with('currentUser')
2759
-			->willReturn($userFolder);
2760
-
2761
-		$userFolder->expects($this->once())
2762
-			->method('get')
2763
-			->with('valid-path')
2764
-			->willReturn($path);
2765
-		$userFolder->method('getById')
2766
-			->willReturn([]);
2767
-
2768
-		$path->expects($this->once())
2769
-			->method('lock')
2770
-			->with(ILockingProvider::LOCK_SHARED);
2771
-
2772
-		$this->appManager->method('isEnabledForUser')
2773
-			->with('spreed')
2774
-			->willReturn(true);
2775
-
2776
-		// This is not possible anymore with PHPUnit 10+
2777
-		// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2778
-		// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2779
-		$helper = $this->getMockBuilder(\stdClass::class)
2780
-			->addMethods(['createShare'])
2781
-			->getMock();
2782
-		$helper->method('createShare')
2783
-			->with(
2784
-				$share,
2785
-				'recipientRoom',
2786
-				Constants::PERMISSION_ALL & ~(Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE),
2787
-				''
2788
-			)->willReturnCallback(
2789
-				function ($share): void {
2790
-					throw new OCSNotFoundException('Exception thrown by the helper');
2791
-				}
2792
-			);
2793
-
2794
-		$this->serverContainer->method('get')
2795
-			->with('\OCA\Talk\Share\Helper\ShareAPIController')
2796
-			->willReturn($helper);
2797
-
2798
-		$this->shareManager->expects($this->never())->method('createShare');
2799
-
2800
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2801
-	}
2802
-
2803
-	/**
2804
-	 * Test for https://github.com/owncloud/core/issues/22587
2805
-	 * TODO: Remove once proper solution is in place
2806
-	 */
2807
-	public function testCreateReshareOfFederatedMountNoDeletePermissions(): void {
2808
-		$share = Server::get(IManager::class)->newShare();
2809
-		$this->shareManager->method('newShare')->willReturn($share);
2810
-
2811
-		/** @var ShareAPIController&MockObject $ocs */
2812
-		$ocs = $this->getMockBuilder(ShareAPIController::class)
2813
-			->setConstructorArgs([
2814
-				$this->appName,
2815
-				$this->request,
2816
-				$this->shareManager,
2817
-				$this->groupManager,
2818
-				$this->userManager,
2819
-				$this->rootFolder,
2820
-				$this->urlGenerator,
2821
-				$this->l,
2822
-				$this->config,
2823
-				$this->appConfig,
2824
-				$this->appManager,
2825
-				$this->serverContainer,
2826
-				$this->userStatusManager,
2827
-				$this->previewManager,
2828
-				$this->dateTimeZone,
2829
-				$this->logger,
2830
-				$this->factory,
2831
-				$this->mailer,
2832
-				$this->tagManager,
2833
-				$this->getEmailValidatorWithStrictEmailCheck(),
2834
-				$this->trustedServers,
2835
-				$this->currentUser,
2836
-			])->onlyMethods(['formatShare'])
2837
-			->getMock();
2838
-
2839
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
2840
-		$this->rootFolder->expects($this->exactly(2))
2841
-			->method('getUserFolder')
2842
-			->with('currentUser')
2843
-			->willReturn($userFolder);
2844
-
2845
-		$path = $this->getMockBuilder(Folder::class)->getMock();
2846
-		$path->method('getId')->willReturn(42);
2847
-
2848
-		$storage = $this->createMock(IStorage::class);
2849
-		$storage->method('instanceOfStorage')
2850
-			->willReturnMap([
2851
-				['OCA\Files_Sharing\External\Storage', true],
2852
-				['OCA\Files_Sharing\SharedStorage', false],
2853
-			]);
2854
-		$userFolder->method('getStorage')->willReturn($storage);
2855
-		$path->method('getStorage')->willReturn($storage);
2856
-
2857
-		$path->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
2858
-		$userFolder->expects($this->once())
2859
-			->method('get')
2860
-			->with('valid-path')
2861
-			->willReturn($path);
2862
-		$userFolder->method('getById')
2863
-			->willReturn([]);
2864
-
2865
-		$this->userManager->method('userExists')->with('validUser')->willReturn(true);
2866
-
2867
-		$this->shareManager
2868
-			->expects($this->once())
2869
-			->method('createShare')
2870
-			->with($this->callback(function (IShare $share) {
2871
-				return $share->getPermissions() === Constants::PERMISSION_READ;
2872
-			}))
2873
-			->willReturnArgument(0);
2874
-
2875
-		$ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
2876
-	}
2877
-
2878
-
2879
-	public function testUpdateShareCantAccess(): void {
2880
-		$this->expectException(OCSNotFoundException::class);
2881
-		$this->expectExceptionMessage('Wrong share ID, share does not exist');
2882
-
2883
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
2884
-		$share = $this->newShare();
2885
-		$share->setNode($node);
2886
-
2887
-		$node->expects($this->once())
2888
-			->method('lock')
2889
-			->with(ILockingProvider::LOCK_SHARED);
2890
-
2891
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2892
-
2893
-		$this->rootFolder->method('getUserFolder')
2894
-			->with($this->currentUser)
2895
-			->willReturn($userFolder);
2896
-
2897
-		$userFolder->method('getById')
2898
-			->with($share->getNodeId())
2899
-			->willReturn([$share->getNode()]);
2900
-
2901
-		$this->ocs->updateShare(42);
2902
-	}
2903
-
2904
-
2905
-	public function testUpdateNoParametersLink(): void {
2906
-		$this->expectException(OCSBadRequestException::class);
2907
-		$this->expectExceptionMessage('Wrong or no update parameter given');
2908
-
2909
-		$node = $this->getMockBuilder(Folder::class)->getMock();
2910
-		$share = $this->newShare();
2911
-		$share->setPermissions(Constants::PERMISSION_ALL)
2912
-			->setSharedBy($this->currentUser)
2913
-			->setShareType(IShare::TYPE_LINK)
2914
-			->setNode($node);
2915
-
2916
-		$node->expects($this->once())
2917
-			->method('lock')
2918
-			->with(ILockingProvider::LOCK_SHARED);
2919
-
2920
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2921
-
2922
-		$this->ocs->updateShare(42);
2923
-	}
2924
-
2925
-
2926
-	public function testUpdateNoParametersOther(): void {
2927
-		$this->expectException(OCSBadRequestException::class);
2928
-		$this->expectExceptionMessage('Wrong or no update parameter given');
2929
-
2930
-		$node = $this->getMockBuilder(Folder::class)->getMock();
2931
-		$share = $this->newShare();
2932
-		$share->setPermissions(Constants::PERMISSION_ALL)
2933
-			->setSharedBy($this->currentUser)
2934
-			->setShareType(IShare::TYPE_GROUP)
2935
-			->setNode($node);
2936
-
2937
-		$node->expects($this->once())
2938
-			->method('lock')
2939
-			->with(ILockingProvider::LOCK_SHARED);
2940
-
2941
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2942
-
2943
-		$this->ocs->updateShare(42);
2944
-	}
2945
-
2946
-	public function testUpdateLinkShareClear(): void {
2947
-		$ocs = $this->mockFormatShare();
2948
-
2949
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
2950
-		$node->method('getId')
2951
-			->willReturn(42);
2952
-		$share = $this->newShare();
2953
-		$share->setPermissions(Constants::PERMISSION_ALL)
2954
-			->setSharedBy($this->currentUser)
2955
-			->setShareType(IShare::TYPE_LINK)
2956
-			->setPassword('password')
2957
-			->setExpirationDate(new \DateTime())
2958
-			->setNote('note')
2959
-			->setLabel('label')
2960
-			->setHideDownload(true)
2961
-			->setPermissions(Constants::PERMISSION_ALL)
2962
-			->setNode($node);
2963
-
2964
-		$node->expects($this->once())
2965
-			->method('lock')
2966
-			->with(ILockingProvider::LOCK_SHARED);
2967
-
2968
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2969
-
2970
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
2971
-			$this->callback(function (IShare $share) {
2972
-				return $share->getPermissions() === Constants::PERMISSION_READ
2973
-				&& $share->getPassword() === null
2974
-				&& $share->getExpirationDate() === null
2975
-				// Once set a note or a label are never back to null, only to an
2976
-				// empty string.
2977
-				&& $share->getNote() === ''
2978
-				&& $share->getLabel() === ''
2979
-				&& $share->getHideDownload() === false;
2980
-			})
2981
-		)->willReturnArgument(0);
2982
-
2983
-		$this->shareManager->method('getSharedWith')
2984
-			->willReturn([]);
2985
-
2986
-		$this->rootFolder->method('getUserFolder')
2987
-			->with($this->currentUser)
2988
-			->willReturn($userFolder);
2989
-
2990
-		$userFolder->method('getById')
2991
-			->with(42)
2992
-			->willReturn([$node]);
2993
-		$userFolder->method('getFirstNodeById')
2994
-			->with(42)
2995
-			->willReturn($node);
2996
-
2997
-		$mountPoint = $this->createMock(IMountPoint::class);
2998
-		$node->method('getMountPoint')
2999
-			->willReturn($mountPoint);
3000
-		$mountPoint->method('getStorageRootId')
3001
-			->willReturn(42);
3002
-
3003
-		$expected = new DataResponse([]);
3004
-		$result = $ocs->updateShare(42, null, '', null, 'false', '', '', '', 'false');
3005
-
3006
-		$this->assertInstanceOf(get_class($expected), $result);
3007
-		$this->assertEquals($expected->getData(), $result->getData());
3008
-	}
3009
-
3010
-	public function testUpdateLinkShareSet(): void {
3011
-		$ocs = $this->mockFormatShare();
3012
-
3013
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3014
-		$folder->method('getId')
3015
-			->willReturn(42);
3016
-
3017
-		$share = Server::get(IManager::class)->newShare();
3018
-		$share->setPermissions(Constants::PERMISSION_ALL)
3019
-			->setSharedBy($this->currentUser)
3020
-			->setShareType(IShare::TYPE_LINK)
3021
-			->setNode($folder);
3022
-
3023
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3024
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3025
-
3026
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3027
-			$this->callback(function (IShare $share) {
3028
-				$date = new \DateTime('2000-01-01');
3029
-				$date->setTime(0, 0, 0);
3030
-
3031
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3032
-				&& $share->getPassword() === 'password'
3033
-				&& $share->getExpirationDate() == $date
3034
-				&& $share->getNote() === 'note'
3035
-				&& $share->getLabel() === 'label'
3036
-				&& $share->getHideDownload() === true;
3037
-			})
3038
-		)->willReturnArgument(0);
3039
-
3040
-		$this->shareManager->method('getSharedWith')
3041
-			->willReturn([]);
3042
-
3043
-		$this->rootFolder->method('getUserFolder')
3044
-			->with($this->currentUser)
3045
-			->willReturn($userFolder);
3046
-
3047
-		$userFolder->method('getById')
3048
-			->with(42)
3049
-			->willReturn([$folder]);
3050
-
3051
-		$mountPoint = $this->createMock(IMountPoint::class);
3052
-		$folder->method('getMountPoint')
3053
-			->willReturn($mountPoint);
3054
-		$mountPoint->method('getStorageRootId')
3055
-			->willReturn(42);
3056
-
3057
-		$expected = new DataResponse([]);
3058
-		$result = $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-01', 'note', 'label', 'true');
3059
-
3060
-		$this->assertInstanceOf(get_class($expected), $result);
3061
-		$this->assertEquals($expected->getData(), $result->getData());
3062
-	}
3063
-
3064
-	#[DataProvider(methodName: 'publicUploadParamsProvider')]
3065
-	public function testUpdateLinkShareEnablePublicUpload($permissions, $publicUpload, $expireDate, $password): void {
3066
-		$ocs = $this->mockFormatShare();
3067
-
3068
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3069
-		$folder->method('getId')
3070
-			->willReturn(42);
3071
-
3072
-		$share = Server::get(IManager::class)->newShare();
3073
-		$share->setPermissions(Constants::PERMISSION_ALL)
3074
-			->setSharedBy($this->currentUser)
3075
-			->setShareType(IShare::TYPE_LINK)
3076
-			->setPassword('password')
3077
-			->setNode($folder);
3078
-
3079
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3080
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3081
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3082
-
3083
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3084
-			$this->callback(function (IShare $share) {
3085
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3086
-				&& $share->getPassword() === 'password'
3087
-				&& $share->getExpirationDate() === null;
3088
-			})
3089
-		)->willReturnArgument(0);
3090
-
3091
-		$this->rootFolder->method('getUserFolder')
3092
-			->with($this->currentUser)
3093
-			->willReturn($userFolder);
3094
-
3095
-		$userFolder->method('getById')
3096
-			->with(42)
3097
-			->willReturn([$folder]);
3098
-
3099
-		$mountPoint = $this->createMock(IMountPoint::class);
3100
-		$folder->method('getMountPoint')
3101
-			->willReturn($mountPoint);
3102
-		$mountPoint->method('getStorageRootId')
3103
-			->willReturn(42);
3104
-
3105
-		$expected = new DataResponse([]);
3106
-		$result = $ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
3107
-
3108
-		$this->assertInstanceOf(get_class($expected), $result);
3109
-		$this->assertEquals($expected->getData(), $result->getData());
3110
-	}
3111
-
3112
-
3113
-	public static function publicLinkValidPermissionsProvider() {
3114
-		return [
3115
-			[Constants::PERMISSION_CREATE],
3116
-			[Constants::PERMISSION_READ],
3117
-			[Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE],
3118
-			[Constants::PERMISSION_READ | Constants::PERMISSION_DELETE],
3119
-			[Constants::PERMISSION_READ | Constants::PERMISSION_CREATE],
3120
-		];
3121
-	}
3122
-
3123
-	#[DataProvider(methodName: 'publicLinkValidPermissionsProvider')]
3124
-	public function testUpdateLinkShareSetCRUDPermissions($permissions): void {
3125
-		$ocs = $this->mockFormatShare();
3126
-
3127
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3128
-		$folder->method('getId')
3129
-			->willReturn(42);
3130
-
3131
-		$share = Server::get(IManager::class)->newShare();
3132
-		$share->setPermissions(Constants::PERMISSION_ALL)
3133
-			->setSharedBy($this->currentUser)
3134
-			->setShareType(IShare::TYPE_LINK)
3135
-			->setPassword('password')
3136
-			->setNode($folder);
3137
-
3138
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3139
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3140
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3141
-
3142
-		$this->shareManager
3143
-			->expects($this->any())
3144
-			->method('updateShare')
3145
-			->willReturnArgument(0);
3146
-
3147
-		$this->rootFolder->method('getUserFolder')
3148
-			->with($this->currentUser)
3149
-			->willReturn($userFolder);
3150
-
3151
-		$userFolder->method('getById')
3152
-			->with(42)
3153
-			->willReturn([$folder]);
3154
-
3155
-		$mountPoint = $this->createMock(IMountPoint::class);
3156
-		$folder->method('getMountPoint')
3157
-			->willReturn($mountPoint);
3158
-		$mountPoint->method('getStorageRootId')
3159
-			->willReturn(42);
3160
-
3161
-		$expected = new DataResponse([]);
3162
-		$result = $ocs->updateShare(42, $permissions, 'password', null, null, null);
3163
-
3164
-		$this->assertInstanceOf(get_class($expected), $result);
3165
-		$this->assertEquals($expected->getData(), $result->getData());
3166
-	}
3167
-
3168
-	public static function publicLinkInvalidPermissionsProvider1() {
3169
-		return [
3170
-			[Constants::PERMISSION_DELETE],
3171
-			[Constants::PERMISSION_UPDATE],
3172
-			[Constants::PERMISSION_SHARE],
3173
-		];
3174
-	}
3175
-
3176
-	#[DataProvider(methodName: 'publicLinkInvalidPermissionsProvider1')]
3177
-	public function testUpdateLinkShareSetInvalidCRUDPermissions1($permissions): void {
3178
-		$this->expectException(OCSBadRequestException::class);
3179
-		$this->expectExceptionMessage('Share must at least have READ or CREATE permissions');
3180
-
3181
-		$this->testUpdateLinkShareSetCRUDPermissions($permissions, null);
3182
-	}
3183
-
3184
-	public static function publicLinkInvalidPermissionsProvider2() {
3185
-		return [
3186
-			[Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE],
3187
-			[Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE],
3188
-		];
3189
-	}
3190
-
3191
-	#[DataProvider(methodName: 'publicLinkInvalidPermissionsProvider2')]
3192
-	public function testUpdateLinkShareSetInvalidCRUDPermissions2($permissions): void {
3193
-		$this->expectException(OCSBadRequestException::class);
3194
-		$this->expectExceptionMessage('Share must have READ permission if UPDATE or DELETE permission is set');
3195
-
3196
-		$this->testUpdateLinkShareSetCRUDPermissions($permissions);
3197
-	}
3198
-
3199
-	public function testUpdateLinkShareInvalidDate(): void {
3200
-		$this->expectException(OCSBadRequestException::class);
3201
-		$this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
3202
-
3203
-		$ocs = $this->mockFormatShare();
3204
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3205
-		$userFolder->method('getById')
3206
-			->with(42)
3207
-			->willReturn([$folder]);
3208
-		$this->rootFolder->method('getUserFolder')
3209
-			->with($this->currentUser)
3210
-			->willReturn($userFolder);
3211
-
3212
-		$folder->method('getId')
3213
-			->willReturn(42);
3214
-
3215
-		$share = Server::get(IManager::class)->newShare();
3216
-		$share->setPermissions(Constants::PERMISSION_ALL)
3217
-			->setSharedBy($this->currentUser)
3218
-			->setShareType(IShare::TYPE_LINK)
3219
-			->setNode($folder);
3220
-
3221
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3222
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3223
-
3224
-		$ocs->updateShare(42, null, 'password', null, 'true', '2000-01-a');
3225
-	}
3226
-
3227
-	public static function publicUploadParamsProvider() {
3228
-		return [
3229
-			[null, 'true', null, 'password'],
3230
-			// legacy had no delete
3231
-			[
3232
-				Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE,
3233
-				'true', null, 'password'
3234
-			],
3235
-			// correct
3236
-			[
3237
-				Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE,
3238
-				null, null, 'password'
3239
-			],
3240
-		];
3241
-	}
3242
-
3243
-	#[DataProvider(methodName: 'publicUploadParamsProvider')]
3244
-	public function testUpdateLinkSharePublicUploadNotAllowed($permissions, $publicUpload, $expireDate, $password): void {
3245
-		$this->expectException(OCSForbiddenException::class);
3246
-		$this->expectExceptionMessage('Public upload disabled by the administrator');
3247
-
3248
-		$ocs = $this->mockFormatShare();
3249
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3250
-		$userFolder->method('getById')
3251
-			->with(42)
3252
-			->willReturn([$folder]);
3253
-		$this->rootFolder->method('getUserFolder')
3254
-			->with($this->currentUser)
3255
-			->willReturn($userFolder);
3256
-
3257
-		$folder->method('getId')->willReturn(42);
3258
-
3259
-		$share = Server::get(IManager::class)->newShare();
3260
-		$share->setPermissions(Constants::PERMISSION_ALL)
3261
-			->setSharedBy($this->currentUser)
3262
-			->setShareType(IShare::TYPE_LINK)
3263
-			->setNode($folder);
3264
-
3265
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3266
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false);
3267
-
3268
-		$ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
3269
-	}
3270
-
3271
-
3272
-	public function testUpdateLinkSharePublicUploadOnFile(): void {
3273
-		$this->expectException(OCSBadRequestException::class);
3274
-		$this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
3275
-
3276
-		$ocs = $this->mockFormatShare();
3277
-
3278
-		$file = $this->getMockBuilder(File::class)->getMock();
3279
-		$file->method('getId')
3280
-			->willReturn(42);
3281
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3282
-		$userFolder->method('getById')
3283
-			->with(42)
3284
-			->willReturn([$folder]);
3285
-		$this->rootFolder->method('getUserFolder')
3286
-			->with($this->currentUser)
3287
-			->willReturn($userFolder);
3288
-
3289
-		$share = Server::get(IManager::class)->newShare();
3290
-		$share->setPermissions(Constants::PERMISSION_ALL)
3291
-			->setSharedBy($this->currentUser)
3292
-			->setShareType(IShare::TYPE_LINK)
3293
-			->setNode($file);
3294
-
3295
-		$this->shareManager
3296
-			->method('getShareById')
3297
-			->with('ocinternal:42')
3298
-			->willReturn($share);
3299
-		$this->shareManager
3300
-			->method('shareApiLinkAllowPublicUpload')
3301
-			->willReturn(true);
3302
-		$this->shareManager
3303
-			->method('updateShare')
3304
-			->with($share)
3305
-			->willThrowException(new \InvalidArgumentException('File shares cannot have create or delete permissions'));
3306
-
3307
-		$ocs->updateShare(42, null, 'password', null, 'true', '');
3308
-	}
3309
-
3310
-	public function testUpdateLinkSharePasswordDoesNotChangeOther(): void {
3311
-		$ocs = $this->mockFormatShare();
3312
-
3313
-		$date = new \DateTime('2000-01-01');
3314
-		$date->setTime(0, 0, 0);
3315
-
3316
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3317
-		$node->method('getId')->willReturn(42);
3318
-		$userFolder->method('getById')
3319
-			->with(42)
3320
-			->willReturn([$node]);
3321
-		$this->rootFolder->method('getUserFolder')
3322
-			->with($this->currentUser)
3323
-			->willReturn($userFolder);
3324
-		$share = $this->newShare();
3325
-		$share->setPermissions(Constants::PERMISSION_ALL)
3326
-			->setSharedBy($this->currentUser)
3327
-			->setShareType(IShare::TYPE_LINK)
3328
-			->setPassword('password')
3329
-			->setSendPasswordByTalk(true)
3330
-			->setExpirationDate($date)
3331
-			->setNote('note')
3332
-			->setLabel('label')
3333
-			->setHideDownload(true)
3334
-			->setPermissions(Constants::PERMISSION_ALL)
3335
-			->setNode($node);
3336
-
3337
-		$node->expects($this->once())
3338
-			->method('lock')
3339
-			->with(ILockingProvider::LOCK_SHARED);
3340
-
3341
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3342
-
3343
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3344
-			$this->callback(function (IShare $share) use ($date) {
3345
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3346
-				&& $share->getPassword() === 'newpassword'
3347
-				&& $share->getSendPasswordByTalk() === true
3348
-				&& $share->getExpirationDate() === $date
3349
-				&& $share->getNote() === 'note'
3350
-				&& $share->getLabel() === 'label'
3351
-				&& $share->getHideDownload() === true;
3352
-			})
3353
-		)->willReturnArgument(0);
3354
-
3355
-		$expected = new DataResponse([]);
3356
-		$result = $ocs->updateShare(42, null, 'newpassword', null, null, null, null, null, null);
3357
-
3358
-		$this->assertInstanceOf(get_class($expected), $result);
3359
-		$this->assertEquals($expected->getData(), $result->getData());
3360
-	}
3361
-
3362
-	public function testUpdateLinkShareSendPasswordByTalkDoesNotChangeOther(): void {
3363
-		$ocs = $this->mockFormatShare();
3364
-
3365
-		$date = new \DateTime('2000-01-01');
3366
-		$date->setTime(0, 0, 0);
3367
-
3368
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3369
-		$userFolder->method('getById')
3370
-			->with(42)
3371
-			->willReturn([$node]);
3372
-		$this->rootFolder->method('getUserFolder')
3373
-			->with($this->currentUser)
3374
-			->willReturn($userFolder);
3375
-		$node->method('getId')->willReturn(42);
3376
-		$share = $this->newShare();
3377
-		$share->setPermissions(Constants::PERMISSION_ALL)
3378
-			->setSharedBy($this->currentUser)
3379
-			->setShareType(IShare::TYPE_LINK)
3380
-			->setPassword('password')
3381
-			->setSendPasswordByTalk(false)
3382
-			->setExpirationDate($date)
3383
-			->setNote('note')
3384
-			->setLabel('label')
3385
-			->setHideDownload(true)
3386
-			->setPermissions(Constants::PERMISSION_ALL)
3387
-			->setNode($node);
3388
-
3389
-		$node->expects($this->once())
3390
-			->method('lock')
3391
-			->with(ILockingProvider::LOCK_SHARED);
3392
-
3393
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3394
-
3395
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3396
-
3397
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3398
-			$this->callback(function (IShare $share) use ($date) {
3399
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3400
-				&& $share->getPassword() === 'password'
3401
-				&& $share->getSendPasswordByTalk() === true
3402
-				&& $share->getExpirationDate() === $date
3403
-				&& $share->getNote() === 'note'
3404
-				&& $share->getLabel() === 'label'
3405
-				&& $share->getHideDownload() === true;
3406
-			})
3407
-		)->willReturnArgument(0);
3408
-
3409
-		$expected = new DataResponse([]);
3410
-		$result = $ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3411
-
3412
-		$this->assertInstanceOf(get_class($expected), $result);
3413
-		$this->assertEquals($expected->getData(), $result->getData());
3414
-	}
3415
-
3416
-
3417
-	public function testUpdateLinkShareSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3418
-		$this->expectException(OCSForbiddenException::class);
3419
-		$this->expectExceptionMessage('"Sending the password by Nextcloud Talk" for sharing a file or folder failed because Nextcloud Talk is not enabled.');
3420
-
3421
-		$ocs = $this->mockFormatShare();
3422
-
3423
-		$date = new \DateTime('2000-01-01');
3424
-		$date->setTime(0, 0, 0);
3425
-
3426
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3427
-		$userFolder->method('getById')
3428
-			->with(42)
3429
-			->willReturn([$node]);
3430
-		$this->rootFolder->method('getUserFolder')
3431
-			->with($this->currentUser)
3432
-			->willReturn($userFolder);
3433
-		$node->method('getId')->willReturn(42);
3434
-		$share = $this->newShare();
3435
-		$share->setPermissions(Constants::PERMISSION_ALL)
3436
-			->setSharedBy($this->currentUser)
3437
-			->setShareType(IShare::TYPE_LINK)
3438
-			->setPassword('password')
3439
-			->setSendPasswordByTalk(false)
3440
-			->setExpirationDate($date)
3441
-			->setNote('note')
3442
-			->setLabel('label')
3443
-			->setHideDownload(true)
3444
-			->setPermissions(Constants::PERMISSION_ALL)
3445
-			->setNode($node);
3446
-
3447
-		$node->expects($this->once())
3448
-			->method('lock')
3449
-			->with(ILockingProvider::LOCK_SHARED);
3450
-
3451
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3452
-
3453
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3454
-
3455
-		$this->shareManager->expects($this->never())->method('updateShare');
3456
-
3457
-		$ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3458
-	}
3459
-
3460
-	public function testUpdateLinkShareDoNotSendPasswordByTalkDoesNotChangeOther(): void {
3461
-		$ocs = $this->mockFormatShare();
3462
-
3463
-		$date = new \DateTime('2000-01-01');
3464
-		$date->setTime(0, 0, 0);
3465
-
3466
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3467
-		$userFolder->method('getById')
3468
-			->with(42)
3469
-			->willReturn([$node]);
3470
-		$this->rootFolder->method('getUserFolder')
3471
-			->with($this->currentUser)
3472
-			->willReturn($userFolder);
3473
-		$node->method('getId')->willReturn(42);
3474
-		$share = $this->newShare();
3475
-		$share->setPermissions(Constants::PERMISSION_ALL)
3476
-			->setSharedBy($this->currentUser)
3477
-			->setShareType(IShare::TYPE_LINK)
3478
-			->setPassword('password')
3479
-			->setSendPasswordByTalk(true)
3480
-			->setExpirationDate($date)
3481
-			->setNote('note')
3482
-			->setLabel('label')
3483
-			->setHideDownload(true)
3484
-			->setPermissions(Constants::PERMISSION_ALL)
3485
-			->setNode($node);
3486
-
3487
-		$node->expects($this->once())
3488
-			->method('lock')
3489
-			->with(ILockingProvider::LOCK_SHARED);
3490
-
3491
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3492
-
3493
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3494
-
3495
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3496
-			$this->callback(function (IShare $share) use ($date) {
3497
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3498
-				&& $share->getPassword() === 'password'
3499
-				&& $share->getSendPasswordByTalk() === false
3500
-				&& $share->getExpirationDate() === $date
3501
-				&& $share->getNote() === 'note'
3502
-				&& $share->getLabel() === 'label'
3503
-				&& $share->getHideDownload() === true;
3504
-			})
3505
-		)->willReturnArgument(0);
3506
-
3507
-		$expected = new DataResponse([]);
3508
-		$result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3509
-
3510
-		$this->assertInstanceOf(get_class($expected), $result);
3511
-		$this->assertEquals($expected->getData(), $result->getData());
3512
-	}
3513
-
3514
-	public function testUpdateLinkShareDoNotSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3515
-		$ocs = $this->mockFormatShare();
3516
-
3517
-		$date = new \DateTime('2000-01-01');
3518
-		$date->setTime(0, 0, 0);
3519
-
3520
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3521
-		$node->method('getId')
3522
-			->willReturn(42);
3523
-
3524
-		$share = $this->newShare();
3525
-		$share->setPermissions(Constants::PERMISSION_ALL)
3526
-			->setSharedBy($this->currentUser)
3527
-			->setShareType(IShare::TYPE_LINK)
3528
-			->setPassword('password')
3529
-			->setSendPasswordByTalk(true)
3530
-			->setExpirationDate($date)
3531
-			->setNote('note')
3532
-			->setLabel('label')
3533
-			->setHideDownload(true)
3534
-			->setPermissions(Constants::PERMISSION_ALL)
3535
-			->setNode($node);
3536
-
3537
-		$node->expects($this->once())
3538
-			->method('lock')
3539
-			->with(ILockingProvider::LOCK_SHARED);
3540
-
3541
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3542
-
3543
-		$this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3544
-
3545
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3546
-			$this->callback(function (IShare $share) use ($date) {
3547
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3548
-				&& $share->getPassword() === 'password'
3549
-				&& $share->getSendPasswordByTalk() === false
3550
-				&& $share->getExpirationDate() === $date
3551
-				&& $share->getNote() === 'note'
3552
-				&& $share->getLabel() === 'label'
3553
-				&& $share->getHideDownload() === true;
3554
-			})
3555
-		)->willReturnArgument(0);
3556
-
3557
-		$this->rootFolder->method('getUserFolder')
3558
-			->with($this->currentUser)
3559
-			->willReturn($userFolder);
3560
-
3561
-		$userFolder->method('getById')
3562
-			->with(42)
3563
-			->willReturn([$node]);
3564
-
3565
-		$mountPoint = $this->createMock(IMountPoint::class);
3566
-		$node->method('getMountPoint')
3567
-			->willReturn($mountPoint);
3568
-		$mountPoint->method('getStorageRootId')
3569
-			->willReturn(42);
3570
-
3571
-		$mountPoint = $this->createMock(IMountPoint::class);
3572
-		$node->method('getMountPoint')
3573
-			->willReturn($mountPoint);
3574
-		$mountPoint->method('getStorageRootId')
3575
-			->willReturn(42);
3576
-
3577
-		$expected = new DataResponse([]);
3578
-		$result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3579
-
3580
-		$this->assertInstanceOf(get_class($expected), $result);
3581
-		$this->assertEquals($expected->getData(), $result->getData());
3582
-	}
3583
-
3584
-	public function testUpdateLinkShareExpireDateDoesNotChangeOther(): void {
3585
-		$ocs = $this->mockFormatShare();
3586
-
3587
-		[$userFolder, $node] = $this->getNonSharedUserFolder();
3588
-		$node->method('getId')
3589
-			->willReturn(42);
3590
-
3591
-		$share = $this->newShare();
3592
-		$share->setPermissions(Constants::PERMISSION_ALL)
3593
-			->setSharedBy($this->currentUser)
3594
-			->setShareType(IShare::TYPE_LINK)
3595
-			->setPassword('password')
3596
-			->setSendPasswordByTalk(true)
3597
-			->setExpirationDate(new \DateTime())
3598
-			->setNote('note')
3599
-			->setLabel('label')
3600
-			->setHideDownload(true)
3601
-			->setPermissions(Constants::PERMISSION_ALL)
3602
-			->setNode($node);
3603
-
3604
-		$node->expects($this->once())
3605
-			->method('lock')
3606
-			->with(ILockingProvider::LOCK_SHARED);
3607
-
3608
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3609
-
3610
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3611
-			$this->callback(function (IShare $share) {
3612
-				$date = new \DateTime('2010-12-23');
3613
-				$date->setTime(0, 0, 0);
3614
-
3615
-				return $share->getPermissions() === Constants::PERMISSION_ALL
3616
-				&& $share->getPassword() === 'password'
3617
-				&& $share->getSendPasswordByTalk() === true
3618
-				&& $share->getExpirationDate() == $date
3619
-				&& $share->getNote() === 'note'
3620
-				&& $share->getLabel() === 'label'
3621
-				&& $share->getHideDownload() === true;
3622
-			})
3623
-		)->willReturnArgument(0);
3624
-
3625
-		$this->rootFolder->method('getUserFolder')
3626
-			->with($this->currentUser)
3627
-			->willReturn($userFolder);
3628
-
3629
-		$userFolder->method('getById')
3630
-			->with(42)
3631
-			->willReturn([$node]);
3632
-
3633
-		$mountPoint = $this->createMock(IMountPoint::class);
3634
-		$node->method('getMountPoint')
3635
-			->willReturn($mountPoint);
3636
-		$mountPoint->method('getStorageRootId')
3637
-			->willReturn(42);
3638
-
3639
-		$expected = new DataResponse([]);
3640
-		$result = $ocs->updateShare(42, null, null, null, null, '2010-12-23', null, null, null);
3641
-
3642
-		$this->assertInstanceOf(get_class($expected), $result);
3643
-		$this->assertEquals($expected->getData(), $result->getData());
3644
-	}
3645
-
3646
-	public function testUpdateLinkSharePublicUploadDoesNotChangeOther(): void {
3647
-		$ocs = $this->mockFormatShare();
3648
-
3649
-		$date = new \DateTime('2000-01-01');
3650
-
3651
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3652
-		$folder->method('getId')
3653
-			->willReturn(42);
3654
-
3655
-		$share = Server::get(IManager::class)->newShare();
3656
-		$share->setPermissions(Constants::PERMISSION_ALL)
3657
-			->setSharedBy($this->currentUser)
3658
-			->setShareType(IShare::TYPE_LINK)
3659
-			->setPassword('password')
3660
-			->setSendPasswordByTalk(true)
3661
-			->setExpirationDate($date)
3662
-			->setNote('note')
3663
-			->setLabel('label')
3664
-			->setHideDownload(true)
3665
-			->setPermissions(Constants::PERMISSION_ALL)
3666
-			->setNode($folder);
3667
-
3668
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3669
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3670
-
3671
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3672
-			$this->callback(function (IShare $share) use ($date) {
3673
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3674
-				&& $share->getPassword() === 'password'
3675
-				&& $share->getSendPasswordByTalk() === true
3676
-				&& $share->getExpirationDate() === $date
3677
-				&& $share->getNote() === 'note'
3678
-				&& $share->getLabel() === 'label'
3679
-				&& $share->getHideDownload() === true;
3680
-			})
3681
-		)->willReturnArgument(0);
3682
-
3683
-		$this->shareManager->method('getSharedWith')
3684
-			->willReturn([]);
3685
-
3686
-		$this->rootFolder->method('getUserFolder')
3687
-			->with($this->currentUser)
3688
-			->willReturn($userFolder);
3689
-
3690
-		$userFolder->method('getById')
3691
-			->with(42)
3692
-			->willReturn([$folder]);
3693
-
3694
-		$mountPoint = $this->createMock(IMountPoint::class);
3695
-		$folder->method('getMountPoint')
3696
-			->willReturn($mountPoint);
3697
-		$mountPoint->method('getStorageRootId')
3698
-			->willReturn(42);
3699
-
3700
-		$expected = new DataResponse([]);
3701
-		$result = $ocs->updateShare(42, null, null, null, 'true', null, null, null, null);
3702
-
3703
-		$this->assertInstanceOf(get_class($expected), $result);
3704
-		$this->assertEquals($expected->getData(), $result->getData());
3705
-	}
3706
-
3707
-	public function testUpdateLinkSharePermissions(): void {
3708
-		$ocs = $this->mockFormatShare();
3709
-
3710
-		$date = new \DateTime('2000-01-01');
3711
-
3712
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3713
-		$folder->method('getId')
3714
-			->willReturn(42);
3715
-
3716
-		$share = Server::get(IManager::class)->newShare();
3717
-		$share->setPermissions(Constants::PERMISSION_ALL)
3718
-			->setSharedBy($this->currentUser)
3719
-			->setShareType(IShare::TYPE_LINK)
3720
-			->setPassword('password')
3721
-			->setSendPasswordByTalk(true)
3722
-			->setExpirationDate($date)
3723
-			->setNote('note')
3724
-			->setLabel('label')
3725
-			->setHideDownload(true)
3726
-			->setPermissions(Constants::PERMISSION_ALL)
3727
-			->setNode($folder);
3728
-
3729
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3730
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3731
-
3732
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3733
-			$this->callback(function (IShare $share) use ($date): bool {
3734
-				return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3735
-				&& $share->getPassword() === 'password'
3736
-				&& $share->getSendPasswordByTalk() === true
3737
-				&& $share->getExpirationDate() === $date
3738
-				&& $share->getNote() === 'note'
3739
-				&& $share->getLabel() === 'label'
3740
-				&& $share->getHideDownload() === true;
3741
-			})
3742
-		)->willReturnArgument(0);
3743
-
3744
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3745
-
3746
-		$this->rootFolder->method('getUserFolder')
3747
-			->with($this->currentUser)
3748
-			->willReturn($userFolder);
3749
-
3750
-		$userFolder->method('getById')
3751
-			->with(42)
3752
-			->willReturn([$folder]);
3753
-
3754
-		$mountPoint = $this->createMock(IMountPoint::class);
3755
-		$folder->method('getMountPoint')
3756
-			->willReturn($mountPoint);
3757
-		$mountPoint->method('getStorageRootId')
3758
-			->willReturn(42);
3759
-
3760
-		$expected = new DataResponse([]);
3761
-		$result = $ocs->updateShare(42, 7, null, null, 'true', null, null, null, null);
3762
-
3763
-		$this->assertInstanceOf(get_class($expected), $result);
3764
-		$this->assertEquals($expected->getData(), $result->getData());
3765
-	}
3766
-
3767
-	public function testUpdateLinkSharePermissionsShare(): void {
3768
-		$ocs = $this->mockFormatShare();
3769
-
3770
-		$date = new \DateTime('2000-01-01');
3771
-
3772
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3773
-		$folder->method('getId')
3774
-			->willReturn(42);
3775
-
3776
-		$share = Server::get(IManager::class)->newShare();
3777
-		$share->setPermissions(Constants::PERMISSION_ALL)
3778
-			->setSharedBy($this->currentUser)
3779
-			->setShareType(IShare::TYPE_LINK)
3780
-			->setPassword('password')
3781
-			->setSendPasswordByTalk(true)
3782
-			->setExpirationDate($date)
3783
-			->setNote('note')
3784
-			->setLabel('label')
3785
-			->setHideDownload(true)
3786
-			->setPermissions(Constants::PERMISSION_READ)
3787
-			->setNode($folder);
3788
-
3789
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3790
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3791
-
3792
-		$this->shareManager->expects($this->once())
3793
-			->method('updateShare')
3794
-			->with(
3795
-				$this->callback(function (IShare $share) use ($date) {
3796
-					return $share->getPermissions() === Constants::PERMISSION_ALL
3797
-						&& $share->getPassword() === 'password'
3798
-						&& $share->getSendPasswordByTalk() === true
3799
-						&& $share->getExpirationDate() === $date
3800
-						&& $share->getNote() === 'note'
3801
-						&& $share->getLabel() === 'label'
3802
-						&& $share->getHideDownload() === true;
3803
-				})
3804
-			)->willReturnArgument(0);
3805
-
3806
-		$this->rootFolder->method('getUserFolder')
3807
-			->with($this->currentUser)
3808
-			->willReturn($userFolder);
3809
-
3810
-		$userFolder->method('getById')
3811
-			->with(42)
3812
-			->willReturn([$folder]);
3813
-
3814
-		$mountPoint = $this->createMock(IMountPoint::class);
3815
-		$folder->method('getMountPoint')
3816
-			->willReturn($mountPoint);
3817
-		$mountPoint->method('getStorageRootId')
3818
-			->willReturn(42);
3819
-
3820
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3821
-
3822
-		$expected = new DataResponse([]);
3823
-		$result = $ocs->updateShare(42, Constants::PERMISSION_ALL, null, null, null, null, null, null, null);
3824
-
3825
-		$this->assertInstanceOf(get_class($expected), $result);
3826
-		$this->assertEquals($expected->getData(), $result->getData());
3827
-	}
3828
-
3829
-	public function testUpdateOtherPermissions(): void {
3830
-		$ocs = $this->mockFormatShare();
3831
-
3832
-		[$userFolder, $file] = $this->getNonSharedUserFolder();
3833
-		$file->method('getId')
3834
-			->willReturn(42);
3835
-
3836
-		$share = Server::get(IManager::class)->newShare();
3837
-		$share->setPermissions(Constants::PERMISSION_ALL)
3838
-			->setSharedBy($this->currentUser)
3839
-			->setShareType(IShare::TYPE_USER)
3840
-			->setNode($file);
3841
-
3842
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3843
-		$this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3844
-
3845
-		$this->shareManager->expects($this->once())->method('updateShare')->with(
3846
-			$this->callback(function (IShare $share) {
3847
-				return $share->getPermissions() === Constants::PERMISSION_ALL;
3848
-			})
3849
-		)->willReturnArgument(0);
3850
-
3851
-		$this->shareManager->method('getSharedWith')->willReturn([]);
3852
-
3853
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3854
-		$this->rootFolder->method('getUserFolder')
3855
-			->with($this->currentUser)
3856
-			->willReturn($userFolder);
3857
-
3858
-		$userFolder->method('getById')
3859
-			->with(42)
3860
-			->willReturn([$file]);
3861
-
3862
-		$mountPoint = $this->createMock(IMountPoint::class);
3863
-		$file->method('getMountPoint')
3864
-			->willReturn($mountPoint);
3865
-		$mountPoint->method('getStorageRootId')
3866
-			->willReturn(42);
3867
-
3868
-		$expected = new DataResponse([]);
3869
-		$result = $ocs->updateShare(42, 31, null, null, null, null);
3870
-
3871
-		$this->assertInstanceOf(get_class($expected), $result);
3872
-		$this->assertEquals($expected->getData(), $result->getData());
3873
-	}
3874
-
3875
-	public function testUpdateShareCannotIncreasePermissions(): void {
3876
-		$ocs = $this->mockFormatShare();
3877
-
3878
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3879
-		$folder->method('getId')
3880
-			->willReturn(42);
3881
-
3882
-		$share = Server::get(IManager::class)->newShare();
3883
-		$share
3884
-			->setId(42)
3885
-			->setSharedBy($this->currentUser)
3886
-			->setShareOwner('anotheruser')
3887
-			->setShareType(IShare::TYPE_GROUP)
3888
-			->setSharedWith('group1')
3889
-			->setPermissions(Constants::PERMISSION_READ)
3890
-			->setNode($folder);
3891
-
3892
-		// note: updateShare will modify the received instance but getSharedWith will reread from the database,
3893
-		// so their values will be different
3894
-		$incomingShare = Server::get(IManager::class)->newShare();
3895
-		$incomingShare
3896
-			->setId(42)
3897
-			->setSharedBy($this->currentUser)
3898
-			->setShareOwner('anotheruser')
3899
-			->setShareType(IShare::TYPE_GROUP)
3900
-			->setSharedWith('group1')
3901
-			->setPermissions(Constants::PERMISSION_READ)
3902
-			->setNode($folder);
3903
-
3904
-		$this->request
3905
-			->method('getParam')
3906
-			->willReturnMap([
3907
-				['permissions', null, '31'],
3908
-			]);
3909
-
3910
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3911
-
3912
-		$this->shareManager->expects($this->any())
3913
-			->method('getSharedWith')
3914
-			->willReturnMap([
3915
-				['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3916
-				['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]],
3917
-				['currentUser', IShare::TYPE_ROOM, $share->getNode(), -1, 0, []]
3918
-			]);
3919
-
3920
-		$this->rootFolder->method('getUserFolder')
3921
-			->with($this->currentUser)
3922
-			->willReturn($userFolder);
3923
-
3924
-		$userFolder->method('getById')
3925
-			->with(42)
3926
-			->willReturn([$folder]);
3927
-		$userFolder->method('getFirstNodeById')
3928
-			->with(42)
3929
-			->willReturn($folder);
3930
-
3931
-		$mountPoint = $this->createMock(IMountPoint::class);
3932
-		$folder->method('getMountPoint')
3933
-			->willReturn($mountPoint);
3934
-		$mountPoint->method('getStorageRootId')
3935
-			->willReturn(42);
3936
-
3937
-		$this->shareManager->expects($this->once())
3938
-			->method('updateShare')
3939
-			->with($share)
3940
-			->willThrowException(new GenericShareException('Cannot increase permissions of path/file', 'Cannot increase permissions of path/file', 404));
3941
-
3942
-		try {
3943
-			$ocs->updateShare(42, 31);
3944
-			$this->fail();
3945
-		} catch (OCSException $e) {
3946
-			$this->assertEquals('Cannot increase permissions of path/file', $e->getMessage());
3947
-		}
3948
-	}
3949
-
3950
-	public function testUpdateShareCanIncreasePermissionsIfOwner(): void {
3951
-		$ocs = $this->mockFormatShare();
3952
-
3953
-		[$userFolder, $folder] = $this->getNonSharedUserFolder();
3954
-		$folder->method('getId')
3955
-			->willReturn(42);
3956
-
3957
-		$share = Server::get(IManager::class)->newShare();
3958
-		$share
3959
-			->setId(42)
3960
-			->setSharedBy($this->currentUser)
3961
-			->setShareOwner($this->currentUser)
3962
-			->setShareType(IShare::TYPE_GROUP)
3963
-			->setSharedWith('group1')
3964
-			->setPermissions(Constants::PERMISSION_READ)
3965
-			->setNode($folder);
3966
-
3967
-		// note: updateShare will modify the received instance but getSharedWith will reread from the database,
3968
-		// so their values will be different
3969
-		$incomingShare = Server::get(IManager::class)->newShare();
3970
-		$incomingShare
3971
-			->setId(42)
3972
-			->setSharedBy($this->currentUser)
3973
-			->setShareOwner($this->currentUser)
3974
-			->setShareType(IShare::TYPE_GROUP)
3975
-			->setSharedWith('group1')
3976
-			->setPermissions(Constants::PERMISSION_READ)
3977
-			->setNode($folder);
3978
-
3979
-		$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3980
-
3981
-		$this->shareManager->expects($this->any())
3982
-			->method('getSharedWith')
3983
-			->willReturnMap([
3984
-				['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3985
-				['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]]
3986
-			]);
3987
-
3988
-		$this->shareManager->expects($this->once())
3989
-			->method('updateShare')
3990
-			->with($share)
3991
-			->willReturn($share);
3992
-
3993
-		$this->rootFolder->method('getUserFolder')
3994
-			->with($this->currentUser)
3995
-			->willReturn($userFolder);
3996
-
3997
-		$userFolder->method('getById')
3998
-			->with(42)
3999
-			->willReturn([$folder]);
4000
-
4001
-		$mountPoint = $this->createMock(IMountPoint::class);
4002
-		$folder->method('getMountPoint')
4003
-			->willReturn($mountPoint);
4004
-		$mountPoint->method('getStorageRootId')
4005
-			->willReturn(42);
4006
-
4007
-		$result = $ocs->updateShare(42, 31);
4008
-		$this->assertInstanceOf(DataResponse::class, $result);
4009
-	}
4010
-
4011
-	public function testUpdateShareOwnerless(): void {
4012
-		$ocs = $this->mockFormatShare();
4013
-
4014
-		$mount = $this->createMock(IShareOwnerlessMount::class);
4015
-
4016
-		$file = $this->createMock(File::class);
4017
-		$file
4018
-			->expects($this->exactly(2))
4019
-			->method('getPermissions')
4020
-			->willReturn(Constants::PERMISSION_SHARE);
4021
-		$file
4022
-			->expects($this->once())
4023
-			->method('getMountPoint')
4024
-			->willReturn($mount);
4025
-
4026
-		$userFolder = $this->createMock(Folder::class);
4027
-		$userFolder->method('getById')
4028
-			->with(2)
4029
-			->willReturn([$file]);
4030
-		$userFolder->method('getFirstNodeById')
4031
-			->with(2)
4032
-			->willReturn($file);
4033
-
4034
-		$this->rootFolder
4035
-			->method('getUserFolder')
4036
-			->with($this->currentUser)
4037
-			->willReturn($userFolder);
4038
-
4039
-		$share = $this->createMock(IShare::class);
4040
-		$share
4041
-			->expects($this->once())
4042
-			->method('getNode')
4043
-			->willReturn($file);
4044
-		$share
4045
-			->expects($this->exactly(2))
4046
-			->method('getNodeId')
4047
-			->willReturn(2);
4048
-		$share
4049
-			->expects($this->exactly(2))
4050
-			->method('getPermissions')
4051
-			->willReturn(Constants::PERMISSION_SHARE);
4052
-
4053
-		$this->shareManager
4054
-			->expects($this->once())
4055
-			->method('getShareById')
4056
-			->with('ocinternal:1', $this->currentUser)
4057
-			->willReturn($share);
4058
-
4059
-		$this->shareManager
4060
-			->expects($this->once())
4061
-			->method('updateShare')
4062
-			->with($share)
4063
-			->willReturn($share);
4064
-
4065
-		$result = $ocs->updateShare(1, Constants::PERMISSION_ALL);
4066
-		$this->assertInstanceOf(DataResponse::class, $result);
4067
-	}
4068
-
4069
-	public static function dataFormatShare(): array {
4070
-		$owner = ['getDisplayName' => 'ownerDN'];
4071
-		$initiator = ['getDisplayName' => 'initiatorDN'];
4072
-		$recipient = [
4073
-			'getDisplayName' => 'recipientDN',
4074
-			'getSystemEMailAddress' => 'recipient'
4075
-		];
4076
-
4077
-		$folder = [
4078
-			'class' => Folder::class,
4079
-			'mimeType' => 'myFolderMimeType',
4080
-			'path' => 'folder',
4081
-			'id' => 2,
4082
-		];
4083
-		$file = [
4084
-			'class' => File::class,
4085
-			'mimeType' => 'myMimeType',
4086
-			'path' => 'file',
4087
-			'id' => 3,
4088
-		];
4089
-		$fileWithPreview = [
4090
-			'class' => File::class,
4091
-			'mimeType' => 'mimeWithPreview',
4092
-			'path' => 'fileWithPreview',
4093
-			'id' => 4,
4094
-		];
4095
-
4096
-		$result = [];
4097
-
4098
-		$share = [
4099
-			'type' => IShare::TYPE_USER,
4100
-			'owner' => 'owner',
4101
-			'sharedWith' => 'recipient',
4102
-			'attributes' => [
4103
-				'scope' => 'permissions',
4104
-				'key' => 'download',
4105
-				'value' => true
4106
-			],
4107
-			'node' => $file,
4108
-			'note' => 'personal note',
4109
-		];
4110
-
4111
-		// User backend down
4112
-		$result[] = [
4113
-			[
4114
-				'id' => '42',
4115
-				'share_type' => IShare::TYPE_USER,
4116
-				'uid_owner' => 'initiator',
4117
-				'displayname_owner' => 'initiator',
4118
-				'permissions' => 1,
4119
-				'stime' => 946684862,
4120
-				'parent' => null,
4121
-				'expiration' => null,
4122
-				'token' => null,
4123
-				'uid_file_owner' => 'owner',
4124
-				'displayname_file_owner' => 'owner',
4125
-				'path' => 'file',
4126
-				'item_type' => 'file',
4127
-				'storage_id' => 'storageId',
4128
-				'storage' => 100,
4129
-				'item_source' => 3,
4130
-				'file_source' => 3,
4131
-				'file_parent' => 1,
4132
-				'file_target' => 'myTarget',
4133
-				'share_with' => 'recipient',
4134
-				'share_with_displayname' => 'recipient',
4135
-				'share_with_displayname_unique' => 'recipient',
4136
-				'note' => 'personal note',
4137
-				'label' => '',
4138
-				'mail_send' => 0,
4139
-				'mimetype' => 'myMimeType',
4140
-				'has_preview' => false,
4141
-				'hide_download' => 0,
4142
-				'can_edit' => false,
4143
-				'can_delete' => false,
4144
-				'item_size' => 123456,
4145
-				'item_mtime' => 1234567890,
4146
-				'is-mount-root' => false,
4147
-				'mount-type' => '',
4148
-				'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4149
-				'item_permissions' => 1,
4150
-			],
4151
-			$share,
4152
-			[], false
4153
-		];
4154
-		// User backend up
4155
-		$result[] = [
4156
-			[
4157
-				'id' => '42',
4158
-				'share_type' => IShare::TYPE_USER,
4159
-				'uid_owner' => 'initiator',
4160
-				'displayname_owner' => 'initiatorDN',
4161
-				'permissions' => 1,
4162
-				'stime' => 946684862,
4163
-				'parent' => null,
4164
-				'expiration' => null,
4165
-				'token' => null,
4166
-				'uid_file_owner' => 'owner',
4167
-				'displayname_file_owner' => 'ownerDN',
4168
-				'note' => 'personal note',
4169
-				'label' => '',
4170
-				'path' => 'file',
4171
-				'item_type' => 'file',
4172
-				'storage_id' => 'storageId',
4173
-				'storage' => 100,
4174
-				'item_source' => 3,
4175
-				'file_source' => 3,
4176
-				'file_parent' => 1,
4177
-				'file_target' => 'myTarget',
4178
-				'share_with' => 'recipient',
4179
-				'share_with_displayname' => 'recipientDN',
4180
-				'share_with_displayname_unique' => 'recipient',
4181
-				'mail_send' => 0,
4182
-				'mimetype' => 'myMimeType',
4183
-				'has_preview' => false,
4184
-				'hide_download' => 0,
4185
-				'can_edit' => false,
4186
-				'can_delete' => false,
4187
-				'item_size' => 123456,
4188
-				'item_mtime' => 1234567890,
4189
-				'is-mount-root' => false,
4190
-				'mount-type' => '',
4191
-				'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4192
-				'item_permissions' => 1,
4193
-			], $share, [
4194
-				['owner', $owner],
4195
-				['initiator', $initiator],
4196
-				['recipient', $recipient],
4197
-			], false
4198
-		];
4199
-
4200
-		// Same but no attributes
4201
-		$share = [
4202
-			'type' => IShare::TYPE_USER,
4203
-			'owner' => 'owner',
4204
-			'sharedWith' => 'recipient',
4205
-			'node' => $file,
4206
-			'note' => 'personal note',
4207
-		];
4208
-
4209
-		// User backend down
4210
-		$result[] = [
4211
-			[
4212
-				'id' => '42',
4213
-				'share_type' => IShare::TYPE_USER,
4214
-				'uid_owner' => 'initiator',
4215
-				'displayname_owner' => 'initiator',
4216
-				'permissions' => 1,
4217
-				'attributes' => null,
4218
-				'stime' => 946684862,
4219
-				'parent' => null,
4220
-				'expiration' => null,
4221
-				'token' => null,
4222
-				'uid_file_owner' => 'owner',
4223
-				'displayname_file_owner' => 'owner',
4224
-				'note' => 'personal note',
4225
-				'label' => '',
4226
-				'path' => 'file',
4227
-				'item_type' => 'file',
4228
-				'storage_id' => 'storageId',
4229
-				'storage' => 100,
4230
-				'item_source' => 3,
4231
-				'file_source' => 3,
4232
-				'file_parent' => 1,
4233
-				'file_target' => 'myTarget',
4234
-				'share_with' => 'recipient',
4235
-				'share_with_displayname' => 'recipient',
4236
-				'share_with_displayname_unique' => 'recipient',
4237
-				'mail_send' => 0,
4238
-				'mimetype' => 'myMimeType',
4239
-				'has_preview' => false,
4240
-				'hide_download' => 0,
4241
-				'can_edit' => false,
4242
-				'can_delete' => false,
4243
-				'item_size' => 123456,
4244
-				'item_mtime' => 1234567890,
4245
-				'is-mount-root' => false,
4246
-				'mount-type' => '',
4247
-				'attributes' => null,
4248
-				'item_permissions' => 1,
4249
-			], $share, [], false
4250
-		];
4251
-
4252
-		$share['owner'] = 'currentUser';
4253
-
4254
-		// User backend down
4255
-		$result[] = [
4256
-			[
4257
-				'id' => '42',
4258
-				'share_type' => IShare::TYPE_USER,
4259
-				'uid_owner' => 'initiator',
4260
-				'displayname_owner' => 'initiator',
4261
-				'permissions' => 1,
4262
-				'attributes' => null,
4263
-				'stime' => 946684862,
4264
-				'parent' => null,
4265
-				'expiration' => null,
4266
-				'token' => null,
4267
-				'uid_file_owner' => 'currentUser',
4268
-				'displayname_file_owner' => 'currentUser',
4269
-				'note' => 'personal note',
4270
-				'label' => '',
4271
-				'path' => 'file',
4272
-				'item_type' => 'file',
4273
-				'storage_id' => 'storageId',
4274
-				'storage' => 100,
4275
-				'item_source' => 3,
4276
-				'file_source' => 3,
4277
-				'file_parent' => 1,
4278
-				'file_target' => 'myTarget',
4279
-				'share_with' => 'recipient',
4280
-				'share_with_displayname' => 'recipient',
4281
-				'share_with_displayname_unique' => 'recipient',
4282
-				'mail_send' => 0,
4283
-				'mimetype' => 'myMimeType',
4284
-				'has_preview' => false,
4285
-				'hide_download' => 0,
4286
-				'can_edit' => true,
4287
-				'can_delete' => true,
4288
-				'item_size' => 123456,
4289
-				'item_mtime' => 1234567890,
4290
-				'is-mount-root' => false,
4291
-				'mount-type' => '',
4292
-				'attributes' => null,
4293
-				'item_permissions' => 11,
4294
-			], $share, [], false
4295
-		];
4296
-
4297
-		// with existing group
4298
-		$share = [
4299
-			'type' => IShare::TYPE_GROUP,
4300
-			'owner' => 'owner',
4301
-			'sharedWith' => 'recipientGroup',
4302
-			'node' => $file,
4303
-			'note' => 'personal note',
4304
-		];
4305
-
4306
-		$result[] = [
4307
-			[
4308
-				'id' => '42',
4309
-				'share_type' => IShare::TYPE_GROUP,
4310
-				'uid_owner' => 'initiator',
4311
-				'displayname_owner' => 'initiator',
4312
-				'permissions' => 1,
4313
-				'attributes' => null,
4314
-				'stime' => 946684862,
4315
-				'parent' => null,
4316
-				'expiration' => null,
4317
-				'token' => null,
4318
-				'uid_file_owner' => 'owner',
4319
-				'displayname_file_owner' => 'owner',
4320
-				'note' => 'personal note',
4321
-				'label' => '',
4322
-				'path' => 'file',
4323
-				'item_type' => 'file',
4324
-				'storage_id' => 'storageId',
4325
-				'storage' => 100,
4326
-				'item_source' => 3,
4327
-				'file_source' => 3,
4328
-				'file_parent' => 1,
4329
-				'file_target' => 'myTarget',
4330
-				'share_with' => 'recipientGroup',
4331
-				'share_with_displayname' => 'recipientGroupDisplayName',
4332
-				'mail_send' => 0,
4333
-				'mimetype' => 'myMimeType',
4334
-				'has_preview' => false,
4335
-				'hide_download' => 0,
4336
-				'can_edit' => false,
4337
-				'can_delete' => false,
4338
-				'item_size' => 123456,
4339
-				'item_mtime' => 1234567890,
4340
-				'is-mount-root' => false,
4341
-				'mount-type' => '',
4342
-				'attributes' => null,
4343
-				'item_permissions' => 1,
4344
-			], $share, [], false
4345
-		];
4346
-
4347
-		// with unknown group / no group backend
4348
-		$share['sharedWith'] = 'recipientGroup2';
4349
-
4350
-		$result[] = [
4351
-			[
4352
-				'id' => '42',
4353
-				'share_type' => IShare::TYPE_GROUP,
4354
-				'uid_owner' => 'initiator',
4355
-				'displayname_owner' => 'initiator',
4356
-				'permissions' => 1,
4357
-				'stime' => 946684862,
4358
-				'parent' => null,
4359
-				'expiration' => null,
4360
-				'token' => null,
4361
-				'uid_file_owner' => 'owner',
4362
-				'displayname_file_owner' => 'owner',
4363
-				'note' => 'personal note',
4364
-				'label' => '',
4365
-				'path' => 'file',
4366
-				'item_type' => 'file',
4367
-				'storage_id' => 'storageId',
4368
-				'storage' => 100,
4369
-				'item_source' => 3,
4370
-				'file_source' => 3,
4371
-				'file_parent' => 1,
4372
-				'file_target' => 'myTarget',
4373
-				'share_with' => 'recipientGroup2',
4374
-				'share_with_displayname' => 'recipientGroup2',
4375
-				'mail_send' => 0,
4376
-				'mimetype' => 'myMimeType',
4377
-				'has_preview' => false,
4378
-				'hide_download' => 0,
4379
-				'can_edit' => false,
4380
-				'can_delete' => false,
4381
-				'item_size' => 123456,
4382
-				'item_mtime' => 1234567890,
4383
-				'is-mount-root' => false,
4384
-				'mount-type' => '',
4385
-				'attributes' => null,
4386
-				'item_permissions' => 1,
4387
-			], $share, [], false
4388
-		];
4389
-
4390
-		$share = [
4391
-			'type' => IShare::TYPE_LINK,
4392
-			'owner' => 'owner',
4393
-			'node' => $file,
4394
-			'note' => 'personal note',
4395
-			'password' => 'mypassword',
4396
-			'expirationDate' => new \DateTime('2001-01-02T00:00:00'),
4397
-			'token' => 'myToken',
4398
-			'label' => 'new link share',
4399
-		];
4400
-
4401
-		$result[] = [
4402
-			[
4403
-				'id' => '42',
4404
-				'share_type' => IShare::TYPE_LINK,
4405
-				'uid_owner' => 'initiator',
4406
-				'displayname_owner' => 'initiator',
4407
-				'permissions' => 1,
4408
-				'attributes' => null,
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' => false,
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['sendPasswordByTalk'] = true;
4446
-
4447
-		$result[] = [
4448
-			[
4449
-				'id' => '42',
4450
-				'share_type' => IShare::TYPE_LINK,
4451
-				'uid_owner' => 'initiator',
4452
-				'displayname_owner' => 'initiator',
4453
-				'permissions' => 1,
4454
-				'stime' => 946684862,
4455
-				'parent' => null,
4456
-				'expiration' => '2001-01-02 00:00:00',
4457
-				'token' => 'myToken',
4458
-				'uid_file_owner' => 'owner',
4459
-				'displayname_file_owner' => 'owner',
4460
-				'note' => 'personal note',
4461
-				'label' => 'new link share',
4462
-				'path' => 'file',
4463
-				'item_type' => 'file',
4464
-				'storage_id' => 'storageId',
4465
-				'storage' => 100,
4466
-				'item_source' => 3,
4467
-				'file_source' => 3,
4468
-				'file_parent' => 1,
4469
-				'file_target' => 'myTarget',
4470
-				'password' => 'mypassword',
4471
-				'share_with' => 'mypassword',
4472
-				'share_with_displayname' => '(Shared link)',
4473
-				'send_password_by_talk' => true,
4474
-				'mail_send' => 0,
4475
-				'url' => 'myLink',
4476
-				'mimetype' => 'myMimeType',
4477
-				'has_preview' => false,
4478
-				'hide_download' => 0,
4479
-				'can_edit' => false,
4480
-				'can_delete' => false,
4481
-				'item_size' => 123456,
4482
-				'item_mtime' => 1234567890,
4483
-				'is-mount-root' => false,
4484
-				'mount-type' => '',
4485
-				'attributes' => null,
4486
-				'item_permissions' => 1,
4487
-			], $share, [], false
4488
-		];
4489
-
4490
-		$share = [
4491
-			'type' => IShare::TYPE_REMOTE,
4492
-			'owner' => 'owner',
4493
-			'sharedWith' => '[email protected]',
4494
-			'node' => $folder,
4495
-			'note' => 'personal note',
4496
-			'expirationDate' => new \DateTime('2001-02-03T04:05:06'),
4497
-		];
4498
-
4499
-		$result[] = [
4500
-			[
4501
-				'id' => '42',
4502
-				'share_type' => IShare::TYPE_REMOTE,
4503
-				'uid_owner' => 'initiator',
4504
-				'displayname_owner' => 'initiator',
4505
-				'permissions' => 1,
4506
-				'stime' => 946684862,
4507
-				'parent' => null,
4508
-				'expiration' => '2001-02-03 00:00:00',
4509
-				'token' => null,
4510
-				'uid_file_owner' => 'owner',
4511
-				'displayname_file_owner' => 'owner',
4512
-				'note' => 'personal note',
4513
-				'label' => '',
4514
-				'path' => 'folder',
4515
-				'item_type' => 'folder',
4516
-				'storage_id' => 'storageId',
4517
-				'storage' => 100,
4518
-				'item_source' => 2,
4519
-				'file_source' => 2,
4520
-				'file_parent' => 1,
4521
-				'file_target' => 'myTarget',
4522
-				'share_with' => '[email protected]',
4523
-				'share_with_displayname' => 'foobar',
4524
-				'mail_send' => 0,
4525
-				'mimetype' => 'myFolderMimeType',
4526
-				'has_preview' => false,
4527
-				'hide_download' => 0,
4528
-				'can_edit' => false,
4529
-				'can_delete' => false,
4530
-				'item_size' => 123456,
4531
-				'item_mtime' => 1234567890,
4532
-				'is-mount-root' => false,
4533
-				'mount-type' => '',
4534
-				'attributes' => null,
4535
-				'item_permissions' => 1,
4536
-				'is_trusted_server' => false,
4537
-			], $share, [], false
4538
-		];
4539
-
4540
-		$share = [
4541
-			'type' => IShare::TYPE_REMOTE_GROUP,
4542
-			'owner' => 'owner',
4543
-			'sharedWith' => '[email protected]',
4544
-			'node' => $folder,
4545
-			'note' => 'personal note',
4546
-			'expirationDate' => new \DateTime('2001-02-03T04:05:06'),
4547
-		];
4548
-
4549
-		$result[] = [
4550
-			[
4551
-				'id' => '42',
4552
-				'share_type' => IShare::TYPE_REMOTE_GROUP,
4553
-				'uid_owner' => 'initiator',
4554
-				'displayname_owner' => 'initiator',
4555
-				'permissions' => 1,
4556
-				'stime' => 946684862,
4557
-				'parent' => null,
4558
-				'expiration' => '2001-02-03 00:00:00',
4559
-				'token' => null,
4560
-				'uid_file_owner' => 'owner',
4561
-				'displayname_file_owner' => 'owner',
4562
-				'note' => 'personal note',
4563
-				'label' => '',
4564
-				'path' => 'folder',
4565
-				'item_type' => 'folder',
4566
-				'storage_id' => 'storageId',
4567
-				'storage' => 100,
4568
-				'item_source' => 2,
4569
-				'file_source' => 2,
4570
-				'file_parent' => 1,
4571
-				'file_target' => 'myTarget',
4572
-				'share_with' => '[email protected]',
4573
-				'share_with_displayname' => 'foobar',
4574
-				'mail_send' => 0,
4575
-				'mimetype' => 'myFolderMimeType',
4576
-				'has_preview' => false,
4577
-				'hide_download' => 0,
4578
-				'can_edit' => false,
4579
-				'can_delete' => false,
4580
-				'item_size' => 123456,
4581
-				'item_mtime' => 1234567890,
4582
-				'is-mount-root' => false,
4583
-				'mount-type' => '',
4584
-				'attributes' => null,
4585
-				'item_permissions' => 1,
4586
-				'is_trusted_server' => false,
4587
-			], $share, [], false
4588
-		];
4589
-
4590
-		// Circle with id, display name and avatar set by the Circles app
4591
-		$share = [
4592
-			'type' => IShare::TYPE_CIRCLE,
4593
-			'owner' => 'owner',
4594
-			'sharedWith' => 'Circle (Public circle, circleOwner) [4815162342]',
4595
-			'sharedWithDisplayName' => 'The display name',
4596
-			'sharedWithAvatar' => 'path/to/the/avatar',
4597
-			'node' => $folder,
4598
-		];
4599
-
4600
-		$result[] = [
4601
-			[
4602
-				'id' => '42',
4603
-				'share_type' => IShare::TYPE_CIRCLE,
4604
-				'uid_owner' => 'initiator',
4605
-				'displayname_owner' => 'initiator',
4606
-				'permissions' => 1,
4607
-				'attributes' => null,
4608
-				'stime' => 946684862,
4609
-				'parent' => null,
4610
-				'expiration' => null,
4611
-				'token' => null,
4612
-				'uid_file_owner' => 'owner',
4613
-				'displayname_file_owner' => 'owner',
4614
-				'note' => '',
4615
-				'label' => '',
4616
-				'path' => 'folder',
4617
-				'item_type' => 'folder',
4618
-				'storage_id' => 'storageId',
4619
-				'storage' => 100,
4620
-				'item_source' => 2,
4621
-				'file_source' => 2,
4622
-				'file_parent' => 1,
4623
-				'file_target' => 'myTarget',
4624
-				'share_with' => '4815162342',
4625
-				'share_with_displayname' => 'The display name',
4626
-				'share_with_avatar' => 'path/to/the/avatar',
4627
-				'mail_send' => 0,
4628
-				'mimetype' => 'myFolderMimeType',
4629
-				'has_preview' => false,
4630
-				'hide_download' => 0,
4631
-				'can_edit' => false,
4632
-				'can_delete' => false,
4633
-				'item_size' => 123456,
4634
-				'item_mtime' => 1234567890,
4635
-				'is-mount-root' => false,
4636
-				'mount-type' => '',
4637
-				'attributes' => null,
4638
-				'item_permissions' => 1,
4639
-			], $share, [], false
4640
-		];
4641
-
4642
-		// Circle with id set by the Circles app
4643
-		$share = [
4644
-			'type' => IShare::TYPE_CIRCLE,
4645
-			'owner' => 'owner',
4646
-			'sharedWith' => 'Circle (Public circle, circleOwner) [4815162342]',
4647
-			'node' => $folder,
4648
-		];
4649
-
4650
-		$result[] = [
4651
-			[
4652
-				'id' => '42',
4653
-				'share_type' => IShare::TYPE_CIRCLE,
4654
-				'uid_owner' => 'initiator',
4655
-				'displayname_owner' => 'initiator',
4656
-				'permissions' => 1,
4657
-				'stime' => 946684862,
4658
-				'parent' => null,
4659
-				'expiration' => null,
4660
-				'token' => null,
4661
-				'uid_file_owner' => 'owner',
4662
-				'displayname_file_owner' => 'owner',
4663
-				'note' => '',
4664
-				'label' => '',
4665
-				'path' => 'folder',
4666
-				'item_type' => 'folder',
4667
-				'storage_id' => 'storageId',
4668
-				'storage' => 100,
4669
-				'item_source' => 2,
4670
-				'file_source' => 2,
4671
-				'file_parent' => 1,
4672
-				'file_target' => 'myTarget',
4673
-				'share_with' => '4815162342',
4674
-				'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4675
-				'share_with_avatar' => '',
4676
-				'mail_send' => 0,
4677
-				'mimetype' => 'myFolderMimeType',
4678
-				'has_preview' => false,
4679
-				'hide_download' => 0,
4680
-				'can_edit' => false,
4681
-				'can_delete' => false,
4682
-				'item_size' => 123456,
4683
-				'item_mtime' => 1234567890,
4684
-				'is-mount-root' => false,
4685
-				'mount-type' => '',
4686
-				'attributes' => null,
4687
-				'item_permissions' => 1,
4688
-			], $share, [], false
4689
-		];
4690
-
4691
-		// Circle with id not set by the Circles app
4692
-		$share = [
4693
-			'type' => IShare::TYPE_CIRCLE,
4694
-			'owner' => 'owner',
4695
-			'sharedWith' => 'Circle (Public circle, circleOwner)',
4696
-			'node' => $folder,
4697
-		];
4698
-
4699
-		$result[] = [
4700
-			[
4701
-				'id' => '42',
4702
-				'share_type' => IShare::TYPE_CIRCLE,
4703
-				'uid_owner' => 'initiator',
4704
-				'displayname_owner' => 'initiator',
4705
-				'permissions' => 1,
4706
-				'stime' => 946684862,
4707
-				'parent' => null,
4708
-				'expiration' => null,
4709
-				'token' => null,
4710
-				'uid_file_owner' => 'owner',
4711
-				'displayname_file_owner' => 'owner',
4712
-				'note' => '',
4713
-				'label' => '',
4714
-				'path' => 'folder',
4715
-				'item_type' => 'folder',
4716
-				'storage_id' => 'storageId',
4717
-				'storage' => 100,
4718
-				'item_source' => 2,
4719
-				'file_source' => 2,
4720
-				'file_parent' => 1,
4721
-				'file_target' => 'myTarget',
4722
-				'share_with' => 'Circle',
4723
-				'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4724
-				'share_with_avatar' => '',
4725
-				'mail_send' => 0,
4726
-				'mimetype' => 'myFolderMimeType',
4727
-				'has_preview' => false,
4728
-				'hide_download' => 0,
4729
-				'can_edit' => false,
4730
-				'can_delete' => false,
4731
-				'item_size' => 123456,
4732
-				'item_mtime' => 1234567890,
4733
-				'is-mount-root' => false,
4734
-				'mount-type' => '',
4735
-				'attributes' => null,
4736
-				'item_permissions' => 1,
4737
-			], $share, [], false
4738
-		];
4739
-
4740
-		// No node
4741
-		$share = [
4742
-			'type' => IShare::TYPE_USER,
4743
-			'owner' => 'owner',
4744
-			'sharedWith' => 'recipient',
4745
-			'note' => 'personal note',
4746
-		];
4747
-
4748
-		$result[] = [
4749
-			[], $share, [], true
4750
-		];
4751
-
4752
-		$share = [
4753
-			'type' => IShare::TYPE_EMAIL,
4754
-			'owner' => 'owner',
4755
-			'sharedWith' => '[email protected]',
4756
-			'node' => $folder,
4757
-			'password' => 'password',
4758
-		];
4759
-
4760
-		$result[] = [
4761
-			[
4762
-				'id' => '42',
4763
-				'share_type' => IShare::TYPE_EMAIL,
4764
-				'uid_owner' => 'initiator',
4765
-				'displayname_owner' => 'initiator',
4766
-				'permissions' => 1,
4767
-				'stime' => 946684862,
4768
-				'parent' => null,
4769
-				'expiration' => null,
4770
-				'token' => null,
4771
-				'uid_file_owner' => 'owner',
4772
-				'displayname_file_owner' => 'owner',
4773
-				'note' => '',
4774
-				'label' => '',
4775
-				'path' => 'folder',
4776
-				'item_type' => 'folder',
4777
-				'storage_id' => 'storageId',
4778
-				'storage' => 100,
4779
-				'item_source' => 2,
4780
-				'file_source' => 2,
4781
-				'file_parent' => 1,
4782
-				'file_target' => 'myTarget',
4783
-				'share_with' => '[email protected]',
4784
-				'share_with_displayname' => 'mail display name',
4785
-				'mail_send' => 0,
4786
-				'mimetype' => 'myFolderMimeType',
4787
-				'has_preview' => false,
4788
-				'password' => 'password',
4789
-				'send_password_by_talk' => false,
4790
-				'hide_download' => 0,
4791
-				'can_edit' => false,
4792
-				'can_delete' => false,
4793
-				'password_expiration_time' => null,
4794
-				'item_size' => 123456,
4795
-				'item_mtime' => 1234567890,
4796
-				'is-mount-root' => false,
4797
-				'mount-type' => '',
4798
-				'attributes' => null,
4799
-				'item_permissions' => 1,
4800
-			], $share, [], false
4801
-		];
4802
-
4803
-		$share['sendPasswordByTalk'] = true;
4804
-
4805
-		$result[] = [
4806
-			[
4807
-				'id' => '42',
4808
-				'share_type' => IShare::TYPE_EMAIL,
4809
-				'uid_owner' => 'initiator',
4810
-				'displayname_owner' => 'initiator',
4811
-				'permissions' => 1,
4812
-				'stime' => 946684862,
4813
-				'parent' => null,
4814
-				'expiration' => null,
4815
-				'token' => null,
4816
-				'uid_file_owner' => 'owner',
4817
-				'displayname_file_owner' => 'owner',
4818
-				'note' => '',
4819
-				'label' => '',
4820
-				'path' => 'folder',
4821
-				'item_type' => 'folder',
4822
-				'storage_id' => 'storageId',
4823
-				'storage' => 100,
4824
-				'item_source' => 2,
4825
-				'file_source' => 2,
4826
-				'file_parent' => 1,
4827
-				'file_target' => 'myTarget',
4828
-				'share_with' => '[email protected]',
4829
-				'share_with_displayname' => 'mail display name',
4830
-				'mail_send' => 0,
4831
-				'mimetype' => 'myFolderMimeType',
4832
-				'has_preview' => false,
4833
-				'password' => 'password',
4834
-				'send_password_by_talk' => true,
4835
-				'hide_download' => 0,
4836
-				'can_edit' => false,
4837
-				'can_delete' => false,
4838
-				'password_expiration_time' => null,
4839
-				'item_size' => 123456,
4840
-				'item_mtime' => 1234567890,
4841
-				'is-mount-root' => false,
4842
-				'mount-type' => '',
4843
-				'attributes' => null,
4844
-				'item_permissions' => 1,
4845
-			], $share, [], false
4846
-		];
4847
-
4848
-		// Preview is available
4849
-		$share = [
4850
-			'type' => IShare::TYPE_USER,
4851
-			'owner' => 'currentUser',
4852
-			'sharedWith' => 'recipient',
4853
-			'node' => $fileWithPreview,
4854
-			'note' => 'personal note',
4855
-		];
4856
-
4857
-		$result[] = [
4858
-			[
4859
-				'id' => '42',
4860
-				'share_type' => IShare::TYPE_USER,
4861
-				'uid_owner' => 'initiator',
4862
-				'displayname_owner' => 'initiator',
4863
-				'permissions' => 1,
4864
-				'stime' => 946684862,
4865
-				'parent' => null,
4866
-				'expiration' => null,
4867
-				'token' => null,
4868
-				'uid_file_owner' => 'currentUser',
4869
-				'displayname_file_owner' => 'currentUser',
4870
-				'note' => 'personal note',
4871
-				'label' => '',
4872
-				'path' => 'fileWithPreview',
4873
-				'item_type' => 'file',
4874
-				'storage_id' => 'storageId',
4875
-				'storage' => 100,
4876
-				'item_source' => 4,
4877
-				'file_source' => 4,
4878
-				'file_parent' => 1,
4879
-				'file_target' => 'myTarget',
4880
-				'share_with' => 'recipient',
4881
-				'share_with_displayname' => 'recipient',
4882
-				'share_with_displayname_unique' => 'recipient',
4883
-				'mail_send' => 0,
4884
-				'mimetype' => 'mimeWithPreview',
4885
-				'has_preview' => true,
4886
-				'hide_download' => 0,
4887
-				'can_edit' => true,
4888
-				'can_delete' => true,
4889
-				'item_size' => 123456,
4890
-				'item_mtime' => 1234567890,
4891
-				'is-mount-root' => false,
4892
-				'mount-type' => '',
4893
-				'attributes' => null,
4894
-				'item_permissions' => 11,
4895
-			], $share, [], false
4896
-		];
4897
-
4898
-		return $result;
4899
-	}
4900
-
4901
-	#[DataProvider(methodName: 'dataFormatShare')]
4902
-	public function testFormatShare(
4903
-		array $expects,
4904
-		array $shareParams,
4905
-		array $users,
4906
-		bool $exception,
4907
-	): void {
4908
-		$users = array_map(
4909
-			function ($user) {
4910
-				$mock = $this->createMock(IUser::class);
4911
-				foreach ($user[1] as $method => $return) {
4912
-					$mock->method($method)->willReturn($return);
4913
-				}
4914
-				return [$user[0],$mock];
4915
-			},
4916
-			$users
4917
-		);
4918
-
4919
-		$share = Server::get(IManager::class)->newShare();
4920
-		$share->setShareType($shareParams['type'])
4921
-			->setSharedBy('initiator')
4922
-			->setShareOwner($shareParams['owner'])
4923
-			->setPermissions(Constants::PERMISSION_READ)
4924
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4925
-			->setTarget('myTarget')
4926
-			->setId(42);
4927
-		if (isset($shareParams['sharedWith'])) {
4928
-			$share->setSharedWith($shareParams['sharedWith']);
4929
-		}
4930
-		if (isset($shareParams['sharedWithDisplayName'])) {
4931
-			$share->setSharedWithDisplayName($shareParams['sharedWithDisplayName']);
4932
-		}
4933
-		if (isset($shareParams['sharedWithAvatar'])) {
4934
-			$share->setSharedWithAvatar($shareParams['sharedWithAvatar']);
4935
-		}
4936
-		if (isset($shareParams['attributes'])) {
4937
-			$shareAttributes = $this->createMock(IShareAttributes::class);
4938
-			$shareAttributes->method('toArray')->willReturn($shareParams['attributes']);
4939
-			$shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
4940
-			$share->setAttributes($shareAttributes);
4941
-
4942
-			$expects['attributes'] = \json_encode($shareParams['attributes']);
4943
-		}
4944
-		if (isset($shareParams['node'])) {
4945
-			$node = $this->createMock($shareParams['node']['class']);
4946
-
4947
-			$node->method('getMimeType')->willReturn($shareParams['node']['mimeType']);
4948
-
4949
-			$mountPoint = $this->createMock(IMountPoint::class);
4950
-			$mountPoint->method('getMountType')->willReturn('');
4951
-			$node->method('getMountPoint')->willReturn($mountPoint);
4952
-
4953
-			$node->method('getPath')->willReturn($shareParams['node']['path']);
4954
-			$node->method('getId')->willReturn($shareParams['node']['id']);
4955
-
4956
-			$parent = $this->createMock(Folder::class);
4957
-			$parent->method('getId')->willReturn(1);
4958
-			$node->method('getParent')->willReturn($parent);
4959
-
4960
-			$node->method('getSize')->willReturn(123456);
4961
-			$node->method('getMTime')->willReturn(1234567890);
4962
-
4963
-			$cache = $this->createMock(ICache::class);
4964
-			$cache->method('getNumericStorageId')->willReturn(100);
4965
-			$storage = $this->createMock(IStorage::class);
4966
-			$storage->method('getId')->willReturn('storageId');
4967
-			$storage->method('getCache')->willReturn($cache);
4968
-
4969
-			$node->method('getStorage')->willReturn($storage);
4970
-
4971
-			$share->setNode($node);
4972
-		}
4973
-		if (isset($shareParams['note'])) {
4974
-			$share->setNote($shareParams['note']);
4975
-		}
4976
-		if (isset($shareParams['expirationDate'])) {
4977
-			$share->setExpirationDate($shareParams['expirationDate']);
4978
-		}
4979
-		if (isset($shareParams['token'])) {
4980
-			$share->setToken($shareParams['token']);
4981
-		}
4982
-		if (isset($shareParams['label'])) {
4983
-			$share->setLabel($shareParams['label']);
4984
-		}
4985
-		if (isset($shareParams['password'])) {
4986
-			$share->setPassword($shareParams['password']);
4987
-		}
4988
-		if (isset($shareParams['sendPasswordByTalk'])) {
4989
-			$share->setSendPasswordByTalk($shareParams['sendPasswordByTalk']);
4990
-		}
4991
-
4992
-		$this->userManager->method('get')->willReturnMap($users);
4993
-
4994
-		$recipientGroup = $this->createMock(IGroup::class);
4995
-		$recipientGroup->method('getDisplayName')->willReturn('recipientGroupDisplayName');
4996
-		$this->groupManager->method('get')->willReturnMap([
4997
-			['recipientGroup', $recipientGroup],
4998
-		]);
4999
-
5000
-		$this->urlGenerator->method('linkToRouteAbsolute')
5001
-			->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken'])
5002
-			->willReturn('myLink');
5003
-
5004
-		$this->rootFolder->method('getUserFolder')
5005
-			->with($this->currentUser)
5006
-			->willReturnSelf();
5007
-		$this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
5008
-
5009
-		if (!$exception) {
5010
-			$this->rootFolder->method('getFirstNodeById')
5011
-				->with($share->getNodeId())
5012
-				->willReturn($share->getNode());
5013
-
5014
-			$this->rootFolder->method('getRelativePath')
5015
-				->with($share->getNode()->getPath())
5016
-				->willReturnArgument(0);
5017
-		}
5018
-
5019
-		$cm = $this->createMock(\OCP\Contacts\IManager::class);
5020
-		$this->overwriteService(\OCP\Contacts\IManager::class, $cm);
5021
-
5022
-		$cm->method('search')
5023
-			->willReturnMap([
5024
-				['[email protected]', ['CLOUD'], [
5025
-					'limit' => 1,
5026
-					'enumeration' => false,
5027
-					'strict_search' => true,
5028
-				],
5029
-					[
5030
-						[
5031
-							'CLOUD' => [
5032
-								'[email protected]',
5033
-							],
5034
-							'FN' => 'foobar',
5035
-						],
5036
-					],
5037
-				],
5038
-				['[email protected]', ['EMAIL'], [
5039
-					'limit' => 1,
5040
-					'enumeration' => false,
5041
-					'strict_search' => true,
5042
-				],
5043
-					[
5044
-						[
5045
-							'EMAIL' => [
5046
-								'[email protected]',
5047
-							],
5048
-							'FN' => 'mail display name',
5049
-						],
5050
-					],
5051
-				],
5052
-			]);
5053
-
5054
-		try {
5055
-			$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5056
-			$this->assertFalse($exception);
5057
-			$this->assertEquals($expects, $result);
5058
-		} catch (NotFoundException $e) {
5059
-			$this->assertTrue($exception);
5060
-		}
5061
-	}
5062
-
5063
-	public static function dataFormatRoomShare(): array {
5064
-		$result = [];
5065
-
5066
-		$result[] = [
5067
-			[
5068
-				'id' => '42',
5069
-				'share_type' => IShare::TYPE_ROOM,
5070
-				'uid_owner' => 'initiator',
5071
-				'displayname_owner' => 'initiator',
5072
-				'permissions' => 1,
5073
-				'stime' => 946684862,
5074
-				'parent' => null,
5075
-				'expiration' => null,
5076
-				'token' => null,
5077
-				'uid_file_owner' => 'owner',
5078
-				'displayname_file_owner' => 'owner',
5079
-				'note' => 'personal note',
5080
-				'path' => 'file',
5081
-				'item_type' => 'file',
5082
-				'storage_id' => 'storageId',
5083
-				'storage' => 100,
5084
-				'item_source' => 3,
5085
-				'file_source' => 3,
5086
-				'file_parent' => 1,
5087
-				'file_target' => 'myTarget',
5088
-				'share_with' => 'recipientRoom',
5089
-				'share_with_displayname' => '',
5090
-				'mail_send' => 0,
5091
-				'mimetype' => 'myMimeType',
5092
-				'has_preview' => false,
5093
-				'hide_download' => 0,
5094
-				'label' => '',
5095
-				'can_edit' => false,
5096
-				'can_delete' => false,
5097
-				'item_size' => 123456,
5098
-				'item_mtime' => 1234567890,
5099
-				'is-mount-root' => false,
5100
-				'mount-type' => '',
5101
-				'attributes' => null,
5102
-				'item_permissions' => 1,
5103
-			], false, []
5104
-		];
5105
-
5106
-		$result[] = [
5107
-			[
5108
-				'id' => '42',
5109
-				'share_type' => IShare::TYPE_ROOM,
5110
-				'uid_owner' => 'initiator',
5111
-				'displayname_owner' => 'initiator',
5112
-				'permissions' => 1,
5113
-				'stime' => 946684862,
5114
-				'parent' => null,
5115
-				'expiration' => null,
5116
-				'token' => null,
5117
-				'uid_file_owner' => 'owner',
5118
-				'displayname_file_owner' => 'owner',
5119
-				'note' => 'personal note',
5120
-				'path' => 'file',
5121
-				'item_type' => 'file',
5122
-				'storage_id' => 'storageId',
5123
-				'storage' => 100,
5124
-				'item_source' => 3,
5125
-				'file_source' => 3,
5126
-				'file_parent' => 1,
5127
-				'file_target' => 'myTarget',
5128
-				'share_with' => 'recipientRoom',
5129
-				'share_with_displayname' => 'recipientRoomName',
5130
-				'mail_send' => 0,
5131
-				'mimetype' => 'myMimeType',
5132
-				'has_preview' => false,
5133
-				'hide_download' => 0,
5134
-				'label' => '',
5135
-				'can_edit' => false,
5136
-				'can_delete' => false,
5137
-				'item_size' => 123456,
5138
-				'item_mtime' => 1234567890,
5139
-				'is-mount-root' => false,
5140
-				'mount-type' => '',
5141
-				'attributes' => null,
5142
-				'item_permissions' => 9,
5143
-			], true, [
5144
-				'share_with_displayname' => 'recipientRoomName'
5145
-			]
5146
-		];
5147
-
5148
-		return $result;
5149
-	}
5150
-
5151
-	/**
5152
-	 *
5153
-	 * @param array $expects
5154
-	 * @param IShare $share
5155
-	 * @param bool $helperAvailable
5156
-	 * @param array $formatShareByHelper
5157
-	 */
5158
-	#[DataProvider(methodName: 'dataFormatRoomShare')]
5159
-	public function testFormatRoomShare(array $expects, bool $helperAvailable, array $formatShareByHelper): void {
5160
-		$file = $this->createMock(File::class);
5161
-
5162
-		$file->method('getMimeType')->willReturn('myMimeType');
5163
-		$file->method('getPath')->willReturn('file');
5164
-		$file->method('getId')->willReturn(3);
5165
-
5166
-		$parent = $this->createMock(Folder::class);
5167
-		$parent->method('getId')->willReturn(1);
5168
-		$file->method('getParent')->willReturn($parent);
5169
-
5170
-		$file->method('getSize')->willReturn(123456);
5171
-		$file->method('getMTime')->willReturn(1234567890);
5172
-
5173
-		$mountPoint = $this->createMock(IMountPoint::class);
5174
-		$mountPoint->method('getMountType')->willReturn('');
5175
-		$file->method('getMountPoint')->willReturn($mountPoint);
5176
-
5177
-		$cache = $this->createMock(ICache::class);
5178
-		$cache->method('getNumericStorageId')->willReturn(100);
5179
-		$storage = $this->createMock(IStorage::class);
5180
-		$storage->method('getId')->willReturn('storageId');
5181
-		$storage->method('getCache')->willReturn($cache);
5182
-
5183
-		$file->method('getStorage')->willReturn($storage);
5184
-
5185
-		$share = Server::get(IManager::class)->newShare();
5186
-		$share->setShareType(IShare::TYPE_ROOM)
5187
-			->setSharedWith('recipientRoom')
5188
-			->setSharedBy('initiator')
5189
-			->setShareOwner('owner')
5190
-			->setPermissions(Constants::PERMISSION_READ)
5191
-			->setNode($file)
5192
-			->setShareTime(new \DateTime('2000-01-01T00:01:02'))
5193
-			->setTarget('myTarget')
5194
-			->setNote('personal note')
5195
-			->setId(42);
5196
-
5197
-		$this->rootFolder->method('getUserFolder')
5198
-			->with($this->currentUser)
5199
-			->willReturnSelf();
5200
-
5201
-		$this->rootFolder->method('getFirstNodeById')
5202
-			->with($share->getNodeId())
5203
-			->willReturn($share->getNode());
5204
-
5205
-		$this->rootFolder->method('getRelativePath')
5206
-			->with($share->getNode()->getPath())
5207
-			->willReturnArgument(0);
5208
-
5209
-		if (!$helperAvailable) {
5210
-			$this->appManager->method('isEnabledForUser')
5211
-				->with('spreed')
5212
-				->willReturn(false);
5213
-		} else {
5214
-			$this->appManager->method('isEnabledForUser')
5215
-				->with('spreed')
5216
-				->willReturn(true);
5217
-
5218
-			// This is not possible anymore with PHPUnit 10+
5219
-			// as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
5220
-			// $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
5221
-			$helper = $this->getMockBuilder(\stdClass::class)
5222
-				->addMethods(['formatShare', 'canAccessShare'])
5223
-				->getMock();
5224
-			$helper->method('formatShare')
5225
-				->with($share)
5226
-				->willReturn($formatShareByHelper);
5227
-			$helper->method('canAccessShare')
5228
-				->with($share)
5229
-				->willReturn(true);
5230
-
5231
-			$this->serverContainer->method('get')
5232
-				->with('\OCA\Talk\Share\Helper\ShareAPIController')
5233
-				->willReturn($helper);
5234
-		}
5235
-
5236
-		$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5237
-		$this->assertEquals($expects, $result);
5238
-	}
5239
-
5240
-	/**
5241
-	 * @return list{Folder, Folder}
5242
-	 */
5243
-	private function getNonSharedUserFolder(): array {
5244
-		$node = $this->getMockBuilder(Folder::class)->getMock();
5245
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
5246
-		$storage = $this->createMock(IStorage::class);
5247
-		$storage->method('instanceOfStorage')
5248
-			->willReturnMap([
5249
-				['OCA\Files_Sharing\External\Storage', false],
5250
-				['OCA\Files_Sharing\SharedStorage', false],
5251
-			]);
5252
-		$userFolder->method('getStorage')->willReturn($storage);
5253
-		$node->method('getStorage')->willReturn($storage);
5254
-		$node->method('getId')->willReturn(42);
5255
-		$user = $this->createMock(IUser::class);
5256
-		$user->method('getUID')->willReturn($this->currentUser);
5257
-		$node->method('getOwner')->willReturn($user);
5258
-		return [$userFolder, $node];
5259
-	}
5260
-
5261
-	/**
5262
-	 * @return list{Folder, File}
5263
-	 */
5264
-	private function getNonSharedUserFile(): array {
5265
-		$node = $this->getMockBuilder(File::class)->getMock();
5266
-		$userFolder = $this->getMockBuilder(Folder::class)->getMock();
5267
-		$storage = $this->createMock(IStorage::class);
5268
-		$storage->method('instanceOfStorage')
5269
-			->willReturnMap([
5270
-				['OCA\Files_Sharing\External\Storage', false],
5271
-				['OCA\Files_Sharing\SharedStorage', false],
5272
-			]);
5273
-		$userFolder->method('getStorage')->willReturn($storage);
5274
-		$node->method('getStorage')->willReturn($storage);
5275
-		$node->method('getId')->willReturn(42);
5276
-		return [$userFolder, $node];
5277
-	}
5278
-
5279
-	public function testPopulateTags(): void {
5280
-		$tagger = $this->createMock(ITags::class);
5281
-		$this->tagManager->method('load')
5282
-			->with('files')
5283
-			->willReturn($tagger);
5284
-		$data = [
5285
-			['file_source' => 10],
5286
-			['file_source' => 22, 'foo' => 'bar'],
5287
-			['file_source' => 42, 'x' => 'y'],
5288
-		];
5289
-		$tags = [
5290
-			10 => ['tag3'],
5291
-			42 => ['tag1', 'tag2'],
5292
-		];
5293
-		$tagger->method('getTagsForObjects')
5294
-			->with([10, 22, 42])
5295
-			->willReturn($tags);
5296
-
5297
-		$result = self::invokePrivate($this->ocs, 'populateTags', [$data]);
5298
-		$this->assertSame([
5299
-			['file_source' => 10, 'tags' => ['tag3']],
5300
-			['file_source' => 22, 'foo' => 'bar', 'tags' => []],
5301
-			['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']],
5302
-		], $result);
5303
-	}
5304
-
5305
-	public static function trustedServerProvider(): array {
5306
-		return [
5307
-			'Trusted server' => [true, true],
5308
-			'Untrusted server' => [false, false],
5309
-		];
5310
-	}
5311
-
5312
-	#[DataProvider(methodName: 'trustedServerProvider')]
5313
-	public function testFormatShareWithFederatedShare(bool $isKnownServer, bool $isTrusted): void {
5314
-		$nodeId = 12;
5315
-		$nodePath = '/test.txt';
5316
-
5317
-		$node = $this->createMock(File::class);
5318
-		$node->method('getId')->willReturn($nodeId);
5319
-		$node->method('getPath')->willReturn($nodePath);
5320
-		$node->method('getInternalPath')->willReturn(ltrim($nodePath, '/'));
5321
-		$mountPoint = $this->createMock(IMountPoint::class);
5322
-		$mountPoint->method('getMountType')->willReturn('local');
5323
-		$node->method('getMountPoint')->willReturn($mountPoint);
5324
-		$node->method('getMimetype')->willReturn('text/plain');
5325
-		$storage = $this->createMock(IStorage::class);
5326
-		$storageCache = $this->createMock(ICache::class);
5327
-		$storageCache->method('getNumericStorageId')->willReturn(1);
5328
-		$storage->method('getCache')->willReturn($storageCache);
5329
-		$storage->method('getId')->willReturn('home::shareOwner');
5330
-		$node->method('getStorage')->willReturn($storage);
5331
-		$parent = $this->createMock(Folder::class);
5332
-		$parent->method('getId')->willReturn(2);
5333
-		$node->method('getParent')->willReturn($parent);
5334
-		$node->method('getSize')->willReturn(1234);
5335
-		$node->method('getMTime')->willReturn(1234567890);
5336
-
5337
-		$share = $this->createShare(
5338
-			1,
5339
-			IShare::TYPE_REMOTE,
5340
-			'[email protected]', // shared with
5341
-			'[email protected]',      // shared by
5342
-			'shareOwner',                 // share owner
5343
-			$node,
5344
-			Constants::PERMISSION_READ,
5345
-			time(),
5346
-			null,
5347
-			2,
5348
-			$nodePath,
5349
-			$nodeId
5350
-		);
5351
-
5352
-		$this->previewManager->method('isAvailable')->with($node)->willReturn(false);
5353
-
5354
-		$this->rootFolder->method('getUserFolder')
5355
-			->with($this->currentUser)
5356
-			->willReturnSelf();
5357
-
5358
-		$this->rootFolder->method('getFirstNodeById')
5359
-			->with($share->getNodeId())
5360
-			->willReturn($node);
5361
-
5362
-		$this->rootFolder->method('getRelativePath')
5363
-			->with($node->getPath())
5364
-			->willReturnArgument(0);
5365
-
5366
-		$serverName = 'remoteserver.com';
5367
-		$this->trustedServers->method('isTrustedServer')
5368
-			->with($serverName)
5369
-			->willReturn($isKnownServer);
5370
-
5371
-		$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5372
-
5373
-		$this->assertSame($isTrusted, $result['is_trusted_server']);
5374
-	}
5375
-
5376
-	public function testFormatShareWithFederatedShareWithAtInUsername(): void {
5377
-		$nodeId = 12;
5378
-		$nodePath = '/test.txt';
5379
-
5380
-		$node = $this->createMock(File::class);
5381
-		$node->method('getId')->willReturn($nodeId);
5382
-		$node->method('getPath')->willReturn($nodePath);
5383
-		$node->method('getInternalPath')->willReturn(ltrim($nodePath, '/'));
5384
-		$mountPoint = $this->createMock(IMountPoint::class);
5385
-		$mountPoint->method('getMountType')->willReturn('local');
5386
-		$node->method('getMountPoint')->willReturn($mountPoint);
5387
-		$node->method('getMimetype')->willReturn('text/plain');
5388
-		$storage = $this->createMock(IStorage::class);
5389
-		$storageCache = $this->createMock(ICache::class);
5390
-		$storageCache->method('getNumericStorageId')->willReturn(1);
5391
-		$storage->method('getCache')->willReturn($storageCache);
5392
-		$storage->method('getId')->willReturn('home::shareOwner');
5393
-		$node->method('getStorage')->willReturn($storage);
5394
-		$parent = $this->createMock(Folder::class);
5395
-		$parent->method('getId')->willReturn(2);
5396
-		$node->method('getParent')->willReturn($parent);
5397
-		$node->method('getSize')->willReturn(1234);
5398
-		$node->method('getMTime')->willReturn(1234567890);
5399
-
5400
-		$share = $this->createShare(
5401
-			1,
5402
-			IShare::TYPE_REMOTE,
5403
-			'[email protected]@remoteserver.com',
5404
-			'[email protected]',
5405
-			'shareOwner',
5406
-			$node,
5407
-			Constants::PERMISSION_READ,
5408
-			time(),
5409
-			null,
5410
-			2,
5411
-			$nodePath,
5412
-			$nodeId
5413
-		);
5414
-
5415
-		$this->previewManager->method('isAvailable')->with($node)->willReturn(false);
5416
-
5417
-		$this->rootFolder->method('getUserFolder')
5418
-			->with($this->currentUser)
5419
-			->willReturnSelf();
5420
-
5421
-		$this->rootFolder->method('getFirstNodeById')
5422
-			->with($share->getNodeId())
5423
-			->willReturn($node);
5424
-
5425
-		$this->rootFolder->method('getRelativePath')
5426
-			->with($node->getPath())
5427
-			->willReturnArgument(0);
5428
-
5429
-		$serverName = 'remoteserver.com';
5430
-		$this->trustedServers->method('isTrustedServer')
5431
-			->with($serverName)
5432
-			->willReturn(true);
5433
-
5434
-		$result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5435
-
5436
-		$this->assertTrue($result['is_trusted_server']);
5437
-	}
5438
-
5439
-	public function testOwnerCanAlwaysDownload(): void {
5440
-		$ocs = $this->mockFormatShare();
5441
-
5442
-		$share = $this->createMock(IShare::class);
5443
-		$node = $this->createMock(File::class);
5444
-		$userFolder = $this->createMock(Folder::class);
5445
-		$owner = $this->createMock(IUser::class);
5446
-
5447
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5448
-		$share->method('getNodeId')->willReturn(42);
5449
-		$node->method('getOwner')->willReturn($owner);
5450
-		$owner->method('getUID')->willReturn('sharedByUser');
5451
-
5452
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5453
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5454
-
5455
-		// Expect hideDownload to be set to false since owner can always download
5456
-		$share->expects($this->once())->method('setHideDownload')->with(false);
5457
-
5458
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5459
-	}
5460
-
5461
-	public function testParentHideDownloadEnforcedOnChild(): void {
5462
-		$ocs = $this->mockFormatShare();
5463
-
5464
-		$share = $this->createMock(IShare::class);
5465
-		$node = $this->createMock(File::class);
5466
-		$userFolder = $this->createMock(Folder::class);
5467
-		$owner = $this->createMock(IUser::class);
5468
-		$storage = $this->createMock(SharedStorage::class);
5469
-		$originalShare = $this->createMock(IShare::class);
5470
-
5471
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5472
-		$share->method('getNodeId')->willReturn(42);
5473
-		$share->method('getHideDownload')->willReturn(false); // User wants to allow downloads
5474
-		$node->method('getOwner')->willReturn($owner);
5475
-		$owner->method('getUID')->willReturn('differentOwner');
5476
-		$node->method('getStorage')->willReturn($storage);
5477
-		$storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5478
-		$storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5479
-		$storage->method('getShare')->willReturn($originalShare);
5480
-		$originalShare->method('getHideDownload')->willReturn(true); // Parent hides download
5481
-		$originalShare->method('getAttributes')->willReturn(null);
5482
-
5483
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5484
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5485
-
5486
-		// Should be forced to hide download due to parent restriction
5487
-		$share->expects($this->once())->method('setHideDownload')->with(true);
5488
-
5489
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5490
-	}
5491
-
5492
-	public function testUserCanHideWhenParentAllows(): void {
5493
-		$ocs = $this->mockFormatShare();
5494
-
5495
-		$share = $this->createMock(IShare::class);
5496
-		$node = $this->createMock(File::class);
5497
-		$userFolder = $this->createMock(Folder::class);
5498
-		$owner = $this->createMock(IUser::class);
5499
-		$storage = $this->createMock(SharedStorage::class);
5500
-		$originalShare = $this->createMock(IShare::class);
5501
-
5502
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5503
-		$share->method('getNodeId')->willReturn(42);
5504
-		$share->method('getHideDownload')->willReturn(true); // User chooses to hide downloads
5505
-		$node->method('getOwner')->willReturn($owner);
5506
-		$owner->method('getUID')->willReturn('differentOwner');
5507
-		$node->method('getStorage')->willReturn($storage);
5508
-		$storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5509
-		$storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5510
-		$storage->method('getShare')->willReturn($originalShare);
5511
-		$originalShare->method('getHideDownload')->willReturn(false); // Parent allows download
5512
-		$originalShare->method('getAttributes')->willReturn(null);
5513
-
5514
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5515
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5516
-
5517
-		// Should respect user's choice to hide downloads
5518
-		$share->expects($this->once())->method('setHideDownload')->with(true);
5519
-
5520
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5521
-	}
5522
-
5523
-	public function testParentDownloadAttributeInherited(): void {
5524
-		$ocs = $this->mockFormatShare();
5525
-
5526
-		$share = $this->createMock(IShare::class);
5527
-		$node = $this->createMock(File::class);
5528
-		$userFolder = $this->createMock(Folder::class);
5529
-		$owner = $this->createMock(IUser::class);
5530
-		$storage = $this->createMock(SharedStorage::class);
5531
-		$originalShare = $this->createMock(IShare::class);
5532
-		$attributes = $this->createMock(IShareAttributes::class);
5533
-		$shareAttributes = $this->createMock(IShareAttributes::class);
5534
-
5535
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5536
-		$share->method('getNodeId')->willReturn(42);
5537
-		$share->method('getHideDownload')->willReturn(false); // User wants to allow downloads
5538
-		$share->method('getAttributes')->willReturn($shareAttributes);
5539
-		$share->method('newAttributes')->willReturn($shareAttributes);
5540
-		$node->method('getOwner')->willReturn($owner);
5541
-		$owner->method('getUID')->willReturn('differentOwner');
5542
-		$node->method('getStorage')->willReturn($storage);
5543
-		$storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5544
-		$storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5545
-		$storage->method('getShare')->willReturn($originalShare);
5546
-		$originalShare->method('getHideDownload')->willReturn(false);
5547
-		$originalShare->method('getAttributes')->willReturn($attributes);
5548
-		$attributes->method('getAttribute')->with('permissions', 'download')->willReturn(false); // Parent forbids download
5549
-
5550
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5551
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5552
-
5553
-		// Should be forced to hide download and set download attribute to false
5554
-		$share->expects($this->once())->method('setHideDownload')->with(true);
5555
-		$shareAttributes->expects($this->once())->method('setAttribute')->with('permissions', 'download', false);
5556
-		$share->expects($this->once())->method('setAttributes')->with($shareAttributes);
5557
-
5558
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5559
-	}
5560
-
5561
-	public function testFederatedStorageRespectsUserChoice(): void {
5562
-		$ocs = $this->mockFormatShare();
5563
-
5564
-		$share = $this->createMock(IShare::class);
5565
-		$node = $this->createMock(File::class);
5566
-		$userFolder = $this->createMock(Folder::class);
5567
-		$owner = $this->createMock(IUser::class);
5568
-		$storage = $this->createMock(Storage::class);
5569
-
5570
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5571
-		$share->method('getNodeId')->willReturn(42);
5572
-		$share->method('getHideDownload')->willReturn(true); // User chooses to hide downloads
5573
-		$node->method('getOwner')->willReturn($owner);
5574
-		$owner->method('getUID')->willReturn('differentOwner');
5575
-		$node->method('getStorage')->willReturn($storage);
5576
-		$storage->method('instanceOfStorage')->willReturnMap([
5577
-			[SharedStorage::class, false],
5578
-			[Storage::class, true]
5579
-		]);
5580
-
5581
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5582
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5583
-
5584
-		// For federated storage, should respect user's choice
5585
-		$share->expects($this->once())->method('setHideDownload')->with(true);
5586
-
5587
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5588
-	}
5589
-
5590
-	public function testUserAllowsDownloadWhenParentPermits(): void {
5591
-		$ocs = $this->mockFormatShare();
5592
-
5593
-		$share = $this->createMock(IShare::class);
5594
-		$node = $this->createMock(File::class);
5595
-		$userFolder = $this->createMock(Folder::class);
5596
-		$owner = $this->createMock(IUser::class);
5597
-		$storage = $this->createMock(SharedStorage::class);
5598
-		$originalShare = $this->createMock(IShare::class);
5599
-
5600
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5601
-		$share->method('getNodeId')->willReturn(42);
5602
-		$share->method('getHideDownload')->willReturn(false); // User wants to allow downloads
5603
-		$node->method('getOwner')->willReturn($owner);
5604
-		$owner->method('getUID')->willReturn('differentOwner');
5605
-		$node->method('getStorage')->willReturn($storage);
5606
-		$storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5607
-		$storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5608
-		$storage->method('getShare')->willReturn($originalShare);
5609
-		$originalShare->method('getHideDownload')->willReturn(false); // Parent allows download
5610
-		$originalShare->method('getAttributes')->willReturn(null);
5611
-
5612
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5613
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5614
-
5615
-		// Should allow downloads as both user and parent permit it
5616
-		$share->expects($this->once())->method('setHideDownload')->with(false);
5617
-
5618
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5619
-	}
5620
-
5621
-	public function testWrapperStorageUnwrapped(): void {
5622
-		$ocs = $this->mockFormatShare();
5623
-
5624
-		$share = $this->createMock(IShare::class);
5625
-		$node = $this->createMock(File::class);
5626
-		$userFolder = $this->createMock(Folder::class);
5627
-		$owner = $this->createMock(IUser::class);
5628
-		$wrapperStorage = $this->createMock(Wrapper::class);
5629
-		$innerStorage = $this->createMock(SharedStorage::class);
5630
-		$originalShare = $this->createMock(IShare::class);
5631
-
5632
-		$share->method('getSharedBy')->willReturn('sharedByUser');
5633
-		$share->method('getNodeId')->willReturn(42);
5634
-		$share->method('getHideDownload')->willReturn(false);
5635
-		$node->method('getOwner')->willReturn($owner);
5636
-		$owner->method('getUID')->willReturn('differentOwner');
5637
-		$node->method('getStorage')->willReturn($wrapperStorage);
5638
-		$wrapperStorage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5639
-		$wrapperStorage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($innerStorage);
5640
-		$innerStorage->method('getShare')->willReturn($originalShare);
5641
-		$originalShare->method('getHideDownload')->willReturn(false);
5642
-		$originalShare->method('getAttributes')->willReturn(null);
5643
-
5644
-		$userFolder->method('getById')->with(42)->willReturn([$node]);
5645
-		$this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5646
-
5647
-		$share->expects($this->once())->method('setHideDownload')->with(false);
5648
-
5649
-		$this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5650
-	}
594
+    public function createShare(
595
+        string $id,
596
+        int $shareType,
597
+        ?string $sharedWith,
598
+        string $sharedBy,
599
+        string $shareOwner,
600
+        File|Folder|null $node,
601
+        int $permissions,
602
+        int $shareTime,
603
+        ?\DateTime $expiration,
604
+        int $parent,
605
+        string $target,
606
+        int $mail_send,
607
+        string $note = '',
608
+        ?string $token = null,
609
+        ?string $password = null,
610
+        string $label = '',
611
+        ?IShareAttributes $attributes = null,
612
+    ): MockObject {
613
+        $share = $this->createMock(IShare::class);
614
+        $share->method('getId')->willReturn($id);
615
+        $share->method('getShareType')->willReturn($shareType);
616
+        $share->method('getSharedWith')->willReturn($sharedWith);
617
+        $share->method('getSharedBy')->willReturn($sharedBy);
618
+        $share->method('getShareOwner')->willReturn($shareOwner);
619
+        $share->method('getNode')->willReturn($node);
620
+        $share->method('getPermissions')->willReturn($permissions);
621
+        $share->method('getNote')->willReturn($note);
622
+        $share->method('getLabel')->willReturn($label);
623
+        $share->method('getAttributes')->willReturn($attributes);
624
+        $time = new \DateTime();
625
+        $time->setTimestamp($shareTime);
626
+        $share->method('getShareTime')->willReturn($time);
627
+        $share->method('getExpirationDate')->willReturn($expiration);
628
+        $share->method('getTarget')->willReturn($target);
629
+        $share->method('getMailSend')->willReturn($mail_send);
630
+        $share->method('getToken')->willReturn($token);
631
+        $share->method('getPassword')->willReturn($password);
632
+
633
+        if ($shareType === IShare::TYPE_USER
634
+            || $shareType === IShare::TYPE_GROUP
635
+            || $shareType === IShare::TYPE_LINK) {
636
+            $share->method('getFullId')->willReturn('ocinternal:' . $id);
637
+        }
638
+
639
+        return $share;
640
+    }
641
+
642
+    public static function dataGetShare(): array {
643
+        $data = [];
644
+
645
+        $file = [
646
+            'class' => File::class,
647
+            'id' => 1,
648
+            'path' => 'file',
649
+            'mimeType' => 'myMimeType',
650
+        ];
651
+
652
+        $folder = [
653
+            'class' => Folder::class,
654
+            'id' => 2,
655
+            'path' => 'folder',
656
+            'mimeType' => 'myFolderMimeType',
657
+        ];
658
+
659
+        // File shared with user
660
+        $share = [
661
+            '100',
662
+            IShare::TYPE_USER,
663
+            'userId',
664
+            'initiatorId',
665
+            'ownerId',
666
+            $file,
667
+            4,
668
+            5,
669
+            null,
670
+            6,
671
+            'target',
672
+            0,
673
+            'personal note',
674
+            null,
675
+            null,
676
+            '',
677
+            [],
678
+        ];
679
+        $expected = [
680
+            'id' => '100',
681
+            'share_type' => IShare::TYPE_USER,
682
+            'share_with' => 'userId',
683
+            'share_with_displayname' => 'userDisplay',
684
+            'share_with_displayname_unique' => '[email protected]',
685
+            'uid_owner' => 'initiatorId',
686
+            'displayname_owner' => 'initiatorDisplay',
687
+            'item_type' => 'file',
688
+            'item_source' => 1,
689
+            'file_source' => 1,
690
+            'file_target' => 'target',
691
+            'file_parent' => 3,
692
+            'token' => null,
693
+            'expiration' => null,
694
+            'permissions' => 4,
695
+            'stime' => 5,
696
+            'parent' => null,
697
+            'storage_id' => 'STORAGE',
698
+            'path' => 'file',
699
+            'storage' => 101,
700
+            'mail_send' => 0,
701
+            'uid_file_owner' => 'ownerId',
702
+            'note' => 'personal note',
703
+            'label' => '',
704
+            'displayname_file_owner' => 'ownerDisplay',
705
+            'mimetype' => 'myMimeType',
706
+            'has_preview' => false,
707
+            'hide_download' => 0,
708
+            'can_edit' => false,
709
+            'can_delete' => false,
710
+            'item_size' => 123465,
711
+            'item_mtime' => 1234567890,
712
+            'item_permissions' => 4,
713
+            'is-mount-root' => false,
714
+            'mount-type' => '',
715
+        ];
716
+        $data['File shared with user'] = [$share, $expected, true];
717
+
718
+        // Folder shared with group
719
+        $share = [
720
+            '101',
721
+            IShare::TYPE_GROUP,
722
+            'groupId',
723
+            'initiatorId',
724
+            'ownerId',
725
+            $folder,
726
+            4,
727
+            5,
728
+            null,
729
+            6,
730
+            'target',
731
+            0,
732
+            'personal note',
733
+            null,
734
+            null,
735
+            '',
736
+            [],
737
+        ];
738
+        $expected = [
739
+            'id' => '101',
740
+            'share_type' => IShare::TYPE_GROUP,
741
+            'share_with' => 'groupId',
742
+            'share_with_displayname' => 'groupId',
743
+            'uid_owner' => 'initiatorId',
744
+            'displayname_owner' => 'initiatorDisplay',
745
+            'item_type' => 'folder',
746
+            'item_source' => 2,
747
+            'file_source' => 2,
748
+            'file_target' => 'target',
749
+            'file_parent' => 3,
750
+            'token' => null,
751
+            'expiration' => null,
752
+            'permissions' => 4,
753
+            'stime' => 5,
754
+            'parent' => null,
755
+            'storage_id' => 'STORAGE',
756
+            'path' => 'folder',
757
+            'storage' => 101,
758
+            'mail_send' => 0,
759
+            'uid_file_owner' => 'ownerId',
760
+            'note' => 'personal note',
761
+            'label' => '',
762
+            'displayname_file_owner' => 'ownerDisplay',
763
+            'mimetype' => 'myFolderMimeType',
764
+            'has_preview' => false,
765
+            'hide_download' => 0,
766
+            'can_edit' => false,
767
+            'can_delete' => false,
768
+            'item_size' => 123465,
769
+            'item_mtime' => 1234567890,
770
+            'item_permissions' => 4,
771
+            'is-mount-root' => false,
772
+            'mount-type' => '',
773
+        ];
774
+        $data['Folder shared with group'] = [$share, $expected, true];
775
+
776
+        // File shared by link with Expire
777
+        $expire = \DateTime::createFromFormat('Y-m-d h:i:s', '2000-01-02 01:02:03');
778
+        $share = [
779
+            '101',
780
+            IShare::TYPE_LINK,
781
+            null,
782
+            'initiatorId',
783
+            'ownerId',
784
+            $folder,
785
+            4,
786
+            5,
787
+            $expire,
788
+            6,
789
+            'target',
790
+            0,
791
+            'personal note',
792
+            'token',
793
+            'password',
794
+            'first link share'
795
+        ];
796
+        $expected = [
797
+            'id' => '101',
798
+            'share_type' => IShare::TYPE_LINK,
799
+            'password' => 'password',
800
+            'share_with' => 'password',
801
+            'share_with_displayname' => '(Shared link)',
802
+            'send_password_by_talk' => false,
803
+            'uid_owner' => 'initiatorId',
804
+            'displayname_owner' => 'initiatorDisplay',
805
+            'item_type' => 'folder',
806
+            'item_source' => 2,
807
+            'file_source' => 2,
808
+            'file_target' => 'target',
809
+            'file_parent' => 3,
810
+            'token' => 'token',
811
+            'expiration' => '2000-01-02 00:00:00',
812
+            'permissions' => 4,
813
+            'attributes' => null,
814
+            'stime' => 5,
815
+            'parent' => null,
816
+            'storage_id' => 'STORAGE',
817
+            'path' => 'folder',
818
+            'storage' => 101,
819
+            'mail_send' => 0,
820
+            'url' => 'url',
821
+            'uid_file_owner' => 'ownerId',
822
+            'note' => 'personal note',
823
+            'label' => 'first link share',
824
+            'displayname_file_owner' => 'ownerDisplay',
825
+            'mimetype' => 'myFolderMimeType',
826
+            'has_preview' => false,
827
+            'hide_download' => 0,
828
+            'can_edit' => false,
829
+            'can_delete' => false,
830
+            'item_size' => 123465,
831
+            'item_mtime' => 1234567890,
832
+            'item_permissions' => 4,
833
+            'is-mount-root' => false,
834
+            'mount-type' => '',
835
+        ];
836
+        $data['File shared by link with Expire'] = [$share, $expected, false];
837
+
838
+        return $data;
839
+    }
840
+
841
+    #[DataProvider(methodName: 'dataGetShare')]
842
+    public function testGetShare(array $shareParams, array $result, bool $attributes): void {
843
+
844
+        $cache = $this->createMock(ICache::class);
845
+        $cache->method('getNumericStorageId')->willReturn(101);
846
+
847
+        $storage = $this->createMock(IStorage::class);
848
+        $storage->method('getId')->willReturn('STORAGE');
849
+        $storage->method('getCache')->willReturn($cache);
850
+
851
+        $parentFolder = $this->createMock(Folder::class);
852
+        $parentFolder->method('getId')->willReturn(3);
853
+
854
+        $mountPoint = $this->createMock(IMountPoint::class);
855
+        $mountPoint->method('getMountType')->willReturn('');
856
+
857
+        $nodeParams = $shareParams[5];
858
+        $node = $this->createMock($nodeParams['class']);
859
+        $node->method('getId')->willReturn($nodeParams['id']);
860
+        $node->method('getPath')->willReturn($nodeParams['path']);
861
+        $node->method('getStorage')->willReturn($storage);
862
+        $node->method('getParent')->willReturn($parentFolder);
863
+        $node->method('getSize')->willReturn(123465);
864
+        $node->method('getMTime')->willReturn(1234567890);
865
+        $node->method('getMimeType')->willReturn($nodeParams['mimeType']);
866
+        $node->method('getMountPoint')->willReturn($mountPoint);
867
+
868
+        $shareParams[5] = $node;
869
+
870
+        if ($attributes) {
871
+            [$shareAttributes, $shareAttributesReturnJson] = $this->mockShareAttributes();
872
+            $result['attributes'] = $shareAttributesReturnJson;
873
+            $shareParams[16] = $shareAttributes;
874
+        }
875
+
876
+        $share = $this->createShare(...$shareParams);
877
+        /** @var ShareAPIController&MockObject $ocs */
878
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
879
+            ->setConstructorArgs([
880
+                $this->appName,
881
+                $this->request,
882
+                $this->shareManager,
883
+                $this->groupManager,
884
+                $this->userManager,
885
+                $this->rootFolder,
886
+                $this->urlGenerator,
887
+                $this->l,
888
+                $this->config,
889
+                $this->appConfig,
890
+                $this->appManager,
891
+                $this->serverContainer,
892
+                $this->userStatusManager,
893
+                $this->previewManager,
894
+                $this->dateTimeZone,
895
+                $this->logger,
896
+                $this->factory,
897
+                $this->mailer,
898
+                $this->tagManager,
899
+                $this->getEmailValidatorWithStrictEmailCheck(),
900
+                $this->trustedServers,
901
+                $this->currentUser,
902
+            ])
903
+            ->onlyMethods(['canAccessShare'])
904
+            ->getMock();
905
+
906
+        $ocs->expects($this->any())
907
+            ->method('canAccessShare')
908
+            ->willReturn(true);
909
+
910
+        $this->shareManager
911
+            ->expects($this->any())
912
+            ->method('getShareById')
913
+            ->with($share->getFullId(), 'currentUser')
914
+            ->willReturn($share);
915
+
916
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
917
+        $userFolder
918
+            ->method('getRelativePath')
919
+            ->willReturnArgument(0);
920
+
921
+        $userFolder->method('getById')
922
+            ->with($share->getNodeId())
923
+            ->willReturn([$share->getNode()]);
924
+        $userFolder->method('getFirstNodeById')
925
+            ->with($share->getNodeId())
926
+            ->willReturn($share->getNode());
927
+
928
+        $this->rootFolder->method('getUserFolder')
929
+            ->with($this->currentUser)
930
+            ->willReturn($userFolder);
931
+
932
+        $this->urlGenerator
933
+            ->method('linkToRouteAbsolute')
934
+            ->willReturn('url');
935
+
936
+        $initiator = $this->getMockBuilder(IUser::class)->getMock();
937
+        $initiator->method('getUID')->willReturn('initiatorId');
938
+        $initiator->method('getDisplayName')->willReturn('initiatorDisplay');
939
+
940
+        $owner = $this->getMockBuilder(IUser::class)->getMock();
941
+        $owner->method('getUID')->willReturn('ownerId');
942
+        $owner->method('getDisplayName')->willReturn('ownerDisplay');
943
+
944
+        $user = $this->getMockBuilder(IUser::class)->getMock();
945
+        $user->method('getUID')->willReturn('userId');
946
+        $user->method('getDisplayName')->willReturn('userDisplay');
947
+        $user->method('getSystemEMailAddress')->willReturn('[email protected]');
948
+
949
+        $group = $this->getMockBuilder(IGroup::class)->getMock();
950
+        $group->method('getGID')->willReturn('groupId');
951
+
952
+        $this->userManager->method('get')->willReturnMap([
953
+            ['userId', $user],
954
+            ['initiatorId', $initiator],
955
+            ['ownerId', $owner],
956
+        ]);
957
+        $this->groupManager->method('get')->willReturnMap([
958
+            ['group', $group],
959
+        ]);
960
+        $this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
961
+
962
+        $data = $ocs->getShare((string)$share->getId())->getData()[0];
963
+        $this->assertEquals($result, $data);
964
+    }
965
+
966
+
967
+    public function testGetShareInvalidNode(): void {
968
+        $this->expectException(OCSNotFoundException::class);
969
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
970
+
971
+        $share = Server::get(IManager::class)->newShare();
972
+        $share->setSharedBy('initiator')
973
+            ->setSharedWith('recipient')
974
+            ->setShareOwner('owner');
975
+
976
+        $this->shareManager
977
+            ->expects($this->once())
978
+            ->method('getShareById')
979
+            ->with('ocinternal:42', 'currentUser')
980
+            ->willReturn($share);
981
+
982
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
983
+        $this->rootFolder->method('getUserFolder')
984
+            ->with($this->currentUser)
985
+            ->willReturn($userFolder);
986
+
987
+        $this->ocs->getShare('42');
988
+    }
989
+
990
+    public static function dataGetShares(): array {
991
+        $file1 = [
992
+            'class' => File::class,
993
+            'methods' => [
994
+                'getName' => 'file1',
995
+            ]
996
+        ];
997
+        $file2 = [
998
+            'class' => File::class,
999
+            'methods' => [
1000
+                'getName' => 'file2',
1001
+            ]
1002
+        ];
1003
+
1004
+        $folder = [
1005
+            'class' => Folder::class,
1006
+            'methods' => [
1007
+                'getDirectoryListing' => [$file1, $file2]
1008
+            ]
1009
+        ];
1010
+
1011
+        $file1UserShareOwner = [
1012
+            'type' => IShare::TYPE_USER,
1013
+            'sharedWith' => 'recipient',
1014
+            'sharedBy' => 'initiator',
1015
+            'owner' => 'currentUser',
1016
+            'node' => $file1,
1017
+            'id' => 4,
1018
+        ];
1019
+
1020
+        $file1UserShareOwnerExpected = [
1021
+            'id' => 4,
1022
+            'share_type' => IShare::TYPE_USER,
1023
+        ];
1024
+
1025
+        $file1UserShareInitiator = [
1026
+            'type' => IShare::TYPE_USER,
1027
+            'sharedWith' => 'recipient',
1028
+            'sharedBy' => 'currentUser',
1029
+            'owner' => 'owner',
1030
+            'node' => $file1,
1031
+            'id' => 8,
1032
+        ];
1033
+
1034
+        $file1UserShareInitiatorExpected = [
1035
+            'id' => 8,
1036
+            'share_type' => IShare::TYPE_USER,
1037
+        ];
1038
+
1039
+        $file1UserShareRecipient = [
1040
+            'type' => IShare::TYPE_USER,
1041
+            'sharedWith' => 'currentUser',
1042
+            'sharedBy' => 'initiator',
1043
+            'owner' => 'owner',
1044
+            'node' => $file1,
1045
+            'id' => 15,
1046
+        ];
1047
+
1048
+        $file1UserShareRecipientExpected = [
1049
+            'id' => 15,
1050
+            'share_type' => IShare::TYPE_USER,
1051
+        ];
1052
+
1053
+        $file1UserShareOther = [
1054
+            'type' => IShare::TYPE_USER,
1055
+            'sharedWith' => 'recipient',
1056
+            'sharedBy' => 'initiator',
1057
+            'owner' => 'owner',
1058
+            'node' => $file1,
1059
+            'id' => 16,
1060
+        ];
1061
+
1062
+        $file1UserShareOtherExpected = [
1063
+            'id' => 16,
1064
+            'share_type' => IShare::TYPE_USER,
1065
+        ];
1066
+
1067
+        $file1GroupShareOwner = [
1068
+            'type' => IShare::TYPE_GROUP,
1069
+            'sharedWith' => 'recipient',
1070
+            'sharedBy' => 'initiator',
1071
+            'owner' => 'currentUser',
1072
+            'node' => $file1,
1073
+            'id' => 23,
1074
+        ];
1075
+
1076
+        $file1GroupShareOwnerExpected = [
1077
+            'id' => 23,
1078
+            'share_type' => IShare::TYPE_GROUP,
1079
+        ];
1080
+
1081
+        $file1GroupShareRecipient = [
1082
+            'type' => IShare::TYPE_GROUP,
1083
+            'sharedWith' => 'currentUserGroup',
1084
+            'sharedBy' => 'initiator',
1085
+            'owner' => 'owner',
1086
+            'node' => $file1,
1087
+            'id' => 42,
1088
+        ];
1089
+
1090
+        $file1GroupShareRecipientExpected = [
1091
+            'id' => 42,
1092
+            'share_type' => IShare::TYPE_GROUP,
1093
+        ];
1094
+
1095
+        $file1GroupShareOther = [
1096
+            'type' => IShare::TYPE_GROUP,
1097
+            'sharedWith' => 'recipient',
1098
+            'sharedBy' => 'initiator',
1099
+            'owner' => 'owner',
1100
+            'node' => $file1,
1101
+            'id' => 108,
1102
+        ];
1103
+
1104
+        $file1LinkShareOwner = [
1105
+            'type' => IShare::TYPE_LINK,
1106
+            'sharedWith' => 'recipient',
1107
+            'sharedBy' => 'initiator',
1108
+            'owner' => 'currentUser',
1109
+            'node' => $file1,
1110
+            'id' => 415,
1111
+        ];
1112
+
1113
+        $file1LinkShareOwnerExpected = [
1114
+            'id' => 415,
1115
+            'share_type' => IShare::TYPE_LINK,
1116
+        ];
1117
+
1118
+        $file1EmailShareOwner = [
1119
+            'type' => IShare::TYPE_EMAIL,
1120
+            'sharedWith' => 'recipient',
1121
+            'sharedBy' => 'initiator',
1122
+            'owner' => 'currentUser',
1123
+            'node' => $file1,
1124
+            'id' => 416,
1125
+        ];
1126
+
1127
+        $file1EmailShareOwnerExpected = [
1128
+            'id' => 416,
1129
+            'share_type' => IShare::TYPE_EMAIL,
1130
+        ];
1131
+
1132
+        $file1CircleShareOwner = [
1133
+            'type' => IShare::TYPE_CIRCLE,
1134
+            'sharedWith' => 'recipient',
1135
+            'sharedBy' => 'initiator',
1136
+            'owner' => 'currentUser',
1137
+            'node' => $file1,
1138
+            'id' => 423,
1139
+        ];
1140
+
1141
+        $file1CircleShareOwnerExpected = [
1142
+            'id' => 423,
1143
+            'share_type' => IShare::TYPE_CIRCLE,
1144
+        ];
1145
+
1146
+        $file1RoomShareOwner = [
1147
+            'type' => IShare::TYPE_ROOM,
1148
+            'sharedWith' => 'recipient',
1149
+            'sharedBy' => 'initiator',
1150
+            'owner' => 'currentUser',
1151
+            'node' => $file1,
1152
+            'id' => 442,
1153
+        ];
1154
+
1155
+        $file1RoomShareOwnerExpected = [
1156
+            'id' => 442,
1157
+            'share_type' => IShare::TYPE_ROOM,
1158
+        ];
1159
+
1160
+        $file1RemoteShareOwner = [
1161
+            'type' => IShare::TYPE_REMOTE,
1162
+            'sharedWith' => 'recipient',
1163
+            'sharedBy' => 'initiator',
1164
+            'owner' => 'currentUser',
1165
+            'expirationDate' => new \DateTime('2000-01-01T01:02:03'),
1166
+            'node' => $file1,
1167
+            'id' => 815,
1168
+        ];
1169
+
1170
+        $file1RemoteShareOwnerExpected = [
1171
+            'id' => 815,
1172
+            'share_type' => IShare::TYPE_REMOTE,
1173
+        ];
1174
+
1175
+        $file1RemoteGroupShareOwner = [
1176
+            'type' => IShare::TYPE_REMOTE_GROUP,
1177
+            'sharedWith' => 'recipient',
1178
+            'sharedBy' => 'initiator',
1179
+            'owner' => 'currentUser',
1180
+            'expirationDate' => new \DateTime('2000-01-01T01:02:03'),
1181
+            'node' => $file1,
1182
+            'id' => 816,
1183
+        ];
1184
+
1185
+        $file1RemoteGroupShareOwnerExpected = [
1186
+            'id' => 816,
1187
+            'share_type' => IShare::TYPE_REMOTE_GROUP,
1188
+        ];
1189
+
1190
+        $file2UserShareOwner = [
1191
+            'type' => IShare::TYPE_USER,
1192
+            'sharedWith' => 'recipient',
1193
+            'sharedBy' => 'initiator',
1194
+            'owner' => 'currentUser',
1195
+            'node' => $file2,
1196
+            'id' => 823,
1197
+        ];
1198
+
1199
+        $file2UserShareOwnerExpected = [
1200
+            'id' => 823,
1201
+            'share_type' => IShare::TYPE_USER,
1202
+        ];
1203
+
1204
+        $data = [
1205
+            [
1206
+                [
1207
+                    'node' => $file1,
1208
+                ],
1209
+                [
1210
+                    'file1' => [
1211
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1212
+                    ],
1213
+                ],
1214
+                [
1215
+                ],
1216
+                [
1217
+                    $file1UserShareOwnerExpected
1218
+                ]
1219
+            ],
1220
+            [
1221
+                [
1222
+                    'node' => $file1,
1223
+                ],
1224
+                [
1225
+                    'file1' => [
1226
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1227
+                    ],
1228
+                ],
1229
+                [
1230
+                ],
1231
+                [
1232
+                    $file1UserShareOwnerExpected,
1233
+                ]
1234
+            ],
1235
+            [
1236
+                [
1237
+                    'node' => $file1,
1238
+                ],
1239
+                [
1240
+                    'file1' => [
1241
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1242
+                    ],
1243
+                ],
1244
+                [
1245
+                ],
1246
+                [
1247
+                    $file1UserShareOwnerExpected,
1248
+                    $file1UserShareInitiatorExpected,
1249
+                    $file1UserShareOtherExpected,
1250
+                ]
1251
+            ],
1252
+            [
1253
+                [
1254
+                    'node' => $file1,
1255
+                ],
1256
+                [
1257
+                    'file1' => [
1258
+                        IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1259
+                    ],
1260
+                ],
1261
+                [
1262
+                ],
1263
+                [
1264
+                    $file1UserShareInitiatorExpected,
1265
+                ]
1266
+            ],
1267
+            [
1268
+                [
1269
+                    'node' => $file1,
1270
+                ],
1271
+                [
1272
+                    'file1' => [
1273
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1274
+                        IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1275
+                    ],
1276
+                ],
1277
+                [
1278
+                ],
1279
+                [
1280
+                    $file1UserShareOwnerExpected,
1281
+                    $file1GroupShareRecipientExpected,
1282
+                ]
1283
+            ],
1284
+            [
1285
+                [
1286
+                    'node' => $file1,
1287
+                ],
1288
+                [
1289
+                    'file1' => [
1290
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1291
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1292
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1293
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1294
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1295
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1296
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1297
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1298
+                    ],
1299
+                ],
1300
+                [
1301
+                ],
1302
+                [
1303
+                    $file1UserShareOwnerExpected,
1304
+                    $file1GroupShareOwnerExpected,
1305
+                    $file1LinkShareOwnerExpected,
1306
+                    $file1EmailShareOwnerExpected,
1307
+                    $file1CircleShareOwnerExpected,
1308
+                    $file1RoomShareOwnerExpected,
1309
+                ]
1310
+            ],
1311
+            [
1312
+                [
1313
+                    'node' => $file1,
1314
+                ],
1315
+                [
1316
+                    'file1' => [
1317
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1318
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1319
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1320
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1321
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1322
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1323
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1324
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1325
+                    ],
1326
+                ],
1327
+                [
1328
+                    IShare::TYPE_REMOTE => true,
1329
+                    IShare::TYPE_REMOTE_GROUP => true,
1330
+                ],
1331
+                [
1332
+                    $file1UserShareOwnerExpected,
1333
+                    $file1GroupShareOwnerExpected,
1334
+                    $file1LinkShareOwnerExpected,
1335
+                    $file1EmailShareOwnerExpected,
1336
+                    $file1CircleShareOwnerExpected,
1337
+                    $file1RoomShareOwnerExpected,
1338
+                    $file1RemoteShareOwnerExpected,
1339
+                    $file1RemoteGroupShareOwnerExpected,
1340
+                ]
1341
+            ],
1342
+            [
1343
+                [
1344
+                    'node' => $folder,
1345
+                    'subfiles' => 'true',
1346
+                ],
1347
+                [
1348
+                    'file1' => [
1349
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1350
+                    ],
1351
+                    'file2' => [
1352
+                        IShare::TYPE_USER => [$file2UserShareOwner],
1353
+                    ],
1354
+                ],
1355
+                [
1356
+                ],
1357
+                [
1358
+                    $file1UserShareOwnerExpected,
1359
+                    $file2UserShareOwnerExpected,
1360
+                ]
1361
+            ],
1362
+            [
1363
+                [
1364
+                    'node' => $folder,
1365
+                    'subfiles' => 'true',
1366
+                ],
1367
+                [
1368
+                    'file1' => [
1369
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareOwner, $file1UserShareOwner],
1370
+                    ],
1371
+                ],
1372
+                [
1373
+                ],
1374
+                [
1375
+                    $file1UserShareOwnerExpected,
1376
+                ]
1377
+            ],
1378
+            [
1379
+                [
1380
+                    'node' => $folder,
1381
+                    'subfiles' => 'true',
1382
+                ],
1383
+                [
1384
+                    'file1' => [
1385
+                        IShare::TYPE_USER => [$file1UserShareOwner, $file1UserShareRecipient],
1386
+                    ],
1387
+                ],
1388
+                [
1389
+                ],
1390
+                [
1391
+                    $file1UserShareOwnerExpected
1392
+                ]
1393
+            ],
1394
+            [
1395
+                [
1396
+                    'node' => $folder,
1397
+                    'subfiles' => 'true',
1398
+                ],
1399
+                [
1400
+                    'file1' => [
1401
+                        IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1402
+                    ],
1403
+                    'file2' => [
1404
+                        IShare::TYPE_USER => [$file2UserShareOwner],
1405
+                    ],
1406
+                ],
1407
+                [
1408
+                ],
1409
+                [
1410
+                    $file1UserShareInitiatorExpected,
1411
+                    $file1UserShareOtherExpected,
1412
+                    $file2UserShareOwnerExpected,
1413
+                ]
1414
+            ],
1415
+            // This might not happen in a real environment, as the combination
1416
+            // of shares does not seem to be possible on a folder without
1417
+            // resharing rights; if the folder has resharing rights then the
1418
+            // share with others would be included too in the results.
1419
+            [
1420
+                [
1421
+                    'node' => $folder,
1422
+                    'subfiles' => 'true',
1423
+                ],
1424
+                [
1425
+                    'file1' => [
1426
+                        IShare::TYPE_USER => [$file1UserShareRecipient, $file1UserShareInitiator, $file1UserShareOther],
1427
+                    ],
1428
+                ],
1429
+                [
1430
+                ],
1431
+                [
1432
+                    $file1UserShareInitiatorExpected,
1433
+                ]
1434
+            ],
1435
+            [
1436
+                [
1437
+                    'node' => $folder,
1438
+                    'subfiles' => 'true',
1439
+                ],
1440
+                [
1441
+                    'file1' => [
1442
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1443
+                        IShare::TYPE_GROUP => [$file1GroupShareRecipient],
1444
+                    ],
1445
+                ],
1446
+                [
1447
+                ],
1448
+                [
1449
+                    $file1UserShareOwnerExpected,
1450
+                    $file1GroupShareRecipientExpected,
1451
+                ]
1452
+            ],
1453
+            [
1454
+                [
1455
+                    'node' => $folder,
1456
+                    'subfiles' => 'true',
1457
+                ],
1458
+                [
1459
+                    'file1' => [
1460
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1461
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1462
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1463
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1464
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1465
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1466
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1467
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1468
+                    ],
1469
+                ],
1470
+                [
1471
+                ],
1472
+                [
1473
+                    $file1UserShareOwnerExpected,
1474
+                    $file1GroupShareOwnerExpected,
1475
+                    $file1LinkShareOwnerExpected,
1476
+                    $file1EmailShareOwnerExpected,
1477
+                    $file1CircleShareOwnerExpected,
1478
+                    $file1RoomShareOwnerExpected,
1479
+                ]
1480
+            ],
1481
+            [
1482
+                [
1483
+                    'node' => $folder,
1484
+                    'subfiles' => 'true',
1485
+                ],
1486
+                [
1487
+                    'file1' => [
1488
+                        IShare::TYPE_USER => [$file1UserShareOwner],
1489
+                        IShare::TYPE_GROUP => [$file1GroupShareOwner],
1490
+                        IShare::TYPE_LINK => [$file1LinkShareOwner],
1491
+                        IShare::TYPE_EMAIL => [$file1EmailShareOwner],
1492
+                        IShare::TYPE_CIRCLE => [$file1CircleShareOwner],
1493
+                        IShare::TYPE_ROOM => [$file1RoomShareOwner],
1494
+                        IShare::TYPE_REMOTE => [$file1RemoteShareOwner],
1495
+                        IShare::TYPE_REMOTE_GROUP => [$file1RemoteGroupShareOwner],
1496
+                    ],
1497
+                ],
1498
+                [
1499
+                    IShare::TYPE_REMOTE => true,
1500
+                    IShare::TYPE_REMOTE_GROUP => true,
1501
+                ],
1502
+                [
1503
+                    $file1UserShareOwnerExpected,
1504
+                    $file1GroupShareOwnerExpected,
1505
+                    $file1LinkShareOwnerExpected,
1506
+                    $file1EmailShareOwnerExpected,
1507
+                    $file1CircleShareOwnerExpected,
1508
+                    $file1RoomShareOwnerExpected,
1509
+                    $file1RemoteShareOwnerExpected,
1510
+                    $file1RemoteGroupShareOwnerExpected,
1511
+                ]
1512
+            ],
1513
+        ];
1514
+
1515
+        return $data;
1516
+    }
1517
+
1518
+    private function mockSimpleNode(string $class, array $methods): MockObject {
1519
+        $node = $this->createMock($class);
1520
+        foreach ($methods as $method => $return) {
1521
+            if ($method === 'getDirectoryListing') {
1522
+                $return = array_map(
1523
+                    fn ($nodeParams) => $this->mockSimpleNode(...$nodeParams),
1524
+                    $return
1525
+                );
1526
+            }
1527
+            $node->method($method)->willReturn($return);
1528
+        }
1529
+        return $node;
1530
+    }
1531
+
1532
+    #[DataProvider(methodName: 'dataGetShares')]
1533
+    public function testGetShares(array $getSharesParameters, array $shares, array $extraShareTypes, array $expected): void {
1534
+        $shares = array_map(
1535
+            fn ($sharesByType) => array_map(
1536
+                fn ($shareList) => array_map(
1537
+                    function (array $shareParams): IShare {
1538
+                        $share = Server::get(IManager::class)->newShare();
1539
+                        $share->setShareType($shareParams['type'])
1540
+                            ->setSharedBy($shareParams['sharedBy'])
1541
+                            ->setShareOwner($shareParams['owner'])
1542
+                            ->setPermissions(Constants::PERMISSION_READ)
1543
+                            ->setId($shareParams['id']);
1544
+                        if (isset($shareParams['sharedWith'])) {
1545
+                            $share->setSharedWith($shareParams['sharedWith']);
1546
+                        }
1547
+                        if (isset($shareParams['sharedWithDisplayName'])) {
1548
+                            $share->setSharedWithDisplayName($shareParams['sharedWithDisplayName']);
1549
+                        }
1550
+                        if (isset($shareParams['sharedWithAvatar'])) {
1551
+                            $share->setSharedWithAvatar($shareParams['sharedWithAvatar']);
1552
+                        }
1553
+                        if (isset($shareParams['attributes'])) {
1554
+                            $shareAttributes = $this->createMock(IShareAttributes::class);
1555
+                            $shareAttributes->method('toArray')->willReturn($shareParams['attributes']);
1556
+                            $shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
1557
+                            $share->setAttributes($shareAttributes);
1558
+
1559
+                            $expects['attributes'] = \json_encode($shareParams['attributes']);
1560
+                        }
1561
+                        if (isset($shareParams['node'])) {
1562
+                            $node = $this->mockSimpleNode(...$shareParams['node']);
1563
+                            $share->setNode($node);
1564
+                        }
1565
+                        if (isset($shareParams['note'])) {
1566
+                            $share->setNote($shareParams['note']);
1567
+                        }
1568
+                        if (isset($shareParams['expirationDate'])) {
1569
+                            $share->setExpirationDate($shareParams['expirationDate']);
1570
+                        }
1571
+                        if (isset($shareParams['token'])) {
1572
+                            $share->setToken($shareParams['token']);
1573
+                        }
1574
+                        if (isset($shareParams['label'])) {
1575
+                            $share->setLabel($shareParams['label']);
1576
+                        }
1577
+                        if (isset($shareParams['password'])) {
1578
+                            $share->setPassword($shareParams['password']);
1579
+                        }
1580
+                        if (isset($shareParams['sendPasswordByTalk'])) {
1581
+                            $share->setSendPasswordByTalk($shareParams['sendPasswordByTalk']);
1582
+                        }
1583
+                        return $share;
1584
+                    },
1585
+                    $shareList
1586
+                ),
1587
+                $sharesByType
1588
+            ),
1589
+            $shares
1590
+        );
1591
+
1592
+        /** @var ShareAPIController&MockObject $ocs */
1593
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
1594
+            ->setConstructorArgs([
1595
+                $this->appName,
1596
+                $this->request,
1597
+                $this->shareManager,
1598
+                $this->groupManager,
1599
+                $this->userManager,
1600
+                $this->rootFolder,
1601
+                $this->urlGenerator,
1602
+                $this->l,
1603
+                $this->config,
1604
+                $this->appConfig,
1605
+                $this->appManager,
1606
+                $this->serverContainer,
1607
+                $this->userStatusManager,
1608
+                $this->previewManager,
1609
+                $this->dateTimeZone,
1610
+                $this->logger,
1611
+                $this->factory,
1612
+                $this->mailer,
1613
+                $this->tagManager,
1614
+                $this->getEmailValidatorWithStrictEmailCheck(),
1615
+                $this->trustedServers,
1616
+                $this->currentUser,
1617
+            ])
1618
+            ->onlyMethods(['formatShare'])
1619
+            ->getMock();
1620
+
1621
+        $ocs->method('formatShare')
1622
+            ->willReturnCallback(
1623
+                function ($share) {
1624
+                    return [
1625
+                        'id' => $share->getId(),
1626
+                        'share_type' => $share->getShareType()
1627
+                    ];
1628
+                }
1629
+            );
1630
+
1631
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1632
+        $userFolder->method('get')
1633
+            ->with('path')
1634
+            ->willReturn($this->mockSimpleNode(...$getSharesParameters['node']));
1635
+
1636
+        $this->rootFolder->method('getUserFolder')
1637
+            ->with($this->currentUser)
1638
+            ->willReturn($userFolder);
1639
+
1640
+        $this->shareManager
1641
+            ->method('getSharesBy')
1642
+            ->willReturnCallback(
1643
+                function ($user, $shareType, $node) use ($shares) {
1644
+                    if (!isset($shares[$node->getName()]) || !isset($shares[$node->getName()][$shareType])) {
1645
+                        return [];
1646
+                    }
1647
+                    return $shares[$node->getName()][$shareType];
1648
+                }
1649
+            );
1650
+
1651
+        $this->shareManager
1652
+            ->method('outgoingServer2ServerSharesAllowed')
1653
+            ->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE] ?? false);
1654
+
1655
+        $this->shareManager
1656
+            ->method('outgoingServer2ServerGroupSharesAllowed')
1657
+            ->willReturn($extraShareTypes[ISHARE::TYPE_REMOTE_GROUP] ?? false);
1658
+
1659
+        $this->groupManager
1660
+            ->method('isInGroup')
1661
+            ->willReturnCallback(
1662
+                function ($user, $group) {
1663
+                    return $group === 'currentUserGroup';
1664
+                }
1665
+            );
1666
+
1667
+        $result = $ocs->getShares(
1668
+            $getSharesParameters['sharedWithMe'] ?? 'false',
1669
+            $getSharesParameters['reshares'] ?? 'false',
1670
+            $getSharesParameters['subfiles'] ?? 'false',
1671
+            'path'
1672
+        );
1673
+
1674
+        $this->assertEquals($expected, $result->getData());
1675
+    }
1676
+
1677
+    public function testCanAccessShareAsOwner(): void {
1678
+        $share = $this->createMock(IShare::class);
1679
+        $share->method('getShareOwner')->willReturn($this->currentUser);
1680
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1681
+    }
1682
+
1683
+    public function testCanAccessShareAsSharer(): void {
1684
+        $share = $this->createMock(IShare::class);
1685
+        $share->method('getSharedBy')->willReturn($this->currentUser);
1686
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1687
+    }
1688
+
1689
+    public function testCanAccessShareAsSharee(): void {
1690
+        $share = $this->createMock(IShare::class);
1691
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
1692
+        $share->method('getSharedWith')->willReturn($this->currentUser);
1693
+        $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1694
+    }
1695
+
1696
+    public function testCannotAccessLinkShare(): void {
1697
+        $share = $this->createMock(IShare::class);
1698
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
1699
+        $share->method('getNodeId')->willReturn(42);
1700
+
1701
+        $userFolder = $this->createMock(Folder::class);
1702
+        $this->rootFolder->method('getUserFolder')
1703
+            ->with($this->currentUser)
1704
+            ->willReturn($userFolder);
1705
+
1706
+        $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1707
+    }
1708
+
1709
+    #[DataProvider(methodName: 'dataCanAccessShareWithPermissions')]
1710
+    public function testCanAccessShareWithPermissions(int $permissions, bool $expected): void {
1711
+        $share = $this->createMock(IShare::class);
1712
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
1713
+        $share->method('getSharedWith')->willReturn($this->createMock(IUser::class));
1714
+        $share->method('getNodeId')->willReturn(42);
1715
+
1716
+        $file = $this->createMock(File::class);
1717
+
1718
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1719
+        $userFolder->method('getFirstNodeById')
1720
+            ->with($share->getNodeId())
1721
+            ->willReturn($file);
1722
+        $userFolder->method('getById')
1723
+            ->with($share->getNodeId())
1724
+            ->willReturn([$file]);
1725
+        $this->rootFolder->method('getUserFolder')
1726
+            ->with($this->currentUser)
1727
+            ->willReturn($userFolder);
1728
+
1729
+        $file->method('getPermissions')
1730
+            ->willReturn($permissions);
1731
+
1732
+        if ($expected) {
1733
+            $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1734
+        } else {
1735
+            $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1736
+        }
1737
+    }
1738
+
1739
+    public static function dataCanAccessShareWithPermissions(): array {
1740
+        return [
1741
+            [Constants::PERMISSION_SHARE, true],
1742
+            [Constants::PERMISSION_READ, false],
1743
+            [Constants::PERMISSION_READ | Constants::PERMISSION_SHARE, true],
1744
+        ];
1745
+    }
1746
+
1747
+    #[DataProvider(methodName: 'dataCanAccessShareAsGroupMember')]
1748
+    public function testCanAccessShareAsGroupMember(string $group, bool $expected): void {
1749
+        $share = $this->createMock(IShare::class);
1750
+        $share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
1751
+        $share->method('getSharedWith')->willReturn($group);
1752
+        $share->method('getNodeId')->willReturn(42);
1753
+
1754
+        $file = $this->createMock(File::class);
1755
+
1756
+        $userFolder = $this->createMock(Folder::class);
1757
+        $userFolder->method('getFirstNodeById')
1758
+            ->with($share->getNodeId())
1759
+            ->willReturn($file);
1760
+        $userFolder->method('getById')
1761
+            ->with($share->getNodeId())
1762
+            ->willReturn([$file]);
1763
+        $this->rootFolder->method('getUserFolder')
1764
+            ->with($this->currentUser)
1765
+            ->willReturn($userFolder);
1766
+
1767
+        $user = $this->createMock(IUser::class);
1768
+        $this->userManager->method('get')
1769
+            ->with($this->currentUser)
1770
+            ->willReturn($user);
1771
+
1772
+        $group = $this->createMock(IGroup::class);
1773
+        $group->method('inGroup')->with($user)->willReturn(true);
1774
+        $group2 = $this->createMock(IGroup::class);
1775
+        $group2->method('inGroup')->with($user)->willReturn(false);
1776
+
1777
+        $this->groupManager->method('get')->willReturnMap([
1778
+            ['group', $group],
1779
+            ['group2', $group2],
1780
+            ['group-null', null],
1781
+        ]);
1782
+
1783
+        if ($expected) {
1784
+            $this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1785
+        } else {
1786
+            $this->assertFalse($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1787
+        }
1788
+    }
1789
+
1790
+    public static function dataCanAccessShareAsGroupMember(): array {
1791
+        return [
1792
+            ['group', true],
1793
+            ['group2', false],
1794
+            ['group-null', false],
1795
+        ];
1796
+    }
1797
+
1798
+    public static function dataCanAccessRoomShare(): array {
1799
+        return [
1800
+            [false, false, false],
1801
+            [false, false, true],
1802
+            [true, true, true],
1803
+            [false, true, false],
1804
+        ];
1805
+    }
1806
+
1807
+    #[DataProvider(methodName: 'dataCanAccessRoomShare')]
1808
+    public function testCanAccessRoomShare(
1809
+        bool $expected,
1810
+        bool $helperAvailable,
1811
+        bool $canAccessShareByHelper,
1812
+    ): void {
1813
+        $share = $this->createMock(IShare::class);
1814
+        $share->method('getShareType')->willReturn(IShare::TYPE_ROOM);
1815
+        $share->method('getSharedWith')->willReturn('recipientRoom');
1816
+
1817
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1818
+        $this->rootFolder->method('getUserFolder')
1819
+            ->with($this->currentUser)
1820
+            ->willReturn($userFolder);
1821
+
1822
+        $userFolder->method('getById')
1823
+            ->with($share->getNodeId())
1824
+            ->willReturn([$share->getNode()]);
1825
+
1826
+        if (!$helperAvailable) {
1827
+            $this->appManager->method('isEnabledForUser')
1828
+                ->with('spreed')
1829
+                ->willReturn(false);
1830
+        } else {
1831
+            $this->appManager->method('isEnabledForUser')
1832
+                ->with('spreed')
1833
+                ->willReturn(true);
1834
+
1835
+            // This is not possible anymore with PHPUnit 10+
1836
+            // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
1837
+            // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
1838
+            $helper = $this->getMockBuilder(\stdClass::class)
1839
+                ->addMethods(['canAccessShare'])
1840
+                ->getMock();
1841
+            $helper->method('canAccessShare')
1842
+                ->with($share, $this->currentUser)
1843
+                ->willReturn($canAccessShareByHelper);
1844
+
1845
+            $this->serverContainer->method('get')
1846
+                ->with('\OCA\Talk\Share\Helper\ShareAPIController')
1847
+                ->willReturn($helper);
1848
+        }
1849
+
1850
+        $this->assertEquals($expected, $this->invokePrivate($this->ocs, 'canAccessShare', [$share]));
1851
+    }
1852
+
1853
+
1854
+    public function testCreateShareNoPath(): void {
1855
+        $this->expectException(OCSNotFoundException::class);
1856
+        $this->expectExceptionMessage('Please specify a file or folder path');
1857
+
1858
+        $this->ocs->createShare();
1859
+    }
1860
+
1861
+
1862
+    public function testCreateShareInvalidPath(): void {
1863
+        $this->expectException(OCSNotFoundException::class);
1864
+        $this->expectExceptionMessage('Wrong path, file/folder does not exist');
1865
+
1866
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
1867
+        $this->rootFolder->expects($this->once())
1868
+            ->method('getUserFolder')
1869
+            ->with('currentUser')
1870
+            ->willReturn($userFolder);
1871
+
1872
+        $userFolder->expects($this->once())
1873
+            ->method('get')
1874
+            ->with('invalid-path')
1875
+            ->willThrowException(new NotFoundException());
1876
+
1877
+        $this->ocs->createShare('invalid-path');
1878
+    }
1879
+
1880
+    public function testCreateShareInvalidShareType(): void {
1881
+        $this->expectException(OCSBadRequestException::class);
1882
+        $this->expectExceptionMessage('Unknown share type');
1883
+
1884
+        $share = $this->newShare();
1885
+        $this->shareManager->method('newShare')->willReturn($share);
1886
+
1887
+        [$userFolder, $file] = $this->getNonSharedUserFile();
1888
+        $this->rootFolder->expects($this->atLeastOnce())
1889
+            ->method('getUserFolder')
1890
+            ->with('currentUser')
1891
+            ->willReturn($userFolder);
1892
+
1893
+        $userFolder->expects($this->atLeastOnce())
1894
+            ->method('get')
1895
+            ->with('valid-path')
1896
+            ->willReturn($file);
1897
+        $userFolder->method('getById')
1898
+            ->willReturn([]);
1899
+
1900
+        $file->expects($this->once())
1901
+            ->method('lock')
1902
+            ->with(ILockingProvider::LOCK_SHARED);
1903
+
1904
+        $this->ocs->createShare('valid-path', 31);
1905
+    }
1906
+
1907
+    public function testCreateShareUserNoShareWith(): void {
1908
+        $this->expectException(OCSNotFoundException::class);
1909
+        $this->expectExceptionMessage('Please specify a valid account to share with');
1910
+
1911
+        $share = $this->newShare();
1912
+        $this->shareManager->method('newShare')->willReturn($share);
1913
+
1914
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1915
+        $this->rootFolder->method('getUserFolder')
1916
+            ->with('currentUser')
1917
+            ->willReturn($userFolder);
1918
+
1919
+        $userFolder->expects($this->once())
1920
+            ->method('get')
1921
+            ->with('valid-path')
1922
+            ->willReturn($path);
1923
+        $userFolder->method('getById')
1924
+            ->willReturn([]);
1925
+
1926
+        $path->expects($this->once())
1927
+            ->method('lock')
1928
+            ->with(ILockingProvider::LOCK_SHARED);
1929
+
1930
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER);
1931
+    }
1932
+
1933
+
1934
+    public function testCreateShareUserNoValidShareWith(): void {
1935
+        $this->expectException(OCSNotFoundException::class);
1936
+        $this->expectExceptionMessage('Please specify a valid account to share with');
1937
+
1938
+        $share = $this->newShare();
1939
+        $this->shareManager->method('newShare')->willReturn($share);
1940
+
1941
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1942
+        $this->rootFolder->method('getUserFolder')
1943
+            ->with('currentUser')
1944
+            ->willReturn($userFolder);
1945
+
1946
+        $userFolder->expects($this->once())
1947
+            ->method('get')
1948
+            ->with('valid-path')
1949
+            ->willReturn($path);
1950
+        $userFolder->method('getById')
1951
+            ->willReturn([]);
1952
+        $path->expects($this->once())
1953
+            ->method('lock')
1954
+            ->with(ILockingProvider::LOCK_SHARED);
1955
+        $this->userManager->method('userExists')
1956
+            ->with('invalidUser')
1957
+            ->willReturn(false);
1958
+
1959
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'invalidUser');
1960
+    }
1961
+
1962
+    public function testCreateShareUser(): void {
1963
+        $share = $this->newShare();
1964
+        $this->shareManager->method('newShare')->willReturn($share);
1965
+
1966
+        /** @var ShareAPIController $ocs */
1967
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
1968
+            ->setConstructorArgs([
1969
+                $this->appName,
1970
+                $this->request,
1971
+                $this->shareManager,
1972
+                $this->groupManager,
1973
+                $this->userManager,
1974
+                $this->rootFolder,
1975
+                $this->urlGenerator,
1976
+                $this->l,
1977
+                $this->config,
1978
+                $this->appConfig,
1979
+                $this->appManager,
1980
+                $this->serverContainer,
1981
+                $this->userStatusManager,
1982
+                $this->previewManager,
1983
+                $this->dateTimeZone,
1984
+                $this->logger,
1985
+                $this->factory,
1986
+                $this->mailer,
1987
+                $this->tagManager,
1988
+                $this->getEmailValidatorWithStrictEmailCheck(),
1989
+                $this->trustedServers,
1990
+                $this->currentUser,
1991
+            ])->onlyMethods(['formatShare'])
1992
+            ->getMock();
1993
+
1994
+        [$userFolder, $path] = $this->getNonSharedUserFile();
1995
+        $this->rootFolder->expects($this->exactly(2))
1996
+            ->method('getUserFolder')
1997
+            ->with('currentUser')
1998
+            ->willReturn($userFolder);
1999
+
2000
+        $userFolder->expects($this->once())
2001
+            ->method('get')
2002
+            ->with('valid-path')
2003
+            ->willReturn($path);
2004
+        $userFolder->method('getById')
2005
+            ->willReturn([]);
2006
+
2007
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2008
+
2009
+        $path->expects($this->once())
2010
+            ->method('lock')
2011
+            ->with(ILockingProvider::LOCK_SHARED);
2012
+
2013
+        $this->shareManager->method('createShare')
2014
+            ->with($this->callback(function (IShare $share) use ($path) {
2015
+                return $share->getNode() === $path
2016
+                    && $share->getPermissions() === (
2017
+                        Constants::PERMISSION_ALL
2018
+                        & ~Constants::PERMISSION_DELETE
2019
+                        & ~Constants::PERMISSION_CREATE
2020
+                    )
2021
+                    && $share->getShareType() === IShare::TYPE_USER
2022
+                    && $share->getSharedWith() === 'validUser'
2023
+                    && $share->getSharedBy() === 'currentUser';
2024
+            }))
2025
+            ->willReturnArgument(0);
2026
+
2027
+        $expected = new DataResponse([]);
2028
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
2029
+
2030
+        $this->assertInstanceOf(get_class($expected), $result);
2031
+        $this->assertEquals($expected->getData(), $result->getData());
2032
+    }
2033
+
2034
+
2035
+    public function testCreateShareGroupNoValidShareWith(): void {
2036
+        $this->expectException(OCSNotFoundException::class);
2037
+        $this->expectExceptionMessage('Please specify a valid group');
2038
+
2039
+        $share = $this->newShare();
2040
+        $this->shareManager->method('newShare')->willReturn($share);
2041
+        $this->shareManager->method('createShare')->willReturnArgument(0);
2042
+        $this->shareManager->method('allowGroupSharing')->willReturn(true);
2043
+
2044
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2045
+        $this->rootFolder->method('getUserFolder')
2046
+            ->with('currentUser')
2047
+            ->willReturn($userFolder);
2048
+
2049
+        $userFolder->expects($this->once())
2050
+            ->method('get')
2051
+            ->with('valid-path')
2052
+            ->willReturn($path);
2053
+        $userFolder->method('getById')
2054
+            ->willReturn([]);
2055
+
2056
+        $path->expects($this->once())
2057
+            ->method('lock')
2058
+            ->with(ILockingProvider::LOCK_SHARED);
2059
+
2060
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
2061
+    }
2062
+
2063
+    public function testCreateShareGroup(): void {
2064
+        $share = $this->newShare();
2065
+        $this->shareManager->method('newShare')->willReturn($share);
2066
+
2067
+        /** @var ShareAPIController&MockObject $ocs */
2068
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2069
+            ->setConstructorArgs([
2070
+                $this->appName,
2071
+                $this->request,
2072
+                $this->shareManager,
2073
+                $this->groupManager,
2074
+                $this->userManager,
2075
+                $this->rootFolder,
2076
+                $this->urlGenerator,
2077
+                $this->l,
2078
+                $this->config,
2079
+                $this->appConfig,
2080
+                $this->appManager,
2081
+                $this->serverContainer,
2082
+                $this->userStatusManager,
2083
+                $this->previewManager,
2084
+                $this->dateTimeZone,
2085
+                $this->logger,
2086
+                $this->factory,
2087
+                $this->mailer,
2088
+                $this->tagManager,
2089
+                $this->getEmailValidatorWithStrictEmailCheck(),
2090
+                $this->trustedServers,
2091
+                $this->currentUser,
2092
+            ])->onlyMethods(['formatShare'])
2093
+            ->getMock();
2094
+
2095
+        $this->request
2096
+            ->method('getParam')
2097
+            ->willReturnMap([
2098
+                ['path', null, 'valid-path'],
2099
+                ['permissions', null, Constants::PERMISSION_ALL],
2100
+                ['shareType', '-1', IShare::TYPE_GROUP],
2101
+                ['shareWith', null, 'validGroup'],
2102
+            ]);
2103
+
2104
+        [$userFolder, $path] = $this->getNonSharedUserFolder();
2105
+        $this->rootFolder->expects($this->exactly(2))
2106
+            ->method('getUserFolder')
2107
+            ->with('currentUser')
2108
+            ->willReturn($userFolder);
2109
+
2110
+        $userFolder->expects($this->once())
2111
+            ->method('get')
2112
+            ->with('valid-path')
2113
+            ->willReturn($path);
2114
+        $userFolder->method('getById')
2115
+            ->willReturn([]);
2116
+
2117
+        $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2118
+
2119
+        $this->shareManager->expects($this->once())
2120
+            ->method('allowGroupSharing')
2121
+            ->willReturn(true);
2122
+
2123
+        $path->expects($this->once())
2124
+            ->method('lock')
2125
+            ->with(ILockingProvider::LOCK_SHARED);
2126
+
2127
+        $this->shareManager->method('createShare')
2128
+            ->with($this->callback(function (IShare $share) use ($path) {
2129
+                return $share->getNode() === $path
2130
+                && $share->getPermissions() === Constants::PERMISSION_ALL
2131
+                && $share->getShareType() === IShare::TYPE_GROUP
2132
+                && $share->getSharedWith() === 'validGroup'
2133
+                && $share->getSharedBy() === 'currentUser';
2134
+            }))
2135
+            ->willReturnArgument(0);
2136
+
2137
+        $expected = new DataResponse([]);
2138
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'validGroup');
2139
+
2140
+        $this->assertInstanceOf(get_class($expected), $result);
2141
+        $this->assertEquals($expected->getData(), $result->getData());
2142
+    }
2143
+
2144
+
2145
+    public function testCreateShareGroupNotAllowed(): void {
2146
+        $this->expectException(OCSNotFoundException::class);
2147
+        $this->expectExceptionMessage('Group sharing is disabled by the administrator');
2148
+
2149
+        $share = $this->newShare();
2150
+        $this->shareManager->method('newShare')->willReturn($share);
2151
+
2152
+        [$userFolder, $path] = $this->getNonSharedUserFolder();
2153
+        $this->rootFolder->method('getUserFolder')
2154
+            ->with('currentUser')
2155
+            ->willReturn($userFolder);
2156
+
2157
+        $userFolder->expects($this->once())
2158
+            ->method('get')
2159
+            ->with('valid-path')
2160
+            ->willReturn($path);
2161
+        $userFolder->method('getById')
2162
+            ->willReturn([]);
2163
+
2164
+        $this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
2165
+
2166
+        $this->shareManager->expects($this->once())
2167
+            ->method('allowGroupSharing')
2168
+            ->willReturn(false);
2169
+
2170
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_GROUP, 'invalidGroup');
2171
+    }
2172
+
2173
+
2174
+    public function testCreateShareLinkNoLinksAllowed(): void {
2175
+        $this->expectException(OCSNotFoundException::class);
2176
+        $this->expectExceptionMessage('Public link sharing is disabled by the administrator');
2177
+
2178
+        $this->request
2179
+            ->method('getParam')
2180
+            ->willReturnMap([
2181
+                ['path', null, 'valid-path'],
2182
+                ['shareType', '-1', IShare::TYPE_LINK],
2183
+            ]);
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('shareApiLinkAllowPublicUpload')->willReturn(true);
2201
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(false);
2202
+
2203
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK);
2204
+    }
2205
+
2206
+
2207
+    public function testCreateShareLinkNoPublicUpload(): void {
2208
+        $this->expectException(OCSForbiddenException::class);
2209
+        $this->expectExceptionMessage('Public upload disabled by the administrator');
2210
+
2211
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2212
+        $path->method('getId')->willReturn(42);
2213
+        $storage = $this->createMock(IStorage::class);
2214
+        $storage->method('instanceOfStorage')
2215
+            ->willReturnMap([
2216
+                ['OCA\Files_Sharing\External\Storage', false],
2217
+                ['OCA\Files_Sharing\SharedStorage', false],
2218
+            ]);
2219
+        $path->method('getStorage')->willReturn($storage);
2220
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2221
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2222
+        $this->rootFolder->method('getById')
2223
+            ->willReturn([]);
2224
+
2225
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2226
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2227
+
2228
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2229
+    }
2230
+
2231
+
2232
+    public function testCreateShareLinkPublicUploadFile(): void {
2233
+        $this->expectException(OCSBadRequestException::class);
2234
+        $this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
2235
+
2236
+        $storage = $this->createMock(IStorage::class);
2237
+        $storage->method('instanceOfStorage')
2238
+            ->willReturnMap([
2239
+                ['OCA\Files_Sharing\External\Storage', false],
2240
+                ['OCA\Files_Sharing\SharedStorage', false],
2241
+            ]);
2242
+
2243
+        $file = $this->createMock(File::class);
2244
+        $file->method('getId')->willReturn(42);
2245
+        $file->method('getStorage')->willReturn($storage);
2246
+
2247
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2248
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($file);
2249
+        $this->rootFolder->method('getById')
2250
+            ->willReturn([]);
2251
+
2252
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2253
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2254
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2255
+
2256
+        $this->ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true');
2257
+    }
2258
+
2259
+    public function testCreateShareLinkPublicUploadFolder(): void {
2260
+        $ocs = $this->mockFormatShare();
2261
+
2262
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2263
+        $path->method('getId')->willReturn(1);
2264
+        $storage = $this->createMock(IStorage::class);
2265
+        $storage->method('instanceOfStorage')
2266
+            ->willReturnMap([
2267
+                ['OCA\Files_Sharing\External\Storage', false],
2268
+                ['OCA\Files_Sharing\SharedStorage', false],
2269
+            ]);
2270
+        $path->method('getStorage')->willReturn($storage);
2271
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2272
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2273
+        $this->rootFolder->method('getById')
2274
+            ->willReturn([]);
2275
+
2276
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2277
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2278
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2279
+
2280
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2281
+            $this->callback(function (IShare $share) use ($path) {
2282
+                return $share->getNode() === $path
2283
+                    && $share->getShareType() === IShare::TYPE_LINK
2284
+                    && $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
2285
+                    && $share->getSharedBy() === 'currentUser'
2286
+                    && $share->getPassword() === null
2287
+                    && $share->getExpirationDate() === null;
2288
+            })
2289
+        )->willReturnArgument(0);
2290
+
2291
+        $expected = new DataResponse([]);
2292
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', '', null, '');
2293
+
2294
+        $this->assertInstanceOf(get_class($expected), $result);
2295
+        $this->assertEquals($expected->getData(), $result->getData());
2296
+    }
2297
+
2298
+    public function testCreateShareLinkPassword(): void {
2299
+        $ocs = $this->mockFormatShare();
2300
+
2301
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2302
+        $path->method('getId')->willReturn(42);
2303
+        $storage = $this->createMock(IStorage::class);
2304
+        $storage->method('instanceOfStorage')
2305
+            ->willReturnMap([
2306
+                ['OCA\Files_Sharing\External\Storage', false],
2307
+                ['OCA\Files_Sharing\SharedStorage', false],
2308
+            ]);
2309
+        $path->method('getStorage')->willReturn($storage);
2310
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2311
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2312
+        $this->rootFolder->method('getById')
2313
+            ->willReturn([]);
2314
+
2315
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2316
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2317
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2318
+
2319
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2320
+            $this->callback(function (IShare $share) use ($path) {
2321
+                return $share->getNode() === $path
2322
+                && $share->getShareType() === IShare::TYPE_LINK
2323
+                && $share->getPermissions() === Constants::PERMISSION_READ // publicUpload was set to false
2324
+                && $share->getSharedBy() === 'currentUser'
2325
+                && $share->getPassword() === 'password'
2326
+                && $share->getExpirationDate() === null;
2327
+            })
2328
+        )->willReturnArgument(0);
2329
+
2330
+        $expected = new DataResponse([]);
2331
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_READ, IShare::TYPE_LINK, null, 'false', 'password', null, '');
2332
+
2333
+        $this->assertInstanceOf(get_class($expected), $result);
2334
+        $this->assertEquals($expected->getData(), $result->getData());
2335
+    }
2336
+
2337
+    public function testCreateShareLinkSendPasswordByTalk(): void {
2338
+        $ocs = $this->mockFormatShare();
2339
+
2340
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2341
+        $path->method('getId')->willReturn(42);
2342
+        $storage = $this->createMock(IStorage::class);
2343
+        $storage->method('instanceOfStorage')
2344
+            ->willReturnMap([
2345
+                ['OCA\Files_Sharing\External\Storage', false],
2346
+                ['OCA\Files_Sharing\SharedStorage', false],
2347
+            ]);
2348
+        $path->method('getStorage')->willReturn($storage);
2349
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2350
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2351
+        $this->rootFolder->method('getById')
2352
+            ->willReturn([]);
2353
+
2354
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2355
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2356
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2357
+
2358
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
2359
+
2360
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2361
+            $this->callback(function (IShare $share) use ($path) {
2362
+                return $share->getNode() === $path
2363
+                && $share->getShareType() === IShare::TYPE_LINK
2364
+                && $share->getPermissions() === (Constants::PERMISSION_ALL & ~(Constants::PERMISSION_SHARE))
2365
+                && $share->getSharedBy() === 'currentUser'
2366
+                && $share->getPassword() === 'password'
2367
+                && $share->getSendPasswordByTalk() === true
2368
+                && $share->getExpirationDate() === null;
2369
+            })
2370
+        )->willReturnArgument(0);
2371
+
2372
+        $expected = new DataResponse([]);
2373
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'true', 'password', 'true', '');
2374
+
2375
+        $this->assertInstanceOf(get_class($expected), $result);
2376
+        $this->assertEquals($expected->getData(), $result->getData());
2377
+    }
2378
+
2379
+
2380
+    public function testCreateShareLinkSendPasswordByTalkWithTalkDisabled(): void {
2381
+        $this->expectException(OCSForbiddenException::class);
2382
+        $this->expectExceptionMessage('Sharing valid-path sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled');
2383
+
2384
+        $ocs = $this->mockFormatShare();
2385
+
2386
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2387
+        $path->method('getId')->willReturn(42);
2388
+        $storage = $this->createMock(IStorage::class);
2389
+        $storage->method('instanceOfStorage')
2390
+            ->willReturnMap([
2391
+                ['OCA\Files_Sharing\External\Storage', false],
2392
+                ['OCA\Files_Sharing\SharedStorage', false],
2393
+            ]);
2394
+        $path->method('getStorage')->willReturn($storage);
2395
+        $path->method('getPath')->willReturn('valid-path');
2396
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2397
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2398
+        $this->rootFolder->method('getById')
2399
+            ->willReturn([]);
2400
+
2401
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2402
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2403
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2404
+
2405
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
2406
+
2407
+        $this->shareManager->expects($this->never())->method('createShare');
2408
+
2409
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', 'password', 'true', '');
2410
+    }
2411
+
2412
+    public function testCreateShareValidExpireDate(): void {
2413
+        $ocs = $this->mockFormatShare();
2414
+
2415
+        $this->request
2416
+            ->method('getParam')
2417
+            ->willReturnMap([
2418
+                ['path', null, 'valid-path'],
2419
+                ['shareType', '-1', IShare::TYPE_LINK],
2420
+                ['publicUpload', null, 'false'],
2421
+                ['expireDate', '', '2000-01-01'],
2422
+                ['password', '', ''],
2423
+            ]);
2424
+
2425
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2426
+        $path->method('getId')->willReturn(42);
2427
+        $storage = $this->createMock(IStorage::class);
2428
+        $storage->method('instanceOfStorage')
2429
+            ->willReturnMap([
2430
+                ['OCA\Files_Sharing\External\Storage', false],
2431
+                ['OCA\Files_Sharing\SharedStorage', false],
2432
+            ]);
2433
+        $path->method('getStorage')->willReturn($storage);
2434
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2435
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2436
+        $this->rootFolder->method('getById')
2437
+            ->willReturn([]);
2438
+
2439
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2440
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2441
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2442
+
2443
+        $this->shareManager->expects($this->once())->method('createShare')->with(
2444
+            $this->callback(function (IShare $share) use ($path) {
2445
+                $date = new \DateTime('2000-01-01');
2446
+                $date->setTime(0, 0, 0);
2447
+
2448
+                return $share->getNode() === $path
2449
+                && $share->getShareType() === IShare::TYPE_LINK
2450
+                && $share->getPermissions() === Constants::PERMISSION_READ | Constants::PERMISSION_SHARE
2451
+                && $share->getSharedBy() === 'currentUser'
2452
+                && $share->getPassword() === null
2453
+                && $share->getExpirationDate() == $date;
2454
+            })
2455
+        )->willReturnArgument(0);
2456
+
2457
+        $expected = new DataResponse([]);
2458
+        $result = $ocs->createShare('valid-path', null, IShare::TYPE_LINK, null, 'false', '', null, '2000-01-01');
2459
+
2460
+        $this->assertInstanceOf(get_class($expected), $result);
2461
+        $this->assertEquals($expected->getData(), $result->getData());
2462
+    }
2463
+
2464
+
2465
+    public function testCreateShareInvalidExpireDate(): void {
2466
+        $this->expectException(OCSNotFoundException::class);
2467
+        $this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
2468
+
2469
+        $ocs = $this->mockFormatShare();
2470
+
2471
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2472
+        $path->method('getId')->willReturn(42);
2473
+        $storage = $this->createMock(IStorage::class);
2474
+        $storage->method('instanceOfStorage')
2475
+            ->willReturnMap([
2476
+                ['OCA\Files_Sharing\External\Storage', false],
2477
+                ['OCA\Files_Sharing\SharedStorage', false],
2478
+            ]);
2479
+        $path->method('getStorage')->willReturn($storage);
2480
+        $this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
2481
+        $this->rootFolder->method('get')->with('valid-path')->willReturn($path);
2482
+        $this->rootFolder->method('getById')
2483
+            ->willReturn([]);
2484
+
2485
+        $this->shareManager->method('newShare')->willReturn(Server::get(IManager::class)->newShare());
2486
+        $this->shareManager->method('shareApiAllowLinks')->willReturn(true);
2487
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
2488
+
2489
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_LINK, null, 'false', '', null, 'a1b2d3');
2490
+    }
2491
+
2492
+    public function testCreateShareRemote(): void {
2493
+        $share = $this->newShare();
2494
+        $this->shareManager->method('newShare')->willReturn($share);
2495
+
2496
+        /** @var ShareAPIController $ocs */
2497
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2498
+            ->setConstructorArgs([
2499
+                $this->appName,
2500
+                $this->request,
2501
+                $this->shareManager,
2502
+                $this->groupManager,
2503
+                $this->userManager,
2504
+                $this->rootFolder,
2505
+                $this->urlGenerator,
2506
+                $this->l,
2507
+                $this->config,
2508
+                $this->appConfig,
2509
+                $this->appManager,
2510
+                $this->serverContainer,
2511
+                $this->userStatusManager,
2512
+                $this->previewManager,
2513
+                $this->dateTimeZone,
2514
+                $this->logger,
2515
+                $this->factory,
2516
+                $this->mailer,
2517
+                $this->tagManager,
2518
+                $this->getEmailValidatorWithStrictEmailCheck(),
2519
+                $this->trustedServers,
2520
+                $this->currentUser,
2521
+            ])->onlyMethods(['formatShare'])
2522
+            ->getMock();
2523
+
2524
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2525
+        $this->rootFolder->expects($this->exactly(2))
2526
+            ->method('getUserFolder')
2527
+            ->with('currentUser')
2528
+            ->willReturn($userFolder);
2529
+
2530
+        $userFolder->expects($this->once())
2531
+            ->method('get')
2532
+            ->with('valid-path')
2533
+            ->willReturn($path);
2534
+        $userFolder->method('getById')
2535
+            ->willReturn([]);
2536
+
2537
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2538
+
2539
+        $path->expects($this->once())
2540
+            ->method('lock')
2541
+            ->with(ILockingProvider::LOCK_SHARED);
2542
+
2543
+        $this->shareManager->method('createShare')
2544
+            ->with($this->callback(function (IShare $share) use ($path) {
2545
+                return $share->getNode() === $path
2546
+                    && $share->getPermissions() === (
2547
+                        Constants::PERMISSION_ALL
2548
+                        & ~Constants::PERMISSION_DELETE
2549
+                        & ~Constants::PERMISSION_CREATE
2550
+                    )
2551
+                    && $share->getShareType() === IShare::TYPE_REMOTE
2552
+                    && $share->getSharedWith() === '[email protected]'
2553
+                    && $share->getSharedBy() === 'currentUser';
2554
+            }))
2555
+            ->willReturnArgument(0);
2556
+
2557
+        $this->shareManager->method('outgoingServer2ServerSharesAllowed')->willReturn(true);
2558
+
2559
+        $expected = new DataResponse([]);
2560
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE, '[email protected]');
2561
+
2562
+        $this->assertInstanceOf(get_class($expected), $result);
2563
+        $this->assertEquals($expected->getData(), $result->getData());
2564
+    }
2565
+
2566
+    public function testCreateShareRemoteGroup(): void {
2567
+        $share = $this->newShare();
2568
+        $this->shareManager->method('newShare')->willReturn($share);
2569
+
2570
+        /** @var ShareAPIController $ocs */
2571
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2572
+            ->setConstructorArgs([
2573
+                $this->appName,
2574
+                $this->request,
2575
+                $this->shareManager,
2576
+                $this->groupManager,
2577
+                $this->userManager,
2578
+                $this->rootFolder,
2579
+                $this->urlGenerator,
2580
+                $this->l,
2581
+                $this->config,
2582
+                $this->appConfig,
2583
+                $this->appManager,
2584
+                $this->serverContainer,
2585
+                $this->userStatusManager,
2586
+                $this->previewManager,
2587
+                $this->dateTimeZone,
2588
+                $this->logger,
2589
+                $this->factory,
2590
+                $this->mailer,
2591
+                $this->tagManager,
2592
+                $this->getEmailValidatorWithStrictEmailCheck(),
2593
+                $this->trustedServers,
2594
+                $this->currentUser,
2595
+            ])->onlyMethods(['formatShare'])
2596
+            ->getMock();
2597
+
2598
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2599
+        $this->rootFolder->expects($this->exactly(2))
2600
+            ->method('getUserFolder')
2601
+            ->with('currentUser')
2602
+            ->willReturn($userFolder);
2603
+
2604
+        $userFolder->expects($this->once())
2605
+            ->method('get')
2606
+            ->with('valid-path')
2607
+            ->willReturn($path);
2608
+        $userFolder->method('getById')
2609
+            ->willReturn([]);
2610
+
2611
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2612
+
2613
+        $path->expects($this->once())
2614
+            ->method('lock')
2615
+            ->with(ILockingProvider::LOCK_SHARED);
2616
+
2617
+        $this->shareManager->method('createShare')
2618
+            ->with($this->callback(function (IShare $share) use ($path) {
2619
+                return $share->getNode() === $path
2620
+                    && $share->getPermissions() === (
2621
+                        Constants::PERMISSION_ALL
2622
+                        & ~Constants::PERMISSION_DELETE
2623
+                        & ~Constants::PERMISSION_CREATE
2624
+                    )
2625
+                    && $share->getShareType() === IShare::TYPE_REMOTE_GROUP
2626
+                    && $share->getSharedWith() === '[email protected]'
2627
+                    && $share->getSharedBy() === 'currentUser';
2628
+            }))
2629
+            ->willReturnArgument(0);
2630
+
2631
+        $this->shareManager->method('outgoingServer2ServerGroupSharesAllowed')->willReturn(true);
2632
+
2633
+        $expected = new DataResponse([]);
2634
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_REMOTE_GROUP, '[email protected]');
2635
+
2636
+        $this->assertInstanceOf(get_class($expected), $result);
2637
+        $this->assertEquals($expected->getData(), $result->getData());
2638
+    }
2639
+
2640
+    public function testCreateShareRoom(): void {
2641
+        $ocs = $this->mockFormatShare();
2642
+
2643
+        $share = $this->newShare();
2644
+        $this->shareManager->method('newShare')->willReturn($share);
2645
+
2646
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2647
+        $this->rootFolder->expects($this->exactly(2))
2648
+            ->method('getUserFolder')
2649
+            ->with('currentUser')
2650
+            ->willReturn($userFolder);
2651
+
2652
+        $userFolder->expects($this->once())
2653
+            ->method('get')
2654
+            ->with('valid-path')
2655
+            ->willReturn($path);
2656
+        $userFolder->method('getById')
2657
+            ->willReturn([]);
2658
+
2659
+        $path->expects($this->once())
2660
+            ->method('lock')
2661
+            ->with(ILockingProvider::LOCK_SHARED);
2662
+
2663
+        $this->appManager->method('isEnabledForUser')
2664
+            ->with('spreed')
2665
+            ->willReturn(true);
2666
+
2667
+        // This is not possible anymore with PHPUnit 10+
2668
+        // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2669
+        // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2670
+        $helper = $this->getMockBuilder(\stdClass::class)
2671
+            ->addMethods(['createShare'])
2672
+            ->getMock();
2673
+        $helper->method('createShare')
2674
+            ->with(
2675
+                $share,
2676
+                'recipientRoom',
2677
+                Constants::PERMISSION_ALL
2678
+                & ~Constants::PERMISSION_DELETE
2679
+                & ~Constants::PERMISSION_CREATE,
2680
+                ''
2681
+            )->willReturnCallback(
2682
+                function ($share): void {
2683
+                    $share->setSharedWith('recipientRoom');
2684
+                    $share->setPermissions(Constants::PERMISSION_ALL);
2685
+                }
2686
+            );
2687
+
2688
+        $this->serverContainer->method('get')
2689
+            ->with('\OCA\Talk\Share\Helper\ShareAPIController')
2690
+            ->willReturn($helper);
2691
+
2692
+        $this->shareManager->method('createShare')
2693
+            ->with($this->callback(function (IShare $share) use ($path) {
2694
+                return $share->getNode() === $path
2695
+                    && $share->getPermissions() === Constants::PERMISSION_ALL
2696
+                    && $share->getShareType() === IShare::TYPE_ROOM
2697
+                    && $share->getSharedWith() === 'recipientRoom'
2698
+                    && $share->getSharedBy() === 'currentUser';
2699
+            }))
2700
+            ->willReturnArgument(0);
2701
+
2702
+        $expected = new DataResponse([]);
2703
+        $result = $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2704
+
2705
+        $this->assertInstanceOf(get_class($expected), $result);
2706
+        $this->assertEquals($expected->getData(), $result->getData());
2707
+    }
2708
+
2709
+
2710
+    public function testCreateShareRoomHelperNotAvailable(): void {
2711
+        $this->expectException(OCSForbiddenException::class);
2712
+        $this->expectExceptionMessage('Sharing valid-path failed because the back end does not support room shares');
2713
+
2714
+        $ocs = $this->mockFormatShare();
2715
+
2716
+        $share = $this->newShare();
2717
+        $this->shareManager->method('newShare')->willReturn($share);
2718
+
2719
+        [$userFolder, $path] = $this->getNonSharedUserFolder();
2720
+        $this->rootFolder->method('getUserFolder')
2721
+            ->with('currentUser')
2722
+            ->willReturn($userFolder);
2723
+
2724
+        $path->method('getPath')->willReturn('valid-path');
2725
+        $userFolder->expects($this->once())
2726
+            ->method('get')
2727
+            ->with('valid-path')
2728
+            ->willReturn($path);
2729
+        $userFolder->method('getById')
2730
+            ->willReturn([]);
2731
+
2732
+        $path->expects($this->once())
2733
+            ->method('lock')
2734
+            ->with(ILockingProvider::LOCK_SHARED);
2735
+
2736
+        $this->appManager->method('isEnabledForUser')
2737
+            ->with('spreed')
2738
+            ->willReturn(false);
2739
+
2740
+        $this->shareManager->expects($this->never())->method('createShare');
2741
+
2742
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2743
+    }
2744
+
2745
+
2746
+    public function testCreateShareRoomHelperThrowException(): void {
2747
+        $this->expectException(OCSNotFoundException::class);
2748
+        $this->expectExceptionMessage('Exception thrown by the helper');
2749
+
2750
+        $ocs = $this->mockFormatShare();
2751
+
2752
+        $share = $this->newShare();
2753
+        $share->setSharedBy('currentUser');
2754
+        $this->shareManager->method('newShare')->willReturn($share);
2755
+
2756
+        [$userFolder, $path] = $this->getNonSharedUserFile();
2757
+        $this->rootFolder->method('getUserFolder')
2758
+            ->with('currentUser')
2759
+            ->willReturn($userFolder);
2760
+
2761
+        $userFolder->expects($this->once())
2762
+            ->method('get')
2763
+            ->with('valid-path')
2764
+            ->willReturn($path);
2765
+        $userFolder->method('getById')
2766
+            ->willReturn([]);
2767
+
2768
+        $path->expects($this->once())
2769
+            ->method('lock')
2770
+            ->with(ILockingProvider::LOCK_SHARED);
2771
+
2772
+        $this->appManager->method('isEnabledForUser')
2773
+            ->with('spreed')
2774
+            ->willReturn(true);
2775
+
2776
+        // This is not possible anymore with PHPUnit 10+
2777
+        // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
2778
+        // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
2779
+        $helper = $this->getMockBuilder(\stdClass::class)
2780
+            ->addMethods(['createShare'])
2781
+            ->getMock();
2782
+        $helper->method('createShare')
2783
+            ->with(
2784
+                $share,
2785
+                'recipientRoom',
2786
+                Constants::PERMISSION_ALL & ~(Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE),
2787
+                ''
2788
+            )->willReturnCallback(
2789
+                function ($share): void {
2790
+                    throw new OCSNotFoundException('Exception thrown by the helper');
2791
+                }
2792
+            );
2793
+
2794
+        $this->serverContainer->method('get')
2795
+            ->with('\OCA\Talk\Share\Helper\ShareAPIController')
2796
+            ->willReturn($helper);
2797
+
2798
+        $this->shareManager->expects($this->never())->method('createShare');
2799
+
2800
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_ROOM, 'recipientRoom');
2801
+    }
2802
+
2803
+    /**
2804
+     * Test for https://github.com/owncloud/core/issues/22587
2805
+     * TODO: Remove once proper solution is in place
2806
+     */
2807
+    public function testCreateReshareOfFederatedMountNoDeletePermissions(): void {
2808
+        $share = Server::get(IManager::class)->newShare();
2809
+        $this->shareManager->method('newShare')->willReturn($share);
2810
+
2811
+        /** @var ShareAPIController&MockObject $ocs */
2812
+        $ocs = $this->getMockBuilder(ShareAPIController::class)
2813
+            ->setConstructorArgs([
2814
+                $this->appName,
2815
+                $this->request,
2816
+                $this->shareManager,
2817
+                $this->groupManager,
2818
+                $this->userManager,
2819
+                $this->rootFolder,
2820
+                $this->urlGenerator,
2821
+                $this->l,
2822
+                $this->config,
2823
+                $this->appConfig,
2824
+                $this->appManager,
2825
+                $this->serverContainer,
2826
+                $this->userStatusManager,
2827
+                $this->previewManager,
2828
+                $this->dateTimeZone,
2829
+                $this->logger,
2830
+                $this->factory,
2831
+                $this->mailer,
2832
+                $this->tagManager,
2833
+                $this->getEmailValidatorWithStrictEmailCheck(),
2834
+                $this->trustedServers,
2835
+                $this->currentUser,
2836
+            ])->onlyMethods(['formatShare'])
2837
+            ->getMock();
2838
+
2839
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
2840
+        $this->rootFolder->expects($this->exactly(2))
2841
+            ->method('getUserFolder')
2842
+            ->with('currentUser')
2843
+            ->willReturn($userFolder);
2844
+
2845
+        $path = $this->getMockBuilder(Folder::class)->getMock();
2846
+        $path->method('getId')->willReturn(42);
2847
+
2848
+        $storage = $this->createMock(IStorage::class);
2849
+        $storage->method('instanceOfStorage')
2850
+            ->willReturnMap([
2851
+                ['OCA\Files_Sharing\External\Storage', true],
2852
+                ['OCA\Files_Sharing\SharedStorage', false],
2853
+            ]);
2854
+        $userFolder->method('getStorage')->willReturn($storage);
2855
+        $path->method('getStorage')->willReturn($storage);
2856
+
2857
+        $path->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
2858
+        $userFolder->expects($this->once())
2859
+            ->method('get')
2860
+            ->with('valid-path')
2861
+            ->willReturn($path);
2862
+        $userFolder->method('getById')
2863
+            ->willReturn([]);
2864
+
2865
+        $this->userManager->method('userExists')->with('validUser')->willReturn(true);
2866
+
2867
+        $this->shareManager
2868
+            ->expects($this->once())
2869
+            ->method('createShare')
2870
+            ->with($this->callback(function (IShare $share) {
2871
+                return $share->getPermissions() === Constants::PERMISSION_READ;
2872
+            }))
2873
+            ->willReturnArgument(0);
2874
+
2875
+        $ocs->createShare('valid-path', Constants::PERMISSION_ALL, IShare::TYPE_USER, 'validUser');
2876
+    }
2877
+
2878
+
2879
+    public function testUpdateShareCantAccess(): void {
2880
+        $this->expectException(OCSNotFoundException::class);
2881
+        $this->expectExceptionMessage('Wrong share ID, share does not exist');
2882
+
2883
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
2884
+        $share = $this->newShare();
2885
+        $share->setNode($node);
2886
+
2887
+        $node->expects($this->once())
2888
+            ->method('lock')
2889
+            ->with(ILockingProvider::LOCK_SHARED);
2890
+
2891
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2892
+
2893
+        $this->rootFolder->method('getUserFolder')
2894
+            ->with($this->currentUser)
2895
+            ->willReturn($userFolder);
2896
+
2897
+        $userFolder->method('getById')
2898
+            ->with($share->getNodeId())
2899
+            ->willReturn([$share->getNode()]);
2900
+
2901
+        $this->ocs->updateShare(42);
2902
+    }
2903
+
2904
+
2905
+    public function testUpdateNoParametersLink(): void {
2906
+        $this->expectException(OCSBadRequestException::class);
2907
+        $this->expectExceptionMessage('Wrong or no update parameter given');
2908
+
2909
+        $node = $this->getMockBuilder(Folder::class)->getMock();
2910
+        $share = $this->newShare();
2911
+        $share->setPermissions(Constants::PERMISSION_ALL)
2912
+            ->setSharedBy($this->currentUser)
2913
+            ->setShareType(IShare::TYPE_LINK)
2914
+            ->setNode($node);
2915
+
2916
+        $node->expects($this->once())
2917
+            ->method('lock')
2918
+            ->with(ILockingProvider::LOCK_SHARED);
2919
+
2920
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2921
+
2922
+        $this->ocs->updateShare(42);
2923
+    }
2924
+
2925
+
2926
+    public function testUpdateNoParametersOther(): void {
2927
+        $this->expectException(OCSBadRequestException::class);
2928
+        $this->expectExceptionMessage('Wrong or no update parameter given');
2929
+
2930
+        $node = $this->getMockBuilder(Folder::class)->getMock();
2931
+        $share = $this->newShare();
2932
+        $share->setPermissions(Constants::PERMISSION_ALL)
2933
+            ->setSharedBy($this->currentUser)
2934
+            ->setShareType(IShare::TYPE_GROUP)
2935
+            ->setNode($node);
2936
+
2937
+        $node->expects($this->once())
2938
+            ->method('lock')
2939
+            ->with(ILockingProvider::LOCK_SHARED);
2940
+
2941
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2942
+
2943
+        $this->ocs->updateShare(42);
2944
+    }
2945
+
2946
+    public function testUpdateLinkShareClear(): void {
2947
+        $ocs = $this->mockFormatShare();
2948
+
2949
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
2950
+        $node->method('getId')
2951
+            ->willReturn(42);
2952
+        $share = $this->newShare();
2953
+        $share->setPermissions(Constants::PERMISSION_ALL)
2954
+            ->setSharedBy($this->currentUser)
2955
+            ->setShareType(IShare::TYPE_LINK)
2956
+            ->setPassword('password')
2957
+            ->setExpirationDate(new \DateTime())
2958
+            ->setNote('note')
2959
+            ->setLabel('label')
2960
+            ->setHideDownload(true)
2961
+            ->setPermissions(Constants::PERMISSION_ALL)
2962
+            ->setNode($node);
2963
+
2964
+        $node->expects($this->once())
2965
+            ->method('lock')
2966
+            ->with(ILockingProvider::LOCK_SHARED);
2967
+
2968
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
2969
+
2970
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
2971
+            $this->callback(function (IShare $share) {
2972
+                return $share->getPermissions() === Constants::PERMISSION_READ
2973
+                && $share->getPassword() === null
2974
+                && $share->getExpirationDate() === null
2975
+                // Once set a note or a label are never back to null, only to an
2976
+                // empty string.
2977
+                && $share->getNote() === ''
2978
+                && $share->getLabel() === ''
2979
+                && $share->getHideDownload() === false;
2980
+            })
2981
+        )->willReturnArgument(0);
2982
+
2983
+        $this->shareManager->method('getSharedWith')
2984
+            ->willReturn([]);
2985
+
2986
+        $this->rootFolder->method('getUserFolder')
2987
+            ->with($this->currentUser)
2988
+            ->willReturn($userFolder);
2989
+
2990
+        $userFolder->method('getById')
2991
+            ->with(42)
2992
+            ->willReturn([$node]);
2993
+        $userFolder->method('getFirstNodeById')
2994
+            ->with(42)
2995
+            ->willReturn($node);
2996
+
2997
+        $mountPoint = $this->createMock(IMountPoint::class);
2998
+        $node->method('getMountPoint')
2999
+            ->willReturn($mountPoint);
3000
+        $mountPoint->method('getStorageRootId')
3001
+            ->willReturn(42);
3002
+
3003
+        $expected = new DataResponse([]);
3004
+        $result = $ocs->updateShare(42, null, '', null, 'false', '', '', '', 'false');
3005
+
3006
+        $this->assertInstanceOf(get_class($expected), $result);
3007
+        $this->assertEquals($expected->getData(), $result->getData());
3008
+    }
3009
+
3010
+    public function testUpdateLinkShareSet(): void {
3011
+        $ocs = $this->mockFormatShare();
3012
+
3013
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3014
+        $folder->method('getId')
3015
+            ->willReturn(42);
3016
+
3017
+        $share = Server::get(IManager::class)->newShare();
3018
+        $share->setPermissions(Constants::PERMISSION_ALL)
3019
+            ->setSharedBy($this->currentUser)
3020
+            ->setShareType(IShare::TYPE_LINK)
3021
+            ->setNode($folder);
3022
+
3023
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3024
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3025
+
3026
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3027
+            $this->callback(function (IShare $share) {
3028
+                $date = new \DateTime('2000-01-01');
3029
+                $date->setTime(0, 0, 0);
3030
+
3031
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3032
+                && $share->getPassword() === 'password'
3033
+                && $share->getExpirationDate() == $date
3034
+                && $share->getNote() === 'note'
3035
+                && $share->getLabel() === 'label'
3036
+                && $share->getHideDownload() === true;
3037
+            })
3038
+        )->willReturnArgument(0);
3039
+
3040
+        $this->shareManager->method('getSharedWith')
3041
+            ->willReturn([]);
3042
+
3043
+        $this->rootFolder->method('getUserFolder')
3044
+            ->with($this->currentUser)
3045
+            ->willReturn($userFolder);
3046
+
3047
+        $userFolder->method('getById')
3048
+            ->with(42)
3049
+            ->willReturn([$folder]);
3050
+
3051
+        $mountPoint = $this->createMock(IMountPoint::class);
3052
+        $folder->method('getMountPoint')
3053
+            ->willReturn($mountPoint);
3054
+        $mountPoint->method('getStorageRootId')
3055
+            ->willReturn(42);
3056
+
3057
+        $expected = new DataResponse([]);
3058
+        $result = $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-01', 'note', 'label', 'true');
3059
+
3060
+        $this->assertInstanceOf(get_class($expected), $result);
3061
+        $this->assertEquals($expected->getData(), $result->getData());
3062
+    }
3063
+
3064
+    #[DataProvider(methodName: 'publicUploadParamsProvider')]
3065
+    public function testUpdateLinkShareEnablePublicUpload($permissions, $publicUpload, $expireDate, $password): void {
3066
+        $ocs = $this->mockFormatShare();
3067
+
3068
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3069
+        $folder->method('getId')
3070
+            ->willReturn(42);
3071
+
3072
+        $share = Server::get(IManager::class)->newShare();
3073
+        $share->setPermissions(Constants::PERMISSION_ALL)
3074
+            ->setSharedBy($this->currentUser)
3075
+            ->setShareType(IShare::TYPE_LINK)
3076
+            ->setPassword('password')
3077
+            ->setNode($folder);
3078
+
3079
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3080
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3081
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3082
+
3083
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3084
+            $this->callback(function (IShare $share) {
3085
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3086
+                && $share->getPassword() === 'password'
3087
+                && $share->getExpirationDate() === null;
3088
+            })
3089
+        )->willReturnArgument(0);
3090
+
3091
+        $this->rootFolder->method('getUserFolder')
3092
+            ->with($this->currentUser)
3093
+            ->willReturn($userFolder);
3094
+
3095
+        $userFolder->method('getById')
3096
+            ->with(42)
3097
+            ->willReturn([$folder]);
3098
+
3099
+        $mountPoint = $this->createMock(IMountPoint::class);
3100
+        $folder->method('getMountPoint')
3101
+            ->willReturn($mountPoint);
3102
+        $mountPoint->method('getStorageRootId')
3103
+            ->willReturn(42);
3104
+
3105
+        $expected = new DataResponse([]);
3106
+        $result = $ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
3107
+
3108
+        $this->assertInstanceOf(get_class($expected), $result);
3109
+        $this->assertEquals($expected->getData(), $result->getData());
3110
+    }
3111
+
3112
+
3113
+    public static function publicLinkValidPermissionsProvider() {
3114
+        return [
3115
+            [Constants::PERMISSION_CREATE],
3116
+            [Constants::PERMISSION_READ],
3117
+            [Constants::PERMISSION_READ | Constants::PERMISSION_UPDATE],
3118
+            [Constants::PERMISSION_READ | Constants::PERMISSION_DELETE],
3119
+            [Constants::PERMISSION_READ | Constants::PERMISSION_CREATE],
3120
+        ];
3121
+    }
3122
+
3123
+    #[DataProvider(methodName: 'publicLinkValidPermissionsProvider')]
3124
+    public function testUpdateLinkShareSetCRUDPermissions($permissions): void {
3125
+        $ocs = $this->mockFormatShare();
3126
+
3127
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3128
+        $folder->method('getId')
3129
+            ->willReturn(42);
3130
+
3131
+        $share = Server::get(IManager::class)->newShare();
3132
+        $share->setPermissions(Constants::PERMISSION_ALL)
3133
+            ->setSharedBy($this->currentUser)
3134
+            ->setShareType(IShare::TYPE_LINK)
3135
+            ->setPassword('password')
3136
+            ->setNode($folder);
3137
+
3138
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3139
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3140
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3141
+
3142
+        $this->shareManager
3143
+            ->expects($this->any())
3144
+            ->method('updateShare')
3145
+            ->willReturnArgument(0);
3146
+
3147
+        $this->rootFolder->method('getUserFolder')
3148
+            ->with($this->currentUser)
3149
+            ->willReturn($userFolder);
3150
+
3151
+        $userFolder->method('getById')
3152
+            ->with(42)
3153
+            ->willReturn([$folder]);
3154
+
3155
+        $mountPoint = $this->createMock(IMountPoint::class);
3156
+        $folder->method('getMountPoint')
3157
+            ->willReturn($mountPoint);
3158
+        $mountPoint->method('getStorageRootId')
3159
+            ->willReturn(42);
3160
+
3161
+        $expected = new DataResponse([]);
3162
+        $result = $ocs->updateShare(42, $permissions, 'password', null, null, null);
3163
+
3164
+        $this->assertInstanceOf(get_class($expected), $result);
3165
+        $this->assertEquals($expected->getData(), $result->getData());
3166
+    }
3167
+
3168
+    public static function publicLinkInvalidPermissionsProvider1() {
3169
+        return [
3170
+            [Constants::PERMISSION_DELETE],
3171
+            [Constants::PERMISSION_UPDATE],
3172
+            [Constants::PERMISSION_SHARE],
3173
+        ];
3174
+    }
3175
+
3176
+    #[DataProvider(methodName: 'publicLinkInvalidPermissionsProvider1')]
3177
+    public function testUpdateLinkShareSetInvalidCRUDPermissions1($permissions): void {
3178
+        $this->expectException(OCSBadRequestException::class);
3179
+        $this->expectExceptionMessage('Share must at least have READ or CREATE permissions');
3180
+
3181
+        $this->testUpdateLinkShareSetCRUDPermissions($permissions, null);
3182
+    }
3183
+
3184
+    public static function publicLinkInvalidPermissionsProvider2() {
3185
+        return [
3186
+            [Constants::PERMISSION_CREATE | Constants::PERMISSION_DELETE],
3187
+            [Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE],
3188
+        ];
3189
+    }
3190
+
3191
+    #[DataProvider(methodName: 'publicLinkInvalidPermissionsProvider2')]
3192
+    public function testUpdateLinkShareSetInvalidCRUDPermissions2($permissions): void {
3193
+        $this->expectException(OCSBadRequestException::class);
3194
+        $this->expectExceptionMessage('Share must have READ permission if UPDATE or DELETE permission is set');
3195
+
3196
+        $this->testUpdateLinkShareSetCRUDPermissions($permissions);
3197
+    }
3198
+
3199
+    public function testUpdateLinkShareInvalidDate(): void {
3200
+        $this->expectException(OCSBadRequestException::class);
3201
+        $this->expectExceptionMessage('Invalid date. Format must be YYYY-MM-DD');
3202
+
3203
+        $ocs = $this->mockFormatShare();
3204
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3205
+        $userFolder->method('getById')
3206
+            ->with(42)
3207
+            ->willReturn([$folder]);
3208
+        $this->rootFolder->method('getUserFolder')
3209
+            ->with($this->currentUser)
3210
+            ->willReturn($userFolder);
3211
+
3212
+        $folder->method('getId')
3213
+            ->willReturn(42);
3214
+
3215
+        $share = Server::get(IManager::class)->newShare();
3216
+        $share->setPermissions(Constants::PERMISSION_ALL)
3217
+            ->setSharedBy($this->currentUser)
3218
+            ->setShareType(IShare::TYPE_LINK)
3219
+            ->setNode($folder);
3220
+
3221
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3222
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3223
+
3224
+        $ocs->updateShare(42, null, 'password', null, 'true', '2000-01-a');
3225
+    }
3226
+
3227
+    public static function publicUploadParamsProvider() {
3228
+        return [
3229
+            [null, 'true', null, 'password'],
3230
+            // legacy had no delete
3231
+            [
3232
+                Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE,
3233
+                'true', null, 'password'
3234
+            ],
3235
+            // correct
3236
+            [
3237
+                Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE,
3238
+                null, null, 'password'
3239
+            ],
3240
+        ];
3241
+    }
3242
+
3243
+    #[DataProvider(methodName: 'publicUploadParamsProvider')]
3244
+    public function testUpdateLinkSharePublicUploadNotAllowed($permissions, $publicUpload, $expireDate, $password): void {
3245
+        $this->expectException(OCSForbiddenException::class);
3246
+        $this->expectExceptionMessage('Public upload disabled by the administrator');
3247
+
3248
+        $ocs = $this->mockFormatShare();
3249
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3250
+        $userFolder->method('getById')
3251
+            ->with(42)
3252
+            ->willReturn([$folder]);
3253
+        $this->rootFolder->method('getUserFolder')
3254
+            ->with($this->currentUser)
3255
+            ->willReturn($userFolder);
3256
+
3257
+        $folder->method('getId')->willReturn(42);
3258
+
3259
+        $share = Server::get(IManager::class)->newShare();
3260
+        $share->setPermissions(Constants::PERMISSION_ALL)
3261
+            ->setSharedBy($this->currentUser)
3262
+            ->setShareType(IShare::TYPE_LINK)
3263
+            ->setNode($folder);
3264
+
3265
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3266
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(false);
3267
+
3268
+        $ocs->updateShare(42, $permissions, $password, null, $publicUpload, $expireDate);
3269
+    }
3270
+
3271
+
3272
+    public function testUpdateLinkSharePublicUploadOnFile(): void {
3273
+        $this->expectException(OCSBadRequestException::class);
3274
+        $this->expectExceptionMessage('Public upload is only possible for publicly shared folders');
3275
+
3276
+        $ocs = $this->mockFormatShare();
3277
+
3278
+        $file = $this->getMockBuilder(File::class)->getMock();
3279
+        $file->method('getId')
3280
+            ->willReturn(42);
3281
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3282
+        $userFolder->method('getById')
3283
+            ->with(42)
3284
+            ->willReturn([$folder]);
3285
+        $this->rootFolder->method('getUserFolder')
3286
+            ->with($this->currentUser)
3287
+            ->willReturn($userFolder);
3288
+
3289
+        $share = Server::get(IManager::class)->newShare();
3290
+        $share->setPermissions(Constants::PERMISSION_ALL)
3291
+            ->setSharedBy($this->currentUser)
3292
+            ->setShareType(IShare::TYPE_LINK)
3293
+            ->setNode($file);
3294
+
3295
+        $this->shareManager
3296
+            ->method('getShareById')
3297
+            ->with('ocinternal:42')
3298
+            ->willReturn($share);
3299
+        $this->shareManager
3300
+            ->method('shareApiLinkAllowPublicUpload')
3301
+            ->willReturn(true);
3302
+        $this->shareManager
3303
+            ->method('updateShare')
3304
+            ->with($share)
3305
+            ->willThrowException(new \InvalidArgumentException('File shares cannot have create or delete permissions'));
3306
+
3307
+        $ocs->updateShare(42, null, 'password', null, 'true', '');
3308
+    }
3309
+
3310
+    public function testUpdateLinkSharePasswordDoesNotChangeOther(): void {
3311
+        $ocs = $this->mockFormatShare();
3312
+
3313
+        $date = new \DateTime('2000-01-01');
3314
+        $date->setTime(0, 0, 0);
3315
+
3316
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3317
+        $node->method('getId')->willReturn(42);
3318
+        $userFolder->method('getById')
3319
+            ->with(42)
3320
+            ->willReturn([$node]);
3321
+        $this->rootFolder->method('getUserFolder')
3322
+            ->with($this->currentUser)
3323
+            ->willReturn($userFolder);
3324
+        $share = $this->newShare();
3325
+        $share->setPermissions(Constants::PERMISSION_ALL)
3326
+            ->setSharedBy($this->currentUser)
3327
+            ->setShareType(IShare::TYPE_LINK)
3328
+            ->setPassword('password')
3329
+            ->setSendPasswordByTalk(true)
3330
+            ->setExpirationDate($date)
3331
+            ->setNote('note')
3332
+            ->setLabel('label')
3333
+            ->setHideDownload(true)
3334
+            ->setPermissions(Constants::PERMISSION_ALL)
3335
+            ->setNode($node);
3336
+
3337
+        $node->expects($this->once())
3338
+            ->method('lock')
3339
+            ->with(ILockingProvider::LOCK_SHARED);
3340
+
3341
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3342
+
3343
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3344
+            $this->callback(function (IShare $share) use ($date) {
3345
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3346
+                && $share->getPassword() === 'newpassword'
3347
+                && $share->getSendPasswordByTalk() === true
3348
+                && $share->getExpirationDate() === $date
3349
+                && $share->getNote() === 'note'
3350
+                && $share->getLabel() === 'label'
3351
+                && $share->getHideDownload() === true;
3352
+            })
3353
+        )->willReturnArgument(0);
3354
+
3355
+        $expected = new DataResponse([]);
3356
+        $result = $ocs->updateShare(42, null, 'newpassword', null, null, null, null, null, null);
3357
+
3358
+        $this->assertInstanceOf(get_class($expected), $result);
3359
+        $this->assertEquals($expected->getData(), $result->getData());
3360
+    }
3361
+
3362
+    public function testUpdateLinkShareSendPasswordByTalkDoesNotChangeOther(): void {
3363
+        $ocs = $this->mockFormatShare();
3364
+
3365
+        $date = new \DateTime('2000-01-01');
3366
+        $date->setTime(0, 0, 0);
3367
+
3368
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3369
+        $userFolder->method('getById')
3370
+            ->with(42)
3371
+            ->willReturn([$node]);
3372
+        $this->rootFolder->method('getUserFolder')
3373
+            ->with($this->currentUser)
3374
+            ->willReturn($userFolder);
3375
+        $node->method('getId')->willReturn(42);
3376
+        $share = $this->newShare();
3377
+        $share->setPermissions(Constants::PERMISSION_ALL)
3378
+            ->setSharedBy($this->currentUser)
3379
+            ->setShareType(IShare::TYPE_LINK)
3380
+            ->setPassword('password')
3381
+            ->setSendPasswordByTalk(false)
3382
+            ->setExpirationDate($date)
3383
+            ->setNote('note')
3384
+            ->setLabel('label')
3385
+            ->setHideDownload(true)
3386
+            ->setPermissions(Constants::PERMISSION_ALL)
3387
+            ->setNode($node);
3388
+
3389
+        $node->expects($this->once())
3390
+            ->method('lock')
3391
+            ->with(ILockingProvider::LOCK_SHARED);
3392
+
3393
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3394
+
3395
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3396
+
3397
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3398
+            $this->callback(function (IShare $share) use ($date) {
3399
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3400
+                && $share->getPassword() === 'password'
3401
+                && $share->getSendPasswordByTalk() === true
3402
+                && $share->getExpirationDate() === $date
3403
+                && $share->getNote() === 'note'
3404
+                && $share->getLabel() === 'label'
3405
+                && $share->getHideDownload() === true;
3406
+            })
3407
+        )->willReturnArgument(0);
3408
+
3409
+        $expected = new DataResponse([]);
3410
+        $result = $ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3411
+
3412
+        $this->assertInstanceOf(get_class($expected), $result);
3413
+        $this->assertEquals($expected->getData(), $result->getData());
3414
+    }
3415
+
3416
+
3417
+    public function testUpdateLinkShareSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3418
+        $this->expectException(OCSForbiddenException::class);
3419
+        $this->expectExceptionMessage('"Sending the password by Nextcloud Talk" for sharing a file or folder failed because Nextcloud Talk is not enabled.');
3420
+
3421
+        $ocs = $this->mockFormatShare();
3422
+
3423
+        $date = new \DateTime('2000-01-01');
3424
+        $date->setTime(0, 0, 0);
3425
+
3426
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3427
+        $userFolder->method('getById')
3428
+            ->with(42)
3429
+            ->willReturn([$node]);
3430
+        $this->rootFolder->method('getUserFolder')
3431
+            ->with($this->currentUser)
3432
+            ->willReturn($userFolder);
3433
+        $node->method('getId')->willReturn(42);
3434
+        $share = $this->newShare();
3435
+        $share->setPermissions(Constants::PERMISSION_ALL)
3436
+            ->setSharedBy($this->currentUser)
3437
+            ->setShareType(IShare::TYPE_LINK)
3438
+            ->setPassword('password')
3439
+            ->setSendPasswordByTalk(false)
3440
+            ->setExpirationDate($date)
3441
+            ->setNote('note')
3442
+            ->setLabel('label')
3443
+            ->setHideDownload(true)
3444
+            ->setPermissions(Constants::PERMISSION_ALL)
3445
+            ->setNode($node);
3446
+
3447
+        $node->expects($this->once())
3448
+            ->method('lock')
3449
+            ->with(ILockingProvider::LOCK_SHARED);
3450
+
3451
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3452
+
3453
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3454
+
3455
+        $this->shareManager->expects($this->never())->method('updateShare');
3456
+
3457
+        $ocs->updateShare(42, null, null, 'true', null, null, null, null, null);
3458
+    }
3459
+
3460
+    public function testUpdateLinkShareDoNotSendPasswordByTalkDoesNotChangeOther(): void {
3461
+        $ocs = $this->mockFormatShare();
3462
+
3463
+        $date = new \DateTime('2000-01-01');
3464
+        $date->setTime(0, 0, 0);
3465
+
3466
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3467
+        $userFolder->method('getById')
3468
+            ->with(42)
3469
+            ->willReturn([$node]);
3470
+        $this->rootFolder->method('getUserFolder')
3471
+            ->with($this->currentUser)
3472
+            ->willReturn($userFolder);
3473
+        $node->method('getId')->willReturn(42);
3474
+        $share = $this->newShare();
3475
+        $share->setPermissions(Constants::PERMISSION_ALL)
3476
+            ->setSharedBy($this->currentUser)
3477
+            ->setShareType(IShare::TYPE_LINK)
3478
+            ->setPassword('password')
3479
+            ->setSendPasswordByTalk(true)
3480
+            ->setExpirationDate($date)
3481
+            ->setNote('note')
3482
+            ->setLabel('label')
3483
+            ->setHideDownload(true)
3484
+            ->setPermissions(Constants::PERMISSION_ALL)
3485
+            ->setNode($node);
3486
+
3487
+        $node->expects($this->once())
3488
+            ->method('lock')
3489
+            ->with(ILockingProvider::LOCK_SHARED);
3490
+
3491
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3492
+
3493
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(true);
3494
+
3495
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3496
+            $this->callback(function (IShare $share) use ($date) {
3497
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3498
+                && $share->getPassword() === 'password'
3499
+                && $share->getSendPasswordByTalk() === false
3500
+                && $share->getExpirationDate() === $date
3501
+                && $share->getNote() === 'note'
3502
+                && $share->getLabel() === 'label'
3503
+                && $share->getHideDownload() === true;
3504
+            })
3505
+        )->willReturnArgument(0);
3506
+
3507
+        $expected = new DataResponse([]);
3508
+        $result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3509
+
3510
+        $this->assertInstanceOf(get_class($expected), $result);
3511
+        $this->assertEquals($expected->getData(), $result->getData());
3512
+    }
3513
+
3514
+    public function testUpdateLinkShareDoNotSendPasswordByTalkWithTalkDisabledDoesNotChangeOther(): void {
3515
+        $ocs = $this->mockFormatShare();
3516
+
3517
+        $date = new \DateTime('2000-01-01');
3518
+        $date->setTime(0, 0, 0);
3519
+
3520
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3521
+        $node->method('getId')
3522
+            ->willReturn(42);
3523
+
3524
+        $share = $this->newShare();
3525
+        $share->setPermissions(Constants::PERMISSION_ALL)
3526
+            ->setSharedBy($this->currentUser)
3527
+            ->setShareType(IShare::TYPE_LINK)
3528
+            ->setPassword('password')
3529
+            ->setSendPasswordByTalk(true)
3530
+            ->setExpirationDate($date)
3531
+            ->setNote('note')
3532
+            ->setLabel('label')
3533
+            ->setHideDownload(true)
3534
+            ->setPermissions(Constants::PERMISSION_ALL)
3535
+            ->setNode($node);
3536
+
3537
+        $node->expects($this->once())
3538
+            ->method('lock')
3539
+            ->with(ILockingProvider::LOCK_SHARED);
3540
+
3541
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3542
+
3543
+        $this->appManager->method('isEnabledForUser')->with('spreed')->willReturn(false);
3544
+
3545
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3546
+            $this->callback(function (IShare $share) use ($date) {
3547
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3548
+                && $share->getPassword() === 'password'
3549
+                && $share->getSendPasswordByTalk() === false
3550
+                && $share->getExpirationDate() === $date
3551
+                && $share->getNote() === 'note'
3552
+                && $share->getLabel() === 'label'
3553
+                && $share->getHideDownload() === true;
3554
+            })
3555
+        )->willReturnArgument(0);
3556
+
3557
+        $this->rootFolder->method('getUserFolder')
3558
+            ->with($this->currentUser)
3559
+            ->willReturn($userFolder);
3560
+
3561
+        $userFolder->method('getById')
3562
+            ->with(42)
3563
+            ->willReturn([$node]);
3564
+
3565
+        $mountPoint = $this->createMock(IMountPoint::class);
3566
+        $node->method('getMountPoint')
3567
+            ->willReturn($mountPoint);
3568
+        $mountPoint->method('getStorageRootId')
3569
+            ->willReturn(42);
3570
+
3571
+        $mountPoint = $this->createMock(IMountPoint::class);
3572
+        $node->method('getMountPoint')
3573
+            ->willReturn($mountPoint);
3574
+        $mountPoint->method('getStorageRootId')
3575
+            ->willReturn(42);
3576
+
3577
+        $expected = new DataResponse([]);
3578
+        $result = $ocs->updateShare(42, null, null, 'false', null, null, null, null, null);
3579
+
3580
+        $this->assertInstanceOf(get_class($expected), $result);
3581
+        $this->assertEquals($expected->getData(), $result->getData());
3582
+    }
3583
+
3584
+    public function testUpdateLinkShareExpireDateDoesNotChangeOther(): void {
3585
+        $ocs = $this->mockFormatShare();
3586
+
3587
+        [$userFolder, $node] = $this->getNonSharedUserFolder();
3588
+        $node->method('getId')
3589
+            ->willReturn(42);
3590
+
3591
+        $share = $this->newShare();
3592
+        $share->setPermissions(Constants::PERMISSION_ALL)
3593
+            ->setSharedBy($this->currentUser)
3594
+            ->setShareType(IShare::TYPE_LINK)
3595
+            ->setPassword('password')
3596
+            ->setSendPasswordByTalk(true)
3597
+            ->setExpirationDate(new \DateTime())
3598
+            ->setNote('note')
3599
+            ->setLabel('label')
3600
+            ->setHideDownload(true)
3601
+            ->setPermissions(Constants::PERMISSION_ALL)
3602
+            ->setNode($node);
3603
+
3604
+        $node->expects($this->once())
3605
+            ->method('lock')
3606
+            ->with(ILockingProvider::LOCK_SHARED);
3607
+
3608
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3609
+
3610
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3611
+            $this->callback(function (IShare $share) {
3612
+                $date = new \DateTime('2010-12-23');
3613
+                $date->setTime(0, 0, 0);
3614
+
3615
+                return $share->getPermissions() === Constants::PERMISSION_ALL
3616
+                && $share->getPassword() === 'password'
3617
+                && $share->getSendPasswordByTalk() === true
3618
+                && $share->getExpirationDate() == $date
3619
+                && $share->getNote() === 'note'
3620
+                && $share->getLabel() === 'label'
3621
+                && $share->getHideDownload() === true;
3622
+            })
3623
+        )->willReturnArgument(0);
3624
+
3625
+        $this->rootFolder->method('getUserFolder')
3626
+            ->with($this->currentUser)
3627
+            ->willReturn($userFolder);
3628
+
3629
+        $userFolder->method('getById')
3630
+            ->with(42)
3631
+            ->willReturn([$node]);
3632
+
3633
+        $mountPoint = $this->createMock(IMountPoint::class);
3634
+        $node->method('getMountPoint')
3635
+            ->willReturn($mountPoint);
3636
+        $mountPoint->method('getStorageRootId')
3637
+            ->willReturn(42);
3638
+
3639
+        $expected = new DataResponse([]);
3640
+        $result = $ocs->updateShare(42, null, null, null, null, '2010-12-23', null, null, null);
3641
+
3642
+        $this->assertInstanceOf(get_class($expected), $result);
3643
+        $this->assertEquals($expected->getData(), $result->getData());
3644
+    }
3645
+
3646
+    public function testUpdateLinkSharePublicUploadDoesNotChangeOther(): void {
3647
+        $ocs = $this->mockFormatShare();
3648
+
3649
+        $date = new \DateTime('2000-01-01');
3650
+
3651
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3652
+        $folder->method('getId')
3653
+            ->willReturn(42);
3654
+
3655
+        $share = Server::get(IManager::class)->newShare();
3656
+        $share->setPermissions(Constants::PERMISSION_ALL)
3657
+            ->setSharedBy($this->currentUser)
3658
+            ->setShareType(IShare::TYPE_LINK)
3659
+            ->setPassword('password')
3660
+            ->setSendPasswordByTalk(true)
3661
+            ->setExpirationDate($date)
3662
+            ->setNote('note')
3663
+            ->setLabel('label')
3664
+            ->setHideDownload(true)
3665
+            ->setPermissions(Constants::PERMISSION_ALL)
3666
+            ->setNode($folder);
3667
+
3668
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3669
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3670
+
3671
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3672
+            $this->callback(function (IShare $share) use ($date) {
3673
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3674
+                && $share->getPassword() === 'password'
3675
+                && $share->getSendPasswordByTalk() === true
3676
+                && $share->getExpirationDate() === $date
3677
+                && $share->getNote() === 'note'
3678
+                && $share->getLabel() === 'label'
3679
+                && $share->getHideDownload() === true;
3680
+            })
3681
+        )->willReturnArgument(0);
3682
+
3683
+        $this->shareManager->method('getSharedWith')
3684
+            ->willReturn([]);
3685
+
3686
+        $this->rootFolder->method('getUserFolder')
3687
+            ->with($this->currentUser)
3688
+            ->willReturn($userFolder);
3689
+
3690
+        $userFolder->method('getById')
3691
+            ->with(42)
3692
+            ->willReturn([$folder]);
3693
+
3694
+        $mountPoint = $this->createMock(IMountPoint::class);
3695
+        $folder->method('getMountPoint')
3696
+            ->willReturn($mountPoint);
3697
+        $mountPoint->method('getStorageRootId')
3698
+            ->willReturn(42);
3699
+
3700
+        $expected = new DataResponse([]);
3701
+        $result = $ocs->updateShare(42, null, null, null, 'true', null, null, null, null);
3702
+
3703
+        $this->assertInstanceOf(get_class($expected), $result);
3704
+        $this->assertEquals($expected->getData(), $result->getData());
3705
+    }
3706
+
3707
+    public function testUpdateLinkSharePermissions(): void {
3708
+        $ocs = $this->mockFormatShare();
3709
+
3710
+        $date = new \DateTime('2000-01-01');
3711
+
3712
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3713
+        $folder->method('getId')
3714
+            ->willReturn(42);
3715
+
3716
+        $share = Server::get(IManager::class)->newShare();
3717
+        $share->setPermissions(Constants::PERMISSION_ALL)
3718
+            ->setSharedBy($this->currentUser)
3719
+            ->setShareType(IShare::TYPE_LINK)
3720
+            ->setPassword('password')
3721
+            ->setSendPasswordByTalk(true)
3722
+            ->setExpirationDate($date)
3723
+            ->setNote('note')
3724
+            ->setLabel('label')
3725
+            ->setHideDownload(true)
3726
+            ->setPermissions(Constants::PERMISSION_ALL)
3727
+            ->setNode($folder);
3728
+
3729
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3730
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3731
+
3732
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3733
+            $this->callback(function (IShare $share) use ($date): bool {
3734
+                return $share->getPermissions() === (Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE | Constants::PERMISSION_DELETE)
3735
+                && $share->getPassword() === 'password'
3736
+                && $share->getSendPasswordByTalk() === true
3737
+                && $share->getExpirationDate() === $date
3738
+                && $share->getNote() === 'note'
3739
+                && $share->getLabel() === 'label'
3740
+                && $share->getHideDownload() === true;
3741
+            })
3742
+        )->willReturnArgument(0);
3743
+
3744
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3745
+
3746
+        $this->rootFolder->method('getUserFolder')
3747
+            ->with($this->currentUser)
3748
+            ->willReturn($userFolder);
3749
+
3750
+        $userFolder->method('getById')
3751
+            ->with(42)
3752
+            ->willReturn([$folder]);
3753
+
3754
+        $mountPoint = $this->createMock(IMountPoint::class);
3755
+        $folder->method('getMountPoint')
3756
+            ->willReturn($mountPoint);
3757
+        $mountPoint->method('getStorageRootId')
3758
+            ->willReturn(42);
3759
+
3760
+        $expected = new DataResponse([]);
3761
+        $result = $ocs->updateShare(42, 7, null, null, 'true', null, null, null, null);
3762
+
3763
+        $this->assertInstanceOf(get_class($expected), $result);
3764
+        $this->assertEquals($expected->getData(), $result->getData());
3765
+    }
3766
+
3767
+    public function testUpdateLinkSharePermissionsShare(): void {
3768
+        $ocs = $this->mockFormatShare();
3769
+
3770
+        $date = new \DateTime('2000-01-01');
3771
+
3772
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3773
+        $folder->method('getId')
3774
+            ->willReturn(42);
3775
+
3776
+        $share = Server::get(IManager::class)->newShare();
3777
+        $share->setPermissions(Constants::PERMISSION_ALL)
3778
+            ->setSharedBy($this->currentUser)
3779
+            ->setShareType(IShare::TYPE_LINK)
3780
+            ->setPassword('password')
3781
+            ->setSendPasswordByTalk(true)
3782
+            ->setExpirationDate($date)
3783
+            ->setNote('note')
3784
+            ->setLabel('label')
3785
+            ->setHideDownload(true)
3786
+            ->setPermissions(Constants::PERMISSION_READ)
3787
+            ->setNode($folder);
3788
+
3789
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3790
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3791
+
3792
+        $this->shareManager->expects($this->once())
3793
+            ->method('updateShare')
3794
+            ->with(
3795
+                $this->callback(function (IShare $share) use ($date) {
3796
+                    return $share->getPermissions() === Constants::PERMISSION_ALL
3797
+                        && $share->getPassword() === 'password'
3798
+                        && $share->getSendPasswordByTalk() === true
3799
+                        && $share->getExpirationDate() === $date
3800
+                        && $share->getNote() === 'note'
3801
+                        && $share->getLabel() === 'label'
3802
+                        && $share->getHideDownload() === true;
3803
+                })
3804
+            )->willReturnArgument(0);
3805
+
3806
+        $this->rootFolder->method('getUserFolder')
3807
+            ->with($this->currentUser)
3808
+            ->willReturn($userFolder);
3809
+
3810
+        $userFolder->method('getById')
3811
+            ->with(42)
3812
+            ->willReturn([$folder]);
3813
+
3814
+        $mountPoint = $this->createMock(IMountPoint::class);
3815
+        $folder->method('getMountPoint')
3816
+            ->willReturn($mountPoint);
3817
+        $mountPoint->method('getStorageRootId')
3818
+            ->willReturn(42);
3819
+
3820
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3821
+
3822
+        $expected = new DataResponse([]);
3823
+        $result = $ocs->updateShare(42, Constants::PERMISSION_ALL, null, null, null, null, null, null, null);
3824
+
3825
+        $this->assertInstanceOf(get_class($expected), $result);
3826
+        $this->assertEquals($expected->getData(), $result->getData());
3827
+    }
3828
+
3829
+    public function testUpdateOtherPermissions(): void {
3830
+        $ocs = $this->mockFormatShare();
3831
+
3832
+        [$userFolder, $file] = $this->getNonSharedUserFolder();
3833
+        $file->method('getId')
3834
+            ->willReturn(42);
3835
+
3836
+        $share = Server::get(IManager::class)->newShare();
3837
+        $share->setPermissions(Constants::PERMISSION_ALL)
3838
+            ->setSharedBy($this->currentUser)
3839
+            ->setShareType(IShare::TYPE_USER)
3840
+            ->setNode($file);
3841
+
3842
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3843
+        $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true);
3844
+
3845
+        $this->shareManager->expects($this->once())->method('updateShare')->with(
3846
+            $this->callback(function (IShare $share) {
3847
+                return $share->getPermissions() === Constants::PERMISSION_ALL;
3848
+            })
3849
+        )->willReturnArgument(0);
3850
+
3851
+        $this->shareManager->method('getSharedWith')->willReturn([]);
3852
+
3853
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3854
+        $this->rootFolder->method('getUserFolder')
3855
+            ->with($this->currentUser)
3856
+            ->willReturn($userFolder);
3857
+
3858
+        $userFolder->method('getById')
3859
+            ->with(42)
3860
+            ->willReturn([$file]);
3861
+
3862
+        $mountPoint = $this->createMock(IMountPoint::class);
3863
+        $file->method('getMountPoint')
3864
+            ->willReturn($mountPoint);
3865
+        $mountPoint->method('getStorageRootId')
3866
+            ->willReturn(42);
3867
+
3868
+        $expected = new DataResponse([]);
3869
+        $result = $ocs->updateShare(42, 31, null, null, null, null);
3870
+
3871
+        $this->assertInstanceOf(get_class($expected), $result);
3872
+        $this->assertEquals($expected->getData(), $result->getData());
3873
+    }
3874
+
3875
+    public function testUpdateShareCannotIncreasePermissions(): void {
3876
+        $ocs = $this->mockFormatShare();
3877
+
3878
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3879
+        $folder->method('getId')
3880
+            ->willReturn(42);
3881
+
3882
+        $share = Server::get(IManager::class)->newShare();
3883
+        $share
3884
+            ->setId(42)
3885
+            ->setSharedBy($this->currentUser)
3886
+            ->setShareOwner('anotheruser')
3887
+            ->setShareType(IShare::TYPE_GROUP)
3888
+            ->setSharedWith('group1')
3889
+            ->setPermissions(Constants::PERMISSION_READ)
3890
+            ->setNode($folder);
3891
+
3892
+        // note: updateShare will modify the received instance but getSharedWith will reread from the database,
3893
+        // so their values will be different
3894
+        $incomingShare = Server::get(IManager::class)->newShare();
3895
+        $incomingShare
3896
+            ->setId(42)
3897
+            ->setSharedBy($this->currentUser)
3898
+            ->setShareOwner('anotheruser')
3899
+            ->setShareType(IShare::TYPE_GROUP)
3900
+            ->setSharedWith('group1')
3901
+            ->setPermissions(Constants::PERMISSION_READ)
3902
+            ->setNode($folder);
3903
+
3904
+        $this->request
3905
+            ->method('getParam')
3906
+            ->willReturnMap([
3907
+                ['permissions', null, '31'],
3908
+            ]);
3909
+
3910
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3911
+
3912
+        $this->shareManager->expects($this->any())
3913
+            ->method('getSharedWith')
3914
+            ->willReturnMap([
3915
+                ['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3916
+                ['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]],
3917
+                ['currentUser', IShare::TYPE_ROOM, $share->getNode(), -1, 0, []]
3918
+            ]);
3919
+
3920
+        $this->rootFolder->method('getUserFolder')
3921
+            ->with($this->currentUser)
3922
+            ->willReturn($userFolder);
3923
+
3924
+        $userFolder->method('getById')
3925
+            ->with(42)
3926
+            ->willReturn([$folder]);
3927
+        $userFolder->method('getFirstNodeById')
3928
+            ->with(42)
3929
+            ->willReturn($folder);
3930
+
3931
+        $mountPoint = $this->createMock(IMountPoint::class);
3932
+        $folder->method('getMountPoint')
3933
+            ->willReturn($mountPoint);
3934
+        $mountPoint->method('getStorageRootId')
3935
+            ->willReturn(42);
3936
+
3937
+        $this->shareManager->expects($this->once())
3938
+            ->method('updateShare')
3939
+            ->with($share)
3940
+            ->willThrowException(new GenericShareException('Cannot increase permissions of path/file', 'Cannot increase permissions of path/file', 404));
3941
+
3942
+        try {
3943
+            $ocs->updateShare(42, 31);
3944
+            $this->fail();
3945
+        } catch (OCSException $e) {
3946
+            $this->assertEquals('Cannot increase permissions of path/file', $e->getMessage());
3947
+        }
3948
+    }
3949
+
3950
+    public function testUpdateShareCanIncreasePermissionsIfOwner(): void {
3951
+        $ocs = $this->mockFormatShare();
3952
+
3953
+        [$userFolder, $folder] = $this->getNonSharedUserFolder();
3954
+        $folder->method('getId')
3955
+            ->willReturn(42);
3956
+
3957
+        $share = Server::get(IManager::class)->newShare();
3958
+        $share
3959
+            ->setId(42)
3960
+            ->setSharedBy($this->currentUser)
3961
+            ->setShareOwner($this->currentUser)
3962
+            ->setShareType(IShare::TYPE_GROUP)
3963
+            ->setSharedWith('group1')
3964
+            ->setPermissions(Constants::PERMISSION_READ)
3965
+            ->setNode($folder);
3966
+
3967
+        // note: updateShare will modify the received instance but getSharedWith will reread from the database,
3968
+        // so their values will be different
3969
+        $incomingShare = Server::get(IManager::class)->newShare();
3970
+        $incomingShare
3971
+            ->setId(42)
3972
+            ->setSharedBy($this->currentUser)
3973
+            ->setShareOwner($this->currentUser)
3974
+            ->setShareType(IShare::TYPE_GROUP)
3975
+            ->setSharedWith('group1')
3976
+            ->setPermissions(Constants::PERMISSION_READ)
3977
+            ->setNode($folder);
3978
+
3979
+        $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);
3980
+
3981
+        $this->shareManager->expects($this->any())
3982
+            ->method('getSharedWith')
3983
+            ->willReturnMap([
3984
+                ['currentUser', IShare::TYPE_USER, $share->getNode(), -1, 0, []],
3985
+                ['currentUser', IShare::TYPE_GROUP, $share->getNode(), -1, 0, [$incomingShare]]
3986
+            ]);
3987
+
3988
+        $this->shareManager->expects($this->once())
3989
+            ->method('updateShare')
3990
+            ->with($share)
3991
+            ->willReturn($share);
3992
+
3993
+        $this->rootFolder->method('getUserFolder')
3994
+            ->with($this->currentUser)
3995
+            ->willReturn($userFolder);
3996
+
3997
+        $userFolder->method('getById')
3998
+            ->with(42)
3999
+            ->willReturn([$folder]);
4000
+
4001
+        $mountPoint = $this->createMock(IMountPoint::class);
4002
+        $folder->method('getMountPoint')
4003
+            ->willReturn($mountPoint);
4004
+        $mountPoint->method('getStorageRootId')
4005
+            ->willReturn(42);
4006
+
4007
+        $result = $ocs->updateShare(42, 31);
4008
+        $this->assertInstanceOf(DataResponse::class, $result);
4009
+    }
4010
+
4011
+    public function testUpdateShareOwnerless(): void {
4012
+        $ocs = $this->mockFormatShare();
4013
+
4014
+        $mount = $this->createMock(IShareOwnerlessMount::class);
4015
+
4016
+        $file = $this->createMock(File::class);
4017
+        $file
4018
+            ->expects($this->exactly(2))
4019
+            ->method('getPermissions')
4020
+            ->willReturn(Constants::PERMISSION_SHARE);
4021
+        $file
4022
+            ->expects($this->once())
4023
+            ->method('getMountPoint')
4024
+            ->willReturn($mount);
4025
+
4026
+        $userFolder = $this->createMock(Folder::class);
4027
+        $userFolder->method('getById')
4028
+            ->with(2)
4029
+            ->willReturn([$file]);
4030
+        $userFolder->method('getFirstNodeById')
4031
+            ->with(2)
4032
+            ->willReturn($file);
4033
+
4034
+        $this->rootFolder
4035
+            ->method('getUserFolder')
4036
+            ->with($this->currentUser)
4037
+            ->willReturn($userFolder);
4038
+
4039
+        $share = $this->createMock(IShare::class);
4040
+        $share
4041
+            ->expects($this->once())
4042
+            ->method('getNode')
4043
+            ->willReturn($file);
4044
+        $share
4045
+            ->expects($this->exactly(2))
4046
+            ->method('getNodeId')
4047
+            ->willReturn(2);
4048
+        $share
4049
+            ->expects($this->exactly(2))
4050
+            ->method('getPermissions')
4051
+            ->willReturn(Constants::PERMISSION_SHARE);
4052
+
4053
+        $this->shareManager
4054
+            ->expects($this->once())
4055
+            ->method('getShareById')
4056
+            ->with('ocinternal:1', $this->currentUser)
4057
+            ->willReturn($share);
4058
+
4059
+        $this->shareManager
4060
+            ->expects($this->once())
4061
+            ->method('updateShare')
4062
+            ->with($share)
4063
+            ->willReturn($share);
4064
+
4065
+        $result = $ocs->updateShare(1, Constants::PERMISSION_ALL);
4066
+        $this->assertInstanceOf(DataResponse::class, $result);
4067
+    }
4068
+
4069
+    public static function dataFormatShare(): array {
4070
+        $owner = ['getDisplayName' => 'ownerDN'];
4071
+        $initiator = ['getDisplayName' => 'initiatorDN'];
4072
+        $recipient = [
4073
+            'getDisplayName' => 'recipientDN',
4074
+            'getSystemEMailAddress' => 'recipient'
4075
+        ];
4076
+
4077
+        $folder = [
4078
+            'class' => Folder::class,
4079
+            'mimeType' => 'myFolderMimeType',
4080
+            'path' => 'folder',
4081
+            'id' => 2,
4082
+        ];
4083
+        $file = [
4084
+            'class' => File::class,
4085
+            'mimeType' => 'myMimeType',
4086
+            'path' => 'file',
4087
+            'id' => 3,
4088
+        ];
4089
+        $fileWithPreview = [
4090
+            'class' => File::class,
4091
+            'mimeType' => 'mimeWithPreview',
4092
+            'path' => 'fileWithPreview',
4093
+            'id' => 4,
4094
+        ];
4095
+
4096
+        $result = [];
4097
+
4098
+        $share = [
4099
+            'type' => IShare::TYPE_USER,
4100
+            'owner' => 'owner',
4101
+            'sharedWith' => 'recipient',
4102
+            'attributes' => [
4103
+                'scope' => 'permissions',
4104
+                'key' => 'download',
4105
+                'value' => true
4106
+            ],
4107
+            'node' => $file,
4108
+            'note' => 'personal note',
4109
+        ];
4110
+
4111
+        // User backend down
4112
+        $result[] = [
4113
+            [
4114
+                'id' => '42',
4115
+                'share_type' => IShare::TYPE_USER,
4116
+                'uid_owner' => 'initiator',
4117
+                'displayname_owner' => 'initiator',
4118
+                'permissions' => 1,
4119
+                'stime' => 946684862,
4120
+                'parent' => null,
4121
+                'expiration' => null,
4122
+                'token' => null,
4123
+                'uid_file_owner' => 'owner',
4124
+                'displayname_file_owner' => 'owner',
4125
+                'path' => 'file',
4126
+                'item_type' => 'file',
4127
+                'storage_id' => 'storageId',
4128
+                'storage' => 100,
4129
+                'item_source' => 3,
4130
+                'file_source' => 3,
4131
+                'file_parent' => 1,
4132
+                'file_target' => 'myTarget',
4133
+                'share_with' => 'recipient',
4134
+                'share_with_displayname' => 'recipient',
4135
+                'share_with_displayname_unique' => 'recipient',
4136
+                'note' => 'personal note',
4137
+                'label' => '',
4138
+                'mail_send' => 0,
4139
+                'mimetype' => 'myMimeType',
4140
+                'has_preview' => false,
4141
+                'hide_download' => 0,
4142
+                'can_edit' => false,
4143
+                'can_delete' => false,
4144
+                'item_size' => 123456,
4145
+                'item_mtime' => 1234567890,
4146
+                'is-mount-root' => false,
4147
+                'mount-type' => '',
4148
+                'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4149
+                'item_permissions' => 1,
4150
+            ],
4151
+            $share,
4152
+            [], false
4153
+        ];
4154
+        // User backend up
4155
+        $result[] = [
4156
+            [
4157
+                'id' => '42',
4158
+                'share_type' => IShare::TYPE_USER,
4159
+                'uid_owner' => 'initiator',
4160
+                'displayname_owner' => 'initiatorDN',
4161
+                'permissions' => 1,
4162
+                'stime' => 946684862,
4163
+                'parent' => null,
4164
+                'expiration' => null,
4165
+                'token' => null,
4166
+                'uid_file_owner' => 'owner',
4167
+                'displayname_file_owner' => 'ownerDN',
4168
+                'note' => 'personal note',
4169
+                'label' => '',
4170
+                'path' => 'file',
4171
+                'item_type' => 'file',
4172
+                'storage_id' => 'storageId',
4173
+                'storage' => 100,
4174
+                'item_source' => 3,
4175
+                'file_source' => 3,
4176
+                'file_parent' => 1,
4177
+                'file_target' => 'myTarget',
4178
+                'share_with' => 'recipient',
4179
+                'share_with_displayname' => 'recipientDN',
4180
+                'share_with_displayname_unique' => 'recipient',
4181
+                'mail_send' => 0,
4182
+                'mimetype' => 'myMimeType',
4183
+                'has_preview' => false,
4184
+                'hide_download' => 0,
4185
+                'can_edit' => false,
4186
+                'can_delete' => false,
4187
+                'item_size' => 123456,
4188
+                'item_mtime' => 1234567890,
4189
+                'is-mount-root' => false,
4190
+                'mount-type' => '',
4191
+                'attributes' => '[{"scope":"permissions","key":"download","value":true}]',
4192
+                'item_permissions' => 1,
4193
+            ], $share, [
4194
+                ['owner', $owner],
4195
+                ['initiator', $initiator],
4196
+                ['recipient', $recipient],
4197
+            ], false
4198
+        ];
4199
+
4200
+        // Same but no attributes
4201
+        $share = [
4202
+            'type' => IShare::TYPE_USER,
4203
+            'owner' => 'owner',
4204
+            'sharedWith' => 'recipient',
4205
+            'node' => $file,
4206
+            'note' => 'personal note',
4207
+        ];
4208
+
4209
+        // User backend down
4210
+        $result[] = [
4211
+            [
4212
+                'id' => '42',
4213
+                'share_type' => IShare::TYPE_USER,
4214
+                'uid_owner' => 'initiator',
4215
+                'displayname_owner' => 'initiator',
4216
+                'permissions' => 1,
4217
+                'attributes' => null,
4218
+                'stime' => 946684862,
4219
+                'parent' => null,
4220
+                'expiration' => null,
4221
+                'token' => null,
4222
+                'uid_file_owner' => 'owner',
4223
+                'displayname_file_owner' => 'owner',
4224
+                'note' => 'personal note',
4225
+                'label' => '',
4226
+                'path' => 'file',
4227
+                'item_type' => 'file',
4228
+                'storage_id' => 'storageId',
4229
+                'storage' => 100,
4230
+                'item_source' => 3,
4231
+                'file_source' => 3,
4232
+                'file_parent' => 1,
4233
+                'file_target' => 'myTarget',
4234
+                'share_with' => 'recipient',
4235
+                'share_with_displayname' => 'recipient',
4236
+                'share_with_displayname_unique' => 'recipient',
4237
+                'mail_send' => 0,
4238
+                'mimetype' => 'myMimeType',
4239
+                'has_preview' => false,
4240
+                'hide_download' => 0,
4241
+                'can_edit' => false,
4242
+                'can_delete' => false,
4243
+                'item_size' => 123456,
4244
+                'item_mtime' => 1234567890,
4245
+                'is-mount-root' => false,
4246
+                'mount-type' => '',
4247
+                'attributes' => null,
4248
+                'item_permissions' => 1,
4249
+            ], $share, [], false
4250
+        ];
4251
+
4252
+        $share['owner'] = 'currentUser';
4253
+
4254
+        // User backend down
4255
+        $result[] = [
4256
+            [
4257
+                'id' => '42',
4258
+                'share_type' => IShare::TYPE_USER,
4259
+                'uid_owner' => 'initiator',
4260
+                'displayname_owner' => 'initiator',
4261
+                'permissions' => 1,
4262
+                'attributes' => null,
4263
+                'stime' => 946684862,
4264
+                'parent' => null,
4265
+                'expiration' => null,
4266
+                'token' => null,
4267
+                'uid_file_owner' => 'currentUser',
4268
+                'displayname_file_owner' => 'currentUser',
4269
+                'note' => 'personal note',
4270
+                'label' => '',
4271
+                'path' => 'file',
4272
+                'item_type' => 'file',
4273
+                'storage_id' => 'storageId',
4274
+                'storage' => 100,
4275
+                'item_source' => 3,
4276
+                'file_source' => 3,
4277
+                'file_parent' => 1,
4278
+                'file_target' => 'myTarget',
4279
+                'share_with' => 'recipient',
4280
+                'share_with_displayname' => 'recipient',
4281
+                'share_with_displayname_unique' => 'recipient',
4282
+                'mail_send' => 0,
4283
+                'mimetype' => 'myMimeType',
4284
+                'has_preview' => false,
4285
+                'hide_download' => 0,
4286
+                'can_edit' => true,
4287
+                'can_delete' => true,
4288
+                'item_size' => 123456,
4289
+                'item_mtime' => 1234567890,
4290
+                'is-mount-root' => false,
4291
+                'mount-type' => '',
4292
+                'attributes' => null,
4293
+                'item_permissions' => 11,
4294
+            ], $share, [], false
4295
+        ];
4296
+
4297
+        // with existing group
4298
+        $share = [
4299
+            'type' => IShare::TYPE_GROUP,
4300
+            'owner' => 'owner',
4301
+            'sharedWith' => 'recipientGroup',
4302
+            'node' => $file,
4303
+            'note' => 'personal note',
4304
+        ];
4305
+
4306
+        $result[] = [
4307
+            [
4308
+                'id' => '42',
4309
+                'share_type' => IShare::TYPE_GROUP,
4310
+                'uid_owner' => 'initiator',
4311
+                'displayname_owner' => 'initiator',
4312
+                'permissions' => 1,
4313
+                'attributes' => null,
4314
+                'stime' => 946684862,
4315
+                'parent' => null,
4316
+                'expiration' => null,
4317
+                'token' => null,
4318
+                'uid_file_owner' => 'owner',
4319
+                'displayname_file_owner' => 'owner',
4320
+                'note' => 'personal note',
4321
+                'label' => '',
4322
+                'path' => 'file',
4323
+                'item_type' => 'file',
4324
+                'storage_id' => 'storageId',
4325
+                'storage' => 100,
4326
+                'item_source' => 3,
4327
+                'file_source' => 3,
4328
+                'file_parent' => 1,
4329
+                'file_target' => 'myTarget',
4330
+                'share_with' => 'recipientGroup',
4331
+                'share_with_displayname' => 'recipientGroupDisplayName',
4332
+                'mail_send' => 0,
4333
+                'mimetype' => 'myMimeType',
4334
+                'has_preview' => false,
4335
+                'hide_download' => 0,
4336
+                'can_edit' => false,
4337
+                'can_delete' => false,
4338
+                'item_size' => 123456,
4339
+                'item_mtime' => 1234567890,
4340
+                'is-mount-root' => false,
4341
+                'mount-type' => '',
4342
+                'attributes' => null,
4343
+                'item_permissions' => 1,
4344
+            ], $share, [], false
4345
+        ];
4346
+
4347
+        // with unknown group / no group backend
4348
+        $share['sharedWith'] = 'recipientGroup2';
4349
+
4350
+        $result[] = [
4351
+            [
4352
+                'id' => '42',
4353
+                'share_type' => IShare::TYPE_GROUP,
4354
+                'uid_owner' => 'initiator',
4355
+                'displayname_owner' => 'initiator',
4356
+                'permissions' => 1,
4357
+                'stime' => 946684862,
4358
+                'parent' => null,
4359
+                'expiration' => null,
4360
+                'token' => null,
4361
+                'uid_file_owner' => 'owner',
4362
+                'displayname_file_owner' => 'owner',
4363
+                'note' => 'personal note',
4364
+                'label' => '',
4365
+                'path' => 'file',
4366
+                'item_type' => 'file',
4367
+                'storage_id' => 'storageId',
4368
+                'storage' => 100,
4369
+                'item_source' => 3,
4370
+                'file_source' => 3,
4371
+                'file_parent' => 1,
4372
+                'file_target' => 'myTarget',
4373
+                'share_with' => 'recipientGroup2',
4374
+                'share_with_displayname' => 'recipientGroup2',
4375
+                'mail_send' => 0,
4376
+                'mimetype' => 'myMimeType',
4377
+                'has_preview' => false,
4378
+                'hide_download' => 0,
4379
+                'can_edit' => false,
4380
+                'can_delete' => false,
4381
+                'item_size' => 123456,
4382
+                'item_mtime' => 1234567890,
4383
+                'is-mount-root' => false,
4384
+                'mount-type' => '',
4385
+                'attributes' => null,
4386
+                'item_permissions' => 1,
4387
+            ], $share, [], false
4388
+        ];
4389
+
4390
+        $share = [
4391
+            'type' => IShare::TYPE_LINK,
4392
+            'owner' => 'owner',
4393
+            'node' => $file,
4394
+            'note' => 'personal note',
4395
+            'password' => 'mypassword',
4396
+            'expirationDate' => new \DateTime('2001-01-02T00:00:00'),
4397
+            'token' => 'myToken',
4398
+            'label' => 'new link share',
4399
+        ];
4400
+
4401
+        $result[] = [
4402
+            [
4403
+                'id' => '42',
4404
+                'share_type' => IShare::TYPE_LINK,
4405
+                'uid_owner' => 'initiator',
4406
+                'displayname_owner' => 'initiator',
4407
+                'permissions' => 1,
4408
+                'attributes' => null,
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' => false,
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['sendPasswordByTalk'] = true;
4446
+
4447
+        $result[] = [
4448
+            [
4449
+                'id' => '42',
4450
+                'share_type' => IShare::TYPE_LINK,
4451
+                'uid_owner' => 'initiator',
4452
+                'displayname_owner' => 'initiator',
4453
+                'permissions' => 1,
4454
+                'stime' => 946684862,
4455
+                'parent' => null,
4456
+                'expiration' => '2001-01-02 00:00:00',
4457
+                'token' => 'myToken',
4458
+                'uid_file_owner' => 'owner',
4459
+                'displayname_file_owner' => 'owner',
4460
+                'note' => 'personal note',
4461
+                'label' => 'new link share',
4462
+                'path' => 'file',
4463
+                'item_type' => 'file',
4464
+                'storage_id' => 'storageId',
4465
+                'storage' => 100,
4466
+                'item_source' => 3,
4467
+                'file_source' => 3,
4468
+                'file_parent' => 1,
4469
+                'file_target' => 'myTarget',
4470
+                'password' => 'mypassword',
4471
+                'share_with' => 'mypassword',
4472
+                'share_with_displayname' => '(Shared link)',
4473
+                'send_password_by_talk' => true,
4474
+                'mail_send' => 0,
4475
+                'url' => 'myLink',
4476
+                'mimetype' => 'myMimeType',
4477
+                'has_preview' => false,
4478
+                'hide_download' => 0,
4479
+                'can_edit' => false,
4480
+                'can_delete' => false,
4481
+                'item_size' => 123456,
4482
+                'item_mtime' => 1234567890,
4483
+                'is-mount-root' => false,
4484
+                'mount-type' => '',
4485
+                'attributes' => null,
4486
+                'item_permissions' => 1,
4487
+            ], $share, [], false
4488
+        ];
4489
+
4490
+        $share = [
4491
+            'type' => IShare::TYPE_REMOTE,
4492
+            'owner' => 'owner',
4493
+            'sharedWith' => '[email protected]',
4494
+            'node' => $folder,
4495
+            'note' => 'personal note',
4496
+            'expirationDate' => new \DateTime('2001-02-03T04:05:06'),
4497
+        ];
4498
+
4499
+        $result[] = [
4500
+            [
4501
+                'id' => '42',
4502
+                'share_type' => IShare::TYPE_REMOTE,
4503
+                'uid_owner' => 'initiator',
4504
+                'displayname_owner' => 'initiator',
4505
+                'permissions' => 1,
4506
+                'stime' => 946684862,
4507
+                'parent' => null,
4508
+                'expiration' => '2001-02-03 00:00:00',
4509
+                'token' => null,
4510
+                'uid_file_owner' => 'owner',
4511
+                'displayname_file_owner' => 'owner',
4512
+                'note' => 'personal note',
4513
+                'label' => '',
4514
+                'path' => 'folder',
4515
+                'item_type' => 'folder',
4516
+                'storage_id' => 'storageId',
4517
+                'storage' => 100,
4518
+                'item_source' => 2,
4519
+                'file_source' => 2,
4520
+                'file_parent' => 1,
4521
+                'file_target' => 'myTarget',
4522
+                'share_with' => '[email protected]',
4523
+                'share_with_displayname' => 'foobar',
4524
+                'mail_send' => 0,
4525
+                'mimetype' => 'myFolderMimeType',
4526
+                'has_preview' => false,
4527
+                'hide_download' => 0,
4528
+                'can_edit' => false,
4529
+                'can_delete' => false,
4530
+                'item_size' => 123456,
4531
+                'item_mtime' => 1234567890,
4532
+                'is-mount-root' => false,
4533
+                'mount-type' => '',
4534
+                'attributes' => null,
4535
+                'item_permissions' => 1,
4536
+                'is_trusted_server' => false,
4537
+            ], $share, [], false
4538
+        ];
4539
+
4540
+        $share = [
4541
+            'type' => IShare::TYPE_REMOTE_GROUP,
4542
+            'owner' => 'owner',
4543
+            'sharedWith' => '[email protected]',
4544
+            'node' => $folder,
4545
+            'note' => 'personal note',
4546
+            'expirationDate' => new \DateTime('2001-02-03T04:05:06'),
4547
+        ];
4548
+
4549
+        $result[] = [
4550
+            [
4551
+                'id' => '42',
4552
+                'share_type' => IShare::TYPE_REMOTE_GROUP,
4553
+                'uid_owner' => 'initiator',
4554
+                'displayname_owner' => 'initiator',
4555
+                'permissions' => 1,
4556
+                'stime' => 946684862,
4557
+                'parent' => null,
4558
+                'expiration' => '2001-02-03 00:00:00',
4559
+                'token' => null,
4560
+                'uid_file_owner' => 'owner',
4561
+                'displayname_file_owner' => 'owner',
4562
+                'note' => 'personal note',
4563
+                'label' => '',
4564
+                'path' => 'folder',
4565
+                'item_type' => 'folder',
4566
+                'storage_id' => 'storageId',
4567
+                'storage' => 100,
4568
+                'item_source' => 2,
4569
+                'file_source' => 2,
4570
+                'file_parent' => 1,
4571
+                'file_target' => 'myTarget',
4572
+                'share_with' => '[email protected]',
4573
+                'share_with_displayname' => 'foobar',
4574
+                'mail_send' => 0,
4575
+                'mimetype' => 'myFolderMimeType',
4576
+                'has_preview' => false,
4577
+                'hide_download' => 0,
4578
+                'can_edit' => false,
4579
+                'can_delete' => false,
4580
+                'item_size' => 123456,
4581
+                'item_mtime' => 1234567890,
4582
+                'is-mount-root' => false,
4583
+                'mount-type' => '',
4584
+                'attributes' => null,
4585
+                'item_permissions' => 1,
4586
+                'is_trusted_server' => false,
4587
+            ], $share, [], false
4588
+        ];
4589
+
4590
+        // Circle with id, display name and avatar set by the Circles app
4591
+        $share = [
4592
+            'type' => IShare::TYPE_CIRCLE,
4593
+            'owner' => 'owner',
4594
+            'sharedWith' => 'Circle (Public circle, circleOwner) [4815162342]',
4595
+            'sharedWithDisplayName' => 'The display name',
4596
+            'sharedWithAvatar' => 'path/to/the/avatar',
4597
+            'node' => $folder,
4598
+        ];
4599
+
4600
+        $result[] = [
4601
+            [
4602
+                'id' => '42',
4603
+                'share_type' => IShare::TYPE_CIRCLE,
4604
+                'uid_owner' => 'initiator',
4605
+                'displayname_owner' => 'initiator',
4606
+                'permissions' => 1,
4607
+                'attributes' => null,
4608
+                'stime' => 946684862,
4609
+                'parent' => null,
4610
+                'expiration' => null,
4611
+                'token' => null,
4612
+                'uid_file_owner' => 'owner',
4613
+                'displayname_file_owner' => 'owner',
4614
+                'note' => '',
4615
+                'label' => '',
4616
+                'path' => 'folder',
4617
+                'item_type' => 'folder',
4618
+                'storage_id' => 'storageId',
4619
+                'storage' => 100,
4620
+                'item_source' => 2,
4621
+                'file_source' => 2,
4622
+                'file_parent' => 1,
4623
+                'file_target' => 'myTarget',
4624
+                'share_with' => '4815162342',
4625
+                'share_with_displayname' => 'The display name',
4626
+                'share_with_avatar' => 'path/to/the/avatar',
4627
+                'mail_send' => 0,
4628
+                'mimetype' => 'myFolderMimeType',
4629
+                'has_preview' => false,
4630
+                'hide_download' => 0,
4631
+                'can_edit' => false,
4632
+                'can_delete' => false,
4633
+                'item_size' => 123456,
4634
+                'item_mtime' => 1234567890,
4635
+                'is-mount-root' => false,
4636
+                'mount-type' => '',
4637
+                'attributes' => null,
4638
+                'item_permissions' => 1,
4639
+            ], $share, [], false
4640
+        ];
4641
+
4642
+        // Circle with id set by the Circles app
4643
+        $share = [
4644
+            'type' => IShare::TYPE_CIRCLE,
4645
+            'owner' => 'owner',
4646
+            'sharedWith' => 'Circle (Public circle, circleOwner) [4815162342]',
4647
+            'node' => $folder,
4648
+        ];
4649
+
4650
+        $result[] = [
4651
+            [
4652
+                'id' => '42',
4653
+                'share_type' => IShare::TYPE_CIRCLE,
4654
+                'uid_owner' => 'initiator',
4655
+                'displayname_owner' => 'initiator',
4656
+                'permissions' => 1,
4657
+                'stime' => 946684862,
4658
+                'parent' => null,
4659
+                'expiration' => null,
4660
+                'token' => null,
4661
+                'uid_file_owner' => 'owner',
4662
+                'displayname_file_owner' => 'owner',
4663
+                'note' => '',
4664
+                'label' => '',
4665
+                'path' => 'folder',
4666
+                'item_type' => 'folder',
4667
+                'storage_id' => 'storageId',
4668
+                'storage' => 100,
4669
+                'item_source' => 2,
4670
+                'file_source' => 2,
4671
+                'file_parent' => 1,
4672
+                'file_target' => 'myTarget',
4673
+                'share_with' => '4815162342',
4674
+                'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4675
+                'share_with_avatar' => '',
4676
+                'mail_send' => 0,
4677
+                'mimetype' => 'myFolderMimeType',
4678
+                'has_preview' => false,
4679
+                'hide_download' => 0,
4680
+                'can_edit' => false,
4681
+                'can_delete' => false,
4682
+                'item_size' => 123456,
4683
+                'item_mtime' => 1234567890,
4684
+                'is-mount-root' => false,
4685
+                'mount-type' => '',
4686
+                'attributes' => null,
4687
+                'item_permissions' => 1,
4688
+            ], $share, [], false
4689
+        ];
4690
+
4691
+        // Circle with id not set by the Circles app
4692
+        $share = [
4693
+            'type' => IShare::TYPE_CIRCLE,
4694
+            'owner' => 'owner',
4695
+            'sharedWith' => 'Circle (Public circle, circleOwner)',
4696
+            'node' => $folder,
4697
+        ];
4698
+
4699
+        $result[] = [
4700
+            [
4701
+                'id' => '42',
4702
+                'share_type' => IShare::TYPE_CIRCLE,
4703
+                'uid_owner' => 'initiator',
4704
+                'displayname_owner' => 'initiator',
4705
+                'permissions' => 1,
4706
+                'stime' => 946684862,
4707
+                'parent' => null,
4708
+                'expiration' => null,
4709
+                'token' => null,
4710
+                'uid_file_owner' => 'owner',
4711
+                'displayname_file_owner' => 'owner',
4712
+                'note' => '',
4713
+                'label' => '',
4714
+                'path' => 'folder',
4715
+                'item_type' => 'folder',
4716
+                'storage_id' => 'storageId',
4717
+                'storage' => 100,
4718
+                'item_source' => 2,
4719
+                'file_source' => 2,
4720
+                'file_parent' => 1,
4721
+                'file_target' => 'myTarget',
4722
+                'share_with' => 'Circle',
4723
+                'share_with_displayname' => 'Circle (Public circle, circleOwner)',
4724
+                'share_with_avatar' => '',
4725
+                'mail_send' => 0,
4726
+                'mimetype' => 'myFolderMimeType',
4727
+                'has_preview' => false,
4728
+                'hide_download' => 0,
4729
+                'can_edit' => false,
4730
+                'can_delete' => false,
4731
+                'item_size' => 123456,
4732
+                'item_mtime' => 1234567890,
4733
+                'is-mount-root' => false,
4734
+                'mount-type' => '',
4735
+                'attributes' => null,
4736
+                'item_permissions' => 1,
4737
+            ], $share, [], false
4738
+        ];
4739
+
4740
+        // No node
4741
+        $share = [
4742
+            'type' => IShare::TYPE_USER,
4743
+            'owner' => 'owner',
4744
+            'sharedWith' => 'recipient',
4745
+            'note' => 'personal note',
4746
+        ];
4747
+
4748
+        $result[] = [
4749
+            [], $share, [], true
4750
+        ];
4751
+
4752
+        $share = [
4753
+            'type' => IShare::TYPE_EMAIL,
4754
+            'owner' => 'owner',
4755
+            'sharedWith' => '[email protected]',
4756
+            'node' => $folder,
4757
+            'password' => 'password',
4758
+        ];
4759
+
4760
+        $result[] = [
4761
+            [
4762
+                'id' => '42',
4763
+                'share_type' => IShare::TYPE_EMAIL,
4764
+                'uid_owner' => 'initiator',
4765
+                'displayname_owner' => 'initiator',
4766
+                'permissions' => 1,
4767
+                'stime' => 946684862,
4768
+                'parent' => null,
4769
+                'expiration' => null,
4770
+                'token' => null,
4771
+                'uid_file_owner' => 'owner',
4772
+                'displayname_file_owner' => 'owner',
4773
+                'note' => '',
4774
+                'label' => '',
4775
+                'path' => 'folder',
4776
+                'item_type' => 'folder',
4777
+                'storage_id' => 'storageId',
4778
+                'storage' => 100,
4779
+                'item_source' => 2,
4780
+                'file_source' => 2,
4781
+                'file_parent' => 1,
4782
+                'file_target' => 'myTarget',
4783
+                'share_with' => '[email protected]',
4784
+                'share_with_displayname' => 'mail display name',
4785
+                'mail_send' => 0,
4786
+                'mimetype' => 'myFolderMimeType',
4787
+                'has_preview' => false,
4788
+                'password' => 'password',
4789
+                'send_password_by_talk' => false,
4790
+                'hide_download' => 0,
4791
+                'can_edit' => false,
4792
+                'can_delete' => false,
4793
+                'password_expiration_time' => null,
4794
+                'item_size' => 123456,
4795
+                'item_mtime' => 1234567890,
4796
+                'is-mount-root' => false,
4797
+                'mount-type' => '',
4798
+                'attributes' => null,
4799
+                'item_permissions' => 1,
4800
+            ], $share, [], false
4801
+        ];
4802
+
4803
+        $share['sendPasswordByTalk'] = true;
4804
+
4805
+        $result[] = [
4806
+            [
4807
+                'id' => '42',
4808
+                'share_type' => IShare::TYPE_EMAIL,
4809
+                'uid_owner' => 'initiator',
4810
+                'displayname_owner' => 'initiator',
4811
+                'permissions' => 1,
4812
+                'stime' => 946684862,
4813
+                'parent' => null,
4814
+                'expiration' => null,
4815
+                'token' => null,
4816
+                'uid_file_owner' => 'owner',
4817
+                'displayname_file_owner' => 'owner',
4818
+                'note' => '',
4819
+                'label' => '',
4820
+                'path' => 'folder',
4821
+                'item_type' => 'folder',
4822
+                'storage_id' => 'storageId',
4823
+                'storage' => 100,
4824
+                'item_source' => 2,
4825
+                'file_source' => 2,
4826
+                'file_parent' => 1,
4827
+                'file_target' => 'myTarget',
4828
+                'share_with' => '[email protected]',
4829
+                'share_with_displayname' => 'mail display name',
4830
+                'mail_send' => 0,
4831
+                'mimetype' => 'myFolderMimeType',
4832
+                'has_preview' => false,
4833
+                'password' => 'password',
4834
+                'send_password_by_talk' => true,
4835
+                'hide_download' => 0,
4836
+                'can_edit' => false,
4837
+                'can_delete' => false,
4838
+                'password_expiration_time' => null,
4839
+                'item_size' => 123456,
4840
+                'item_mtime' => 1234567890,
4841
+                'is-mount-root' => false,
4842
+                'mount-type' => '',
4843
+                'attributes' => null,
4844
+                'item_permissions' => 1,
4845
+            ], $share, [], false
4846
+        ];
4847
+
4848
+        // Preview is available
4849
+        $share = [
4850
+            'type' => IShare::TYPE_USER,
4851
+            'owner' => 'currentUser',
4852
+            'sharedWith' => 'recipient',
4853
+            'node' => $fileWithPreview,
4854
+            'note' => 'personal note',
4855
+        ];
4856
+
4857
+        $result[] = [
4858
+            [
4859
+                'id' => '42',
4860
+                'share_type' => IShare::TYPE_USER,
4861
+                'uid_owner' => 'initiator',
4862
+                'displayname_owner' => 'initiator',
4863
+                'permissions' => 1,
4864
+                'stime' => 946684862,
4865
+                'parent' => null,
4866
+                'expiration' => null,
4867
+                'token' => null,
4868
+                'uid_file_owner' => 'currentUser',
4869
+                'displayname_file_owner' => 'currentUser',
4870
+                'note' => 'personal note',
4871
+                'label' => '',
4872
+                'path' => 'fileWithPreview',
4873
+                'item_type' => 'file',
4874
+                'storage_id' => 'storageId',
4875
+                'storage' => 100,
4876
+                'item_source' => 4,
4877
+                'file_source' => 4,
4878
+                'file_parent' => 1,
4879
+                'file_target' => 'myTarget',
4880
+                'share_with' => 'recipient',
4881
+                'share_with_displayname' => 'recipient',
4882
+                'share_with_displayname_unique' => 'recipient',
4883
+                'mail_send' => 0,
4884
+                'mimetype' => 'mimeWithPreview',
4885
+                'has_preview' => true,
4886
+                'hide_download' => 0,
4887
+                'can_edit' => true,
4888
+                'can_delete' => true,
4889
+                'item_size' => 123456,
4890
+                'item_mtime' => 1234567890,
4891
+                'is-mount-root' => false,
4892
+                'mount-type' => '',
4893
+                'attributes' => null,
4894
+                'item_permissions' => 11,
4895
+            ], $share, [], false
4896
+        ];
4897
+
4898
+        return $result;
4899
+    }
4900
+
4901
+    #[DataProvider(methodName: 'dataFormatShare')]
4902
+    public function testFormatShare(
4903
+        array $expects,
4904
+        array $shareParams,
4905
+        array $users,
4906
+        bool $exception,
4907
+    ): void {
4908
+        $users = array_map(
4909
+            function ($user) {
4910
+                $mock = $this->createMock(IUser::class);
4911
+                foreach ($user[1] as $method => $return) {
4912
+                    $mock->method($method)->willReturn($return);
4913
+                }
4914
+                return [$user[0],$mock];
4915
+            },
4916
+            $users
4917
+        );
4918
+
4919
+        $share = Server::get(IManager::class)->newShare();
4920
+        $share->setShareType($shareParams['type'])
4921
+            ->setSharedBy('initiator')
4922
+            ->setShareOwner($shareParams['owner'])
4923
+            ->setPermissions(Constants::PERMISSION_READ)
4924
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
4925
+            ->setTarget('myTarget')
4926
+            ->setId(42);
4927
+        if (isset($shareParams['sharedWith'])) {
4928
+            $share->setSharedWith($shareParams['sharedWith']);
4929
+        }
4930
+        if (isset($shareParams['sharedWithDisplayName'])) {
4931
+            $share->setSharedWithDisplayName($shareParams['sharedWithDisplayName']);
4932
+        }
4933
+        if (isset($shareParams['sharedWithAvatar'])) {
4934
+            $share->setSharedWithAvatar($shareParams['sharedWithAvatar']);
4935
+        }
4936
+        if (isset($shareParams['attributes'])) {
4937
+            $shareAttributes = $this->createMock(IShareAttributes::class);
4938
+            $shareAttributes->method('toArray')->willReturn($shareParams['attributes']);
4939
+            $shareAttributes->method('getAttribute')->with('permissions', 'download')->willReturn(true);
4940
+            $share->setAttributes($shareAttributes);
4941
+
4942
+            $expects['attributes'] = \json_encode($shareParams['attributes']);
4943
+        }
4944
+        if (isset($shareParams['node'])) {
4945
+            $node = $this->createMock($shareParams['node']['class']);
4946
+
4947
+            $node->method('getMimeType')->willReturn($shareParams['node']['mimeType']);
4948
+
4949
+            $mountPoint = $this->createMock(IMountPoint::class);
4950
+            $mountPoint->method('getMountType')->willReturn('');
4951
+            $node->method('getMountPoint')->willReturn($mountPoint);
4952
+
4953
+            $node->method('getPath')->willReturn($shareParams['node']['path']);
4954
+            $node->method('getId')->willReturn($shareParams['node']['id']);
4955
+
4956
+            $parent = $this->createMock(Folder::class);
4957
+            $parent->method('getId')->willReturn(1);
4958
+            $node->method('getParent')->willReturn($parent);
4959
+
4960
+            $node->method('getSize')->willReturn(123456);
4961
+            $node->method('getMTime')->willReturn(1234567890);
4962
+
4963
+            $cache = $this->createMock(ICache::class);
4964
+            $cache->method('getNumericStorageId')->willReturn(100);
4965
+            $storage = $this->createMock(IStorage::class);
4966
+            $storage->method('getId')->willReturn('storageId');
4967
+            $storage->method('getCache')->willReturn($cache);
4968
+
4969
+            $node->method('getStorage')->willReturn($storage);
4970
+
4971
+            $share->setNode($node);
4972
+        }
4973
+        if (isset($shareParams['note'])) {
4974
+            $share->setNote($shareParams['note']);
4975
+        }
4976
+        if (isset($shareParams['expirationDate'])) {
4977
+            $share->setExpirationDate($shareParams['expirationDate']);
4978
+        }
4979
+        if (isset($shareParams['token'])) {
4980
+            $share->setToken($shareParams['token']);
4981
+        }
4982
+        if (isset($shareParams['label'])) {
4983
+            $share->setLabel($shareParams['label']);
4984
+        }
4985
+        if (isset($shareParams['password'])) {
4986
+            $share->setPassword($shareParams['password']);
4987
+        }
4988
+        if (isset($shareParams['sendPasswordByTalk'])) {
4989
+            $share->setSendPasswordByTalk($shareParams['sendPasswordByTalk']);
4990
+        }
4991
+
4992
+        $this->userManager->method('get')->willReturnMap($users);
4993
+
4994
+        $recipientGroup = $this->createMock(IGroup::class);
4995
+        $recipientGroup->method('getDisplayName')->willReturn('recipientGroupDisplayName');
4996
+        $this->groupManager->method('get')->willReturnMap([
4997
+            ['recipientGroup', $recipientGroup],
4998
+        ]);
4999
+
5000
+        $this->urlGenerator->method('linkToRouteAbsolute')
5001
+            ->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken'])
5002
+            ->willReturn('myLink');
5003
+
5004
+        $this->rootFolder->method('getUserFolder')
5005
+            ->with($this->currentUser)
5006
+            ->willReturnSelf();
5007
+        $this->dateTimeZone->method('getTimezone')->willReturn(new \DateTimeZone('UTC'));
5008
+
5009
+        if (!$exception) {
5010
+            $this->rootFolder->method('getFirstNodeById')
5011
+                ->with($share->getNodeId())
5012
+                ->willReturn($share->getNode());
5013
+
5014
+            $this->rootFolder->method('getRelativePath')
5015
+                ->with($share->getNode()->getPath())
5016
+                ->willReturnArgument(0);
5017
+        }
5018
+
5019
+        $cm = $this->createMock(\OCP\Contacts\IManager::class);
5020
+        $this->overwriteService(\OCP\Contacts\IManager::class, $cm);
5021
+
5022
+        $cm->method('search')
5023
+            ->willReturnMap([
5024
+                ['[email protected]', ['CLOUD'], [
5025
+                    'limit' => 1,
5026
+                    'enumeration' => false,
5027
+                    'strict_search' => true,
5028
+                ],
5029
+                    [
5030
+                        [
5031
+                            'CLOUD' => [
5032
+                                '[email protected]',
5033
+                            ],
5034
+                            'FN' => 'foobar',
5035
+                        ],
5036
+                    ],
5037
+                ],
5038
+                ['[email protected]', ['EMAIL'], [
5039
+                    'limit' => 1,
5040
+                    'enumeration' => false,
5041
+                    'strict_search' => true,
5042
+                ],
5043
+                    [
5044
+                        [
5045
+                            'EMAIL' => [
5046
+                                '[email protected]',
5047
+                            ],
5048
+                            'FN' => 'mail display name',
5049
+                        ],
5050
+                    ],
5051
+                ],
5052
+            ]);
5053
+
5054
+        try {
5055
+            $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5056
+            $this->assertFalse($exception);
5057
+            $this->assertEquals($expects, $result);
5058
+        } catch (NotFoundException $e) {
5059
+            $this->assertTrue($exception);
5060
+        }
5061
+    }
5062
+
5063
+    public static function dataFormatRoomShare(): array {
5064
+        $result = [];
5065
+
5066
+        $result[] = [
5067
+            [
5068
+                'id' => '42',
5069
+                'share_type' => IShare::TYPE_ROOM,
5070
+                'uid_owner' => 'initiator',
5071
+                'displayname_owner' => 'initiator',
5072
+                'permissions' => 1,
5073
+                'stime' => 946684862,
5074
+                'parent' => null,
5075
+                'expiration' => null,
5076
+                'token' => null,
5077
+                'uid_file_owner' => 'owner',
5078
+                'displayname_file_owner' => 'owner',
5079
+                'note' => 'personal note',
5080
+                'path' => 'file',
5081
+                'item_type' => 'file',
5082
+                'storage_id' => 'storageId',
5083
+                'storage' => 100,
5084
+                'item_source' => 3,
5085
+                'file_source' => 3,
5086
+                'file_parent' => 1,
5087
+                'file_target' => 'myTarget',
5088
+                'share_with' => 'recipientRoom',
5089
+                'share_with_displayname' => '',
5090
+                'mail_send' => 0,
5091
+                'mimetype' => 'myMimeType',
5092
+                'has_preview' => false,
5093
+                'hide_download' => 0,
5094
+                'label' => '',
5095
+                'can_edit' => false,
5096
+                'can_delete' => false,
5097
+                'item_size' => 123456,
5098
+                'item_mtime' => 1234567890,
5099
+                'is-mount-root' => false,
5100
+                'mount-type' => '',
5101
+                'attributes' => null,
5102
+                'item_permissions' => 1,
5103
+            ], false, []
5104
+        ];
5105
+
5106
+        $result[] = [
5107
+            [
5108
+                'id' => '42',
5109
+                'share_type' => IShare::TYPE_ROOM,
5110
+                'uid_owner' => 'initiator',
5111
+                'displayname_owner' => 'initiator',
5112
+                'permissions' => 1,
5113
+                'stime' => 946684862,
5114
+                'parent' => null,
5115
+                'expiration' => null,
5116
+                'token' => null,
5117
+                'uid_file_owner' => 'owner',
5118
+                'displayname_file_owner' => 'owner',
5119
+                'note' => 'personal note',
5120
+                'path' => 'file',
5121
+                'item_type' => 'file',
5122
+                'storage_id' => 'storageId',
5123
+                'storage' => 100,
5124
+                'item_source' => 3,
5125
+                'file_source' => 3,
5126
+                'file_parent' => 1,
5127
+                'file_target' => 'myTarget',
5128
+                'share_with' => 'recipientRoom',
5129
+                'share_with_displayname' => 'recipientRoomName',
5130
+                'mail_send' => 0,
5131
+                'mimetype' => 'myMimeType',
5132
+                'has_preview' => false,
5133
+                'hide_download' => 0,
5134
+                'label' => '',
5135
+                'can_edit' => false,
5136
+                'can_delete' => false,
5137
+                'item_size' => 123456,
5138
+                'item_mtime' => 1234567890,
5139
+                'is-mount-root' => false,
5140
+                'mount-type' => '',
5141
+                'attributes' => null,
5142
+                'item_permissions' => 9,
5143
+            ], true, [
5144
+                'share_with_displayname' => 'recipientRoomName'
5145
+            ]
5146
+        ];
5147
+
5148
+        return $result;
5149
+    }
5150
+
5151
+    /**
5152
+     *
5153
+     * @param array $expects
5154
+     * @param IShare $share
5155
+     * @param bool $helperAvailable
5156
+     * @param array $formatShareByHelper
5157
+     */
5158
+    #[DataProvider(methodName: 'dataFormatRoomShare')]
5159
+    public function testFormatRoomShare(array $expects, bool $helperAvailable, array $formatShareByHelper): void {
5160
+        $file = $this->createMock(File::class);
5161
+
5162
+        $file->method('getMimeType')->willReturn('myMimeType');
5163
+        $file->method('getPath')->willReturn('file');
5164
+        $file->method('getId')->willReturn(3);
5165
+
5166
+        $parent = $this->createMock(Folder::class);
5167
+        $parent->method('getId')->willReturn(1);
5168
+        $file->method('getParent')->willReturn($parent);
5169
+
5170
+        $file->method('getSize')->willReturn(123456);
5171
+        $file->method('getMTime')->willReturn(1234567890);
5172
+
5173
+        $mountPoint = $this->createMock(IMountPoint::class);
5174
+        $mountPoint->method('getMountType')->willReturn('');
5175
+        $file->method('getMountPoint')->willReturn($mountPoint);
5176
+
5177
+        $cache = $this->createMock(ICache::class);
5178
+        $cache->method('getNumericStorageId')->willReturn(100);
5179
+        $storage = $this->createMock(IStorage::class);
5180
+        $storage->method('getId')->willReturn('storageId');
5181
+        $storage->method('getCache')->willReturn($cache);
5182
+
5183
+        $file->method('getStorage')->willReturn($storage);
5184
+
5185
+        $share = Server::get(IManager::class)->newShare();
5186
+        $share->setShareType(IShare::TYPE_ROOM)
5187
+            ->setSharedWith('recipientRoom')
5188
+            ->setSharedBy('initiator')
5189
+            ->setShareOwner('owner')
5190
+            ->setPermissions(Constants::PERMISSION_READ)
5191
+            ->setNode($file)
5192
+            ->setShareTime(new \DateTime('2000-01-01T00:01:02'))
5193
+            ->setTarget('myTarget')
5194
+            ->setNote('personal note')
5195
+            ->setId(42);
5196
+
5197
+        $this->rootFolder->method('getUserFolder')
5198
+            ->with($this->currentUser)
5199
+            ->willReturnSelf();
5200
+
5201
+        $this->rootFolder->method('getFirstNodeById')
5202
+            ->with($share->getNodeId())
5203
+            ->willReturn($share->getNode());
5204
+
5205
+        $this->rootFolder->method('getRelativePath')
5206
+            ->with($share->getNode()->getPath())
5207
+            ->willReturnArgument(0);
5208
+
5209
+        if (!$helperAvailable) {
5210
+            $this->appManager->method('isEnabledForUser')
5211
+                ->with('spreed')
5212
+                ->willReturn(false);
5213
+        } else {
5214
+            $this->appManager->method('isEnabledForUser')
5215
+                ->with('spreed')
5216
+                ->willReturn(true);
5217
+
5218
+            // This is not possible anymore with PHPUnit 10+
5219
+            // as `setMethods` was removed and now real reflection is used, thus the class needs to exist.
5220
+            // $helper = $this->getMockBuilder('\OCA\Talk\Share\Helper\ShareAPIController')
5221
+            $helper = $this->getMockBuilder(\stdClass::class)
5222
+                ->addMethods(['formatShare', 'canAccessShare'])
5223
+                ->getMock();
5224
+            $helper->method('formatShare')
5225
+                ->with($share)
5226
+                ->willReturn($formatShareByHelper);
5227
+            $helper->method('canAccessShare')
5228
+                ->with($share)
5229
+                ->willReturn(true);
5230
+
5231
+            $this->serverContainer->method('get')
5232
+                ->with('\OCA\Talk\Share\Helper\ShareAPIController')
5233
+                ->willReturn($helper);
5234
+        }
5235
+
5236
+        $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5237
+        $this->assertEquals($expects, $result);
5238
+    }
5239
+
5240
+    /**
5241
+     * @return list{Folder, Folder}
5242
+     */
5243
+    private function getNonSharedUserFolder(): array {
5244
+        $node = $this->getMockBuilder(Folder::class)->getMock();
5245
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
5246
+        $storage = $this->createMock(IStorage::class);
5247
+        $storage->method('instanceOfStorage')
5248
+            ->willReturnMap([
5249
+                ['OCA\Files_Sharing\External\Storage', false],
5250
+                ['OCA\Files_Sharing\SharedStorage', false],
5251
+            ]);
5252
+        $userFolder->method('getStorage')->willReturn($storage);
5253
+        $node->method('getStorage')->willReturn($storage);
5254
+        $node->method('getId')->willReturn(42);
5255
+        $user = $this->createMock(IUser::class);
5256
+        $user->method('getUID')->willReturn($this->currentUser);
5257
+        $node->method('getOwner')->willReturn($user);
5258
+        return [$userFolder, $node];
5259
+    }
5260
+
5261
+    /**
5262
+     * @return list{Folder, File}
5263
+     */
5264
+    private function getNonSharedUserFile(): array {
5265
+        $node = $this->getMockBuilder(File::class)->getMock();
5266
+        $userFolder = $this->getMockBuilder(Folder::class)->getMock();
5267
+        $storage = $this->createMock(IStorage::class);
5268
+        $storage->method('instanceOfStorage')
5269
+            ->willReturnMap([
5270
+                ['OCA\Files_Sharing\External\Storage', false],
5271
+                ['OCA\Files_Sharing\SharedStorage', false],
5272
+            ]);
5273
+        $userFolder->method('getStorage')->willReturn($storage);
5274
+        $node->method('getStorage')->willReturn($storage);
5275
+        $node->method('getId')->willReturn(42);
5276
+        return [$userFolder, $node];
5277
+    }
5278
+
5279
+    public function testPopulateTags(): void {
5280
+        $tagger = $this->createMock(ITags::class);
5281
+        $this->tagManager->method('load')
5282
+            ->with('files')
5283
+            ->willReturn($tagger);
5284
+        $data = [
5285
+            ['file_source' => 10],
5286
+            ['file_source' => 22, 'foo' => 'bar'],
5287
+            ['file_source' => 42, 'x' => 'y'],
5288
+        ];
5289
+        $tags = [
5290
+            10 => ['tag3'],
5291
+            42 => ['tag1', 'tag2'],
5292
+        ];
5293
+        $tagger->method('getTagsForObjects')
5294
+            ->with([10, 22, 42])
5295
+            ->willReturn($tags);
5296
+
5297
+        $result = self::invokePrivate($this->ocs, 'populateTags', [$data]);
5298
+        $this->assertSame([
5299
+            ['file_source' => 10, 'tags' => ['tag3']],
5300
+            ['file_source' => 22, 'foo' => 'bar', 'tags' => []],
5301
+            ['file_source' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']],
5302
+        ], $result);
5303
+    }
5304
+
5305
+    public static function trustedServerProvider(): array {
5306
+        return [
5307
+            'Trusted server' => [true, true],
5308
+            'Untrusted server' => [false, false],
5309
+        ];
5310
+    }
5311
+
5312
+    #[DataProvider(methodName: 'trustedServerProvider')]
5313
+    public function testFormatShareWithFederatedShare(bool $isKnownServer, bool $isTrusted): void {
5314
+        $nodeId = 12;
5315
+        $nodePath = '/test.txt';
5316
+
5317
+        $node = $this->createMock(File::class);
5318
+        $node->method('getId')->willReturn($nodeId);
5319
+        $node->method('getPath')->willReturn($nodePath);
5320
+        $node->method('getInternalPath')->willReturn(ltrim($nodePath, '/'));
5321
+        $mountPoint = $this->createMock(IMountPoint::class);
5322
+        $mountPoint->method('getMountType')->willReturn('local');
5323
+        $node->method('getMountPoint')->willReturn($mountPoint);
5324
+        $node->method('getMimetype')->willReturn('text/plain');
5325
+        $storage = $this->createMock(IStorage::class);
5326
+        $storageCache = $this->createMock(ICache::class);
5327
+        $storageCache->method('getNumericStorageId')->willReturn(1);
5328
+        $storage->method('getCache')->willReturn($storageCache);
5329
+        $storage->method('getId')->willReturn('home::shareOwner');
5330
+        $node->method('getStorage')->willReturn($storage);
5331
+        $parent = $this->createMock(Folder::class);
5332
+        $parent->method('getId')->willReturn(2);
5333
+        $node->method('getParent')->willReturn($parent);
5334
+        $node->method('getSize')->willReturn(1234);
5335
+        $node->method('getMTime')->willReturn(1234567890);
5336
+
5337
+        $share = $this->createShare(
5338
+            1,
5339
+            IShare::TYPE_REMOTE,
5340
+            '[email protected]', // shared with
5341
+            '[email protected]',      // shared by
5342
+            'shareOwner',                 // share owner
5343
+            $node,
5344
+            Constants::PERMISSION_READ,
5345
+            time(),
5346
+            null,
5347
+            2,
5348
+            $nodePath,
5349
+            $nodeId
5350
+        );
5351
+
5352
+        $this->previewManager->method('isAvailable')->with($node)->willReturn(false);
5353
+
5354
+        $this->rootFolder->method('getUserFolder')
5355
+            ->with($this->currentUser)
5356
+            ->willReturnSelf();
5357
+
5358
+        $this->rootFolder->method('getFirstNodeById')
5359
+            ->with($share->getNodeId())
5360
+            ->willReturn($node);
5361
+
5362
+        $this->rootFolder->method('getRelativePath')
5363
+            ->with($node->getPath())
5364
+            ->willReturnArgument(0);
5365
+
5366
+        $serverName = 'remoteserver.com';
5367
+        $this->trustedServers->method('isTrustedServer')
5368
+            ->with($serverName)
5369
+            ->willReturn($isKnownServer);
5370
+
5371
+        $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5372
+
5373
+        $this->assertSame($isTrusted, $result['is_trusted_server']);
5374
+    }
5375
+
5376
+    public function testFormatShareWithFederatedShareWithAtInUsername(): void {
5377
+        $nodeId = 12;
5378
+        $nodePath = '/test.txt';
5379
+
5380
+        $node = $this->createMock(File::class);
5381
+        $node->method('getId')->willReturn($nodeId);
5382
+        $node->method('getPath')->willReturn($nodePath);
5383
+        $node->method('getInternalPath')->willReturn(ltrim($nodePath, '/'));
5384
+        $mountPoint = $this->createMock(IMountPoint::class);
5385
+        $mountPoint->method('getMountType')->willReturn('local');
5386
+        $node->method('getMountPoint')->willReturn($mountPoint);
5387
+        $node->method('getMimetype')->willReturn('text/plain');
5388
+        $storage = $this->createMock(IStorage::class);
5389
+        $storageCache = $this->createMock(ICache::class);
5390
+        $storageCache->method('getNumericStorageId')->willReturn(1);
5391
+        $storage->method('getCache')->willReturn($storageCache);
5392
+        $storage->method('getId')->willReturn('home::shareOwner');
5393
+        $node->method('getStorage')->willReturn($storage);
5394
+        $parent = $this->createMock(Folder::class);
5395
+        $parent->method('getId')->willReturn(2);
5396
+        $node->method('getParent')->willReturn($parent);
5397
+        $node->method('getSize')->willReturn(1234);
5398
+        $node->method('getMTime')->willReturn(1234567890);
5399
+
5400
+        $share = $this->createShare(
5401
+            1,
5402
+            IShare::TYPE_REMOTE,
5403
+            '[email protected]@remoteserver.com',
5404
+            '[email protected]',
5405
+            'shareOwner',
5406
+            $node,
5407
+            Constants::PERMISSION_READ,
5408
+            time(),
5409
+            null,
5410
+            2,
5411
+            $nodePath,
5412
+            $nodeId
5413
+        );
5414
+
5415
+        $this->previewManager->method('isAvailable')->with($node)->willReturn(false);
5416
+
5417
+        $this->rootFolder->method('getUserFolder')
5418
+            ->with($this->currentUser)
5419
+            ->willReturnSelf();
5420
+
5421
+        $this->rootFolder->method('getFirstNodeById')
5422
+            ->with($share->getNodeId())
5423
+            ->willReturn($node);
5424
+
5425
+        $this->rootFolder->method('getRelativePath')
5426
+            ->with($node->getPath())
5427
+            ->willReturnArgument(0);
5428
+
5429
+        $serverName = 'remoteserver.com';
5430
+        $this->trustedServers->method('isTrustedServer')
5431
+            ->with($serverName)
5432
+            ->willReturn(true);
5433
+
5434
+        $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]);
5435
+
5436
+        $this->assertTrue($result['is_trusted_server']);
5437
+    }
5438
+
5439
+    public function testOwnerCanAlwaysDownload(): void {
5440
+        $ocs = $this->mockFormatShare();
5441
+
5442
+        $share = $this->createMock(IShare::class);
5443
+        $node = $this->createMock(File::class);
5444
+        $userFolder = $this->createMock(Folder::class);
5445
+        $owner = $this->createMock(IUser::class);
5446
+
5447
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5448
+        $share->method('getNodeId')->willReturn(42);
5449
+        $node->method('getOwner')->willReturn($owner);
5450
+        $owner->method('getUID')->willReturn('sharedByUser');
5451
+
5452
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5453
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5454
+
5455
+        // Expect hideDownload to be set to false since owner can always download
5456
+        $share->expects($this->once())->method('setHideDownload')->with(false);
5457
+
5458
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5459
+    }
5460
+
5461
+    public function testParentHideDownloadEnforcedOnChild(): void {
5462
+        $ocs = $this->mockFormatShare();
5463
+
5464
+        $share = $this->createMock(IShare::class);
5465
+        $node = $this->createMock(File::class);
5466
+        $userFolder = $this->createMock(Folder::class);
5467
+        $owner = $this->createMock(IUser::class);
5468
+        $storage = $this->createMock(SharedStorage::class);
5469
+        $originalShare = $this->createMock(IShare::class);
5470
+
5471
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5472
+        $share->method('getNodeId')->willReturn(42);
5473
+        $share->method('getHideDownload')->willReturn(false); // User wants to allow downloads
5474
+        $node->method('getOwner')->willReturn($owner);
5475
+        $owner->method('getUID')->willReturn('differentOwner');
5476
+        $node->method('getStorage')->willReturn($storage);
5477
+        $storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5478
+        $storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5479
+        $storage->method('getShare')->willReturn($originalShare);
5480
+        $originalShare->method('getHideDownload')->willReturn(true); // Parent hides download
5481
+        $originalShare->method('getAttributes')->willReturn(null);
5482
+
5483
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5484
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5485
+
5486
+        // Should be forced to hide download due to parent restriction
5487
+        $share->expects($this->once())->method('setHideDownload')->with(true);
5488
+
5489
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5490
+    }
5491
+
5492
+    public function testUserCanHideWhenParentAllows(): void {
5493
+        $ocs = $this->mockFormatShare();
5494
+
5495
+        $share = $this->createMock(IShare::class);
5496
+        $node = $this->createMock(File::class);
5497
+        $userFolder = $this->createMock(Folder::class);
5498
+        $owner = $this->createMock(IUser::class);
5499
+        $storage = $this->createMock(SharedStorage::class);
5500
+        $originalShare = $this->createMock(IShare::class);
5501
+
5502
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5503
+        $share->method('getNodeId')->willReturn(42);
5504
+        $share->method('getHideDownload')->willReturn(true); // User chooses to hide downloads
5505
+        $node->method('getOwner')->willReturn($owner);
5506
+        $owner->method('getUID')->willReturn('differentOwner');
5507
+        $node->method('getStorage')->willReturn($storage);
5508
+        $storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5509
+        $storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5510
+        $storage->method('getShare')->willReturn($originalShare);
5511
+        $originalShare->method('getHideDownload')->willReturn(false); // Parent allows download
5512
+        $originalShare->method('getAttributes')->willReturn(null);
5513
+
5514
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5515
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5516
+
5517
+        // Should respect user's choice to hide downloads
5518
+        $share->expects($this->once())->method('setHideDownload')->with(true);
5519
+
5520
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5521
+    }
5522
+
5523
+    public function testParentDownloadAttributeInherited(): void {
5524
+        $ocs = $this->mockFormatShare();
5525
+
5526
+        $share = $this->createMock(IShare::class);
5527
+        $node = $this->createMock(File::class);
5528
+        $userFolder = $this->createMock(Folder::class);
5529
+        $owner = $this->createMock(IUser::class);
5530
+        $storage = $this->createMock(SharedStorage::class);
5531
+        $originalShare = $this->createMock(IShare::class);
5532
+        $attributes = $this->createMock(IShareAttributes::class);
5533
+        $shareAttributes = $this->createMock(IShareAttributes::class);
5534
+
5535
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5536
+        $share->method('getNodeId')->willReturn(42);
5537
+        $share->method('getHideDownload')->willReturn(false); // User wants to allow downloads
5538
+        $share->method('getAttributes')->willReturn($shareAttributes);
5539
+        $share->method('newAttributes')->willReturn($shareAttributes);
5540
+        $node->method('getOwner')->willReturn($owner);
5541
+        $owner->method('getUID')->willReturn('differentOwner');
5542
+        $node->method('getStorage')->willReturn($storage);
5543
+        $storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5544
+        $storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5545
+        $storage->method('getShare')->willReturn($originalShare);
5546
+        $originalShare->method('getHideDownload')->willReturn(false);
5547
+        $originalShare->method('getAttributes')->willReturn($attributes);
5548
+        $attributes->method('getAttribute')->with('permissions', 'download')->willReturn(false); // Parent forbids download
5549
+
5550
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5551
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5552
+
5553
+        // Should be forced to hide download and set download attribute to false
5554
+        $share->expects($this->once())->method('setHideDownload')->with(true);
5555
+        $shareAttributes->expects($this->once())->method('setAttribute')->with('permissions', 'download', false);
5556
+        $share->expects($this->once())->method('setAttributes')->with($shareAttributes);
5557
+
5558
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5559
+    }
5560
+
5561
+    public function testFederatedStorageRespectsUserChoice(): void {
5562
+        $ocs = $this->mockFormatShare();
5563
+
5564
+        $share = $this->createMock(IShare::class);
5565
+        $node = $this->createMock(File::class);
5566
+        $userFolder = $this->createMock(Folder::class);
5567
+        $owner = $this->createMock(IUser::class);
5568
+        $storage = $this->createMock(Storage::class);
5569
+
5570
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5571
+        $share->method('getNodeId')->willReturn(42);
5572
+        $share->method('getHideDownload')->willReturn(true); // User chooses to hide downloads
5573
+        $node->method('getOwner')->willReturn($owner);
5574
+        $owner->method('getUID')->willReturn('differentOwner');
5575
+        $node->method('getStorage')->willReturn($storage);
5576
+        $storage->method('instanceOfStorage')->willReturnMap([
5577
+            [SharedStorage::class, false],
5578
+            [Storage::class, true]
5579
+        ]);
5580
+
5581
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5582
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5583
+
5584
+        // For federated storage, should respect user's choice
5585
+        $share->expects($this->once())->method('setHideDownload')->with(true);
5586
+
5587
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5588
+    }
5589
+
5590
+    public function testUserAllowsDownloadWhenParentPermits(): void {
5591
+        $ocs = $this->mockFormatShare();
5592
+
5593
+        $share = $this->createMock(IShare::class);
5594
+        $node = $this->createMock(File::class);
5595
+        $userFolder = $this->createMock(Folder::class);
5596
+        $owner = $this->createMock(IUser::class);
5597
+        $storage = $this->createMock(SharedStorage::class);
5598
+        $originalShare = $this->createMock(IShare::class);
5599
+
5600
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5601
+        $share->method('getNodeId')->willReturn(42);
5602
+        $share->method('getHideDownload')->willReturn(false); // User wants to allow downloads
5603
+        $node->method('getOwner')->willReturn($owner);
5604
+        $owner->method('getUID')->willReturn('differentOwner');
5605
+        $node->method('getStorage')->willReturn($storage);
5606
+        $storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5607
+        $storage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($storage);
5608
+        $storage->method('getShare')->willReturn($originalShare);
5609
+        $originalShare->method('getHideDownload')->willReturn(false); // Parent allows download
5610
+        $originalShare->method('getAttributes')->willReturn(null);
5611
+
5612
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5613
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5614
+
5615
+        // Should allow downloads as both user and parent permit it
5616
+        $share->expects($this->once())->method('setHideDownload')->with(false);
5617
+
5618
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5619
+    }
5620
+
5621
+    public function testWrapperStorageUnwrapped(): void {
5622
+        $ocs = $this->mockFormatShare();
5623
+
5624
+        $share = $this->createMock(IShare::class);
5625
+        $node = $this->createMock(File::class);
5626
+        $userFolder = $this->createMock(Folder::class);
5627
+        $owner = $this->createMock(IUser::class);
5628
+        $wrapperStorage = $this->createMock(Wrapper::class);
5629
+        $innerStorage = $this->createMock(SharedStorage::class);
5630
+        $originalShare = $this->createMock(IShare::class);
5631
+
5632
+        $share->method('getSharedBy')->willReturn('sharedByUser');
5633
+        $share->method('getNodeId')->willReturn(42);
5634
+        $share->method('getHideDownload')->willReturn(false);
5635
+        $node->method('getOwner')->willReturn($owner);
5636
+        $owner->method('getUID')->willReturn('differentOwner');
5637
+        $node->method('getStorage')->willReturn($wrapperStorage);
5638
+        $wrapperStorage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
5639
+        $wrapperStorage->method('getInstanceOfStorage')->with(SharedStorage::class)->willReturn($innerStorage);
5640
+        $innerStorage->method('getShare')->willReturn($originalShare);
5641
+        $originalShare->method('getHideDownload')->willReturn(false);
5642
+        $originalShare->method('getAttributes')->willReturn(null);
5643
+
5644
+        $userFolder->method('getById')->with(42)->willReturn([$node]);
5645
+        $this->rootFolder->method('getUserFolder')->with('sharedByUser')->willReturn($userFolder);
5646
+
5647
+        $share->expects($this->once())->method('setHideDownload')->with(false);
5648
+
5649
+        $this->invokePrivate($ocs, 'checkInheritedAttributes', [$share]);
5650
+    }
5651 5651
 }
Please login to merge, or discard this patch.
apps/files_sharing/tests/MountProviderTest.php 1 patch
Indentation   +457 added lines, -457 removed lines patch added patch discarded remove patch
@@ -31,461 +31,461 @@
 block discarded – undo
31 31
 #[\PHPUnit\Framework\Attributes\Group(name: 'DB')]
32 32
 class MountProviderTest extends \Test\TestCase {
33 33
 
34
-	protected MountProvider $provider;
35
-
36
-	protected IUser&MockObject $user;
37
-	protected IConfig&MockObject $config;
38
-	protected IManager&MockObject $shareManager;
39
-	protected IStorageFactory&MockObject $loader;
40
-	protected LoggerInterface&MockObject $logger;
41
-	private ICache&MockObject $cache;
42
-
43
-	protected function setUp(): void {
44
-		parent::setUp();
45
-
46
-		$this->config = $this->createMock(IConfig::class);
47
-		$this->user = $this->createMock(IUser::class);
48
-		$this->loader = $this->createMock(IStorageFactory::class);
49
-		$this->shareManager = $this->createMock(IManager::class);
50
-		$this->logger = $this->createMock(LoggerInterface::class);
51
-		$eventDispatcher = $this->createMock(IEventDispatcher::class);
52
-		$this->cache = $this->createMock(ICache::class);
53
-		$this->cache->method('get')->willReturn(true);
54
-		$cacheFactory = $this->createMock(ICacheFactory::class);
55
-		$cacheFactory->method('createLocal')->willReturn($this->cache);
56
-		$mountManager = $this->createMock(IMountManager::class);
57
-
58
-		$this->provider = new MountProvider($this->config, $this->shareManager, $this->logger, $eventDispatcher, $cacheFactory, $mountManager);
59
-	}
60
-
61
-	private function makeMockShareAttributes(array $attrs): IShareAttributes&MockObject {
62
-		$shareAttributes = $this->createMock(IShareAttributes::class);
63
-		$shareAttributes->method('toArray')->willReturn($attrs);
64
-		$shareAttributes->method('getAttribute')->willReturnCallback(
65
-			function ($scope, $key) use ($attrs) {
66
-				$result = null;
67
-				foreach ($attrs as $attr) {
68
-					if ($attr['key'] === $key && $attr['scope'] === $scope) {
69
-						$result = $attr['value'];
70
-					}
71
-				}
72
-				return $result;
73
-			}
74
-		);
75
-		return $shareAttributes;
76
-	}
77
-
78
-	private function makeMockShare(string $id, $nodeId, $owner = 'user2', $target = null, $permissions = 31, $attributes = null) {
79
-		$share = $this->createMock(IShare::class);
80
-		$share->expects($this->any())
81
-			->method('getPermissions')
82
-			->willReturn($permissions);
83
-		$share->expects($this->any())
84
-			->method('getAttributes')
85
-			->willReturn($attributes === null ? null : $this->makeMockShareAttributes($attributes));
86
-		$share->expects($this->any())
87
-			->method('getShareOwner')
88
-			->willReturn($owner);
89
-		$share->expects($this->any())
90
-			->method('getTarget')
91
-			->willReturn($target);
92
-		$share->expects($this->any())
93
-			->method('getId')
94
-			->willReturn($id);
95
-		$share->expects($this->any())
96
-			->method('getNodeId')
97
-			->willReturn($nodeId);
98
-		$share->expects($this->any())
99
-			->method('getShareTime')
100
-			->willReturn(
101
-				// compute share time based on id, simulating share order
102
-				new \DateTime('@' . (1469193980 + 1000 * $id))
103
-			);
104
-		return $share;
105
-	}
106
-
107
-	/**
108
-	 * Tests excluding shares from the current view. This includes:
109
-	 * - shares that were opted out of (permissions === 0)
110
-	 * - shares with a group in which the owner is already in
111
-	 */
112
-	public function testExcludeShares(): void {
113
-		$rootFolder = $this->createMock(IRootFolder::class);
114
-		$userManager = $this->createMock(IUserManager::class);
115
-		$attr1 = [];
116
-		$attr2 = [['scope' => 'permission', 'key' => 'download', 'value' => true]];
117
-		$userShares = [
118
-			$this->makeMockShare('1', 100, 'user2', '/share2', 0, $attr1),
119
-			$this->makeMockShare('2', 100, 'user2', '/share2', 31, $attr2),
120
-		];
121
-		$groupShares = [
122
-			$this->makeMockShare('3', 100, 'user2', '/share2', 0, $attr1),
123
-			$this->makeMockShare('4', 101, 'user2', '/share4', 31, $attr2),
124
-			$this->makeMockShare('5', 100, 'user1', '/share4', 31, $attr2),
125
-		];
126
-		$roomShares = [
127
-			$this->makeMockShare('6', 102, 'user2', '/share6', 0),
128
-			$this->makeMockShare('7', 102, 'user1', '/share6', 31),
129
-			$this->makeMockShare('8', 102, 'user2', '/share6', 31),
130
-			$this->makeMockShare('9', 102, 'user2', '/share6', 31),
131
-		];
132
-		$deckShares = [
133
-			$this->makeMockShare('10', 103, 'user2', '/share7', 0),
134
-			$this->makeMockShare('11', 103, 'user1', '/share7', 31),
135
-			$this->makeMockShare('12', 103, 'user2', '/share7', 31),
136
-			$this->makeMockShare('13', 103, 'user2', '/share7', 31),
137
-		];
138
-		// tests regarding circles and sciencemesh are made in the apps themselves.
139
-		$circleShares = [];
140
-		$scienceMeshShares = [];
141
-		$this->user->expects($this->any())
142
-			->method('getUID')
143
-			->willReturn('user1');
144
-		$this->shareManager->expects($this->exactly(5))
145
-			->method('getSharedWith')
146
-			->willReturnMap([
147
-				['user1', IShare::TYPE_USER, null, -1, 0, $userShares],
148
-				['user1', IShare::TYPE_GROUP, null, -1, 0, $groupShares],
149
-				['user1', IShare::TYPE_CIRCLE, null, -1, 0, $circleShares],
150
-				['user1', IShare::TYPE_ROOM, null, -1, 0, $roomShares],
151
-				['user1', IShare::TYPE_DECK, null, -1, 0, $deckShares],
152
-			]);
153
-
154
-		$this->shareManager->expects($this->any())
155
-			->method('newShare')
156
-			->willReturnCallback(function () use ($rootFolder, $userManager) {
157
-				return new Share($rootFolder, $userManager);
158
-			});
159
-
160
-		/** @var SharedMount[] $mounts */
161
-		$mounts = $this->provider->getMountsForUser($this->user, $this->loader);
162
-		$this->assertCount(4, $mounts);
163
-		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[0]);
164
-		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[1]);
165
-		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[2]);
166
-		$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[3]);
167
-		$mountedShare1 = $mounts[0]->getShare();
168
-		$this->assertEquals('2', $mountedShare1->getId());
169
-		$this->assertEquals('user2', $mountedShare1->getShareOwner());
170
-		$this->assertEquals(100, $mountedShare1->getNodeId());
171
-		$this->assertEquals('/share2', $mountedShare1->getTarget());
172
-		$this->assertEquals(31, $mountedShare1->getPermissions());
173
-		$this->assertEquals(true, $mountedShare1->getAttributes()->getAttribute('permission', 'download'));
174
-		$mountedShare2 = $mounts[1]->getShare();
175
-		$this->assertEquals('4', $mountedShare2->getId());
176
-		$this->assertEquals('user2', $mountedShare2->getShareOwner());
177
-		$this->assertEquals(101, $mountedShare2->getNodeId());
178
-		$this->assertEquals('/share4', $mountedShare2->getTarget());
179
-		$this->assertEquals(31, $mountedShare2->getPermissions());
180
-		$this->assertEquals(true, $mountedShare2->getAttributes()->getAttribute('permission', 'download'));
181
-		$mountedShare3 = $mounts[2]->getShare();
182
-		$this->assertEquals('8', $mountedShare3->getId());
183
-		$this->assertEquals('user2', $mountedShare3->getShareOwner());
184
-		$this->assertEquals(102, $mountedShare3->getNodeId());
185
-		$this->assertEquals('/share6', $mountedShare3->getTarget());
186
-		$this->assertEquals(31, $mountedShare3->getPermissions());
187
-		$mountedShare4 = $mounts[3]->getShare();
188
-		$this->assertEquals('12', $mountedShare4->getId());
189
-		$this->assertEquals('user2', $mountedShare4->getShareOwner());
190
-		$this->assertEquals(103, $mountedShare4->getNodeId());
191
-		$this->assertEquals('/share7', $mountedShare4->getTarget());
192
-		$this->assertEquals(31, $mountedShare4->getPermissions());
193
-	}
194
-
195
-	public static function mergeSharesDataProvider(): array {
196
-		// note: the user in the specs here is the shareOwner not recipient
197
-		// the recipient is always "user1"
198
-		return [
199
-			// #0: share as outsider with "group1" and "user1" with same permissions
200
-			[
201
-				[
202
-					['1', 100, 'user2', '/share2', 31, null],
203
-				],
204
-				[
205
-					['2', 100, 'user2', '/share2', 31, null],
206
-				],
207
-				[
208
-					// combined, user share has higher priority
209
-					['1', 100, 'user2', '/share2', 31, []],
210
-				],
211
-			],
212
-			// #1: share as outsider with "group1" and "user1" with different permissions
213
-			[
214
-				[
215
-					['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true], ['scope' => 'app', 'key' => 'attribute1', 'value' => true]]],
216
-				],
217
-				[
218
-					['2', 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => false], ['scope' => 'app', 'key' => 'attribute2', 'value' => false]]],
219
-				],
220
-				[
221
-					// use highest permissions
222
-					['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true], ['scope' => 'app', 'key' => 'attribute1', 'value' => true], ['scope' => 'app', 'key' => 'attribute2', 'value' => false]]],
223
-				],
224
-			],
225
-			// #2: share as outsider with "group1" and "group2" with same permissions
226
-			[
227
-				[
228
-				],
229
-				[
230
-					['1', 100, 'user2', '/share', 31, null],
231
-					['2', 100, 'user2', '/share', 31, []],
232
-				],
233
-				[
234
-					// combined, first group share has higher priority
235
-					['1', 100, 'user2', '/share', 31, []],
236
-				],
237
-			],
238
-			// #3: share as outsider with "group1" and "group2" with different permissions
239
-			[
240
-				[
241
-				],
242
-				[
243
-					['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => false]]],
244
-					['2', 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
245
-				],
246
-				[
247
-					// use higher permissions (most permissive)
248
-					['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
249
-				],
250
-			],
251
-			// #4: share as insider with "group1"
252
-			[
253
-				[
254
-				],
255
-				[
256
-					['1', 100, 'user1', '/share', 31, []],
257
-				],
258
-				[
259
-					// no received share since "user1" is the sharer/owner
260
-				],
261
-			],
262
-			// #5: share as insider with "group1" and "group2" with different permissions
263
-			[
264
-				[
265
-				],
266
-				[
267
-					['1', 100, 'user1', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
268
-					['2', 100, 'user1', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => false]]],
269
-				],
270
-				[
271
-					// no received share since "user1" is the sharer/owner
272
-				],
273
-			],
274
-			// #6: share as outside with "group1", recipient opted out
275
-			[
276
-				[
277
-				],
278
-				[
279
-					['1', 100, 'user2', '/share', 0, []],
280
-				],
281
-				[
282
-					// no received share since "user1" opted out
283
-				],
284
-			],
285
-			// #7: share as outsider with "group1" and "user1" where recipient renamed in between
286
-			[
287
-				[
288
-					['1', 100, 'user2', '/share2-renamed', 31, []],
289
-				],
290
-				[
291
-					['2', 100, 'user2', '/share2', 31, []],
292
-				],
293
-				[
294
-					// use target of least recent share
295
-					['1', 100, 'user2', '/share2-renamed', 31, []],
296
-				],
297
-			],
298
-			// #8: share as outsider with "group1" and "user1" where recipient renamed in between
299
-			[
300
-				[
301
-					['2', 100, 'user2', '/share2', 31, []],
302
-				],
303
-				[
304
-					['1', 100, 'user2', '/share2-renamed', 31, []],
305
-				],
306
-				[
307
-					// use target of least recent share
308
-					['1', 100, 'user2', '/share2-renamed', 31, []],
309
-				],
310
-			],
311
-			// #9: share as outsider with "nullgroup" and "user1" where recipient renamed in between
312
-			[
313
-				[
314
-					['2', 100, 'user2', '/share2', 31, []],
315
-				],
316
-				[
317
-					['1', 100, 'nullgroup', '/share2-renamed', 31, []],
318
-				],
319
-				[
320
-					// use target of least recent share
321
-					['1', 100, 'nullgroup', '/share2-renamed', 31, []],
322
-				],
323
-				true
324
-			],
325
-		];
326
-	}
327
-
328
-	/**
329
-	 * Tests merging shares.
330
-	 *
331
-	 * Happens when sharing the same entry to a user through multiple ways,
332
-	 * like several groups and also direct shares at the same time.
333
-	 *
334
-	 *
335
-	 * @param array $userShares array of user share specs
336
-	 * @param array $groupShares array of group share specs
337
-	 * @param array $expectedShares array of expected supershare specs
338
-	 */
339
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'mergeSharesDataProvider')]
340
-	public function testMergeShares(array $userShares, array $groupShares, array $expectedShares, bool $moveFails = false): void {
341
-		$rootFolder = $this->createMock(IRootFolder::class);
342
-		$userManager = $this->createMock(IUserManager::class);
343
-
344
-		$userShares = array_map(function ($shareSpec) {
345
-			return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
346
-		}, $userShares);
347
-		$groupShares = array_map(function ($shareSpec) {
348
-			return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
349
-		}, $groupShares);
350
-
351
-		$this->user->expects($this->any())
352
-			->method('getUID')
353
-			->willReturn('user1');
354
-
355
-		// tests regarding circles are made in the app itself.
356
-		$circleShares = [];
357
-		$roomShares = [];
358
-		$deckShares = [];
359
-		$this->shareManager->expects($this->exactly(5))
360
-			->method('getSharedWith')
361
-			->willReturnMap([
362
-				['user1', IShare::TYPE_USER, null, -1, 0, $userShares],
363
-				['user1', IShare::TYPE_GROUP, null, -1, 0, $groupShares],
364
-				['user1', IShare::TYPE_CIRCLE, null, -1, 0, $circleShares],
365
-				['user1', IShare::TYPE_ROOM, null, -1, 0, $roomShares],
366
-				['user1', IShare::TYPE_DECK, null, -1, 0, $deckShares],
367
-			]);
368
-
369
-		$this->shareManager->expects($this->any())
370
-			->method('newShare')
371
-			->willReturnCallback(function () use ($rootFolder, $userManager) {
372
-				return new Share($rootFolder, $userManager);
373
-			});
374
-
375
-		if ($moveFails) {
376
-			$this->shareManager->expects($this->any())
377
-				->method('moveShare')
378
-				->willThrowException(new \InvalidArgumentException());
379
-		}
380
-
381
-		$mounts = $this->provider->getMountsForUser($this->user, $this->loader);
382
-
383
-		$this->assertCount(count($expectedShares), $mounts);
384
-
385
-		foreach ($mounts as $index => $mount) {
386
-			$expectedShare = $expectedShares[$index];
387
-			$this->assertInstanceOf(SharedMount::class, $mount);
388
-
389
-			// supershare
390
-			/** @var SharedMount $mount */
391
-			$share = $mount->getShare();
392
-
393
-			$this->assertEquals($expectedShare[0], $share->getId());
394
-			$this->assertEquals($expectedShare[1], $share->getNodeId());
395
-			$this->assertEquals($expectedShare[2], $share->getShareOwner());
396
-			$this->assertEquals($expectedShare[3], $share->getTarget());
397
-			$this->assertEquals($expectedShare[4], $share->getPermissions());
398
-			if ($expectedShare[5] === null) {
399
-				$this->assertNull($share->getAttributes());
400
-			} else {
401
-				$this->assertEquals($expectedShare[5], $share->getAttributes()->toArray());
402
-			}
403
-		}
404
-	}
405
-
406
-	#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'mergeSharesDataProvider')]
407
-	public function testMergeSharesInGetMountsForPath(array $userShares, array $groupShares, array $expectedShares, bool $moveFails = false): void {
408
-		$rootFolder = $this->createMock(IRootFolder::class);
409
-		$userManager = $this->createMock(IUserManager::class);
410
-
411
-		$userShares = array_map(function ($shareSpec) {
412
-			return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
413
-		}, $userShares);
414
-		$groupShares = array_map(function ($shareSpec) {
415
-			return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
416
-		}, $groupShares);
417
-
418
-		$this->user->expects($this->any())
419
-			->method('getUID')
420
-			->willReturn('user1');
421
-
422
-		// tests regarding circles are made in the app itself.
423
-		$circleShares = [];
424
-		$roomShares = [];
425
-		$deckShares = [];
426
-		$path = '/';
427
-
428
-		// no expected shares? then no calls are performed to providers
429
-		$expectedProviderCalls = \count($expectedShares) ? 5 : 0;
430
-		$this->shareManager->expects($this->exactly($expectedProviderCalls))
431
-			->method('getSharedWithByPath')
432
-			->willReturnMap([
433
-				['user1', IShare::TYPE_USER, $path, true, -1, 0, $userShares],
434
-				['user1', IShare::TYPE_GROUP, $path, true, -1, 0, $groupShares],
435
-				['user1', IShare::TYPE_CIRCLE, $path, true, -1, 0, $circleShares],
436
-				['user1', IShare::TYPE_ROOM, $path, true, -1, 0, $roomShares],
437
-				['user1', IShare::TYPE_DECK, $path, true, -1, 0, $deckShares],
438
-			]);
439
-
440
-		$this->shareManager->expects($this->any())
441
-			->method('newShare')
442
-			->willReturnCallback(function () use ($rootFolder, $userManager) {
443
-				return new Share($rootFolder, $userManager);
444
-			});
445
-
446
-		if ($moveFails) {
447
-			$this->shareManager->expects($this->any())
448
-				->method('moveShare')
449
-				->willThrowException(new \InvalidArgumentException());
450
-		}
451
-
452
-		$mountArgs = [];
453
-		foreach ($expectedShares as $share) {
454
-			$mountInfo = $this->createMock(ICachedMountInfo::class);
455
-			$mountInfo->method('getUser')->willReturn($this->user);
456
-			$mountInfo->method('getRootId')->willReturn($share[1]);
457
-			$rootCacheEntry = $this->createMock(ICacheEntry::class);
458
-			$mountArg = new MountProviderArgs($mountInfo, $rootCacheEntry);
459
-			$mountArgs[] = $mountArg;
460
-		}
461
-
462
-		if (count($mountArgs) === 0) {
463
-			$mounts = [];
464
-		} else {
465
-			$mounts = $this->provider->getMountsForPath('/', true, $mountArgs, $this->loader);
466
-		}
467
-
468
-
469
-		$this->assertCount(\count($expectedShares), $mounts);
470
-
471
-		foreach (array_values($mounts) as $index => $mount) {
472
-			$expectedShare = $expectedShares[$index];
473
-			$this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mount);
474
-
475
-			// supershare
476
-			/** @var SharedMount $mount */
477
-			$share = $mount->getShare();
478
-
479
-			$this->assertEquals($expectedShare[0], $share->getId());
480
-			$this->assertEquals($expectedShare[1], $share->getNodeId());
481
-			$this->assertEquals($expectedShare[2], $share->getShareOwner());
482
-			$this->assertEquals($expectedShare[3], $share->getTarget());
483
-			$this->assertEquals($expectedShare[4], $share->getPermissions());
484
-			if ($expectedShare[5] === null) {
485
-				$this->assertNull($share->getAttributes());
486
-			} else {
487
-				$this->assertEquals($expectedShare[5], $share->getAttributes()->toArray());
488
-			}
489
-		}
490
-	}
34
+    protected MountProvider $provider;
35
+
36
+    protected IUser&MockObject $user;
37
+    protected IConfig&MockObject $config;
38
+    protected IManager&MockObject $shareManager;
39
+    protected IStorageFactory&MockObject $loader;
40
+    protected LoggerInterface&MockObject $logger;
41
+    private ICache&MockObject $cache;
42
+
43
+    protected function setUp(): void {
44
+        parent::setUp();
45
+
46
+        $this->config = $this->createMock(IConfig::class);
47
+        $this->user = $this->createMock(IUser::class);
48
+        $this->loader = $this->createMock(IStorageFactory::class);
49
+        $this->shareManager = $this->createMock(IManager::class);
50
+        $this->logger = $this->createMock(LoggerInterface::class);
51
+        $eventDispatcher = $this->createMock(IEventDispatcher::class);
52
+        $this->cache = $this->createMock(ICache::class);
53
+        $this->cache->method('get')->willReturn(true);
54
+        $cacheFactory = $this->createMock(ICacheFactory::class);
55
+        $cacheFactory->method('createLocal')->willReturn($this->cache);
56
+        $mountManager = $this->createMock(IMountManager::class);
57
+
58
+        $this->provider = new MountProvider($this->config, $this->shareManager, $this->logger, $eventDispatcher, $cacheFactory, $mountManager);
59
+    }
60
+
61
+    private function makeMockShareAttributes(array $attrs): IShareAttributes&MockObject {
62
+        $shareAttributes = $this->createMock(IShareAttributes::class);
63
+        $shareAttributes->method('toArray')->willReturn($attrs);
64
+        $shareAttributes->method('getAttribute')->willReturnCallback(
65
+            function ($scope, $key) use ($attrs) {
66
+                $result = null;
67
+                foreach ($attrs as $attr) {
68
+                    if ($attr['key'] === $key && $attr['scope'] === $scope) {
69
+                        $result = $attr['value'];
70
+                    }
71
+                }
72
+                return $result;
73
+            }
74
+        );
75
+        return $shareAttributes;
76
+    }
77
+
78
+    private function makeMockShare(string $id, $nodeId, $owner = 'user2', $target = null, $permissions = 31, $attributes = null) {
79
+        $share = $this->createMock(IShare::class);
80
+        $share->expects($this->any())
81
+            ->method('getPermissions')
82
+            ->willReturn($permissions);
83
+        $share->expects($this->any())
84
+            ->method('getAttributes')
85
+            ->willReturn($attributes === null ? null : $this->makeMockShareAttributes($attributes));
86
+        $share->expects($this->any())
87
+            ->method('getShareOwner')
88
+            ->willReturn($owner);
89
+        $share->expects($this->any())
90
+            ->method('getTarget')
91
+            ->willReturn($target);
92
+        $share->expects($this->any())
93
+            ->method('getId')
94
+            ->willReturn($id);
95
+        $share->expects($this->any())
96
+            ->method('getNodeId')
97
+            ->willReturn($nodeId);
98
+        $share->expects($this->any())
99
+            ->method('getShareTime')
100
+            ->willReturn(
101
+                // compute share time based on id, simulating share order
102
+                new \DateTime('@' . (1469193980 + 1000 * $id))
103
+            );
104
+        return $share;
105
+    }
106
+
107
+    /**
108
+     * Tests excluding shares from the current view. This includes:
109
+     * - shares that were opted out of (permissions === 0)
110
+     * - shares with a group in which the owner is already in
111
+     */
112
+    public function testExcludeShares(): void {
113
+        $rootFolder = $this->createMock(IRootFolder::class);
114
+        $userManager = $this->createMock(IUserManager::class);
115
+        $attr1 = [];
116
+        $attr2 = [['scope' => 'permission', 'key' => 'download', 'value' => true]];
117
+        $userShares = [
118
+            $this->makeMockShare('1', 100, 'user2', '/share2', 0, $attr1),
119
+            $this->makeMockShare('2', 100, 'user2', '/share2', 31, $attr2),
120
+        ];
121
+        $groupShares = [
122
+            $this->makeMockShare('3', 100, 'user2', '/share2', 0, $attr1),
123
+            $this->makeMockShare('4', 101, 'user2', '/share4', 31, $attr2),
124
+            $this->makeMockShare('5', 100, 'user1', '/share4', 31, $attr2),
125
+        ];
126
+        $roomShares = [
127
+            $this->makeMockShare('6', 102, 'user2', '/share6', 0),
128
+            $this->makeMockShare('7', 102, 'user1', '/share6', 31),
129
+            $this->makeMockShare('8', 102, 'user2', '/share6', 31),
130
+            $this->makeMockShare('9', 102, 'user2', '/share6', 31),
131
+        ];
132
+        $deckShares = [
133
+            $this->makeMockShare('10', 103, 'user2', '/share7', 0),
134
+            $this->makeMockShare('11', 103, 'user1', '/share7', 31),
135
+            $this->makeMockShare('12', 103, 'user2', '/share7', 31),
136
+            $this->makeMockShare('13', 103, 'user2', '/share7', 31),
137
+        ];
138
+        // tests regarding circles and sciencemesh are made in the apps themselves.
139
+        $circleShares = [];
140
+        $scienceMeshShares = [];
141
+        $this->user->expects($this->any())
142
+            ->method('getUID')
143
+            ->willReturn('user1');
144
+        $this->shareManager->expects($this->exactly(5))
145
+            ->method('getSharedWith')
146
+            ->willReturnMap([
147
+                ['user1', IShare::TYPE_USER, null, -1, 0, $userShares],
148
+                ['user1', IShare::TYPE_GROUP, null, -1, 0, $groupShares],
149
+                ['user1', IShare::TYPE_CIRCLE, null, -1, 0, $circleShares],
150
+                ['user1', IShare::TYPE_ROOM, null, -1, 0, $roomShares],
151
+                ['user1', IShare::TYPE_DECK, null, -1, 0, $deckShares],
152
+            ]);
153
+
154
+        $this->shareManager->expects($this->any())
155
+            ->method('newShare')
156
+            ->willReturnCallback(function () use ($rootFolder, $userManager) {
157
+                return new Share($rootFolder, $userManager);
158
+            });
159
+
160
+        /** @var SharedMount[] $mounts */
161
+        $mounts = $this->provider->getMountsForUser($this->user, $this->loader);
162
+        $this->assertCount(4, $mounts);
163
+        $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[0]);
164
+        $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[1]);
165
+        $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[2]);
166
+        $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mounts[3]);
167
+        $mountedShare1 = $mounts[0]->getShare();
168
+        $this->assertEquals('2', $mountedShare1->getId());
169
+        $this->assertEquals('user2', $mountedShare1->getShareOwner());
170
+        $this->assertEquals(100, $mountedShare1->getNodeId());
171
+        $this->assertEquals('/share2', $mountedShare1->getTarget());
172
+        $this->assertEquals(31, $mountedShare1->getPermissions());
173
+        $this->assertEquals(true, $mountedShare1->getAttributes()->getAttribute('permission', 'download'));
174
+        $mountedShare2 = $mounts[1]->getShare();
175
+        $this->assertEquals('4', $mountedShare2->getId());
176
+        $this->assertEquals('user2', $mountedShare2->getShareOwner());
177
+        $this->assertEquals(101, $mountedShare2->getNodeId());
178
+        $this->assertEquals('/share4', $mountedShare2->getTarget());
179
+        $this->assertEquals(31, $mountedShare2->getPermissions());
180
+        $this->assertEquals(true, $mountedShare2->getAttributes()->getAttribute('permission', 'download'));
181
+        $mountedShare3 = $mounts[2]->getShare();
182
+        $this->assertEquals('8', $mountedShare3->getId());
183
+        $this->assertEquals('user2', $mountedShare3->getShareOwner());
184
+        $this->assertEquals(102, $mountedShare3->getNodeId());
185
+        $this->assertEquals('/share6', $mountedShare3->getTarget());
186
+        $this->assertEquals(31, $mountedShare3->getPermissions());
187
+        $mountedShare4 = $mounts[3]->getShare();
188
+        $this->assertEquals('12', $mountedShare4->getId());
189
+        $this->assertEquals('user2', $mountedShare4->getShareOwner());
190
+        $this->assertEquals(103, $mountedShare4->getNodeId());
191
+        $this->assertEquals('/share7', $mountedShare4->getTarget());
192
+        $this->assertEquals(31, $mountedShare4->getPermissions());
193
+    }
194
+
195
+    public static function mergeSharesDataProvider(): array {
196
+        // note: the user in the specs here is the shareOwner not recipient
197
+        // the recipient is always "user1"
198
+        return [
199
+            // #0: share as outsider with "group1" and "user1" with same permissions
200
+            [
201
+                [
202
+                    ['1', 100, 'user2', '/share2', 31, null],
203
+                ],
204
+                [
205
+                    ['2', 100, 'user2', '/share2', 31, null],
206
+                ],
207
+                [
208
+                    // combined, user share has higher priority
209
+                    ['1', 100, 'user2', '/share2', 31, []],
210
+                ],
211
+            ],
212
+            // #1: share as outsider with "group1" and "user1" with different permissions
213
+            [
214
+                [
215
+                    ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true], ['scope' => 'app', 'key' => 'attribute1', 'value' => true]]],
216
+                ],
217
+                [
218
+                    ['2', 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => false], ['scope' => 'app', 'key' => 'attribute2', 'value' => false]]],
219
+                ],
220
+                [
221
+                    // use highest permissions
222
+                    ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true], ['scope' => 'app', 'key' => 'attribute1', 'value' => true], ['scope' => 'app', 'key' => 'attribute2', 'value' => false]]],
223
+                ],
224
+            ],
225
+            // #2: share as outsider with "group1" and "group2" with same permissions
226
+            [
227
+                [
228
+                ],
229
+                [
230
+                    ['1', 100, 'user2', '/share', 31, null],
231
+                    ['2', 100, 'user2', '/share', 31, []],
232
+                ],
233
+                [
234
+                    // combined, first group share has higher priority
235
+                    ['1', 100, 'user2', '/share', 31, []],
236
+                ],
237
+            ],
238
+            // #3: share as outsider with "group1" and "group2" with different permissions
239
+            [
240
+                [
241
+                ],
242
+                [
243
+                    ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => false]]],
244
+                    ['2', 100, 'user2', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
245
+                ],
246
+                [
247
+                    // use higher permissions (most permissive)
248
+                    ['1', 100, 'user2', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
249
+                ],
250
+            ],
251
+            // #4: share as insider with "group1"
252
+            [
253
+                [
254
+                ],
255
+                [
256
+                    ['1', 100, 'user1', '/share', 31, []],
257
+                ],
258
+                [
259
+                    // no received share since "user1" is the sharer/owner
260
+                ],
261
+            ],
262
+            // #5: share as insider with "group1" and "group2" with different permissions
263
+            [
264
+                [
265
+                ],
266
+                [
267
+                    ['1', 100, 'user1', '/share', 31, [['scope' => 'permission', 'key' => 'download', 'value' => true]]],
268
+                    ['2', 100, 'user1', '/share', 15, [['scope' => 'permission', 'key' => 'download', 'value' => false]]],
269
+                ],
270
+                [
271
+                    // no received share since "user1" is the sharer/owner
272
+                ],
273
+            ],
274
+            // #6: share as outside with "group1", recipient opted out
275
+            [
276
+                [
277
+                ],
278
+                [
279
+                    ['1', 100, 'user2', '/share', 0, []],
280
+                ],
281
+                [
282
+                    // no received share since "user1" opted out
283
+                ],
284
+            ],
285
+            // #7: share as outsider with "group1" and "user1" where recipient renamed in between
286
+            [
287
+                [
288
+                    ['1', 100, 'user2', '/share2-renamed', 31, []],
289
+                ],
290
+                [
291
+                    ['2', 100, 'user2', '/share2', 31, []],
292
+                ],
293
+                [
294
+                    // use target of least recent share
295
+                    ['1', 100, 'user2', '/share2-renamed', 31, []],
296
+                ],
297
+            ],
298
+            // #8: share as outsider with "group1" and "user1" where recipient renamed in between
299
+            [
300
+                [
301
+                    ['2', 100, 'user2', '/share2', 31, []],
302
+                ],
303
+                [
304
+                    ['1', 100, 'user2', '/share2-renamed', 31, []],
305
+                ],
306
+                [
307
+                    // use target of least recent share
308
+                    ['1', 100, 'user2', '/share2-renamed', 31, []],
309
+                ],
310
+            ],
311
+            // #9: share as outsider with "nullgroup" and "user1" where recipient renamed in between
312
+            [
313
+                [
314
+                    ['2', 100, 'user2', '/share2', 31, []],
315
+                ],
316
+                [
317
+                    ['1', 100, 'nullgroup', '/share2-renamed', 31, []],
318
+                ],
319
+                [
320
+                    // use target of least recent share
321
+                    ['1', 100, 'nullgroup', '/share2-renamed', 31, []],
322
+                ],
323
+                true
324
+            ],
325
+        ];
326
+    }
327
+
328
+    /**
329
+     * Tests merging shares.
330
+     *
331
+     * Happens when sharing the same entry to a user through multiple ways,
332
+     * like several groups and also direct shares at the same time.
333
+     *
334
+     *
335
+     * @param array $userShares array of user share specs
336
+     * @param array $groupShares array of group share specs
337
+     * @param array $expectedShares array of expected supershare specs
338
+     */
339
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'mergeSharesDataProvider')]
340
+    public function testMergeShares(array $userShares, array $groupShares, array $expectedShares, bool $moveFails = false): void {
341
+        $rootFolder = $this->createMock(IRootFolder::class);
342
+        $userManager = $this->createMock(IUserManager::class);
343
+
344
+        $userShares = array_map(function ($shareSpec) {
345
+            return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
346
+        }, $userShares);
347
+        $groupShares = array_map(function ($shareSpec) {
348
+            return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
349
+        }, $groupShares);
350
+
351
+        $this->user->expects($this->any())
352
+            ->method('getUID')
353
+            ->willReturn('user1');
354
+
355
+        // tests regarding circles are made in the app itself.
356
+        $circleShares = [];
357
+        $roomShares = [];
358
+        $deckShares = [];
359
+        $this->shareManager->expects($this->exactly(5))
360
+            ->method('getSharedWith')
361
+            ->willReturnMap([
362
+                ['user1', IShare::TYPE_USER, null, -1, 0, $userShares],
363
+                ['user1', IShare::TYPE_GROUP, null, -1, 0, $groupShares],
364
+                ['user1', IShare::TYPE_CIRCLE, null, -1, 0, $circleShares],
365
+                ['user1', IShare::TYPE_ROOM, null, -1, 0, $roomShares],
366
+                ['user1', IShare::TYPE_DECK, null, -1, 0, $deckShares],
367
+            ]);
368
+
369
+        $this->shareManager->expects($this->any())
370
+            ->method('newShare')
371
+            ->willReturnCallback(function () use ($rootFolder, $userManager) {
372
+                return new Share($rootFolder, $userManager);
373
+            });
374
+
375
+        if ($moveFails) {
376
+            $this->shareManager->expects($this->any())
377
+                ->method('moveShare')
378
+                ->willThrowException(new \InvalidArgumentException());
379
+        }
380
+
381
+        $mounts = $this->provider->getMountsForUser($this->user, $this->loader);
382
+
383
+        $this->assertCount(count($expectedShares), $mounts);
384
+
385
+        foreach ($mounts as $index => $mount) {
386
+            $expectedShare = $expectedShares[$index];
387
+            $this->assertInstanceOf(SharedMount::class, $mount);
388
+
389
+            // supershare
390
+            /** @var SharedMount $mount */
391
+            $share = $mount->getShare();
392
+
393
+            $this->assertEquals($expectedShare[0], $share->getId());
394
+            $this->assertEquals($expectedShare[1], $share->getNodeId());
395
+            $this->assertEquals($expectedShare[2], $share->getShareOwner());
396
+            $this->assertEquals($expectedShare[3], $share->getTarget());
397
+            $this->assertEquals($expectedShare[4], $share->getPermissions());
398
+            if ($expectedShare[5] === null) {
399
+                $this->assertNull($share->getAttributes());
400
+            } else {
401
+                $this->assertEquals($expectedShare[5], $share->getAttributes()->toArray());
402
+            }
403
+        }
404
+    }
405
+
406
+    #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'mergeSharesDataProvider')]
407
+    public function testMergeSharesInGetMountsForPath(array $userShares, array $groupShares, array $expectedShares, bool $moveFails = false): void {
408
+        $rootFolder = $this->createMock(IRootFolder::class);
409
+        $userManager = $this->createMock(IUserManager::class);
410
+
411
+        $userShares = array_map(function ($shareSpec) {
412
+            return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
413
+        }, $userShares);
414
+        $groupShares = array_map(function ($shareSpec) {
415
+            return $this->makeMockShare($shareSpec[0], $shareSpec[1], $shareSpec[2], $shareSpec[3], $shareSpec[4], $shareSpec[5]);
416
+        }, $groupShares);
417
+
418
+        $this->user->expects($this->any())
419
+            ->method('getUID')
420
+            ->willReturn('user1');
421
+
422
+        // tests regarding circles are made in the app itself.
423
+        $circleShares = [];
424
+        $roomShares = [];
425
+        $deckShares = [];
426
+        $path = '/';
427
+
428
+        // no expected shares? then no calls are performed to providers
429
+        $expectedProviderCalls = \count($expectedShares) ? 5 : 0;
430
+        $this->shareManager->expects($this->exactly($expectedProviderCalls))
431
+            ->method('getSharedWithByPath')
432
+            ->willReturnMap([
433
+                ['user1', IShare::TYPE_USER, $path, true, -1, 0, $userShares],
434
+                ['user1', IShare::TYPE_GROUP, $path, true, -1, 0, $groupShares],
435
+                ['user1', IShare::TYPE_CIRCLE, $path, true, -1, 0, $circleShares],
436
+                ['user1', IShare::TYPE_ROOM, $path, true, -1, 0, $roomShares],
437
+                ['user1', IShare::TYPE_DECK, $path, true, -1, 0, $deckShares],
438
+            ]);
439
+
440
+        $this->shareManager->expects($this->any())
441
+            ->method('newShare')
442
+            ->willReturnCallback(function () use ($rootFolder, $userManager) {
443
+                return new Share($rootFolder, $userManager);
444
+            });
445
+
446
+        if ($moveFails) {
447
+            $this->shareManager->expects($this->any())
448
+                ->method('moveShare')
449
+                ->willThrowException(new \InvalidArgumentException());
450
+        }
451
+
452
+        $mountArgs = [];
453
+        foreach ($expectedShares as $share) {
454
+            $mountInfo = $this->createMock(ICachedMountInfo::class);
455
+            $mountInfo->method('getUser')->willReturn($this->user);
456
+            $mountInfo->method('getRootId')->willReturn($share[1]);
457
+            $rootCacheEntry = $this->createMock(ICacheEntry::class);
458
+            $mountArg = new MountProviderArgs($mountInfo, $rootCacheEntry);
459
+            $mountArgs[] = $mountArg;
460
+        }
461
+
462
+        if (count($mountArgs) === 0) {
463
+            $mounts = [];
464
+        } else {
465
+            $mounts = $this->provider->getMountsForPath('/', true, $mountArgs, $this->loader);
466
+        }
467
+
468
+
469
+        $this->assertCount(\count($expectedShares), $mounts);
470
+
471
+        foreach (array_values($mounts) as $index => $mount) {
472
+            $expectedShare = $expectedShares[$index];
473
+            $this->assertInstanceOf('OCA\Files_Sharing\SharedMount', $mount);
474
+
475
+            // supershare
476
+            /** @var SharedMount $mount */
477
+            $share = $mount->getShare();
478
+
479
+            $this->assertEquals($expectedShare[0], $share->getId());
480
+            $this->assertEquals($expectedShare[1], $share->getNodeId());
481
+            $this->assertEquals($expectedShare[2], $share->getShareOwner());
482
+            $this->assertEquals($expectedShare[3], $share->getTarget());
483
+            $this->assertEquals($expectedShare[4], $share->getPermissions());
484
+            if ($expectedShare[5] === null) {
485
+                $this->assertNull($share->getAttributes());
486
+            } else {
487
+                $this->assertEquals($expectedShare[5], $share->getAttributes()->toArray());
488
+            }
489
+        }
490
+    }
491 491
 }
Please login to merge, or discard this patch.