diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php index 166e010f3..82f5a7681 100644 --- a/lib/Controller/SignalingController.php +++ b/lib/Controller/SignalingController.php @@ -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); diff --git a/lib/Signaling/BackendNotifier.php b/lib/Signaling/BackendNotifier.php index 50f906c87..73b5d4c31 100644 --- a/lib/Signaling/BackendNotifier.php +++ b/lib/Signaling/BackendNotifier.php @@ -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'; diff --git a/lib/Signaling/Listener.php b/lib/Signaling/Listener.php index 9ebec18bd..e6213e5d0 100644 --- a/lib/Signaling/Listener.php +++ b/lib/Signaling/Listener.php @@ -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; diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php index 47bf31571..8064d8026 100644 --- a/tests/php/Controller/SignalingControllerTest.php +++ b/tests/php/Controller/SignalingControllerTest.php @@ -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)