1<?php
2
3declare(strict_types=1);
4/**
5 * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
6 *
7 * @author Joas Schilling <coding@schilljs.com>
8 *
9 * @license GNU AGPL version 3 or any later version
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Affero General Public License as
13 * published by the Free Software Foundation, either version 3 of the
14 * License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Affero General Public License for more details.
20 *
21 * You should have received a copy of the GNU Affero General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26namespace OCA\Talk;
27
28use OCA\Talk\Model\Attendee;
29use OCA\Talk\Model\Session;
30use OCP\IConfig;
31
32class Participant {
33	public const OWNER = 1;
34	public const MODERATOR = 2;
35	public const USER = 3;
36	public const GUEST = 4;
37	public const USER_SELF_JOINED = 5;
38	public const GUEST_MODERATOR = 6;
39
40	public const FLAG_DISCONNECTED = 0;
41	public const FLAG_IN_CALL = 1;
42	public const FLAG_WITH_AUDIO = 2;
43	public const FLAG_WITH_VIDEO = 4;
44	public const FLAG_WITH_PHONE = 8;
45
46	public const NOTIFY_DEFAULT = 0;
47	public const NOTIFY_ALWAYS = 1;
48	public const NOTIFY_MENTION = 2;
49	public const NOTIFY_NEVER = 3;
50
51	public const NOTIFY_CALLS_OFF = 0;
52	public const NOTIFY_CALLS_ON = 1;
53
54	public const PRIVACY_PUBLIC = 0;
55	public const PRIVACY_PRIVATE = 1;
56
57	/** @var Room */
58	protected $room;
59	/** @var Attendee */
60	protected $attendee;
61	/** @var Session|null */
62	protected $session;
63
64	public function __construct(Room $room,
65								Attendee $attendee,
66								?Session $session) {
67		$this->room = $room;
68		$this->attendee = $attendee;
69		$this->session = $session;
70	}
71
72	public function getAttendee(): Attendee {
73		return $this->attendee;
74	}
75
76	public function getSession(): ?Session {
77		return $this->session;
78	}
79
80	public function setSession(Session $session): void {
81		$this->session = $session;
82	}
83
84	public function isGuest(): bool {
85		$participantType = $this->attendee->getParticipantType();
86		return \in_array($participantType, [self::GUEST, self::GUEST_MODERATOR], true);
87	}
88
89	public function hasModeratorPermissions(bool $guestModeratorAllowed = true): bool {
90		$participantType = $this->attendee->getParticipantType();
91		if (!$guestModeratorAllowed) {
92			return \in_array($participantType, [self::OWNER, self::MODERATOR], true);
93		}
94
95		return \in_array($participantType, [self::OWNER, self::MODERATOR, self::GUEST_MODERATOR], true);
96	}
97
98	public function canStartCall(IConfig $config): bool {
99		$defaultStartCall = (int) $config->getAppValue('spreed', 'start_calls', Room::START_CALL_EVERYONE);
100
101		if (!($this->getPermissions() & Attendee::PERMISSIONS_CALL_START)) {
102			return false;
103		}
104
105		if ($defaultStartCall === Room::START_CALL_EVERYONE) {
106			return true;
107		}
108
109		if ($defaultStartCall === Room::START_CALL_USERS && (!$this->isGuest() || $this->hasModeratorPermissions())) {
110			return true;
111		}
112
113		if ($defaultStartCall === Room::START_CALL_MODERATORS && $this->hasModeratorPermissions()) {
114			return true;
115		}
116
117		return false;
118	}
119
120	public function getPermissions(): int {
121		$permissions = $this->getPermissionsFromFallbackChain();
122
123		if ($this->hasModeratorPermissions()) {
124			// Moderators can always do everything
125			$permissions = Attendee::PERMISSIONS_MAX_DEFAULT;
126		}
127
128		return $permissions;
129	}
130
131	protected function getPermissionsFromFallbackChain(): int {
132		if ($this->getAttendee()->getPermissions() !== Attendee::PERMISSIONS_DEFAULT) {
133			return $this->getAttendee()->getPermissions();
134		}
135
136		if ($this->room->getCallPermissions() !== Attendee::PERMISSIONS_DEFAULT) {
137			// The currently ongoing call is in a special mode
138			return $this->room->getCallPermissions();
139		}
140
141		if ($this->room->getDefaultPermissions() !== Attendee::PERMISSIONS_DEFAULT) {
142			// The conversation has some permissions set
143			return $this->room->getDefaultPermissions();
144		}
145
146		// Falling back to an unrestricted set of permissions, only ignoring the lobby is off
147		return Attendee::PERMISSIONS_MAX_DEFAULT & ~Attendee::PERMISSIONS_LOBBY_IGNORE;
148	}
149}
150