Skip to content

Commit 0e06c4f

Browse files
susnuxAndyScherzinger
authored andcommitted
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 <opensource@fthiessen.de>
1 parent bf7497a commit 0e06c4f

File tree

3 files changed

+99
-48
lines changed

3 files changed

+99
-48
lines changed

lib/FilesHooks.php

Lines changed: 59 additions & 7 deletions
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

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
use OCP\Files\Mount\IMountPoint;
4040
use OCP\Files\NotFoundException;
4141
use OCP\IConfig;
42+
use OCP\IDBConnection;
4243
use OCP\IGroup;
4344
use OCP\IGroupManager;
4445
use OCP\IURLGenerator;
@@ -57,33 +58,25 @@
5758
* @package OCA\Activity
5859
*/
5960
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;
61+
protected FilesHooks $filesHooks;
62+
protected IManager&MockObject $activityManager;
63+
protected Data&MockObject $data;
64+
protected UserSettings&MockObject $settings;
65+
protected IGroupManager&MockObject $groupManager;
66+
protected View&MockObject $view;
67+
protected IRootFolder&MockObject $rootFolder;
68+
protected IShareHelper&MockObject $shareHelper;
69+
protected IURLGenerator&MockObject $urlGenerator;
70+
protected IUserMountCache&MockObject $userMountCache;
71+
protected IConfig&MockObject $config;
72+
protected NotificationGenerator&MockObject $notificationGenerator;
73+
protected TagManager&MockObject $tagManager;
8674
protected $tags;
75+
/**
76+
* @todo With PHP 8.2 we can put this directly on the declaration instead of a comment but 8.1 does not allow the parenthesis
77+
* @var (OCA\Circles\CirclesManager&MockObject)|null
78+
*/
79+
protected $teamManager;
8780

8881
protected function setUp(): void {
8982
parent::setUp();
@@ -103,6 +96,7 @@ protected function setUp(): void {
10396
$this->tags = $this->createMock(Tags::class);
10497
$this->tagManager->method('getUsersFavoritingObject')
10598
->willReturn([]);
99+
$this->teamManager = null;
106100

107101
$this->tagManager->method('load')
108102
->willReturn($this->tags);
@@ -113,7 +107,7 @@ protected function setUp(): void {
113107
/**
114108
* @param array $mockedMethods
115109
* @param string $user
116-
* @return FilesHooks|MockObject
110+
* @return FilesHooks&MockObject
117111
*/
118112
protected function getFilesHooks(array $mockedMethods = [], string $user = 'user'): FilesHooks {
119113
$currentUser = $this->createMock(CurrentUser::class);
@@ -136,14 +130,15 @@ protected function getFilesHooks(array $mockedMethods = [], string $user = 'user
136130
$this->view,
137131
$this->rootFolder,
138132
$this->shareHelper,
139-
\OC::$server->getDatabaseConnection(),
133+
\OCP\Server::get(IDBConnection::class),
140134
$this->urlGenerator,
141135
$logger,
142136
$currentUser,
143137
$this->userMountCache,
144138
$this->config,
145139
$this->notificationGenerator,
146-
$this->tagManager
140+
$this->tagManager,
141+
$this->teamManager,
147142
])
148143
->onlyMethods($mockedMethods)
149144
->getMock();
@@ -157,14 +152,15 @@ protected function getFilesHooks(array $mockedMethods = [], string $user = 'user
157152
$this->view,
158153
$this->rootFolder,
159154
$this->shareHelper,
160-
\OC::$server->getDatabaseConnection(),
155+
\OCP\Server::get(IDBConnection::class),
161156
$this->urlGenerator,
162157
$logger,
163158
$currentUser,
164159
$this->userMountCache,
165160
$this->config,
166161
$this->notificationGenerator,
167-
$this->tagManager
162+
$this->tagManager,
163+
$this->teamManager,
168164
);
169165
}
170166

tests/psalm-baseline.xml

Lines changed: 13 additions & 10 deletions
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)