Grant permissions in the HPB based on publishing permissions

When a participant does not have publishing permissions the HPB will
block signaling messages related to establishing a connection, like
sending the candidates. This would prevent participants using clients
not supporting yet the publishing permissions (and thus still trying to
publish even if they are not allowed to) from sending media in a call.

Unfortunately the lack of permissions only prevents the connection from
being established. If a participant is already sending media revoking
the publishing permissions will not cause the connection to be stopped
by the HPB.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Daniel Calviño Sánchez 2021-02-08 20:55:52 +01:00 коммит произвёл Joas Schilling
Родитель 3b73e10ca4
Коммит 7631251c99
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 7076EA9751AACDDA
4 изменённых файлов: 133 добавлений и 6 удалений

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

@ -645,9 +645,17 @@ class SignalingController extends OCSController {
}
}
$permissions = ['publish-media', 'publish-screen'];
if ($participant instanceof Participant && $participant->hasModeratorPermissions(false)) {
$permissions[] = 'control';
$permissions = [];
if ($participant instanceof Participant) {
if ($participant->getAttendee()->getPublishingPermissions() & (Attendee::PUBLISHING_PERMISSIONS_AUDIO | Attendee::PUBLISHING_PERMISSIONS_VIDEO)) {
$permissions[] = 'publish-media';
}
if ($participant->getAttendee()->getPublishingPermissions() & Attendee::PUBLISHING_PERMISSIONS_SCREENSHARING) {
$permissions[] = 'publish-screen';
}
if ($participant->hasModeratorPermissions(false)) {
$permissions[] = 'control';
}
}
$event = new SignalingEvent($room, $participant, $action);

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

@ -277,7 +277,13 @@ class BackendNotifier {
$users[] = $data;
if (\in_array($session->getSessionId(), $sessionIds, true)) {
$data['permissions'] = ['publish-media', 'publish-screen'];
$data['permissions'] = [];
if ($attendee->getPublishingPermissions() & (Attendee::PUBLISHING_PERMISSIONS_AUDIO | Attendee::PUBLISHING_PERMISSIONS_VIDEO)) {
$data['permissions'][] = 'publish-media';
}
if ($attendee->getPublishingPermissions() & Attendee::PUBLISHING_PERMISSIONS_SCREENSHARING) {
$data['permissions'][] = 'publish-screen';
}
if ($attendee->getParticipantType() === Participant::OWNER ||
$attendee->getParticipantType() === Participant::MODERATOR) {
$data['permissions'][] = 'control';

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

@ -130,7 +130,8 @@ class Listener {
// "participantsModified" once the clients no longer expect a
// "roomModified" message for participant type changes.
$dispatcher->addListener(Room::EVENT_AFTER_PARTICIPANT_TYPE_SET, $listener);
$dispatcher->addListener(Room::EVENT_AFTER_PARTICIPANT_TYPE_SET, static function (ModifyParticipantEvent $event) {
$listener = static function (ModifyParticipantEvent $event) {
if (self::isUsingInternalSignaling()) {
return;
}
@ -151,7 +152,10 @@ class Listener {
}
$notifier->participantsModified($event->getRoom(), $sessionIds);
});
};
$dispatcher->addListener(Room::EVENT_AFTER_PARTICIPANT_TYPE_SET, $listener);
$dispatcher->addListener(Room::EVENT_AFTER_PARTICIPANT_PUBLISHING_PERMISSIONS_SET, $listener);
$dispatcher->addListener(Room::EVENT_BEFORE_ROOM_DELETE, static function (RoomEvent $event) {
if (self::isUsingInternalSignaling()) {
return;

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

@ -29,6 +29,7 @@ use OCA\Talk\Events\SignalingEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Model\Attendee;
use OCA\Talk\Model\AttendeeMapper;
use OCA\Talk\Model\SessionMapper;
use OCA\Talk\Participant;
@ -384,7 +385,13 @@ class SignalingControllerTest extends \Test\TestCase {
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => Attendee::PUBLISHING_PERMISSIONS_ALL,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$room->expects($this->once())
->method('getParticipant')
->with($this->userId)
@ -434,7 +441,13 @@ class SignalingControllerTest extends \Test\TestCase {
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => Attendee::PUBLISHING_PERMISSIONS_ALL,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$room->expects($this->once())
->method('getParticipant')
->with($this->userId)
@ -484,7 +497,13 @@ class SignalingControllerTest extends \Test\TestCase {
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => Attendee::PUBLISHING_PERMISSIONS_ALL,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$participant->expects($this->once())
->method('hasModeratorPermissions')
->with(false)
@ -540,7 +559,13 @@ class SignalingControllerTest extends \Test\TestCase {
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => Attendee::PUBLISHING_PERMISSIONS_ALL,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$room->expects($this->once())
->method('getParticipantBySession')
->with($sessionId)
@ -591,7 +616,13 @@ class SignalingControllerTest extends \Test\TestCase {
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => Attendee::PUBLISHING_PERMISSIONS_ALL,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$room->expects($this->once())
->method('getParticipantBySession')
->with($sessionId)
@ -632,6 +663,78 @@ class SignalingControllerTest extends \Test\TestCase {
], $result->getData());
}
public function dataBackendRoomUserPublicPublishingPermissions(): array {
return [
[Attendee::PUBLISHING_PERMISSIONS_NONE, []],
[Attendee::PUBLISHING_PERMISSIONS_AUDIO, ['publish-media']],
[Attendee::PUBLISHING_PERMISSIONS_VIDEO, ['publish-media']],
[Attendee::PUBLISHING_PERMISSIONS_VIDEO | Attendee::PUBLISHING_PERMISSIONS_VIDEO, ['publish-media']],
[Attendee::PUBLISHING_PERMISSIONS_SCREENSHARING, ['publish-screen']],
[Attendee::PUBLISHING_PERMISSIONS_AUDIO | Attendee::PUBLISHING_PERMISSIONS_SCREENSHARING, ['publish-media', 'publish-screen']],
[Attendee::PUBLISHING_PERMISSIONS_VIDEO | Attendee::PUBLISHING_PERMISSIONS_SCREENSHARING, ['publish-media', 'publish-screen']],
[Attendee::PUBLISHING_PERMISSIONS_AUDIO | Attendee::PUBLISHING_PERMISSIONS_VIDEO | Attendee::PUBLISHING_PERMISSIONS_SCREENSHARING, ['publish-media', 'publish-screen']],
];
}
/**
* @dataProvider dataBackendRoomUserPublicPublishingPermissions
*
* @param int $publishingPermissions
* @param array $expectedBackendPermissions
*/
public function testBackendRoomUserPublicPublishingPermissions(int $publishingPermissions, array $expectedBackendPermissions) {
$roomToken = 'the-room';
$roomName = 'the-room-name';
$room = $this->createMock(Room::class);
$this->manager->expects($this->once())
->method('getRoomByToken')
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => $publishingPermissions,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$room->expects($this->once())
->method('getParticipant')
->with($this->userId)
->willReturn($participant);
$room->expects($this->once())
->method('getToken')
->willReturn($roomToken);
$room->expects($this->once())
->method('getPropertiesForSignaling')
->with($this->userId)
->willReturn([
'name' => $roomName,
'type' => Room::PUBLIC_CALL,
]);
$result = $this->performBackendRequest([
'type' => 'room',
'room' => [
'roomid' => $roomToken,
'userid' => $this->userId,
'sessionid' => '',
],
]);
$this->assertSame([
'type' => 'room',
'room' => [
'version' => '1.0',
'roomid' => $roomToken,
'properties' => [
'name' => $roomName,
'type' => Room::PUBLIC_CALL,
],
'permissions' => $expectedBackendPermissions,
],
], $result->getData());
}
public function testBackendRoomAnonymousOneToOne() {
$roomToken = 'the-room';
$sessionId = 'the-session';
@ -679,7 +782,13 @@ class SignalingControllerTest extends \Test\TestCase {
->with($roomToken)
->willReturn($room);
$attendee = Attendee::fromRow([
'publishing_permissions' => Attendee::PUBLISHING_PERMISSIONS_ALL,
]);
$participant = $this->createMock(Participant::class);
$participant->expects($this->any())
->method('getAttendee')
->willReturn($attendee);
$room->expects($this->once())
->method('getParticipant')
->with($this->userId)