Skip to content

Commit 77c9ace

Browse files
committed
Add and remove users from conversations when their group membership changes
Signed-off-by: Joas Schilling <[email protected]>
1 parent 1ce337e commit 77c9ace

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

lib/AppInfo/Application.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
use OCA\Talk\Listener\BeforeUserLoggedOutListener;
4545
use OCA\Talk\Listener\CSPListener;
4646
use OCA\Talk\Listener\FeaturePolicyListener;
47+
use OCA\Talk\Listener\GroupMembershipListener;
4748
use OCA\Talk\Listener\RestrictStartingCalls as RestrictStartingCallsListener;
4849
use OCA\Talk\Listener\UserDeletedListener;
4950
use OCA\Talk\Middleware\CanUseTalkMiddleware;
@@ -69,6 +70,8 @@
6970
use OCP\AppFramework\Utility\ITimeFactory;
7071
use OCP\Collaboration\Resources\IProviderManager;
7172
use OCP\EventDispatcher\IEventDispatcher;
73+
use OCP\Group\Events\UserAddedEvent;
74+
use OCP\Group\Events\UserRemovedEvent;
7275
use OCP\IServerContainer;
7376
use OCP\IUser;
7477
use OCP\Security\CSP\AddContentSecurityPolicyEvent;
@@ -92,6 +95,8 @@ public function register(IRegistrationContext $context): void {
9295
$context->registerEventListener(AddContentSecurityPolicyEvent::class, CSPListener::class);
9396
$context->registerEventListener(AddFeaturePolicyEvent::class, FeaturePolicyListener::class);
9497
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
98+
$context->registerEventListener(UserAddedEvent::class, GroupMembershipListener::class);
99+
$context->registerEventListener(UserRemovedEvent::class, GroupMembershipListener::class);
95100
$context->registerEventListener(BeforeUserLoggedOutEvent::class, BeforeUserLoggedOutListener::class);
96101
$context->registerEventListener(BeforeTemplateRenderedEvent::class, PublicShareTemplateLoader::class);
97102
$context->registerEventListener(BeforeTemplateRenderedEvent::class, PublicShareAuthTemplateLoader::class);
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* @copyright Copyright (c) 2020 Joas Schilling <[email protected]>
6+
*
7+
* @license GNU AGPL version 3 or any later version
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License as
11+
* published by the Free Software Foundation, either version 3 of the
12+
* License, or (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Affero General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Affero General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
namespace OCA\Talk\Listener;
25+
26+
use OCA\Talk\Manager;
27+
use OCA\Talk\Model\Attendee;
28+
use OCA\Talk\Room;
29+
use OCA\Talk\Service\ParticipantService;
30+
use OCP\EventDispatcher\Event;
31+
use OCP\EventDispatcher\IEventListener;
32+
use OCP\Group\Events\UserAddedEvent;
33+
use OCP\Group\Events\UserRemovedEvent;
34+
use OCP\IGroup;
35+
use OCP\IGroupManager;
36+
use OCP\IUser;
37+
38+
class GroupMembershipListener implements IEventListener {
39+
40+
/** @var IGroupManager */
41+
private $groupManager;
42+
/** @var Manager */
43+
private $manager;
44+
/** @var ParticipantService */
45+
private $participantService;
46+
47+
public function __construct(IGroupManager $groupManager,
48+
Manager $manager,
49+
ParticipantService $participantService) {
50+
$this->groupManager = $groupManager;
51+
$this->manager = $manager;
52+
$this->participantService = $participantService;
53+
}
54+
55+
public function handle(Event $event): void {
56+
if ($event instanceof UserAddedEvent) {
57+
$this->addNewMemberToRooms($event->getGroup(), $event->getUser());
58+
}
59+
if ($event instanceof UserRemovedEvent) {
60+
$this->removeFormerMemberFromRooms($event->getGroup(), $event->getUser());
61+
}
62+
}
63+
64+
protected function addNewMemberToRooms(IGroup $group, IUser $user): void {
65+
$rooms = $this->manager->getRoomsForActor(Attendee::ACTOR_GROUP, $group->getGID());
66+
67+
foreach ($rooms as $room) {
68+
$this->participantService->addUsers($room, [[
69+
'actorType' => Attendee::ACTOR_USERS,
70+
'actorId' => $user->getUID(),
71+
]]);
72+
}
73+
}
74+
75+
protected function removeFormerMemberFromRooms(IGroup $group, IUser $user): void {
76+
$rooms = $this->manager->getRoomsForActor(Attendee::ACTOR_GROUP, $group->getGID());
77+
if (empty($rooms)) {
78+
return;
79+
}
80+
81+
$userGroupIds = $this->groupManager->getUserGroupIds($user);
82+
83+
$furtherMemberships = [];
84+
foreach ($userGroupIds as $groupId) {
85+
$groupRooms = $this->manager->getRoomsForActor(Attendee::ACTOR_GROUP, $groupId);
86+
foreach ($groupRooms as $room) {
87+
$furtherMemberships[$room->getId()] = true;
88+
}
89+
}
90+
91+
$rooms = array_filter($rooms, static function (Room $room) use ($furtherMemberships) {
92+
// Only delete from rooms where the user is not member via another group
93+
return !isset($furtherMemberships[$room->getId()]);
94+
});
95+
96+
foreach ($rooms as $room) {
97+
$this->participantService->removeUser($room, $user, Room::PARTICIPANT_REMOVED);
98+
}
99+
}
100+
}

lib/Manager.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,15 +302,25 @@ public function searchRoomsByToken(string $searchToken = '', int $limit = null,
302302
* @return Room[]
303303
*/
304304
public function getRoomsForUser(string $userId, bool $includeLastMessage = false): array {
305+
return $this->getRoomsForActor(Attendee::ACTOR_USERS, $userId, $includeLastMessage);
306+
}
307+
308+
/**
309+
* @param string $actorType
310+
* @param string $actorId
311+
* @param bool $includeLastMessage
312+
* @return Room[]
313+
*/
314+
public function getRoomsForActor(string $actorType, string $actorId, bool $includeLastMessage = false): array {
305315
$query = $this->db->getQueryBuilder();
306316
$helper = new SelectHelper();
307317
$helper->selectRoomsTable($query);
308318
$helper->selectAttendeesTable($query);
309319
$helper->selectSessionsTable($query);
310320
$query->from('talk_rooms', 'r')
311321
->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
312-
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
313-
$query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)),
322+
$query->expr()->eq('a.actor_id', $query->createNamedParameter($actorId)),
323+
$query->expr()->eq('a.actor_type', $query->createNamedParameter($actorType)),
314324
$query->expr()->eq('a.room_id', 'r.id')
315325
))
316326
->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
@@ -331,7 +341,7 @@ public function getRoomsForUser(string $userId, bool $includeLastMessage = false
331341
}
332342

333343
$room = $this->createRoomObject($row);
334-
if ($userId !== null && isset($row['actor_id'])) {
344+
if ($actorType === Attendee::ACTOR_USERS && isset($row['actor_id'])) {
335345
$room->setParticipant($row['actor_id'], $this->createParticipantObject($room, $row));
336346
}
337347
$rooms[] = $room;

0 commit comments

Comments
 (0)