Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2021-08-25 18:30:20 +0300
committerJoas Schilling <coding@schilljs.com>2021-08-25 18:30:20 +0300
commita073dc4f5ef63b5c068a56aa69b4178757b237cc (patch)
treea9629d60f103cbaac205fcee8af79839f6df9fb7 /lib
parent1253bb22e8a0dee0a7f7eb25d629800ce40e7dca (diff)
Also remove circle members when removing a circle
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Service/MembershipService.php122
-rw-r--r--lib/Service/ParticipantService.php92
2 files changed, 198 insertions, 16 deletions
diff --git a/lib/Service/MembershipService.php b/lib/Service/MembershipService.php
new file mode 100644
index 000000000..511d89a9b
--- /dev/null
+++ b/lib/Service/MembershipService.php
@@ -0,0 +1,122 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Service;
+
+use OCA\Circles\CirclesManager;
+use OCA\Circles\Model\Member;
+use OCA\Circles\Model\Membership;
+use OCA\Talk\Model\Attendee;
+use OCA\Talk\Model\AttendeeMapper;
+use OCA\Talk\Room;
+use OCP\App\IAppManager;
+use OCP\IGroupManager;
+use OCP\IUser;
+use Psr\Log\LoggerInterface;
+
+class MembershipService {
+
+ /** @var IAppManager */
+ protected $appManager;
+ /** @var IGroupManager */
+ protected $groupManager;
+ /** @var AttendeeMapper */
+ protected $attendeeMapper;
+
+ public function __construct(IAppManager $appManager,
+ IGroupManager $groupManager,
+ AttendeeMapper $attendeeMapper) {
+ $this->appManager = $appManager;
+ $this->groupManager = $groupManager;
+ $this->attendeeMapper = $attendeeMapper;
+ }
+
+ /**
+ * @param Room $room
+ * @param IUser[] $users
+ * @return IUser[]
+ */
+ public function getUsersWithoutOtherMemberships(Room $room, array $users): array {
+ $users = $this->filterUsersWithOtherGroupMemberships($room, $users);
+ $users = $this->filterUsersWithOtherCircleMemberships($room, $users);
+ return $users;
+ }
+
+ /**
+ * @param Room $room
+ * @param IUser[] $users
+ * @return IUser[]
+ */
+ protected function filterUsersWithOtherGroupMemberships(Room $room, array $users): array {
+ $groupAttendees = $this->attendeeMapper->getActorsByType($room->getId(), Attendee::ACTOR_GROUPS);
+ $groupIds = array_map(static function(Attendee $attendee) {
+ return $attendee->getActorId();
+ }, $groupAttendees);
+
+ if (empty($groupIds)) {
+ return $users;
+ }
+
+ return array_filter($users, function (IUser $user) use ($groupIds) {
+ // Only delete users when the user is not member via another group
+ $userGroups = $this->groupManager->getUserGroupIds($user);
+ return empty(array_intersect($userGroups, $groupIds));
+ });
+ }
+
+ /**
+ * @param Room $room
+ * @param IUser[] $users
+ * @return IUser[]
+ */
+ protected function filterUsersWithOtherCircleMemberships(Room $room, array $users): array {
+ if (empty($users)) {
+ return $users;
+ }
+ $anyUser = reset($users);
+ if (!$this->appManager->isEnabledForUser('circles', $anyUser)) {
+ \OC::$server->get(LoggerInterface::class)->debug('Circles not enabled', ['app' => 'spreed']);
+ return $users;
+ }
+
+ $circleAttendees = $this->attendeeMapper->getActorsByType($room->getId(), Attendee::ACTOR_CIRCLES);
+ $circleIds = array_map(static function(Attendee $attendee) {
+ return $attendee->getActorId();
+ }, $circleAttendees);
+
+ if (empty($circleIds)) {
+ return $users;
+ }
+
+ $circlesManager = \OC::$server->get(CirclesManager::class);
+ return array_filter($users, function (IUser $user) use ($circlesManager, $circleIds) {
+ // Only delete users when the user is not member via another circle
+ $federatedUser = $circlesManager->getFederatedUser($user->getUID(), Member::TYPE_USER);
+ $memberships = $federatedUser->getMemberships();
+ $userCircles = array_map(static function(Membership $membership) {
+ return $membership->getCircleId();
+ }, $memberships);
+ return empty(array_intersect($userCircles, $circleIds));
+ });
+ }
+}
diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php
index a79dc5f71..d564a2e47 100644
--- a/lib/Service/ParticipantService.php
+++ b/lib/Service/ParticipantService.php
@@ -82,6 +82,8 @@ class ParticipantService {
private $userManager;
/** @var IGroupManager */
private $groupManager;
+ /** @var MembershipService */
+ private $membershipService;
/** @var ITimeFactory */
private $timeFactory;
@@ -95,6 +97,7 @@ class ParticipantService {
IEventDispatcher $dispatcher,
IUserManager $userManager,
IGroupManager $groupManager,
+ MembershipService $membershipService,
ITimeFactory $timeFactory) {
$this->serverConfig = $serverConfig;
$this->talkConfig = $talkConfig;
@@ -106,6 +109,7 @@ class ParticipantService {
$this->dispatcher = $dispatcher;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
+ $this->membershipService = $membershipService;
$this->timeFactory = $timeFactory;
}
@@ -426,7 +430,7 @@ class ParticipantService {
} catch (\Exception $e) {
}
- $circlesManager->stopSession($federatedUser);
+ $circlesManager->stopSession();
throw new ParticipantNotFoundException('Circle not found or not a member');
}
@@ -629,40 +633,96 @@ class ParticipantService {
if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_GROUPS) {
$this->removeGroupMembers($room, $participant, $reason);
+ } else if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_CIRCLES) {
+ $this->removeCircleMembers($room, $participant, $reason);
}
}
+ public function getActorsByType(Room $room, string $actorType): array {
+ return $this->attendeeMapper->getActorsByType($room->getId(), $actorType);
+ }
+
public function removeGroupMembers(Room $room, Participant $removedGroupParticipant, string $reason): void {
$removedGroup = $this->groupManager->get($removedGroupParticipant->getAttendee()->getActorId());
if (!$removedGroup instanceof IGroup) {
return;
}
- $attendeeGroups = $this->attendeeMapper->getActorsByType($room->getId(), Attendee::ACTOR_GROUPS);
-
- $groupsInRoom = [];
- foreach ($attendeeGroups as $attendee) {
- $groupsInRoom[] = $attendee->getActorId();
- }
-
+ $users = $this->membershipService->getUsersWithoutOtherMemberships($room, $removedGroup->getUsers());
$attendees = [];
- foreach ($removedGroup->getUsers() as $user) {
+ foreach ($users as $user) {
try {
$participant = $room->getParticipant($user->getUID());
+ $participantType = $participant->getAttendee()->getParticipantType();
+
+ $attendees[] = $participant->getAttendee();
+ if ($participantType === Participant::USER) {
+ // Only remove normal users, not moderators/admins
+ $this->removeAttendee($room, $participant, $reason, true);
+ }
} catch (ParticipantNotFoundException $e) {
+ }
+ }
+
+ $attendeeEvent = new AttendeesRemovedEvent($room, $attendees);
+ $this->dispatcher->dispatchTyped($attendeeEvent);
+ }
+
+ public function removeCircleMembers(Room $room, Participant $removedCircleParticipant, string $reason): void {
+ try {
+ $circlesManager = \OC::$server->get(CirclesManager::class);
+ $circlesManager->startSuperSession();
+ $circle = $circlesManager->getCircle($removedCircleParticipant->getAttendee()->getActorId());
+ $circlesManager->stopSession();
+ } catch (\Exception $e) {
+ // Circles not enabled
+ return;
+ }
+
+ $circlesManager->startSuperSession();
+ try {
+ $circle = $circlesManager->getCircle($removedCircleParticipant->getAttendee()->getActorId());
+ $circlesManager->stopSession();
+ } catch (\Exception $e) {
+ $circlesManager->stopSession();
+ return;
+ }
+
+ $membersInCircle = $circle->getInheritedMembers();
+ $users = [];
+ foreach ($membersInCircle as $member) {
+ /** @var Member $member */
+ if ($member->getUserType() !== Member::TYPE_USER || $member->getUserId() === '') {
+ // Not a user?
continue;
}
- $userGroups = $this->groupManager->getUserGroupIds($user);
- $stillHasGroup = array_intersect($userGroups, $groupsInRoom);
- if (!empty($stillHasGroup)) {
+ if ($member->getStatus() !== Member::STATUS_INVITED && $member->getStatus() !== Member::STATUS_MEMBER) {
+ // Only allow invited and regular members
continue;
}
- $attendees[] = $participant->getAttendee();
- if ($participant->getAttendee()->getParticipantType() === Participant::USER) {
- // Only remove normal users, not moderators/admins
- $this->removeAttendee($room, $participant, $reason, true);
+ $users[] = $this->userManager->get($member->getUserId());
+ }
+
+
+ if (empty($users)) {
+ return;
+ }
+
+ $users = $this->membershipService->getUsersWithoutOtherMemberships($room, $users);
+ $attendees = [];
+ foreach ($users as $user) {
+ try {
+ $participant = $room->getParticipant($user->getUID());
+ $participantType = $participant->getAttendee()->getParticipantType();
+
+ $attendees[] = $participant->getAttendee();
+ if ($participantType === Participant::USER) {
+ // Only remove normal users, not moderators/admins
+ $this->removeAttendee($room, $participant, $reason, true);
+ }
+ } catch (ParticipantNotFoundException $e) {
}
}