1<?php
2
3declare(strict_types=1);
4/**
5 * @author Joachim Bauch <mail@joachim-bauch.de>
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\Collaboration\Collaborators;
25
26use OCA\Talk\Config;
27use OCA\Talk\Exceptions\ParticipantNotFoundException;
28use OCA\Talk\Exceptions\RoomNotFoundException;
29use OCA\Talk\Manager;
30use OCA\Talk\MatterbridgeManager;
31use OCA\Talk\Model\Attendee;
32use OCA\Talk\Participant;
33use OCA\Talk\Room;
34use OCP\Collaboration\AutoComplete\AutoCompleteEvent;
35use OCP\Collaboration\AutoComplete\IManager;
36use OCP\EventDispatcher\IEventDispatcher;
37use OCP\IUser;
38use OCP\IUserManager;
39
40class Listener {
41
42	/** @var Manager */
43	protected $manager;
44	/** @var IUserManager */
45	protected $userManager;
46	/** @var Config */
47	protected $config;
48	/** @var string[] */
49	protected $allowedGroupIds = [];
50	/** @var string */
51	protected $roomToken;
52	/** @var Room */
53	protected $room;
54
55	public function __construct(Manager $manager,
56								IUserManager $userManager,
57								Config $config) {
58		$this->manager = $manager;
59		$this->userManager = $userManager;
60		$this->config = $config;
61	}
62
63	public static function register(IEventDispatcher $dispatcher): void {
64		$dispatcher->addListener(IManager::class . '::filterResults', static function (AutoCompleteEvent $event) {
65			/** @var self $listener */
66			$listener = \OC::$server->get(self::class);
67
68			if ($event->getItemType() !== 'call') {
69				return;
70			}
71
72			$event->setResults($listener->filterUsersAndGroupsWithoutTalk($event->getResults()));
73
74			$event->setResults($listener->filterBridgeBot($event->getResults()));
75			if ($event->getItemId() !== 'new') {
76				$event->setResults($listener->filterExistingParticipants($event->getItemId(), $event->getResults()));
77			}
78		});
79	}
80
81	protected function filterUsersAndGroupsWithoutTalk(array $results): array {
82		$this->allowedGroupIds = $this->config->getAllowedTalkGroupIds();
83		if (empty($this->allowedGroupIds)) {
84			return $results;
85		}
86
87		if (!empty($results['groups'])) {
88			$results['groups'] = array_filter($results['groups'], [$this, 'filterBlockedGroupResult']);
89		}
90		if (!empty($results['exact']['groups'])) {
91			$results['exact']['groups'] = array_filter($results['exact']['groups'], [$this, 'filterBlockedGroupResult']);
92		}
93
94		if (!empty($results['users'])) {
95			$results['users'] = array_filter($results['users'], [$this, 'filterBlockedUserResult']);
96		}
97		if (!empty($results['exact']['users'])) {
98			$results['exact']['users'] = array_filter($results['exact']['users'], [$this, 'filterBlockedUserResult']);
99		}
100
101		return $results;
102	}
103
104	protected function filterBlockedUserResult(array $result): bool {
105		$user = $this->userManager->get($result['value']['shareWith']);
106		return $user instanceof IUser && !$this->config->isDisabledForUser($user);
107	}
108
109	protected function filterBlockedGroupResult(array $result): bool {
110		return \in_array($result['value']['shareWith'], $this->allowedGroupIds, true);
111	}
112
113	protected function filterBridgeBot(array $results): array {
114		if (!empty($results['users'])) {
115			$results['users'] = array_filter($results['users'], [$this, 'filterBridgeBotUserResult']);
116		}
117		if (!empty($results['exact']['users'])) {
118			$results['exact']['users'] = array_filter($results['exact']['users'], [$this, 'filterBridgeBotUserResult']);
119		}
120
121		return $results;
122	}
123
124	protected function filterExistingParticipants(string $token, array $results): array {
125		try {
126			$this->room = $this->manager->getRoomByToken($token);
127		} catch (RoomNotFoundException $e) {
128			return $results;
129		}
130
131		if (!empty($results['groups'])) {
132			$results['groups'] = array_filter($results['groups'], [$this, 'filterParticipantGroupResult']);
133		}
134		if (!empty($results['exact']['groups'])) {
135			$results['exact']['groups'] = array_filter($results['exact']['groups'], [$this, 'filterParticipantGroupResult']);
136		}
137
138		if (!empty($results['users'])) {
139			$results['users'] = array_filter($results['users'], [$this, 'filterParticipantUserResult']);
140		}
141		if (!empty($results['exact']['users'])) {
142			$results['exact']['users'] = array_filter($results['exact']['users'], [$this, 'filterParticipantUserResult']);
143		}
144
145		return $results;
146	}
147
148	protected function filterBridgeBotUserResult(array $result): bool {
149		return $result['value']['shareWith'] !== MatterbridgeManager::BRIDGE_BOT_USERID;
150	}
151
152	protected function filterParticipantUserResult(array $result): bool {
153		$userId = $result['value']['shareWith'];
154
155		try {
156			$participant = $this->room->getParticipant($userId, false);
157			if ($participant->getAttendee()->getParticipantType() === Participant::USER_SELF_JOINED) {
158				// do list self-joined users so they can be added as permanent participants by moderators
159				return true;
160			}
161			return false;
162		} catch (ParticipantNotFoundException $e) {
163			return true;
164		}
165	}
166
167	protected function filterParticipantGroupResult(array $result): bool {
168		$groupId = $result['value']['shareWith'];
169
170		try {
171			$this->room->getParticipantByActor(Attendee::ACTOR_GROUPS, $groupId);
172			return false;
173		} catch (ParticipantNotFoundException $e) {
174			return true;
175		}
176	}
177}
178