Fix not leaving previous session when joining the same room again

When the same room is joined again from the same PHP session the room is
left with the previous Nextcloud session before joining with the new
one. However, "disinvite" messages were not sent to the external signaling
server for regular users, so their UI was not updated to show that the
previous Nextcloud session was kicked out from the conversation.

Note, however, that as a "disinvite" message is now sent the UI will
show a "conversation not found" message rather than a "duplicated
session" state.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Daniel Calviño Sánchez 2022-08-25 14:33:12 +02:00
Родитель be6fa63298
Коммит 85f73b06b6
5 изменённых файлов: 93 добавлений и 5 удалений

Просмотреть файл

@ -1390,7 +1390,7 @@ class RoomController extends AEnvironmentAwareController {
$this->participantService->changeInCall($room, $previousParticipant, Participant::FLAG_DISCONNECTED);
}
$this->participantService->leaveRoomAsSession($room, $previousParticipant);
$this->participantService->leaveRoomAsSession($room, $previousParticipant, true);
}
$user = $this->userManager->get($this->userId);

Просмотреть файл

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Talk\Events;
use OCA\Talk\Participant;
use OCA\Talk\Room;
class DuplicatedParticipantEvent extends ParticipantEvent {
public function __construct(Room $room,
Participant $participant) {
parent::__construct($room, $participant);
}
}

Просмотреть файл

@ -33,6 +33,7 @@ use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
use OCA\Talk\Events\ChatEvent;
use OCA\Talk\Events\DuplicatedParticipantEvent;
use OCA\Talk\Events\EndCallForEveryoneEvent;
use OCA\Talk\Events\JoinRoomGuestEvent;
use OCA\Talk\Events\JoinRoomUserEvent;
@ -692,8 +693,12 @@ class ParticipantService {
}
}
public function leaveRoomAsSession(Room $room, Participant $participant): void {
$event = new ParticipantEvent($room, $participant);
public function leaveRoomAsSession(Room $room, Participant $participant, bool $duplicatedParticipant = false): void {
if ($duplicatedParticipant) {
$event = new DuplicatedParticipantEvent($room, $participant);
} else {
$event = new ParticipantEvent($room, $participant);
}
$this->dispatcher->dispatch(Room::EVENT_BEFORE_ROOM_DISCONNECT, $event);
$session = $participant->getSession();

Просмотреть файл

@ -27,6 +27,7 @@ use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Config;
use OCA\Talk\Events\AddParticipantsEvent;
use OCA\Talk\Events\ChatEvent;
use OCA\Talk\Events\DuplicatedParticipantEvent;
use OCA\Talk\Events\EndCallForEveryoneEvent;
use OCA\Talk\Events\ModifyEveryoneEvent;
use OCA\Talk\Events\ModifyParticipantEvent;
@ -248,9 +249,13 @@ class Listener {
$sessionIds = [];
if ($event->getParticipant()->getSession()) {
// Only for guests and self-joined users disconnecting is "leaving" and therefor should trigger a disinvite
// If a previous duplicated session is being removed it must be
// notified to the external signaling server. Otherwise only for
// guests and self-joined users disconnecting is "leaving" and
// therefor should trigger a disinvite.
$attendeeParticipantType = $event->getParticipant()->getAttendee()->getParticipantType();
if ($attendeeParticipantType === Participant::GUEST
if ($event instanceof DuplicatedParticipantEvent
|| $attendeeParticipantType === Participant::GUEST
|| $attendeeParticipantType === Participant::GUEST_MODERATOR) {
$sessionIds[] = $event->getParticipant()->getSession()->getSessionId();
$notifier->roomSessionsRemoved($event->getRoom(), $sessionIds);

Просмотреть файл

@ -352,6 +352,50 @@ class BackendNotifierTest extends TestCase {
$this->assertNoMessageOfTypeWasSent($room, 'disinvite');
}
public function testRoomDisinviteOnLeaveOfNormalUserWithDuplicatedSession() {
/** @var IUser|MockObject $testUser */
$testUser = $this->createMock(IUser::class);
$testUser->expects($this->any())
->method('getUID')
->willReturn($this->userId);
$roomService = $this->createMock(RoomService::class);
$roomService->method('verifyPassword')
->willReturn(['result' => true, 'url' => '']);
$room = $this->manager->createRoom(Room::TYPE_PUBLIC);
$this->participantService->addUsers($room, [[
'actorType' => 'users',
'actorId' => $this->userId,
]]);
$participant = $this->participantService->joinRoom($roomService, $room, $testUser, '');
$this->controller->clearRequests();
$this->participantService->leaveRoomAsSession($room, $participant, true);
$this->assertMessageWasSent($room, [
'type' => 'disinvite',
'disinvite' => [
'sessionids' => [
$participant->getSession()->getSessionId(),
],
'alluserids' => [
$this->userId,
],
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
'lobby-state' => Webinary::LOBBY_NONE,
'lobby-timer' => null,
'read-only' => Room::READ_WRITE,
'listable' => Room::LISTABLE_NONE,
'active-since' => null,
'sip-enabled' => 0,
'participant-list' => 'refresh',
],
],
]);
}
public function testRoomDisinviteOnLeaveOfSelfJoinedUser() {
/** @var IUser|MockObject $testUser */
$testUser = $this->createMock(IUser::class);