Skip to content

Commit 77c13d1

Browse files
committed
feat: Add sharing activity for teams
This adds support for Teams (previously "Circles"), the user notification already work, but the notification for the owner and sharer need support in the `files_sharing` app. Signed-off-by: Ferdinand Thiessen <[email protected]>
1 parent bf375f5 commit 77c13d1

File tree

3 files changed

+96
-48
lines changed

3 files changed

+96
-48
lines changed

lib/FilesHooks.php

+59-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use OCA\Activity\BackgroundJob\RemoteActivity;
1212
use OCA\Activity\Extension\Files;
1313
use OCA\Activity\Extension\Files_Sharing;
14+
use OCA\Circles\CirclesManager;
15+
use OCA\Circles\Model\Member;
1416
use OCP\Activity\IManager;
1517
use OCP\Constants;
1618
use OCP\Files\Config\IUserMountCache;
@@ -60,7 +62,8 @@ public function __construct(
6062
protected IUserMountCache $userMountCache,
6163
protected IConfig $config,
6264
protected NotificationGenerator $notificationGenerator,
63-
protected ITagManager $tagManager
65+
protected ITagManager $tagManager,
66+
protected ?CirclesManager $teamManager,
6467
) {
6568
}
6669

@@ -664,6 +667,16 @@ public function share($share) {
664667
(int)$share->getId()
665668
);
666669
break;
670+
case IShare::TYPE_CIRCLE:
671+
$this->shareWithTeam(
672+
$share->getSharedWith(),
673+
$share->getNodeId(),
674+
$share->getNodeType(),
675+
$share->getTarget(),
676+
(int)$share->getId(),
677+
$share->getSharedBy(),
678+
);
679+
break;
667680
case IShare::TYPE_LINK:
668681
$this->shareByLink(
669682
$share->getNodeId(),
@@ -726,7 +739,8 @@ protected function shareWithGroup($shareWith, $fileSource, $itemType, $fileTarge
726739
$offset = 0;
727740
$users = $group->searchUsers('', self::USER_BATCH_SIZE, $offset);
728741
while (!empty($users)) {
729-
$this->addNotificationsForGroupUsers($users, 'shared_with_by', $fileSource, $itemType, $fileTarget, $shareId);
742+
$users = array_map(fn (IUser $user) => $user->getUID(), $users);
743+
$this->addNotificationsForUsers($users, 'shared_with_by', $fileSource, $itemType, $fileTarget, $shareId);
730744
$offset += self::USER_BATCH_SIZE;
731745
$users = $group->searchUsers('', self::USER_BATCH_SIZE, $offset);
732746
}
@@ -758,6 +772,42 @@ protected function shareByLink($fileSource, $itemType, $linkOwner) {
758772
);
759773
}
760774

775+
/**
776+
* Sharing a file or folder with a team
777+
*
778+
* @param string $shareWith
779+
* @param int $fileSource File ID that is being shared
780+
* @param string $itemType File type that is being shared (file or folder)
781+
* @param string $fileTarget File path
782+
* @param int $shareId The Share ID of this share
783+
*/
784+
protected function shareWithTeam(string $shareWith, int $fileSource, string $itemType, string $fileTarget, int $shareId, string $sharer): void {
785+
if ($this->teamManager === null) {
786+
return;
787+
}
788+
789+
try {
790+
$this->teamManager->startSuperSession();
791+
$team = $this->teamManager->getCircle($shareWith);
792+
$members = $team->getInheritedMembers();
793+
$members = array_filter($members, fn ($member) => $member->getUserType() === Member::TYPE_USER);
794+
$users = array_map(fn ($member) => $member->getUserId(), $members);
795+
} catch (\Throwable $e) {
796+
$this->logger->debug('Fetching team members for share activity failed', ['exception' => $e]);
797+
// error in teams app - setting users list to empty
798+
$users = [];
799+
}
800+
801+
// Activity for user performing the share
802+
$this->shareNotificationForSharer('shared_team_self', $shareWith, $fileSource, $itemType);
803+
// Activity for original owner of the file (re-sharing)
804+
if ($this->currentUser->getUID() !== null) {
805+
$this->shareNotificationForOriginalOwners($this->currentUser->getUID(), 're-shared_team_by', $shareWith, $fileSource, $itemType);
806+
}
807+
// Activity for all affected users
808+
$this->addNotificationsForUsers($users, 'shared_with_by', $fileSource, $itemType, $fileTarget, $shareId);
809+
}
810+
761811
/**
762812
* Manage unsharing events
763813
*
@@ -878,9 +928,11 @@ protected function unshareFromGroup(IShare $share) {
878928

879929
$offset = 0;
880930
$users = $group->searchUsers('', self::USER_BATCH_SIZE, $offset);
931+
$users = array_map(fn (IUser $user) => $user->getUID(), $users);
881932
$shouldFlush = $this->startActivityTransaction();
882933
while (!empty($users)) {
883-
$this->addNotificationsForGroupUsers($users, $actionUser, $share->getNodeId(), $share->getNodeType(), $share->getTarget(), (int) $share->getId());
934+
$userIds = array_map(fn (IUser $user) => $user->getUID(), $users);
935+
$this->addNotificationsForUsers($userIds, $actionUser, $share->getNodeId(), $share->getNodeType(), $share->getTarget(), (int)$share->getId());
884936
$offset += self::USER_BATCH_SIZE;
885937
$users = $group->searchUsers('', self::USER_BATCH_SIZE, $offset);
886938
}
@@ -940,18 +992,18 @@ protected function unshareLink(IShare $share) {
940992
}
941993

942994
/**
943-
* @param IUser[] $usersInGroup
995+
* @param string[] $usersIds
944996
* @param string $actionUser
945997
* @param int $fileSource File ID that is being shared
946998
* @param string $itemType File type that is being shared (file or folder)
947999
* @param string $fileTarget File path
9481000
* @param int $shareId The Share ID of this share
9491001
*/
950-
protected function addNotificationsForGroupUsers(array $usersInGroup, $actionUser, $fileSource, $itemType, $fileTarget, $shareId) {
1002+
protected function addNotificationsForUsers(array $usersIds, $actionUser, $fileSource, $itemType, $fileTarget, $shareId) {
9511003
$affectedUsers = [];
9521004

953-
foreach ($usersInGroup as $user) {
954-
$affectedUsers[$user->getUID()] = $fileTarget;
1005+
foreach ($usersIds as $user) {
1006+
$affectedUsers[$user] = $fileTarget;
9551007
}
9561008

9571009
// Remove the triggering user, we already managed his notifications

tests/FilesHooksTest.php

+24-31
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
use OCA\Activity\Extension\Files;
3232
use OCA\Activity\Extension\Files_Sharing;
3333
use OCA\Activity\Tests\TestCase;
34+
use OCA\Circles\CirclesManager;
3435
use OCA\Files_Sharing\SharedStorage;
3536
use OCP\Activity\IEvent;
3637
use OCP\Activity\IManager;
@@ -39,6 +40,7 @@
3940
use OCP\Files\Mount\IMountPoint;
4041
use OCP\Files\NotFoundException;
4142
use OCP\IConfig;
43+
use OCP\IDBConnection;
4244
use OCP\IGroup;
4345
use OCP\IGroupManager;
4446
use OCP\IURLGenerator;
@@ -57,33 +59,21 @@
5759
* @package OCA\Activity
5860
*/
5961
class FilesHooksTest extends TestCase {
60-
/** @var FilesHooks */
61-
protected $filesHooks;
62-
/** @var IManager|MockObject */
63-
protected $activityManager;
64-
/** @var Data|MockObject */
65-
protected $data;
66-
/** @var UserSettings|MockObject */
67-
protected $settings;
68-
/** @var IGroupManager|MockObject */
69-
protected $groupManager;
70-
/** @var View|MockObject */
71-
protected $view;
72-
/** @var IRootFolder|MockObject */
73-
protected $rootFolder;
74-
/** @var IShareHelper|MockObject */
75-
protected $shareHelper;
76-
/** @var IURLGenerator|MockObject */
77-
protected $urlGenerator;
78-
/** @var IUserMountCache|MockObject */
79-
protected $userMountCache;
80-
/** @var IConfig|MockObject */
81-
protected $config;
82-
/** @var NotificationGenerator|MockObject */
83-
protected $notificationGenerator;
84-
/** @var TagManager|MockObject */
85-
protected $tagManager;
62+
protected FilesHooks $filesHooks;
63+
protected IManager&MockObject $activityManager;
64+
protected Data&MockObject $data;
65+
protected UserSettings&MockObject $settings;
66+
protected IGroupManager&MockObject $groupManager;
67+
protected View&MockObject $view;
68+
protected IRootFolder&MockObject $rootFolder;
69+
protected IShareHelper&MockObject $shareHelper;
70+
protected IURLGenerator&MockObject $urlGenerator;
71+
protected IUserMountCache&MockObject $userMountCache;
72+
protected IConfig&MockObject $config;
73+
protected NotificationGenerator&MockObject $notificationGenerator;
74+
protected TagManager&MockObject $tagManager;
8675
protected $tags;
76+
protected (CirclesManager&MockObject)|null $teamManager;
8777

8878
protected function setUp(): void {
8979
parent::setUp();
@@ -103,6 +93,7 @@ protected function setUp(): void {
10393
$this->tags = $this->createMock(Tags::class);
10494
$this->tagManager->method('getUsersFavoritingObject')
10595
->willReturn([]);
96+
$this->teamManager = null;
10697

10798
$this->tagManager->method('load')
10899
->willReturn($this->tags);
@@ -113,7 +104,7 @@ protected function setUp(): void {
113104
/**
114105
* @param array $mockedMethods
115106
* @param string $user
116-
* @return FilesHooks|MockObject
107+
* @return FilesHooks&MockObject
117108
*/
118109
protected function getFilesHooks(array $mockedMethods = [], string $user = 'user'): FilesHooks {
119110
$currentUser = $this->createMock(CurrentUser::class);
@@ -136,14 +127,15 @@ protected function getFilesHooks(array $mockedMethods = [], string $user = 'user
136127
$this->view,
137128
$this->rootFolder,
138129
$this->shareHelper,
139-
\OC::$server->getDatabaseConnection(),
130+
\OCP\Server::get(IDBConnection::class),
140131
$this->urlGenerator,
141132
$logger,
142133
$currentUser,
143134
$this->userMountCache,
144135
$this->config,
145136
$this->notificationGenerator,
146-
$this->tagManager
137+
$this->tagManager,
138+
$this->teamManager,
147139
])
148140
->onlyMethods($mockedMethods)
149141
->getMock();
@@ -157,14 +149,15 @@ protected function getFilesHooks(array $mockedMethods = [], string $user = 'user
157149
$this->view,
158150
$this->rootFolder,
159151
$this->shareHelper,
160-
\OC::$server->getDatabaseConnection(),
152+
\OCP\Server::get(IDBConnection::class),
161153
$this->urlGenerator,
162154
$logger,
163155
$currentUser,
164156
$this->userMountCache,
165157
$this->config,
166158
$this->notificationGenerator,
167-
$this->tagManager
159+
$this->tagManager,
160+
$this->teamManager,
168161
);
169162
}
170163

tests/psalm-baseline.xml

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<files psalm-version="5.19.0@06b71be009a6bd6d81b9811855d6629b9fe90e1b">
2+
<files psalm-version="5.25.0@01a8eb06b9e9cc6cfb6a320bf9fb14331919d505">
33
<file src="lib/BackgroundJob/RemoteActivity.php">
44
<UndefinedClass>
5-
<code>ClientException</code>
5+
<code><![CDATA[ClientException]]></code>
66
</UndefinedClass>
77
</file>
88
<file src="lib/CurrentUser.php">
@@ -21,27 +21,30 @@
2121
</InvalidArrayOffset>
2222
</file>
2323
<file src="lib/FilesHooks.php">
24-
<InvalidArgument>
25-
<code><![CDATA[$share->getId()]]></code>
26-
</InvalidArgument>
24+
<UndefinedClass>
25+
<code><![CDATA[$this->teamManager]]></code>
26+
<code><![CDATA[$this->teamManager]]></code>
27+
<code><![CDATA[Member]]></code>
28+
<code><![CDATA[protected]]></code>
29+
</UndefinedClass>
2730
<UndefinedDocblockClass>
28-
<code>$shareOwner</code>
29-
<code>$storage</code>
31+
<code><![CDATA[$shareOwner]]></code>
32+
<code><![CDATA[$storage]]></code>
3033
</UndefinedDocblockClass>
3134
</file>
3235
<file src="lib/Migration/Version2008Date20181011095117.php">
3336
<UndefinedClass>
34-
<code>SchemaException</code>
37+
<code><![CDATA[SchemaException]]></code>
3538
</UndefinedClass>
3639
</file>
3740
<file src="lib/Migration/Version2011Date20201006132544.php">
3841
<UndefinedClass>
39-
<code>Type</code>
42+
<code><![CDATA[Type]]></code>
4043
</UndefinedClass>
4144
</file>
4245
<file src="lib/Migration/Version2011Date20201006132545.php">
4346
<UndefinedClass>
44-
<code>Type</code>
47+
<code><![CDATA[Type]]></code>
4548
</UndefinedClass>
4649
</file>
4750
</files>

0 commit comments

Comments
 (0)