diff --git a/appinfo/info.xml b/appinfo/info.xml
index 792402e113e..2108f0004de 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -16,7 +16,7 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
]]>
- 11.0.0-dev.6
+ 11.0.0-dev.7
agpl
Daniel Calviño Sánchez
diff --git a/appinfo/routes.php b/appinfo/routes.php
index a97fc9fb1e6..130359c62c5 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -109,7 +109,7 @@
'url' => '/api/{apiVersion}/call/{token}',
'verb' => 'GET',
'requirements' => [
- 'apiVersion' => 'v1',
+ 'apiVersion' => 'v(1|2|3)',
'token' => '^[a-z0-9]{4,30}$',
],
],
@@ -118,7 +118,7 @@
'url' => '/api/{apiVersion}/call/{token}',
'verb' => 'POST',
'requirements' => [
- 'apiVersion' => 'v1',
+ 'apiVersion' => 'v(1|2|3)',
'token' => '^[a-z0-9]{4,30}$',
],
],
@@ -127,7 +127,7 @@
'url' => '/api/{apiVersion}/call/{token}',
'verb' => 'DELETE',
'requirements' => [
- 'apiVersion' => 'v1',
+ 'apiVersion' => 'v(1|2|3)',
'token' => '^[a-z0-9]{4,30}$',
],
],
diff --git a/img/phone.png b/img/phone.png
new file mode 100644
index 00000000000..c385083f17f
Binary files /dev/null and b/img/phone.png differ
diff --git a/lib/Activity/Listener.php b/lib/Activity/Listener.php
index cc1c69ce5f0..47449606775 100644
--- a/lib/Activity/Listener.php
+++ b/lib/Activity/Listener.php
@@ -27,6 +27,7 @@
use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\ModifyParticipantEvent;
use OCA\Talk\Events\RoomEvent;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCP\Activity\IManager;
@@ -129,7 +130,7 @@ public function generateCallActivity(Room $room): bool {
}
$actorId = $userIds[0] ?? 'guests-only';
- $actorType = $actorId !== 'guests-only' ? 'users' : 'guests';
+ $actorType = $actorId !== 'guests-only' ? Attendee::ACTOR_USERS : Attendee::ACTOR_GUESTS;
$this->chatManager->addSystemMessage($room, $actorType, $actorId, json_encode([
'message' => 'call_ended',
'parameters' => [
@@ -205,7 +206,7 @@ public function generateInvitationActivity(Room $room, array $participants): voi
}
foreach ($participants as $participant) {
- if ($participant['actorType'] !== 'users') {
+ if ($participant['actorType'] !== Attendee::ACTOR_USERS) {
// No user => no activity
continue;
}
diff --git a/lib/Chat/AutoComplete/SearchPlugin.php b/lib/Chat/AutoComplete/SearchPlugin.php
index 3469339e5c4..770c963634b 100644
--- a/lib/Chat/AutoComplete/SearchPlugin.php
+++ b/lib/Chat/AutoComplete/SearchPlugin.php
@@ -25,6 +25,7 @@
use OCA\Talk\Files\Util;
use OCA\Talk\GuestManager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\TalkSession;
@@ -102,9 +103,9 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) {
$participants = $this->participantService->getParticipantsForRoom($this->room);
foreach ($participants as $participant) {
$attendee = $participant->getAttendee();
- if ($attendee->getActorType() === 'guests') {
+ if ($attendee->getActorType() === Attendee::ACTOR_GUESTS) {
$guestSessionHashes[] = $attendee->getActorId();
- } elseif ($attendee->getActorType() === 'users') {
+ } elseif ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$userIds[] = $attendee->getActorId();
}
}
diff --git a/lib/Chat/ChatManager.php b/lib/Chat/ChatManager.php
index 3a3d615910c..6b43981db30 100644
--- a/lib/Chat/ChatManager.php
+++ b/lib/Chat/ChatManager.php
@@ -28,6 +28,7 @@
use OC\Memcache\NullCache;
use OCA\Talk\Events\ChatEvent;
use OCA\Talk\Events\ChatParticipantEvent;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
@@ -144,7 +145,7 @@ public function addSystemMessage(Room $chat, string $actorType, string $actorId,
* @return IComment
*/
public function addChangelogMessage(Room $chat, string $message): IComment {
- $comment = $this->commentsManager->create('guests', 'changelog', 'chat', (string) $chat->getId());
+ $comment = $this->commentsManager->create(Attendee::ACTOR_GUESTS, 'changelog', 'chat', (string) $chat->getId());
$comment->setMessage($message, self::MAX_CHAT_LENGTH);
$comment->setCreationDateTime($this->timeFactory->getDateTime());
diff --git a/lib/Chat/Command/Executor.php b/lib/Chat/Command/Executor.php
index 21a01fce954..0862936c4bb 100644
--- a/lib/Chat/Command/Executor.php
+++ b/lib/Chat/Command/Executor.php
@@ -25,6 +25,7 @@
use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Events\CommandEvent;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Command;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -90,7 +91,7 @@ public function exec(Room $room, IComment $message, Command $command, string $ar
try {
$command = $this->commandService->resolveAlias($command);
} catch (DoesNotExistException $e) {
- $user = $message->getActorType() === 'users' ? $message->getActorId() : '';
+ $user = $message->getActorType() === Attendee::ACTOR_USERS ? $message->getActorId() : '';
$message->setMessage(json_encode([
'user' => $user,
'visibility' => $command->getResponse(),
@@ -109,7 +110,7 @@ public function exec(Room $room, IComment $message, Command $command, string $ar
$output = $this->execShell($room, $message, $command, $arguments);
}
- $user = $message->getActorType() === 'users' ? $message->getActorId() : '';
+ $user = $message->getActorType() === Attendee::ACTOR_USERS ? $message->getActorId() : '';
$message->setMessage(json_encode([
'user' => $user,
'visibility' => $command->getResponse(),
@@ -205,7 +206,7 @@ public function execShell(Room $room, IComment $message, Command $command, strin
$command->getScript(),
$arguments,
$room->getToken(),
- $message->getActorType() === 'users' ? $message->getActorId() : ''
+ $message->getActorType() === Attendee::ACTOR_USERS ? $message->getActorId() : ''
);
} catch (\InvalidArgumentException $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
diff --git a/lib/Chat/MessageParser.php b/lib/Chat/MessageParser.php
index 176be751e68..ebea4d20bea 100644
--- a/lib/Chat/MessageParser.php
+++ b/lib/Chat/MessageParser.php
@@ -27,6 +27,7 @@
use OCA\Talk\Events\ChatMessageEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\GuestManager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Message;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -79,10 +80,10 @@ protected function setActor(Message $message): void {
$comment = $message->getComment();
$displayName = '';
- if ($comment->getActorType() === 'users') {
+ if ($comment->getActorType() === Attendee::ACTOR_USERS) {
$user = $this->userManager->get($comment->getActorId());
$displayName = $user instanceof IUser ? $user->getDisplayName() : $comment->getActorId();
- } elseif ($comment->getActorType() === 'guests') {
+ } elseif ($comment->getActorType() === Attendee::ACTOR_GUESTS) {
if (isset($guestNames[$comment->getActorId()])) {
$displayName = $this->guestNames[$comment->getActorId()];
} else {
diff --git a/lib/Chat/Notifier.php b/lib/Chat/Notifier.php
index 13fb7d02797..0b5db45eb3e 100644
--- a/lib/Chat/Notifier.php
+++ b/lib/Chat/Notifier.php
@@ -28,6 +28,7 @@
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Files\Util;
use OCA\Talk\Manager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -135,7 +136,7 @@ public function notifyMentionedUsers(Room $chat, IComment $comment, array $alrea
* @return string[] Users that were mentioned
*/
public function notifyReplyToAuthor(Room $chat, IComment $comment, IComment $replyTo): array {
- if ($replyTo->getActorType() !== 'users') {
+ if ($replyTo->getActorType() !== Attendee::ACTOR_USERS) {
// No reply notification when the replyTo-author was not a user
return [];
}
@@ -308,7 +309,7 @@ protected function getDefaultGroupNotification(): int {
* @return bool
*/
protected function shouldMentionedUserBeNotified(string $userId, IComment $comment): bool {
- if ($comment->getActorType() === 'users' && $userId === $comment->getActorId()) {
+ if ($comment->getActorType() === Attendee::ACTOR_USERS && $userId === $comment->getActorId()) {
// Do not notify the user if they mentioned themselves
return false;
}
@@ -341,7 +342,7 @@ protected function shouldMentionedUserBeNotified(string $userId, IComment $comme
// the notification can be parsed and links to an existing room,
// where they are a participant of.
$this->participantService->addUsers($room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $userId,
]]);
return true;
@@ -364,12 +365,12 @@ protected function shouldMentionedUserBeNotified(string $userId, IComment $comme
* @return bool
*/
protected function shouldParticipantBeNotified(Participant $participant, IComment $comment, array $alreadyNotifiedUsers): bool {
- if ($participant->getAttendee()->getActorType() !== 'users') {
+ if ($participant->getAttendee()->getActorType() !== Attendee::ACTOR_USERS) {
return false;
}
$userId = $participant->getAttendee()->getActorId();
- if ($comment->getActorType() === 'users' && $userId === $comment->getActorId()) {
+ if ($comment->getActorType() === Attendee::ACTOR_USERS && $userId === $comment->getActorId()) {
// Do not notify the author
return false;
}
diff --git a/lib/Chat/Parser/Changelog.php b/lib/Chat/Parser/Changelog.php
index 2f6621848d2..d1c8ce12927 100644
--- a/lib/Chat/Parser/Changelog.php
+++ b/lib/Chat/Parser/Changelog.php
@@ -23,6 +23,7 @@
namespace OCA\Talk\Chat\Parser;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Message;
class Changelog {
@@ -32,7 +33,7 @@ class Changelog {
* @throws \OutOfBoundsException
*/
public function parseMessage(Message $chatMessage): void {
- if ($chatMessage->getActorType() !== 'guests' ||
+ if ($chatMessage->getActorType() !== Attendee::ACTOR_GUESTS ||
$chatMessage->getActorId() !== 'changelog') {
throw new \OutOfBoundsException('Not a changelog');
}
diff --git a/lib/Chat/Parser/Command.php b/lib/Chat/Parser/Command.php
index 1e321d8d8d4..6a69f2c8223 100644
--- a/lib/Chat/Parser/Command.php
+++ b/lib/Chat/Parser/Command.php
@@ -23,6 +23,7 @@
namespace OCA\Talk\Chat\Parser;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Message;
class Command {
@@ -44,7 +45,7 @@ public function parseMessage(Message $message): void {
$participant = $message->getParticipant();
if ($data['visibility'] !== \OCA\Talk\Model\Command::RESPONSE_ALL &&
- ($participant->getAttendee()->getActorType() !== 'users'
+ ($participant->getAttendee()->getActorType() !== Attendee::ACTOR_USERS
|| $data['user'] !== $participant->getAttendee()->getActorId())) {
$message->setVisibility(false);
return;
diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php
index b593c3f2b87..cde11bcc5b0 100644
--- a/lib/Chat/Parser/SystemMessage.php
+++ b/lib/Chat/Parser/SystemMessage.php
@@ -25,6 +25,7 @@
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\GuestManager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Message;
use OCA\Talk\Participant;
use OCA\Talk\Share\RoomShareProvider;
@@ -94,7 +95,7 @@ public function parseMessage(Message $chatMessage): void {
if (!$participant->isGuest()) {
$currentActorId = $participant->getAttendee()->getActorId();
$currentUserIsActor = $parsedParameters['actor']['type'] === 'user' &&
- $participant->getAttendee()->getActorType() === 'users' &&
+ $participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS &&
$currentActorId === $parsedParameters['actor']['id'];
} else {
$currentActorId = $participant->getAttendee()->getActorId();
@@ -385,7 +386,7 @@ protected function getFileFromShare(Participant $participant, string $shareId):
}
protected function getActor(IComment $comment): array {
- if ($comment->getActorType() === 'guests') {
+ if ($comment->getActorType() === Attendee::ACTOR_GUESTS) {
return $this->getGuest($comment->getActorId());
}
diff --git a/lib/Chat/Parser/UserMention.php b/lib/Chat/Parser/UserMention.php
index 1d0f33099f4..1095f3ec4b9 100644
--- a/lib/Chat/Parser/UserMention.php
+++ b/lib/Chat/Parser/UserMention.php
@@ -26,6 +26,7 @@
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\GuestManager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Message;
use OCA\Talk\Room;
use OCP\Comments\ICommentsManager;
@@ -116,7 +117,7 @@ public function parseMessage(Message $chatMessage): void {
if ($mention['type'] === 'call') {
$userId = '';
- if ($chatMessage->getParticipant()->getAttendee()->getActorType() === 'users') {
+ if ($chatMessage->getParticipant()->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
$userId = $chatMessage->getParticipant()->getAttendee()->getActorId();
}
diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php
index 88c5a644dba..e45ab3a5a55 100644
--- a/lib/Chat/SystemMessage/Listener.php
+++ b/lib/Chat/SystemMessage/Listener.php
@@ -31,6 +31,7 @@
use OCA\Talk\Events\RemoveUserEvent;
use OCA\Talk\Events\RoomEvent;
use OCA\Talk\Manager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -80,16 +81,16 @@ public static function register(IEventDispatcher $dispatcher): void {
$participantService = \OC::$server->query(ParticipantService::class);
if ($participantService->hasActiveSessionsInCall($room)) {
- $listener->sendSystemMessage($room, 'call_joined');
+ $listener->sendSystemMessage($room, 'call_joined', [], $event->getParticipant());
} else {
- $listener->sendSystemMessage($room, 'call_started');
+ $listener->sendSystemMessage($room, 'call_started', [], $event->getParticipant());
}
});
$dispatcher->addListener(Room::EVENT_AFTER_SESSION_LEAVE_CALL, static function (ModifyParticipantEvent $event) {
$room = $event->getRoom();
$session = $event->getParticipant()->getSession();
- if (!$session instanceof Session || $session->getInCall() === Participant::FLAG_DISCONNECTED) {
+ if (!$session instanceof Session) {
// This happens in case the user was kicked/lobbied
return;
}
@@ -221,7 +222,7 @@ public static function register(IEventDispatcher $dispatcher): void {
$room = $event->getRoom();
$attendee = $event->getParticipant()->getAttendee();
- if ($attendee->getActorType() !== 'users' && $attendee->getActorType() !== 'guests') {
+ if ($attendee->getActorType() !== Attendee::ACTOR_USERS && $attendee->getActorType() !== Attendee::ACTOR_GUESTS) {
return;
}
@@ -277,10 +278,10 @@ protected function sendSystemMessage(Room $room, string $message, array $paramet
$actorType = 'users';
$actorId = $user->getUID();
} elseif (\OC::$CLI) {
- $actorType = 'guests';
+ $actorType = Attendee::ACTOR_GUESTS;
$actorId = 'cli';
} else {
- $actorType = 'guests';
+ $actorType = Attendee::ACTOR_GUESTS;
$sessionId = $this->talkSession->getSessionForRoom($room->getToken());
$actorId = $sessionId ? sha1($sessionId) : 'failed-to-get-session';
}
diff --git a/lib/Command/Room/TRoomCommand.php b/lib/Command/Room/TRoomCommand.php
index 2c59205e26e..b69c4e5e321 100644
--- a/lib/Command/Room/TRoomCommand.php
+++ b/lib/Command/Room/TRoomCommand.php
@@ -29,6 +29,7 @@
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
@@ -249,7 +250,7 @@ protected function addRoomParticipants(Room $room, array $userIds): void {
}
$participants[] = [
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $user->getUID(),
];
}
@@ -377,7 +378,7 @@ protected function completeParticipantValues(CompletionContext $context): array
$users = [];
$participants = $this->participantService->getParticipantsForRoom($room);
foreach ($participants as $participant) {
- if ($participant->getAttendee()->getActorType() === 'users'
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS
&& stripos($participant->getAttendee()->getActorId(), $context->getCurrentWord()) !== false) {
$users[] = $participant->getAttendee()->getActorId();
}
diff --git a/lib/Config.php b/lib/Config.php
index 6347700bb3f..16255dbfb17 100644
--- a/lib/Config.php
+++ b/lib/Config.php
@@ -43,6 +43,9 @@ class Config {
/** @var ISecureRandom */
private $secureRandom;
+ /** @var array */
+ protected $canEnableSIP = [];
+
public function __construct(IConfig $config,
ISecureRandom $secureRandom,
IGroupManager $groupManager,
@@ -84,6 +87,24 @@ public function getSIPSharedSecret(): string {
return $this->config->getAppValue('spreed', 'sip_bridge_shared_secret');
}
+ public function canUserEnableSIP(IUser $user): bool {
+ if (isset($this->canEnableSIP[$user->getUID()])) {
+ return $this->canEnableSIP[$user->getUID()];
+ }
+
+ $this->canEnableSIP[$user->getUID()] = false;
+
+ $allowedGroups = $this->getSIPGroups();
+ if (empty($allowedGroups)) {
+ $this->canEnableSIP[$user->getUID()] = true;
+ } else {
+ $userGroups = $this->groupManager->getUserGroupIds($user);
+ $this->canEnableSIP[$user->getUID()] = !empty(array_intersect($allowedGroups, $userGroups));
+ }
+
+ return $this->canEnableSIP[$user->getUID()];
+ }
+
public function isDisabledForUser(IUser $user): bool {
$allowedGroups = $this->getAllowedTalkGroupIds();
if (empty($allowedGroups)) {
diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php
index 6e1c66a083d..85c85e834f6 100644
--- a/lib/Controller/CallController.php
+++ b/lib/Controller/CallController.php
@@ -27,6 +27,7 @@
namespace OCA\Talk\Controller;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Service\ParticipantService;
@@ -71,17 +72,29 @@ public function getPeersForCall(): DataResponse {
continue;
}
- $userId = '';
- if ($participant->getAttendee()->getActorType() === 'users') {
- $userId = $participant->getAttendee()->getActorId();
+ if ($this->getAPIVersion() >= 3) {
+ $result[] = [
+ 'actorType' => $participant->getAttendee()->getActorType(),
+ 'actorId' => $participant->getAttendee()->getActorId(),
+ // FIXME 'displayName' => $participant->getAttendee()->getDisplayName(),
+ 'displayName' => $participant->getAttendee()->getActorId(),
+ 'token' => $this->room->getToken(),
+ 'lastPing' => $session->getLastPing(),
+ 'sessionId' => $session->getSessionId(),
+ ];
+ } else {
+ $userId = '';
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
+ $userId = $participant->getAttendee()->getActorId();
+ }
+
+ $result[] = [
+ 'userId' => $userId,
+ 'token' => $this->room->getToken(),
+ 'lastPing' => $session->getLastPing(),
+ 'sessionId' => $session->getSessionId(),
+ ];
}
-
- $result[] = [
- 'userId' => $userId,
- 'token' => $this->room->getToken(),
- 'lastPing' => $session->getLastPing(),
- 'sessionId' => $session->getSessionId(),
- ];
}
return new DataResponse($result);
diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php
index 41da215e198..6e97a747bf0 100644
--- a/lib/Controller/ChatController.php
+++ b/lib/Controller/ChatController.php
@@ -29,6 +29,7 @@
use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Chat\MessageParser;
use OCA\Talk\GuestManager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Message;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
@@ -165,7 +166,7 @@ public function __construct(string $appName,
*/
public function sendMessage(string $message, string $actorDisplayName = '', string $referenceId = '', int $replyTo = 0): DataResponse {
if ($this->userId === null) {
- $actorType = 'guests';
+ $actorType = Attendee::ACTOR_GUESTS;
$sessionId = $this->session->getSessionForRoom($this->room->getToken());
// The character limit for actorId is 64, but the spreed-session is
// 256 characters long, so it has to be hashed to get an ID that
@@ -178,7 +179,7 @@ public function sendMessage(string $message, string $actorDisplayName = '', stri
$this->guestManager->updateName($this->room, $this->participant, $actorDisplayName);
}
} else {
- $actorType = 'users';
+ $actorType = Attendee::ACTOR_USERS;
$actorId = $this->userId;
}
@@ -293,7 +294,7 @@ public function receiveMessages(int $lookIntoFuture, int $limit = 100, int $last
if ($lookIntoFuture) {
$attendee = $this->participant->getAttendee();
- if ($attendee->getActorType() === 'users') {
+ if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
// Bump the user status again
$event = new UserLiveStatusEvent(
$this->userManager->get($attendee->getActorId()),
@@ -485,7 +486,7 @@ public function mentions(string $search, int $limit = 20, bool $includeStatus =
$results = $this->prepareResultArray($results, $statuses);
$attendee = $this->participant->getAttendee();
- $userId = $attendee->getActorType() === 'users' ? $attendee->getActorId() : '';
+ $userId = $attendee->getActorType() === Attendee::ACTOR_USERS ? $attendee->getActorId() : '';
$roomDisplayName = $this->room->getDisplayName($userId);
if (($search === '' || strpos('all', $search) !== false || stripos($roomDisplayName, $search) !== false) && $this->room->getType() !== Room::ONE_TO_ONE_CALL) {
if ($search === '' ||
@@ -524,7 +525,7 @@ protected function prepareResultArray(array $results, array $statuses): array {
'source' => $type,
];
- if ($type === 'users' && isset($statuses[$data['id']])) {
+ if ($type === Attendee::ACTOR_USERS && isset($statuses[$data['id']])) {
$data['status'] = $statuses[$data['id']]->getStatus();
$data['statusIcon'] = $statuses[$data['id']]->getIcon();
$data['statusMessage'] = $statuses[$data['id']]->getMessage();
diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php
index 6a9ef18e217..7afc446ec34 100644
--- a/lib/Controller/RoomController.php
+++ b/lib/Controller/RoomController.php
@@ -40,6 +40,7 @@
use OCA\Talk\Exceptions\UnauthorizedException;
use OCA\Talk\GuestManager;
use OCA\Talk\Manager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -158,6 +159,9 @@ protected function getTalkHashHeader(): array {
$this->config->getAppValue('spreed', 'allowed_groups', '') . '#' .
$this->config->getAppValue('spreed', 'start_conversations', '') . '#' .
$this->config->getAppValue('spreed', 'has_reference_id', '') . '#' .
+ $this->config->getAppValue('spreed', 'sip_bridge_groups', '[]') . '#' .
+ $this->config->getAppValue('spreed', 'sip_bridge_dialin_info') . '#' .
+ $this->config->getAppValue('spreed', 'sip_bridge_shared_secret') . '#' .
$this->config->getAppValue('theming', 'cachebuster', '1')
)];
}
@@ -191,6 +195,7 @@ public function getRooms(int $noStatusUpdate = 0): DataResponse {
}
}
+
$rooms = $this->manager->getRoomsForUser($this->userId, true);
$return = [];
@@ -218,9 +223,11 @@ public function getSingleRoom(string $token): DataResponse {
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
}
- if ($isSIPBridgeRequest && $this->getAPIVersion() === 1) {
+ if ($isSIPBridgeRequest && $this->getAPIVersion() < 3) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
+
+ // The SIP bridge only needs room details (public, sip enabled, lobby state, etc)
$includeLastMessage = !$isSIPBridgeRequest;
try {
@@ -252,21 +259,21 @@ public function getSingleRoom(string $token): DataResponse {
* configuration.
*
* @param string $data
- * @return bool
- * @throws UnauthorizedException when the request tried to sign as SIP bridge but failed
+ * @return bool True if the request is from the SIP bridge and valid, false if not from SIP bridge
+ * @throws UnauthorizedException when the request tried to sign as SIP bridge but is not valid
*/
private function validateSIPBridgeRequest(string $data): bool {
- if (!isset($_SERVER['HTTP_TALK_SIPBRIDGE_RANDOM'])
- && !isset($_SERVER['HTTP_TALK_SIPBRIDGE_CHECKSUM'])) {
+ $random = $this->request->getHeader('TALK_SIPBRIDGE_RANDOM');
+ $checksum = $this->request->getHeader('TALK_SIPBRIDGE_CHECKSUM');
+
+ if ($random === '' && $checksum === '') {
return false;
}
- $random = $_SERVER['HTTP_TALK_SIPBRIDGE_RANDOM'] ?? '';
if (strlen($random) < 32) {
throw new UnauthorizedException('Invalid random provided');
}
- $checksum = $_SERVER['HTTP_TALK_SIPBRIDGE_CHECKSUM'] ?? '';
if (empty($checksum)) {
throw new UnauthorizedException('Invalid checksum provided');
}
@@ -292,7 +299,7 @@ private function validateSIPBridgeRequest(string $data): bool {
* @throws RoomNotFoundException
*/
protected function formatRoom(Room $room, ?Participant $currentParticipant, bool $isSIPBridgeRequest = false): array {
- if ($this->getAPIVersion() !== 1) {
+ if ($this->getAPIVersion() >= 2) {
return $this->formatRoomV2andV3($room, $currentParticipant, $isSIPBridgeRequest);
}
@@ -344,7 +351,7 @@ protected function formatRoomV1(Room $room, ?Participant $currentParticipant): a
}
$attendee = $currentParticipant->getAttendee();
- $userId = $attendee->getActorType() === 'users' ? $attendee->getActorId() : '';
+ $userId = $attendee->getActorType() === Attendee::ACTOR_USERS ? $attendee->getActorId() : '';
$lastActivity = $room->getLastActivity();
if ($lastActivity instanceof \DateTimeInterface) {
@@ -451,7 +458,7 @@ protected function formatRoomV1(Room $room, ?Participant $currentParticipant): a
$numActiveGuests++;
}
}
- } elseif ($participant->getAttendee()->getActorType() === 'users') {
+ } elseif ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
$attendee = $participant->getAttendee();
$session = $participant->getSession();
$user = $this->userManager->get($attendee->getActorId());
@@ -528,17 +535,19 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan
'notificationLevel' => Participant::NOTIFY_NEVER,
'lobbyState' => Webinary::LOBBY_NONE,
'lobbyTimer' => 0,
- 'sipEnabled' => Webinary::SIP_DISABLED,
'lastPing' => 0,
'sessionId' => '0',
'guestList' => '',
'lastMessage' => [],
];
- if ($this->getAPIVersion() === 3) {
+ if ($this->getAPIVersion() >= 3) {
$roomData = array_merge($roomData, [
+ 'sipEnabled' => Webinary::SIP_DISABLED,
'actorType' => '',
'actorId' => '',
'attendeeId' => 0,
+ 'canEnableSIP' => false,
+ 'attendeePin' => '',
]);
}
@@ -576,7 +585,7 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan
}
$attendee = $currentParticipant->getAttendee();
- $userId = $attendee->getActorType() === 'users' ? $attendee->getActorId() : '';
+ $userId = $attendee->getActorType() === Attendee::ACTOR_USERS ? $attendee->getActorId() : '';
$roomData = array_merge($roomData, [
'name' => $room->getName(),
@@ -591,9 +600,13 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan
'notificationLevel' => $attendee->getNotificationLevel(),
'lobbyState' => $room->getLobbyState(),
'lobbyTimer' => $lobbyTimer,
- 'sipEnabled' => $room->getSIPEnabled(),
]);
- if ($this->getAPIVersion() === 3) {
+ if ($this->getAPIVersion() >= 3) {
+ if ($this->talkConfig->isSIPConfigured()) {
+ $roomData['sipEnabled'] = $room->getSIPEnabled();
+ $roomData['attendeePin'] = $attendee->getPin();
+ }
+
$roomData = array_merge($roomData, [
'actorType' => $attendee->getActorType(),
'actorId' => $attendee->getActorId(),
@@ -633,7 +646,7 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan
$roomData['canStartCall'] = $currentParticipant->canStartCall($this->config);
- if ($attendee->getActorType() === 'users') {
+ if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$currentUser = $this->userManager->get($attendee->getActorId());
if ($currentUser instanceof IUser) {
$lastReadMessage = $attendee->getLastReadMessage();
@@ -661,6 +674,14 @@ protected function formatRoomV2andV3(Room $room, ?Participant $currentParticipan
$roomData['canDeleteConversation'] = $room->getType() !== Room::ONE_TO_ONE_CALL
&& $currentParticipant->hasModeratorPermissions(false);
$roomData['canLeaveConversation'] = true;
+ if ($this->getAPIVersion() >= 3) {
+ $roomData['canEnableSIP'] =
+ $this->talkConfig->isSIPConfigured()
+ && !preg_match(Room::SIP_INCOMPATIBLE_REGEX, $room->getToken())
+ && ($room->getType() === Room::GROUP_CALL || $room->getType() === Room::PUBLIC_CALL)
+ && $currentParticipant->hasModeratorPermissions(false)
+ && $this->talkConfig->canUserEnableSIP($currentUser);
+ }
}
}
@@ -817,7 +838,7 @@ protected function createGroupRoom(string $targetGroupName): DataResponse {
}
$participants[] = [
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $user->getUID(),
];
}
@@ -875,7 +896,7 @@ protected function createCircleRoom(string $targetCircleId): DataResponse {
}
$participants[] = [
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $member->getUserId(),
];
}
@@ -1009,7 +1030,7 @@ public function getParticipants(bool $includeStatus = false): DataResponse {
&& count($participants) < 100
&& $this->appManager->isEnabledForUser('user_status')) {
$userIds = array_filter(array_map(static function (Participant $participant) {
- if ($participant->getAttendee()->getActorType() === 'users') {
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
return $participant->getAttendee()->getActorId();
}
return null;
@@ -1022,7 +1043,7 @@ public function getParticipants(bool $includeStatus = false): DataResponse {
$guestSessions = array_filter(array_map(static function (Participant $participant) {
$session = $participant->getSession();
- if (!$session || $participant->getAttendee()->getActorType() !== 'guests') {
+ if (!$session || $participant->getAttendee()->getActorType() !== Attendee::ACTOR_GUESTS) {
return null;
}
@@ -1040,10 +1061,15 @@ public function getParticipants(bool $includeStatus = false): DataResponse {
'sessionId' => '0', // FIXME empty string or null?
'participantType' => $participant->getAttendee()->getParticipantType(),
];
- if ($this->getAPIVersion() === 3) {
+ if ($this->getAPIVersion() >= 3) {
$result['attendeeId'] = $participant->getAttendee()->getId();
$result['actorId'] = $participant->getAttendee()->getActorId();
$result['actorType'] = $participant->getAttendee()->getActorType();
+ if ($this->talkConfig->isSIPConfigured()
+ && ($this->participant->hasModeratorPermissions(false)
+ || $this->participant->getAttendee()->getId() === $participant->getAttendee()->getId())) {
+ $result['attendeePin'] = (string) $participant->getAttendee()->getPin();
+ }
}
if ($participant->getSession() instanceof Session) {
$result['inCall'] = $participant->getSession()->getInCall();
@@ -1051,7 +1077,7 @@ public function getParticipants(bool $includeStatus = false): DataResponse {
$result['sessionId'] = $participant->getSession()->getSessionId();
}
- if ($participant->getAttendee()->getActorType() === 'users') {
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
$userId = $participant->getAttendee()->getActorId();
$user = $this->userManager->get($userId);
if (!$user instanceof IUser) {
@@ -1062,7 +1088,7 @@ public function getParticipants(bool $includeStatus = false): DataResponse {
$this->participantService->leaveRoomAsSession($this->room, $participant);
}
- if ($this->getAPIVersion() !== 3) {
+ if ($this->getAPIVersion() < 3) {
$result['userId'] = $participant->getAttendee()->getActorId();
}
$result['displayName'] = (string) $user->getDisplayName();
@@ -1073,18 +1099,18 @@ public function getParticipants(bool $includeStatus = false): DataResponse {
$result['statusMessage'] = $statuses[$userId]->getMessage();
$result['statusClearAt'] = $statuses[$userId]->getClearAt();
}
- } elseif ($participant->getAttendee()->getActorType() === 'guests') {
+ } elseif ($participant->getAttendee()->getActorType() === Attendee::ACTOR_GUESTS) {
if ($result['lastPing'] <= $maxPingAge) {
$cleanGuests = true;
continue;
}
- if ($this->getAPIVersion() !== 3) {
+ if ($this->getAPIVersion() < 3) {
$result['userId'] = '';
}
$result['displayName'] = $guestNames[$participant->getAttendee()->getActorId()] ?? '';
- } elseif ($this->getAPIVersion() === 3) {
- // Other types are only reported on V3
+ } elseif ($this->getAPIVersion() >= 3) {
+ // Other types are only reported on v3 or later
$result['displayName'] = $participant->getAttendee()->getActorId();
} else {
// Skip unknown actor types
@@ -1128,7 +1154,7 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u
}
$this->participantService->addUsers($this->room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $newUser->getUID(),
]]);
} elseif ($source === 'groups') {
@@ -1144,7 +1170,7 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u
}
$participantsToAdd[] = [
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $user->getUID(),
];
}
@@ -1183,7 +1209,7 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u
}
$participantsToAdd[] = [
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $member->getUserId(),
];
}
@@ -1220,7 +1246,7 @@ public function addParticipantToRoom(string $newParticipant, string $source = 'u
*/
public function removeParticipantFromRoom(string $participant): DataResponse {
$attendee = $this->participant->getAttendee();
- if ($attendee->getActorType() === 'users' && $attendee->getActorId() === $participant) {
+ if ($attendee->getActorType() === Attendee::ACTOR_USERS && $attendee->getActorId() === $participant) {
// Removing self, abusing moderator power
return $this->removeSelfFromRoomLogic($this->room, $this->participant);
}
@@ -1465,6 +1491,7 @@ public function joinRoom(string $token, string $password = '', bool $force = tru
$result = $room->verifyPassword((string) $this->session->getPasswordForRoom($token));
if ($user instanceof IUser) {
$participant = $this->participantService->joinRoom($room, $user, $password, $result['result']);
+ $this->participantService->generatePinForParticipant($room, $participant);
} else {
$participant = $this->participantService->joinRoomAsNewGuest($room, $password, $result['result']);
}
@@ -1541,7 +1568,7 @@ public function leaveRoom(string $token): DataResponse {
* @return DataResponse
*/
public function promoteModerator(?int $attendeeId, ?string $participant, ?string $sessionId): DataResponse {
- return $this->toggleParticipantType($attendeeId, $participant, $sessionId);
+ return $this->changeParticipantType($attendeeId, $participant, $sessionId, true);
}
/**
@@ -1554,7 +1581,7 @@ public function promoteModerator(?int $attendeeId, ?string $participant, ?string
* @return DataResponse
*/
public function demoteModerator(?int $attendeeId, ?string $participant, ?string $sessionId): DataResponse {
- return $this->toggleParticipantType($attendeeId, $participant, $sessionId);
+ return $this->changeParticipantType($attendeeId, $participant, $sessionId, false);
}
/**
@@ -1564,9 +1591,10 @@ public function demoteModerator(?int $attendeeId, ?string $participant, ?string
* @param int|null $attendeeId
* @param string|null $userId
* @param string|null $sessionId
+ * @param bool $promote Shall the attendee be promoted or demoted
* @return DataResponse
*/
- protected function toggleParticipantType(?int $attendeeId, ?string $userId, ?string $sessionId): DataResponse {
+ protected function changeParticipantType(?int $attendeeId, ?string $userId, ?string $sessionId, bool $promote): DataResponse {
try {
if ($attendeeId !== null) {
$targetParticipant = $this->room->getParticipantByAttendeeId($attendeeId);
@@ -1582,11 +1610,11 @@ protected function toggleParticipantType(?int $attendeeId, ?string $userId, ?str
$attendee = $targetParticipant->getAttendee();
// Prevent users/moderators modifying themselves
- if ($attendee->getActorType() === 'users') {
+ if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
if ($attendee->getActorId() === $this->userId) {
return new DataResponse([], Http::STATUS_FORBIDDEN);
}
- } elseif ($attendee->getActorType() === 'guests') {
+ } elseif ($attendee->getActorType() === Attendee::ACTOR_GUESTS) {
$session = $targetParticipant->getSession();
$currentSessionId = $this->session->getSessionForRoom($this->room->getToken());
@@ -1595,6 +1623,11 @@ protected function toggleParticipantType(?int $attendeeId, ?string $userId, ?str
}
}
+ if ($promote === $targetParticipant->hasModeratorPermissions()) {
+ // Prevent concurrent changes
+ return new DataResponse([], Http::STATUS_BAD_REQUEST);
+ }
+
if ($attendee->getParticipantType() === Participant::USER) {
$newType = Participant::MODERATOR;
} elseif ($attendee->getParticipantType() === Participant::GUEST) {
diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php
index 1acb977133e..9902e27deec 100644
--- a/lib/Controller/SignalingController.php
+++ b/lib/Controller/SignalingController.php
@@ -25,11 +25,13 @@
namespace OCA\Talk\Controller;
+use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use OCA\Talk\Config;
use OCA\Talk\Events\SignalingEvent;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Manager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -377,7 +379,7 @@ protected function getUsersInRoom(Room $room, int $pingTimestamp): array {
}
$userId = '';
- if ($participant->getAttendee()->getActorType() === 'users') {
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS) {
$userId = $participant->getAttendee()->getActorId();
}
@@ -519,36 +521,64 @@ private function backendAuth(array $auth): DataResponse {
}
private function backendRoom(array $roomRequest): DataResponse {
- $roomId = $roomRequest['roomid'];
+ $token = $roomRequest['roomid']; // It's actually the room token
$userId = $roomRequest['userid'];
$sessionId = $roomRequest['sessionid'];
$action = !empty($roomRequest['action']) ? $roomRequest['action'] : 'join';
-
- try {
- $room = $this->manager->getRoomByToken($roomId, $userId);
- } catch (RoomNotFoundException $e) {
- return new DataResponse([
- 'type' => 'error',
- 'error' => [
- 'code' => 'no_such_room',
- 'message' => 'The user is not invited to this room.',
- ],
- ]);
- }
+ $actorId = $roomRequest['actorid'] ?? null;
+ $actorType = $roomRequest['actortype'] ?? null;
+ $inCall = $roomRequest['incall'] ?? null;
$participant = null;
- if ($sessionId) {
+ if ($actorId !== null && $actorType !== null) {
try {
- $participant = $room->getParticipantBySession($sessionId);
- } catch (ParticipantNotFoundException $e) {
+ $room = $this->manager->getRoomByActor($token, $actorType, $actorId);
+ } catch (RoomNotFoundException $e) {
+ return new DataResponse([
+ 'type' => 'error',
+ 'error' => [
+ 'code' => 'no_such_room',
+ 'message' => 'The user is not invited to this room.',
+ ],
+ ]);
}
- }
- if (!empty($userId)) {
- // User trying to join room.
+ if ($sessionId) {
+ try {
+ $participant = $room->getParticipantBySession($sessionId);
+ } catch (ParticipantNotFoundException $e) {
+ }
+ } else {
+ try {
+ $participant = $room->getParticipantByActor($actorType, $actorId);
+ } catch (ParticipantNotFoundException $e) {
+ }
+ }
+ } else {
try {
- $participant = $room->getParticipant($userId);
- } catch (ParticipantNotFoundException $e) {
+ // FIXME Don't preload with the user as that misses the session, kinda meh.
+ $room = $this->manager->getRoomByToken($token);
+ } catch (RoomNotFoundException $e) {
+ return new DataResponse([
+ 'type' => 'error',
+ 'error' => [
+ 'code' => 'no_such_room',
+ 'message' => 'The user is not invited to this room.',
+ ],
+ ]);
+ }
+
+ if ($sessionId) {
+ try {
+ $participant = $room->getParticipantBySession($sessionId);
+ } catch (ParticipantNotFoundException $e) {
+ }
+ } elseif (!empty($userId)) {
+ // User trying to join room.
+ try {
+ $participant = $room->getParticipant($userId);
+ } catch (ParticipantNotFoundException $e) {
+ }
}
}
@@ -564,16 +594,36 @@ private function backendRoom(array $roomRequest): DataResponse {
}
if ($action === 'join') {
+ if ($sessionId && !$participant->getSession() instanceof Session) {
+ try {
+ $session = $this->sessionService->createSessionForAttendee($participant->getAttendee(), $sessionId);
+ } catch (UniqueConstraintViolationException $e) {
+ return new DataResponse([
+ 'type' => 'error',
+ 'error' => [
+ 'code' => 'duplicate_session',
+ 'message' => 'The given session is already in use.',
+ ],
+ ]);
+ }
+ $participant->setSession($session);
+ }
+
if ($participant->getSession() instanceof Session) {
+ if ($inCall !== null) {
+ $this->participantService->changeInCall($room, $participant, $inCall);
+ }
$this->sessionService->updateLastPing($participant->getSession(), $this->timeFactory->getTime());
}
} elseif ($action === 'leave') {
- if ($participant instanceof Participant) {
- if (!empty($userId)) {
- $this->participantService->leaveRoomAsSession($room, $participant);
- } else {
- $this->participantService->removeAttendee($room, $participant, Room::PARTICIPANT_LEFT);
- }
+ // Guests are removed completely as they don't reuse attendees,
+ // but this is only true for guests that joined directly.
+ // Emails are retained as their PIN needs to remain and stay
+ // valid.
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_GUESTS) {
+ $this->participantService->removeAttendee($room, $participant, Room::PARTICIPANT_LEFT);
+ } else {
+ $this->participantService->leaveRoomAsSession($room, $participant);
}
}
diff --git a/lib/Controller/WebinarController.php b/lib/Controller/WebinarController.php
index c6fa35ec5c2..b04b4d48761 100644
--- a/lib/Controller/WebinarController.php
+++ b/lib/Controller/WebinarController.php
@@ -33,6 +33,8 @@
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserManager;
class WebinarController extends AEnvironmentAwareController {
@@ -42,16 +44,24 @@ class WebinarController extends AEnvironmentAwareController {
protected $participantService;
/** @var Config */
protected $talkConfig;
+ /** @var IUserManager */
+ protected $userManager;
+ /** @var string|null */
+ protected $userId;
public function __construct(string $appName,
IRequest $request,
ITimeFactory $timeFactory,
ParticipantService $participantService,
- Config $talkConfig) {
+ Config $talkConfig,
+ IUserManager $userManager,
+ ?string $userId) {
parent::__construct($appName, $request);
$this->timeFactory = $timeFactory;
$this->participantService = $participantService;
$this->talkConfig = $talkConfig;
+ $this->userManager = $userManager;
+ $this->userId = $userId;
}
/**
@@ -99,11 +109,19 @@ public function setLobby(int $state, ?int $timer = null): DataResponse {
* @return DataResponse
*/
public function setSIPEnabled(int $state): DataResponse {
+ $user = $this->userManager->get($this->userId);
+ if (!$user instanceof IUser) {
+ return new DataResponse([], Http::STATUS_UNAUTHORIZED);
+ }
+
+ if (!$this->talkConfig->canUserEnableSIP($user)) {
+ return new DataResponse([], Http::STATUS_UNAUTHORIZED);
+ }
+
if (!$this->talkConfig->isSIPConfigured()) {
return new DataResponse([], Http::STATUS_PRECONDITION_FAILED);
}
- // TODO Check if user is in "SIP groups"
if (!$this->room->setSIPEnabled($state)) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
diff --git a/lib/Files/Listener.php b/lib/Files/Listener.php
index 64b2a82f233..f6f2f0e9454 100644
--- a/lib/Files/Listener.php
+++ b/lib/Files/Listener.php
@@ -28,6 +28,7 @@
use OCA\Talk\Events\JoinRoomUserEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\UnauthorizedException;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCA\Talk\TalkSession;
@@ -154,7 +155,7 @@ public function addUserAsPersistentParticipant(Room $room, string $userId): void
$room->getParticipant($userId);
} catch (ParticipantNotFoundException $e) {
$this->participantService->addUsers($room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $userId,
]]);
}
diff --git a/lib/GuestManager.php b/lib/GuestManager.php
index 41bef5ff4eb..067ffac2730 100644
--- a/lib/GuestManager.php
+++ b/lib/GuestManager.php
@@ -45,6 +45,9 @@ class GuestManager {
/** @var IDBConnection */
protected $connection;
+ /** @var Config */
+ protected $talkConfig;
+
/** @var IMailer */
protected $mailer;
@@ -64,6 +67,7 @@ class GuestManager {
protected $dispatcher;
public function __construct(IDBConnection $connection,
+ Config $talkConfig,
IMailer $mailer,
Defaults $defaults,
IUserSession $userSession,
@@ -71,6 +75,7 @@ public function __construct(IDBConnection $connection,
IL10N $l,
IEventDispatcher $dispatcher) {
$this->connection = $connection;
+ $this->talkConfig = $talkConfig;
$this->mailer = $mailer;
$this->defaults = $defaults;
$this->userSession = $userSession;
@@ -205,16 +210,33 @@ public function sendEmailInvitation(Room $room, Participant $participant): void
$subject
);
-// if ($pin) {
-// // FIXME wrap in text
-// $template->addBodyText($pin);
-// }
-
$template->addBodyButton(
$this->l->t('Join »%s«', [$room->getDisplayName('')]),
$link
);
+ if ($pin) {
+ $template->addBodyText($this->l->t('You can also dial-in via phone with the following details'));
+
+ $template->addBodyListItem(
+ $this->talkConfig->getDialInInfo(),
+ $this->l->t('Dial-in information'),
+ $this->url->getAbsoluteURL($this->url->imagePath('spreed', 'phone.png'))
+ );
+
+ $template->addBodyListItem(
+ $room->getToken(),
+ $this->l->t('Meeting ID'),
+ $this->url->getAbsoluteURL($this->url->imagePath('core', 'places/calendar-dark.png'))
+ );
+
+ $template->addBodyListItem(
+ $pin,
+ $this->l->t('Your PIN'),
+ $this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/password.png'))
+ );
+ }
+
$template->addFooter();
$message->setTo([$email]);
diff --git a/lib/Manager.php b/lib/Manager.php
index 6e02ae666a0..84f6faad0b2 100644
--- a/lib/Manager.php
+++ b/lib/Manager.php
@@ -27,6 +27,7 @@
use OCA\Talk\Events\RoomEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\AttendeeMapper;
use OCA\Talk\Model\SessionMapper;
use OCA\Talk\Service\ParticipantService;
@@ -110,6 +111,7 @@ public function __construct(IDBConnection $db,
public function forAllRooms(callable $callback): void {
$query = $this->db->getQueryBuilder();
$query->select('*')
+ ->selectAlias('id', 'r_id')
->from('talk_rooms');
$result = $query->execute();
@@ -289,14 +291,19 @@ public function getRoomsForUser(string $userId, bool $includeLastMessage = false
$query = $this->db->getQueryBuilder();
$query->select('r.*')
->addSelect('a.*')
+ ->addSelect('s.*')
->selectAlias('r.id', 'r_id')
->selectAlias('a.id', 'a_id')
+ ->selectAlias('s.id', 's_id')
->from('talk_rooms', 'r')
->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
- $query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
+ $query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)),
$query->expr()->eq('a.room_id', 'r.id')
))
+ ->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
+ $query->expr()->eq('a.id', 's.attendee_id')
+ ))
->where($query->expr()->isNotNull('a.id'));
if ($includeLastMessage) {
@@ -340,12 +347,17 @@ public function getRoomForUser(int $roomId, ?string $userId): Room {
if ($userId !== null) {
// Non guest user
$query->addSelect('a.*')
+ ->addSelect('s.*')
->selectAlias('a.id', 'a_id')
+ ->selectAlias('s.id', 's_id')
->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
- $query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
+ $query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)),
$query->expr()->eq('a.room_id', 'r.id')
))
+ ->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
+ $query->expr()->eq('a.id', 's.attendee_id')
+ ))
->andWhere($query->expr()->isNotNull('a.id'));
}
@@ -395,11 +407,16 @@ public function getRoomForUserByToken(string $token, ?string $userId, bool $incl
if ($userId !== null) {
// Non guest user
$query->addSelect('a.*')
- ->selectAlias('a.id', 'a_id');
- $query->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
+ ->addSelect('s.*')
+ ->selectAlias('a.id', 'a_id')
+ ->selectAlias('s.id', 's_id')
+ ->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
- $query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
+ $query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)),
$query->expr()->eq('a.room_id', 'r.id')
+ ))
+ ->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
+ $query->expr()->eq('a.id', 's.attendee_id')
));
}
@@ -466,29 +483,30 @@ public function getRoomById(int $roomId): Room {
/**
* @param string $token
- * @param string|null $preloadUserId Load this participants information if possible
+ * @param string $actorType
+ * @param string $actorId
* @return Room
* @throws RoomNotFoundException
*/
- public function getRoomByToken(string $token, ?string $preloadUserId = null): Room {
- $preloadUserId = $preloadUserId === '' ? null : $preloadUserId;
-
+ public function getRoomByActor(string $token, string $actorType, string $actorId): Room {
$query = $this->db->getQueryBuilder();
$query->select('r.*')
+ ->addSelect('a.*')
+ ->addSelect('s.*')
+ ->selectAlias('a.id', 'a_id')
+ ->selectAlias('s.id', 's_id')
->selectAlias('r.id', 'r_id')
->from('talk_rooms', 'r')
+ ->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
+ $query->expr()->eq('a.actor_type', $query->createNamedParameter($actorType)),
+ $query->expr()->eq('a.actor_id', $query->createNamedParameter($actorId)),
+ $query->expr()->eq('a.room_id', 'r.id')
+ ))
+ ->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX(
+ $query->expr()->eq('a.id', 's.attendee_id')
+ ))
->where($query->expr()->eq('r.token', $query->createNamedParameter($token)));
- if ($preloadUserId !== null) {
- $query->addSelect('a.*')
- ->selectAlias('a.id', 'a_id');
- $query->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
- $query->expr()->eq('a.actor_id', $query->createNamedParameter($preloadUserId)),
- $query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
- $query->expr()->eq('a.room_id', 'r.id')
- ));
- }
-
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
@@ -503,13 +521,47 @@ public function getRoomByToken(string $token, ?string $preloadUserId = null): Ro
}
$room = $this->createRoomObject($row);
- if ($preloadUserId !== null && isset($row['actor_id'])) {
+ if ($actorType === Attendee::ACTOR_USERS && isset($row['actor_id'])) {
$room->setParticipant($row['actor_id'], $this->createParticipantObject($room, $row));
}
return $room;
}
+ /**
+ * @param string $token
+ * @param string|null $preloadUserId Load this participants information if possible
+ * @return Room
+ * @throws RoomNotFoundException
+ */
+ public function getRoomByToken(string $token, ?string $preloadUserId = null): Room {
+ $preloadUserId = $preloadUserId === '' ? null : $preloadUserId;
+ if ($preloadUserId !== null) {
+ return $this->getRoomByActor($token, Attendee::ACTOR_USERS, $preloadUserId);
+ }
+
+ $query = $this->db->getQueryBuilder();
+ $query->select('r.*')
+ ->selectAlias('r.id', 'r_id')
+ ->from('talk_rooms', 'r')
+ ->where($query->expr()->eq('r.token', $query->createNamedParameter($token)));
+
+ $result = $query->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
+
+ if ($row === false) {
+ throw new RoomNotFoundException();
+ }
+
+ if ($row['token'] === null) {
+ // FIXME Temporary solution for the Talk6 release
+ throw new RoomNotFoundException();
+ }
+
+ return $this->createRoomObject($row);
+ }
+
/**
* @param string $objectType
* @param string $objectId
@@ -571,11 +623,11 @@ public function getRoomForSession(?string $userId, ?string $sessionId): Room {
}
if ($userId !== null) {
- if ($row['actor_type'] !== 'users' || $userId !== $row['actor_id']) {
+ if ($row['actor_type'] !== Attendee::ACTOR_USERS || $userId !== $row['actor_id']) {
throw new RoomNotFoundException();
}
} else {
- if ($row['actor_type'] !== 'guests') {
+ if ($row['actor_type'] !== Attendee::ACTOR_GUESTS) {
throw new RoomNotFoundException();
}
}
@@ -653,7 +705,7 @@ public function getChangelogRoom(string $userId): Room {
$room->setReadOnly(Room::READ_ONLY);
$this->participantService->addUsers($room,[[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $userId,
]]);
return $room;
@@ -665,7 +717,7 @@ public function getChangelogRoom(string $userId): Room {
$room->getParticipant($userId);
} catch (ParticipantNotFoundException $e) {
$this->participantService->addUsers($room,[[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $userId,
]]);
}
diff --git a/lib/MatterbridgeManager.php b/lib/MatterbridgeManager.php
index 00511a16961..c279a4c7ff5 100644
--- a/lib/MatterbridgeManager.php
+++ b/lib/MatterbridgeManager.php
@@ -24,6 +24,7 @@
namespace OCA\Talk;
use OCA\Talk\Exceptions\RoomNotFoundException;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Service\ParticipantService;
use OCP\IConfig;
use OCP\IDBConnection;
@@ -303,7 +304,7 @@ private function checkBotUser(Room $room, bool $create): array {
$participant = $room->getParticipant($botUserId);
} catch (ParticipantNotFoundException $e) {
$this->participantService->addUsers($room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $botUserId,
'participantType' => Participant::USER,
]]);
@@ -654,7 +655,7 @@ private function compareBridgeParts(array $part1, array $part2): bool {
private function sendSystemMessage(Room $room, string $userId, string $message): void {
$this->chatManager->addSystemMessage(
$room,
- 'users',
+ Attendee::ACTOR_USERS,
$userId,
json_encode(['message' => $message, 'parameters' => []]),
$this->timeFactory->getDateTime(),
diff --git a/lib/Migration/Version10000Date20201015134000.php b/lib/Migration/Version10000Date20201015134000.php
index b050619ff09..aa7e5bb5e00 100644
--- a/lib/Migration/Version10000Date20201015134000.php
+++ b/lib/Migration/Version10000Date20201015134000.php
@@ -27,6 +27,7 @@
use Closure;
use Doctrine\DBAL\Types\Type;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Participant;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\ISchemaWrapper;
@@ -149,7 +150,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
// Unique key to avoid duplication issues
$table->addColumn('session_id', Type::STRING, [
'notnull' => true,
- 'length' => 255,
+ 'length' => 512,
]);
$table->addColumn('in_call', Type::INTEGER, [
@@ -209,7 +210,7 @@ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array
$insert
->setParameter('room_id', (int) $row['room_id'], IQueryBuilder::PARAM_INT)
- ->setParameter('actor_type', 'users')
+ ->setParameter('actor_type', Attendee::ACTOR_USERS)
->setParameter('actor_id', $row['user_id'])
->setParameter('participant_type', (int) $row['participant_type'], IQueryBuilder::PARAM_INT)
->setParameter('favorite', (bool) $row['favorite'], IQueryBuilder::PARAM_BOOL)
diff --git a/lib/Migration/Version10000Date20201015150000.php b/lib/Migration/Version10000Date20201015150000.php
new file mode 100644
index 00000000000..1180257d519
--- /dev/null
+++ b/lib/Migration/Version10000Date20201015150000.php
@@ -0,0 +1,62 @@
+
+ *
+ * @author Joas Schilling
+ *
+ * @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 .
+ *
+ */
+
+namespace OCA\Talk\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * The HPB is generating sessions longer than 255 chars. So we update the length
+ * But the install migration was fixed, so this only does something on update.
+ */
+class Version10000Date20201015150000 extends SimpleMigrationStep {
+
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if ($schema->hasTable('talk_sessions')) {
+ $table = $schema->getTable('talk_sessions');
+
+ $column = $table->getColumn('session_id');
+
+ if ($column->getLength() !== 512) {
+ $column->setLength(512);
+ return $schema;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/lib/Model/Attendee.php b/lib/Model/Attendee.php
index 121139d158e..3189ede37f5 100644
--- a/lib/Model/Attendee.php
+++ b/lib/Model/Attendee.php
@@ -50,6 +50,9 @@
* @method int getLastMentionMessage()
*/
class Attendee extends Entity {
+ public const ACTOR_USERS = 'users';
+ public const ACTOR_GUESTS = 'guests';
+ public const ACTOR_EMAILS = 'emails';
/** @var int */
protected $roomId;
diff --git a/lib/Model/Message.php b/lib/Model/Message.php
index 6d54f04c546..97d578c184e 100644
--- a/lib/Model/Message.php
+++ b/lib/Model/Message.php
@@ -158,7 +158,7 @@ public function getActorDisplayName(): string {
public function isReplyable(): bool {
return $this->getMessageType() !== 'system' &&
$this->getMessageType() !== 'command' &&
- \in_array($this->getActorType(), ['users', 'guests']);
+ \in_array($this->getActorType(), [Attendee::ACTOR_USERS, Attendee::ACTOR_GUESTS]);
}
public function toArray(): array {
diff --git a/lib/Model/Session.php b/lib/Model/Session.php
index 172e39ef9a1..0acabf59383 100644
--- a/lib/Model/Session.php
+++ b/lib/Model/Session.php
@@ -26,6 +26,14 @@
use OCP\AppFramework\Db\Entity;
/**
+ * A session is the "I'm online in this conversation" state of Talk, you get one
+ * when opening the conversation while the inCall flag tells if you are just
+ * online (chatting), or in a call (with audio, camera or even sip).
+ * Currently it's limited to 1 per attendee, but the plan is to remove this
+ * restriction in the future, so e.g. in the future you can join with your phone
+ * on the SIP bridge, have your video/screenshare on the laptop and chat in the
+ * mobile app.
+ *
* @method void setAttendeeId(int $attendeeId)
* @method string getAttendeeId()
* @method void setSessionId(string $sessionId)
diff --git a/lib/Notification/Listener.php b/lib/Notification/Listener.php
index a56d4798028..1ba06641f49 100644
--- a/lib/Notification/Listener.php
+++ b/lib/Notification/Listener.php
@@ -26,6 +26,7 @@
use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\JoinRoomUserEvent;
use OCA\Talk\Events\RoomEvent;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCA\Talk\Service\ParticipantService;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -142,7 +143,7 @@ public function generateInvitation(Room $room, array $participants): void {
}
foreach ($participants as $participant) {
- if ($participant['actorType'] !== 'users') {
+ if ($participant['actorType'] !== Attendee::ACTOR_USERS) {
// No user => no activity
continue;
}
diff --git a/lib/Participant.php b/lib/Participant.php
index 9044c8736e7..b0a6bfaa6fc 100644
--- a/lib/Participant.php
+++ b/lib/Participant.php
@@ -71,6 +71,10 @@ public function getSession(): ?Session {
return $this->session;
}
+ public function setSession(Session $session): void {
+ $this->session = $session;
+ }
+
public function isGuest(): bool {
$participantType = $this->attendee->getParticipantType();
return \in_array($participantType, [self::GUEST, self::GUEST_MODERATOR], true);
diff --git a/lib/Room.php b/lib/Room.php
index e7e13c93fbf..ee655156f0e 100644
--- a/lib/Room.php
+++ b/lib/Room.php
@@ -33,6 +33,7 @@
use OCA\Talk\Events\SignalingRoomPropertiesEvent;
use OCA\Talk\Events\VerifyRoomPasswordEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Service\ParticipantService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
@@ -43,6 +44,15 @@
use OCP\Security\ISecureRandom;
class Room {
+
+ /**
+ * Regex that matches SIP incompatible rooms:
+ * 1. duplicate digit: …11…
+ * 2. leading zero: 0…
+ * 3. non-digit: …a…
+ */
+ public const SIP_INCOMPATIBLE_REGEX = '/((\d)(?=\2+)|^0|\D)/';
+
public const UNKNOWN_CALL = -1;
public const ONE_TO_ONE_CALL = 1;
public const GROUP_CALL = 2;
@@ -352,7 +362,7 @@ public function getParticipant(?string $userId): Participant {
->selectAlias('s.id', 's_id')
->from('talk_attendees', 'a')
->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id'))
- ->where($query->expr()->eq('a.actor_type', $query->createNamedParameter('users')))
+ ->where($query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)))
->andWhere($query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)))
->andWhere($query->expr()->eq('a.room_id', $query->createNamedParameter($this->getId())))
->setMaxResults(1);
@@ -454,6 +464,38 @@ public function getParticipantByAttendeeId(int $attendeeId): Participant {
return $this->manager->createParticipantObject($this, $row);
}
+ /**
+ * @param string $actorType
+ * @param string $actorId
+ * @return Participant
+ * @throws ParticipantNotFoundException When the pin is not valid (has no participant assigned)
+ */
+ public function getParticipantByActor(string $actorType, string $actorId): Participant {
+ if ($actorType === Attendee::ACTOR_USERS) {
+ return $this->getParticipant($actorId);
+ }
+
+ $query = $this->db->getQueryBuilder();
+ $query->select('*')
+ ->selectAlias('a.id', 'a_id')
+ ->selectAlias('s.id', 's_id')
+ ->from('talk_attendees', 'a')
+ ->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id'))
+ ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter($actorType)))
+ ->andWhere($query->expr()->eq('a.actor_id', $query->createNamedParameter($actorId)))
+ ->andWhere($query->expr()->eq('a.room_id', $query->createNamedParameter($this->getId())))
+ ->setMaxResults(1);
+ $result = $query->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
+
+ if ($row === false) {
+ throw new ParticipantNotFoundException('User is not a participant');
+ }
+
+ return $this->manager->createParticipantObject($this, $row);
+ }
+
public function deleteRoom(): void {
$event = new RoomEvent($this);
$this->dispatcher->dispatch(self::EVENT_BEFORE_ROOM_DELETE, $event);
@@ -743,12 +785,10 @@ public function setSIPEnabled(int $newSipEnabled): bool {
return false;
}
- if (!preg_match('/^\d+$/', $this->token)) {
+ if (preg_match(self::SIP_INCOMPATIBLE_REGEX, $this->token)) {
return false;
}
- // FIXME check if SIP is enabled/configured
-
$event = new ModifyRoomEvent($this, 'sipEnabled', $newSipEnabled, $oldSipEnabled);
$this->dispatcher->dispatch(self::EVENT_BEFORE_SIP_ENABLED_SET, $event);
diff --git a/lib/Search/MessageSearch.php b/lib/Search/MessageSearch.php
index ada804a2b00..84b727a9762 100644
--- a/lib/Search/MessageSearch.php
+++ b/lib/Search/MessageSearch.php
@@ -29,6 +29,7 @@
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\UnauthorizedException;
use OCA\Talk\Manager as RoomManager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Room;
use OCP\Comments\IComment;
use OCP\IL10N;
@@ -193,7 +194,7 @@ protected function commentToSearchResultEntry(Room $room, IUser $user, IComment
}
$iconUrl = '';
- if ($message->getActorType() === 'users') {
+ if ($message->getActorType() === Attendee::ACTOR_USERS) {
$iconUrl = $this->url->linkToRouteAbsolute('core.avatar.getAvatar', [
'userId' => $message->getActorId(),
'size' => 64,
diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php
index 1b0458b3f8a..8707cf3ca9e 100644
--- a/lib/Service/ParticipantService.php
+++ b/lib/Service/ParticipantService.php
@@ -23,6 +23,7 @@
namespace OCA\Talk\Service;
+use OCA\Talk\Config;
use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\JoinRoomGuestEvent;
use OCA\Talk\Events\JoinRoomUserEvent;
@@ -40,6 +41,7 @@
use OCA\Talk\Model\SessionMapper;
use OCA\Talk\Participant;
use OCA\Talk\Room;
+use OCA\Talk\Webinary;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
@@ -51,6 +53,8 @@
use OCP\Security\ISecureRandom;
class ParticipantService {
+ /** @var Config */
+ protected $talkConfig;
/** @var AttendeeMapper */
protected $attendeeMapper;
/** @var SessionMapper */
@@ -68,7 +72,8 @@ class ParticipantService {
/** @var ITimeFactory */
private $timeFactory;
- public function __construct(AttendeeMapper $attendeeMapper,
+ public function __construct(Config $talkConfig,
+ AttendeeMapper $attendeeMapper,
SessionMapper $sessionMapper,
SessionService $sessionService,
ISecureRandom $secureRandom,
@@ -76,6 +81,7 @@ public function __construct(AttendeeMapper $attendeeMapper,
IEventDispatcher $dispatcher,
IUserManager $userManager,
ITimeFactory $timeFactory) {
+ $this->talkConfig = $talkConfig;
$this->attendeeMapper = $attendeeMapper;
$this->sessionMapper = $sessionMapper;
$this->sessionService = $sessionService;
@@ -149,7 +155,7 @@ public function joinRoom(Room $room, IUser $user, string $password, bool $passed
}
try {
- $attendee = $this->attendeeMapper->findByActor($room->getId(), 'users', $user->getUID());
+ $attendee = $this->attendeeMapper->findByActor($room->getId(), Attendee::ACTOR_USERS, $user->getUID());
} catch (DoesNotExistException $e) {
if (!$event->getPassedPasswordProtection() && !$room->verifyPassword($password)['result']) {
throw new InvalidPasswordException('Provided password is invalid');
@@ -157,12 +163,12 @@ public function joinRoom(Room $room, IUser $user, string $password, bool $passed
// User joining a public room, without being invited
$this->addUsers($room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $user->getUID(),
'participantType' => Participant::USER_SELF_JOINED,
]]);
- $attendee = $this->attendeeMapper->findByActor($room->getId(), 'users', $user->getUID());
+ $attendee = $this->attendeeMapper->findByActor($room->getId(), Attendee::ACTOR_USERS, $user->getUID());
}
$session = $this->sessionService->createSessionForAttendee($attendee);
@@ -201,7 +207,7 @@ public function joinRoomAsNewGuest(Room $room, string $password, bool $passedPas
$attendee = new Attendee();
$attendee->setRoomId($room->getId());
- $attendee->setActorType('guests');
+ $attendee->setActorType(Attendee::ACTOR_GUESTS);
$attendee->setActorId($randomActorId);
$attendee->setParticipantType(Participant::GUEST);
$attendee->setLastReadMessage($lastMessage);
@@ -257,11 +263,13 @@ public function inviteEmailAddress(Room $room, string $email): Participant {
$attendee = new Attendee();
$attendee->setRoomId($room->getId());
- $attendee->setActorType('emails');
+ $attendee->setActorType(Attendee::ACTOR_EMAILS);
$attendee->setActorId($email);
- // FIXME Only do this when SIP is enabled?
- $attendee->setPin($this->generatePin());
+ if ($room->getSIPEnabled() === Webinary::SIP_ENABLED
+ && $this->talkConfig->isSIPConfigured()) {
+ $attendee->setPin($this->generatePin());
+ }
$attendee->setParticipantType(Participant::GUEST);
$attendee->setLastReadMessage($lastMessage);
@@ -271,6 +279,16 @@ public function inviteEmailAddress(Room $room, string $email): Participant {
return new Participant($room, $attendee, null);
}
+ public function generatePinForParticipant(Room $room, Participant $participant): void {
+ $attendee = $participant->getAttendee();
+ if ($room->getSIPEnabled() === Webinary::SIP_ENABLED
+ && $this->talkConfig->isSIPConfigured()
+ && !$attendee->getPin()) {
+ $attendee->setPin($this->generatePin());
+ $this->attendeeMapper->update($attendee);
+ }
+ }
+
public function ensureOneToOneRoomIsFilled(Room $room): void {
if ($room->getType() !== Room::ONE_TO_ONE_CALL) {
return;
@@ -283,7 +301,7 @@ public function ensureOneToOneRoomIsFilled(Room $room): void {
foreach ($missingUsers as $userId) {
if ($this->userManager->userExists($userId)) {
$this->addUsers($room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $userId,
'participantType' => Participant::OWNER,
]]);
@@ -292,7 +310,7 @@ public function ensureOneToOneRoomIsFilled(Room $room): void {
}
public function leaveRoomAsSession(Room $room, Participant $participant): void {
- if (!$participant->isGuest()) {
+ if ($participant->getAttendee()->getActorType() !== Attendee::ACTOR_GUESTS) {
$event = new ParticipantEvent($room, $participant);
$this->dispatcher->dispatch(Room::EVENT_BEFORE_ROOM_DISCONNECT, $event);
} else {
@@ -302,17 +320,27 @@ public function leaveRoomAsSession(Room $room, Participant $participant): void {
$session = $participant->getSession();
if ($session instanceof Session) {
+ $dispatchLeaveCallEvents = $session->getInCall() !== Participant::FLAG_DISCONNECTED;
+ if ($dispatchLeaveCallEvents) {
+ $event = new ModifyParticipantEvent($room, $participant, 'inCall', Participant::FLAG_DISCONNECTED, $session->getInCall());
+ $this->dispatcher->dispatch(Room::EVENT_BEFORE_SESSION_LEAVE_CALL, $event);
+ }
+
$this->sessionMapper->delete($session);
+
+ if ($dispatchLeaveCallEvents) {
+ $this->dispatcher->dispatch(Room::EVENT_AFTER_SESSION_LEAVE_CALL, $event);
+ }
} else {
$this->sessionMapper->deleteByAttendeeId($participant->getAttendee()->getId());
}
- if ($participant->isGuest()
+ if ($participant->getAttendee()->getActorType() === Attendee::ACTOR_GUESTS
|| $participant->getAttendee()->getParticipantType() === Participant::USER_SELF_JOINED) {
$this->attendeeMapper->delete($participant->getAttendee());
}
- if (!$participant->isGuest()) {
+ if ($participant->getAttendee()->getActorType() !== Attendee::ACTOR_GUESTS) {
$this->dispatcher->dispatch(Room::EVENT_AFTER_ROOM_DISCONNECT, $event);
} else {
$this->dispatcher->dispatch(Room::EVENT_AFTER_PARTICIPANT_REMOVE, $event);
@@ -320,7 +348,7 @@ public function leaveRoomAsSession(Room $room, Participant $participant): void {
}
public function removeAttendee(Room $room, Participant $participant, string $reason): void {
- $isUser = $participant->getAttendee()->getActorType() === 'users';
+ $isUser = $participant->getAttendee()->getActorType() === Attendee::ACTOR_USERS;
if ($isUser) {
$user = $this->userManager->get($participant->getAttendee()->getActorId());
@@ -371,7 +399,7 @@ public function cleanGuestParticipants(Room $room): void {
->from('talk_sessions', 's')
->leftJoin('s', 'talk_attendees', 'a', $query->expr()->eq('s.attendee_id', 'a.id'))
->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter('guests')))
+ ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_GUESTS)))
->andWhere($query->expr()->lte('s.last_ping', $query->createNamedParameter($this->timeFactory->getTime() - 100, IQueryBuilder::PARAM_INT)));
$sessionTableIds = [];
@@ -388,7 +416,7 @@ public function cleanGuestParticipants(Room $room): void {
->from('talk_attendees', 'a')
->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('s.attendee_id', 'a.id'))
->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter('guests')))
+ ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_GUESTS)))
->andWhere($query->expr()->isNull('s.id'));
$attendeeIds = [];
@@ -437,7 +465,7 @@ public function markUsersAsMentioned(Room $room, array $userIds, int $messageId)
$query->update('talk_attendees')
->set('last_mention_message', $query->createNamedParameter($messageId, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->eq('actor_type', $query->createNamedParameter('users')))
+ ->andWhere($query->expr()->eq('actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)))
->andWhere($query->expr()->in('actor_id', $query->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY)));
$query->execute();
}
@@ -562,7 +590,7 @@ public function getParticipantUserIds(Room $room, \DateTime $maxLastJoined = nul
if ($maxLastJoined !== null) {
$maxLastJoinedTimestamp = $maxLastJoined->getTimestamp();
}
- $attendees = $this->attendeeMapper->getActorsByType($room->getId(), 'users', $maxLastJoinedTimestamp);
+ $attendees = $this->attendeeMapper->getActorsByType($room->getId(), Attendee::ACTOR_USERS, $maxLastJoinedTimestamp);
return array_map(static function (Attendee $attendee) {
return $attendee->getActorId();
@@ -583,7 +611,7 @@ public function getParticipantUserIdsNotInCall(Room $room): array {
$query->expr()->eq('s.attendee_id', 'a.id')
)
->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter('users')))
+ ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter(Attendee::ACTOR_USERS)))
->andWhere($query->expr()->orX(
$query->expr()->eq('s.in_call', $query->createNamedParameter(Participant::FLAG_DISCONNECTED)),
$query->expr()->isNull('s.in_call')
diff --git a/lib/Service/RoomService.php b/lib/Service/RoomService.php
index 69ade564dac..afc87851f8c 100644
--- a/lib/Service/RoomService.php
+++ b/lib/Service/RoomService.php
@@ -26,6 +26,7 @@
use InvalidArgumentException;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCP\IUser;
@@ -65,12 +66,12 @@ public function createOneToOneConversation(IUser $actor, IUser $targetUser): Roo
$this->participantService->addUsers($room, [
[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $actor->getUID(),
'participantType' => Participant::OWNER,
],
[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $targetUser->getUID(),
'participantType' => Participant::OWNER,
],
@@ -124,7 +125,7 @@ public function createConversation(int $type, string $name, ?IUser $owner = null
if ($owner instanceof IUser) {
$this->participantService->addUsers($room, [[
- 'actorType' => 'users',
+ 'actorType' => Attendee::ACTOR_USERS,
'actorId' => $owner->getUID(),
'participantType' => Participant::OWNER,
]]);
diff --git a/lib/Service/SessionService.php b/lib/Service/SessionService.php
index 37b8d6af46a..7d66b8d9813 100644
--- a/lib/Service/SessionService.php
+++ b/lib/Service/SessionService.php
@@ -78,21 +78,37 @@ public function deleteSessionsById(array $ids): void {
$this->sessionMapper->deleteByIds($ids);
}
- public function createSessionForAttendee(Attendee $attendee): Session {
+ /**
+ * @param Attendee $attendee
+ * @param string $forceSessionId
+ * @return Session
+ * @throws UniqueConstraintViolationException
+ */
+ public function createSessionForAttendee(Attendee $attendee, string $forceSessionId = ''): Session {
// Currently a participant can only join once
$this->sessionMapper->deleteByAttendeeId($attendee->getId());
$session = new Session();
$session->setAttendeeId($attendee->getId());
- while (true) {
- $sessionId = $this->secureRandom->generate(255);
- $session->setSessionId($sessionId);
+ if ($forceSessionId !== '') {
+ $session->setSessionId($forceSessionId);
try {
$this->sessionMapper->insert($session);
- break;
} catch (UniqueConstraintViolationException $e) {
- // 255 chars are not unique? Try again...
+ // The HPB told us to use a session which exists already…
+ throw $e;
+ }
+ } else {
+ while (true) {
+ $sessionId = $this->secureRandom->generate(255);
+ $session->setSessionId($sessionId);
+ try {
+ $this->sessionMapper->insert($session);
+ break;
+ } catch (UniqueConstraintViolationException $e) {
+ // 255 chars are not unique? Try again...
+ }
}
}
diff --git a/lib/Settings/Admin/AdminSettings.php b/lib/Settings/Admin/AdminSettings.php
index 4623d914d1c..66f6525ff3c 100644
--- a/lib/Settings/Admin/AdminSettings.php
+++ b/lib/Settings/Admin/AdminSettings.php
@@ -99,7 +99,7 @@ public function getForm(): TemplateResponse {
$this->initTurnServers();
$this->initSignalingServers();
$this->initRequestSignalingServerTrial();
-// $this->initSIPBridge();
+ $this->initSIPBridge();
return new TemplateResponse('spreed', 'settings/admin-settings', [], '');
}
diff --git a/lib/Signaling/BackendNotifier.php b/lib/Signaling/BackendNotifier.php
index 1ada571c703..e1429f9e90f 100644
--- a/lib/Signaling/BackendNotifier.php
+++ b/lib/Signaling/BackendNotifier.php
@@ -26,6 +26,7 @@
namespace OCA\Talk\Signaling;
use OCA\Talk\Config;
+use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -147,7 +148,7 @@ public function roomInvited(Room $room, array $users): void {
$this->logger->info('Now invited to ' . $room->getToken() . ': ' . print_r($users, true));
$userIds = [];
foreach ($users as $user) {
- if ($user['actorType'] === 'users') {
+ if ($user['actorType'] === Attendee::ACTOR_USERS) {
$userIds[] = $user['actorId'];
}
}
@@ -253,8 +254,8 @@ public function participantsModified(Room $room, array $sessionIds): void {
$participants = $this->participantService->getParticipantsForRoom($room);
foreach ($participants as $participant) {
$attendee = $participant->getAttendee();
- if ($attendee->getActorType() !== 'users'
- && $attendee->getActorType() !== 'guests') {
+ if ($attendee->getActorType() !== Attendee::ACTOR_USERS
+ && $attendee->getActorType() !== Attendee::ACTOR_GUESTS) {
continue;
}
@@ -264,7 +265,7 @@ public function participantsModified(Room $room, array $sessionIds): void {
'sessionId' => '0',
'participantType' => $attendee->getParticipantType(),
];
- if ($attendee->getActorType() === 'users') {
+ if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$data['userId'] = $attendee->getActorId();
}
@@ -313,8 +314,8 @@ public function roomInCallChanged(Room $room, int $flags, array $sessionIds): vo
$participants = $this->participantService->getParticipantsForRoom($room);
foreach ($participants as $participant) {
$attendee = $participant->getAttendee();
- if ($attendee->getActorType() !== 'users'
- && $attendee->getActorType() !== 'guests') {
+ if ($attendee->getActorType() !== Attendee::ACTOR_USERS
+ && $attendee->getActorType() !== Attendee::ACTOR_GUESTS) {
continue;
}
@@ -324,7 +325,7 @@ public function roomInCallChanged(Room $room, int $flags, array $sessionIds): vo
'sessionId' => '0',
'participantType' => $attendee->getParticipantType(),
];
- if ($attendee->getActorType() === 'users') {
+ if ($attendee->getActorType() === Attendee::ACTOR_USERS) {
$data['userId'] = $attendee->getActorId();
}
diff --git a/lib/TInitialState.php b/lib/TInitialState.php
index c918befe3fa..5b771d50f65 100644
--- a/lib/TInitialState.php
+++ b/lib/TInitialState.php
@@ -67,6 +67,11 @@ protected function publishInitialStateShared(): void {
'talk', 'signaling_mode',
$this->talkConfig->getSignalingMode()
);
+
+ $this->initialStateService->provideInitialState(
+ 'talk', 'sip_dialin_info',
+ $this->talkConfig->getDialInInfo()
+ );
}
protected function publishInitialStateForUser(IUser $user, IRootFolder $rootFolder, IAppManager $appManager): void {
diff --git a/psalm.xml b/psalm.xml
index 050ae81010c..4b701c084c1 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -20,19 +20,25 @@
-
-
+
+
+
+
+
+
+
+
diff --git a/src/components/AdminSettings/SIPBridge.vue b/src/components/AdminSettings/SIPBridge.vue
index e626261512f..6559c4b0a36 100644
--- a/src/components/AdminSettings/SIPBridge.vue
+++ b/src/components/AdminSettings/SIPBridge.vue
@@ -1,5 +1,5 @@
+
+
+
+
{{ t('spreed', 'Dial-in information') }}
+
+
{{ dialInInfo }}
+
{{ meetingIdLabel }}
+
{{ attendeePinLabel }}
+
+
+
+
diff --git a/src/components/TopBar/TopBar.vue b/src/components/TopBar/TopBar.vue
index 4832354305f..1955b70b846 100644
--- a/src/components/TopBar/TopBar.vue
+++ b/src/components/TopBar/TopBar.vue
@@ -141,6 +141,7 @@
{{ t('spreed', 'Start time (optional)') }}
{{ t('spreed', 'Enable SIP dial-in') }}
@@ -296,6 +297,9 @@ export default {
showModerationOptions() {
return !this.isOneToOneConversation && this.canModerate
},
+ canUserEnableSIP() {
+ return this.conversation.canEnableSIP
+ },
token() {
return this.$store.getters.getToken()
},
@@ -311,6 +315,7 @@ export default {
displayName: '',
isFavorite: false,
hasPassword: false,
+ canEnableSIP: false,
type: CONVERSATION.TYPE.PUBLIC,
lobbyState: WEBINAR.LOBBY.NONE,
lobbyTimer: 0,
diff --git a/src/constants.js b/src/constants.js
index e5a5cfb09c5..a3d3c0a9855 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -49,6 +49,12 @@ export const PARTICIPANT = {
WITH_VIDEO: 4,
WITH_PHONE: 8,
},
+ SIP_FLAG: {
+ MUTE_MICROPHONE: 1,
+ MUTE_SPEAKER: 2,
+ SPEAKING: 4,
+ RAISE_HAND: 8,
+ },
NOTIFY: {
DEFAULT: 0,
ALWAYS: 1,
diff --git a/src/services/callsService.js b/src/services/callsService.js
index 3298522c0ea..86b39cb2498 100644
--- a/src/services/callsService.js
+++ b/src/services/callsService.js
@@ -53,17 +53,9 @@ const leaveCall = async function(token) {
}
}
-/**
- * Fetches all peers for a call
- * @param {string} token The token of the call to be fetched.
- */
-const fetchPeers = async function(token) {
- try {
- const response = await axios.get(generateOcsUrl('apps/spreed/api/v1', 2) + `call/${token}`)
- return response
- } catch (error) {
- console.debug('Error while fetching the peers: ', error)
- }
+const fetchPeers = async function(token, options) {
+ const response = await axios.get(generateOcsUrl('apps/spreed/api/v3', 2) + `call/${token}`, options)
+ return response
}
export {
diff --git a/src/store/participantsStore.js b/src/store/participantsStore.js
index 1da71d610ec..b191a8a45a8 100644
--- a/src/store/participantsStore.js
+++ b/src/store/participantsStore.js
@@ -34,6 +34,8 @@ import { PARTICIPANT } from '../constants'
const state = {
participants: {
},
+ peers: {
+ },
}
const getters = {
@@ -71,6 +73,17 @@ const getters = {
return index
},
+ getPeer: (state) => (token, sessionId) => {
+ if (!state.peers[token]) {
+ return {}
+ }
+
+ if (state.peers[token].hasOwnProperty(sessionId)) {
+ return state.peers[token][sessionId]
+ }
+
+ return {}
+ },
}
const mutations = {
@@ -110,6 +123,18 @@ const mutations = {
Vue.delete(state.participants, token)
}
},
+
+ addPeer(state, { token, peer }) {
+ if (!state.peers[token]) {
+ Vue.set(state.peers, token, [])
+ }
+ Vue.set(state.peers[token], peer.sessionId, peer)
+ },
+ purgePeersStore(state, token) {
+ if (state.peers[token]) {
+ Vue.delete(state.peers, token)
+ }
+ },
}
const actions = {
@@ -189,6 +214,13 @@ const actions = {
commit('purgeParticipantsStore', token)
},
+ addPeer({ commit }, { token, peer }) {
+ commit('addPeer', { token, peer })
+ },
+ purgePeersStore({ commit }, token) {
+ commit('purgePeersStore', token)
+ },
+
updateSessionId({ commit, getters }, { token, participantIdentifier, sessionId }) {
const index = getters.getParticipantIndex(token, participantIdentifier)
if (index === -1) {
diff --git a/src/utils/signaling.js b/src/utils/signaling.js
index 1b0af2b75f8..6042e98de0c 100644
--- a/src/utils/signaling.js
+++ b/src/utils/signaling.js
@@ -1147,6 +1147,9 @@ Signaling.Standalone.prototype.processRoomParticipantsEvent = function(data) {
this._trigger('usersChanged', [data.event.update.users || []])
this._trigger('participantListChanged')
break
+ case 'flags':
+ this._trigger('participantFlagsChanged', [data.event.flags || []])
+ break
default:
console.error('Unknown room participant event', data)
break
diff --git a/src/utils/webrtc/models/CallParticipantModel.js b/src/utils/webrtc/models/CallParticipantModel.js
index 88b7e0f6226..185d85a8df2 100644
--- a/src/utils/webrtc/models/CallParticipantModel.js
+++ b/src/utils/webrtc/models/CallParticipantModel.js
@@ -43,6 +43,7 @@ export default function CallParticipantModel(options) {
// are used for known but negative/empty values.
userId: undefined,
name: undefined,
+ internal: undefined,
connectionState: ConnectionState.NEW,
stream: null,
// The audio element is part of the model to ensure that it can be
diff --git a/src/utils/webrtc/webrtc.js b/src/utils/webrtc/webrtc.js
index 0535e15002d..be9ee4e993b 100644
--- a/src/utils/webrtc/webrtc.js
+++ b/src/utils/webrtc/webrtc.js
@@ -237,6 +237,9 @@ function usersChanged(signaling, newUsers, disconnectedSessionIds) {
})
}
callParticipantModel.setUserId(userId)
+ if (user.internal) {
+ callParticipantModel.set('internal', true)
+ }
// When the MCU is used and the other participant has no streams or
// when no MCU is used and neither the local participant nor the
@@ -394,6 +397,20 @@ export default function initWebRTC(signaling, _callParticipantCollection, _local
})
usersInCallChanged(signaling, usersInCallMapping)
})
+ signaling.on('participantFlagsChanged', function(event) {
+ /**
+ * event {
+ * roomid: "1609407087",
+ * sessionid: "…",
+ * flags: 1
+ * }
+ */
+ const callParticipantModel = callParticipantCollection.get(event.sessionid)
+ if (callParticipantModel) {
+ callParticipantModel.set('speaking', (event.flags & PARTICIPANT.SIP_FLAG.SPEAKING) > 0)
+ callParticipantModel.set('audioAvailable', (event.flags & PARTICIPANT.SIP_FLAG.MUTE_MICROPHONE) === 0)
+ }
+ })
signaling.on('usersInRoom', function(users) {
usersInCallMapping = {}
users.forEach(function(user) {
diff --git a/src/views/AdminSettings.vue b/src/views/AdminSettings.vue
index 69cc90c4f14..095c7903b92 100644
--- a/src/views/AdminSettings.vue
+++ b/src/views/AdminSettings.vue
@@ -30,7 +30,7 @@
-
+
@@ -41,7 +41,7 @@ import GeneralSettings from '../components/AdminSettings/GeneralSettings'
import HostedSignalingServer from '../components/AdminSettings/HostedSignalingServer'
import MatterbridgeIntegration from '../components/AdminSettings/MatterbridgeIntegration'
import SignalingServers from '../components/AdminSettings/SignalingServers'
-// import SIPBridge from '../components/AdminSettings/SIPBridge'
+import SIPBridge from '../components/AdminSettings/SIPBridge'
import StunServers from '../components/AdminSettings/StunServers'
import TurnServers from '../components/AdminSettings/TurnServers'
@@ -55,7 +55,7 @@ export default {
HostedSignalingServer,
MatterbridgeIntegration,
SignalingServers,
- // SIPBridge,
+ SIPBridge,
StunServers,
TurnServers,
},
diff --git a/tests/integration/features/command/active-calls.feature b/tests/integration/features/command/active-calls.feature
index f73145c774b..e7ab23b5c44 100644
--- a/tests/integration/features/command/active-calls.feature
+++ b/tests/integration/features/command/active-calls.feature
@@ -30,6 +30,7 @@ Feature: create
And user "participant1" joins call "room" with 200
Given invoking occ with "talk:active-calls"
+ # It didn't really fail, it just has an exit code that is not 0
Then the command failed with exit code 1
And the command output contains the text "There are currently 1 calls in progress with 1 participants"
diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php
index e9da6f7f2f7..b99e10ef191 100644
--- a/tests/php/Controller/SignalingControllerTest.php
+++ b/tests/php/Controller/SignalingControllerTest.php
@@ -591,10 +591,6 @@ public function testBackendRoomInvitedPublic() {
->willReturn($room);
$participant = $this->createMock(Participant::class);
- $room->expects($this->once())
- ->method('getParticipantBySession')
- ->with($sessionId)
- ->willThrowException(new ParticipantNotFoundException());
$room->expects($this->once())
->method('getParticipantBySession')
->with($sessionId)
diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml
index 62636e07546..e3320df41f7 100644
--- a/tests/psalm-baseline.xml
+++ b/tests/psalm-baseline.xml
@@ -1,5 +1,5 @@
-
+
BeforeTemplateRenderedEvent
@@ -38,6 +38,12 @@
getById
+
+
+ $listener
+ $listener
+
+
Base
@@ -172,16 +178,6 @@
DBALException
-
-
- $success
-
-
-
-
- $success
-
-
IRootFolder
@@ -217,10 +213,6 @@
-
- 'Internal signaling disabled.'
- 'Internal signaling disabled.'
-
\GuzzleHttp\Exception\ConnectException
@@ -249,13 +241,16 @@
GroupFolderStorage
+
+
+
\Doctrine\DBAL\DBALException
-
+
@@ -341,6 +336,9 @@
+
+ [self::class, 'listenPreShare']
+
$event->getView()
$event->getView()
@@ -350,16 +348,6 @@
$view
Filesystem
-
-
-
-
- $listener
- $listener
-
-
-
-
@@ -387,12 +375,6 @@
Cache
-
-
- IURLGenerator
- IUrlGenerator
-
-
IRootFolder