1<?php 2 3declare(strict_types=1); 4/** 5 * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com> 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 24namespace OCA\Talk\Listener; 25 26use OCA\Circles\CirclesManager; 27use OCA\Circles\Model\Member; 28use OCA\Talk\Exceptions\ParticipantNotFoundException; 29use OCA\Talk\Manager; 30use OCA\Talk\Model\Attendee; 31use OCA\Talk\Participant; 32use OCA\Talk\Room; 33use OCA\Talk\Service\ParticipantService; 34use OCP\App\IAppManager; 35use OCP\EventDispatcher\IEventListener; 36use OCP\IGroupManager; 37use OCP\IUser; 38use Psr\Log\LoggerInterface; 39 40abstract class AMembershipListener implements IEventListener { 41 42 /** @var Manager */ 43 protected $manager; 44 /** @var IAppManager */ 45 protected $appManager; 46 /** @var IGroupManager */ 47 protected $groupManager; 48 /** @var ParticipantService */ 49 protected $participantService; 50 51 public function __construct(Manager $manager, 52 IAppManager $appManager, 53 IGroupManager $groupManager, 54 ParticipantService $participantService) { 55 $this->manager = $manager; 56 $this->appManager = $appManager; 57 $this->groupManager = $groupManager; 58 $this->participantService = $participantService; 59 } 60 61 protected function removeFromRoomsUnlessStillLinked(array $rooms, IUser $user): void { 62 $rooms = $this->filterRoomsWithOtherGroupMemberships($rooms, $user); 63 $rooms = $this->filterRoomsWithOtherCircleMemberships($rooms, $user); 64 65 foreach ($rooms as $room) { 66 try { 67 $participant = $room->getParticipant($user->getUID()); 68 $participantType = $participant->getAttendee()->getParticipantType(); 69 if ($participantType === Participant::USER) { 70 $this->participantService->removeUser($room, $user, Room::PARTICIPANT_REMOVED); 71 } 72 } catch (ParticipantNotFoundException $e) { 73 } 74 } 75 } 76 77 protected function filterRoomsWithOtherGroupMemberships(array $rooms, IUser $user): array { 78 $userGroupIds = $this->groupManager->getUserGroupIds($user); 79 80 $furtherMemberships = []; 81 foreach ($userGroupIds as $groupId) { 82 $groupRooms = $this->manager->getRoomsForActor(Attendee::ACTOR_GROUPS, $groupId); 83 foreach ($groupRooms as $room) { 84 $furtherMemberships[$room->getId()] = true; 85 } 86 } 87 88 return array_filter($rooms, static function (Room $room) use ($furtherMemberships) { 89 // Only delete from rooms where the user is not member via another group 90 return !isset($furtherMemberships[$room->getId()]); 91 }); 92 } 93 94 protected function filterRoomsWithOtherCircleMemberships(array $rooms, IUser $user): array { 95 if (!$this->appManager->isEnabledForUser('circles', $user)) { 96 \OC::$server->get(LoggerInterface::class)->debug('Circles not enabled', ['app' => 'spreed']); 97 return $rooms; 98 } 99 100 try { 101 $circlesManager = \OC::$server->get(CirclesManager::class); 102 $federatedUser = $circlesManager->getFederatedUser($user->getUID(), Member::TYPE_USER); 103 $memberships = $federatedUser->getMemberships(); 104 } catch (\Exception $e) { 105 return $rooms; 106 } 107 108 $furtherMemberships = []; 109 foreach ($memberships as $membership) { 110 $circleRooms = $this->manager->getRoomsForActor(Attendee::ACTOR_CIRCLES, $membership->getCircleId()); 111 112 foreach ($circleRooms as $room) { 113 $furtherMemberships[$room->getId()] = true; 114 } 115 } 116 117 return array_filter($rooms, static function (Room $room) use ($furtherMemberships) { 118 // Only delete from rooms where the user is not member via another group 119 return !isset($furtherMemberships[$room->getId()]); 120 }); 121 } 122} 123