Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoas Schilling <213943+nickvergessen@users.noreply.github.com>2020-03-02 18:50:49 +0300
committerGitHub <noreply@github.com>2020-03-02 18:50:49 +0300
commit0949866ee9fc849b740da4ca61cb58adee764a51 (patch)
treed22d39061b58bd1511f758dbe7352f97c438f50f
parentdd906a7fc65e7ad209fb6db6de50d714edb01b72 (diff)
parent8e8b5af1f8fdbbe8689afbd0b8fccae4e145f780 (diff)
Merge pull request #3038 from nextcloud/backport/2260/stable18
[stable18] Get room properties for the signaling server from separate function.
-rw-r--r--docs/events.md6
-rw-r--r--lib/Chat/SystemMessage/Listener.php31
-rw-r--r--lib/Controller/CallController.php1
-rw-r--r--lib/Controller/SignalingController.php5
-rw-r--r--lib/Events/SignalingRoomPropertiesEvent.php56
-rw-r--r--lib/Room.php55
-rw-r--r--lib/Signaling/BackendNotifier.php20
-rw-r--r--src/App.vue14
-rw-r--r--src/views/MainView.vue12
-rw-r--r--tests/php/Controller/SignalingControllerTest.php48
-rw-r--r--tests/php/Signaling/BackendNotifierTest.php73
11 files changed, 262 insertions, 59 deletions
diff --git a/docs/events.md b/docs/events.md
index 7212789e9..c4701df75 100644
--- a/docs/events.md
+++ b/docs/events.md
@@ -195,3 +195,9 @@ Explanations:
* Event class: `OCA\Talk\Events\SignalingEvent`
* Event name: `OCA\Talk\Controller\SignalingController::EVENT_BACKEND_SIGNALING_ROOMS`
* Since: 8.0.0
+
+### Get conversation properties for signaling
+
+* Event class: `OCA\Talk\Events\SignalingRoomPropertiesEvent`
+* Event name: `OCA\Talk\Room::EVENT_BEFORE_SIGNALING_PROPERTIES`
+* Since: 8.0.5
diff --git a/lib/Chat/SystemMessage/Listener.php b/lib/Chat/SystemMessage/Listener.php
index 71ea8c625..2fa0ce69f 100644
--- a/lib/Chat/SystemMessage/Listener.php
+++ b/lib/Chat/SystemMessage/Listener.php
@@ -78,10 +78,16 @@ class Listener {
});
$dispatcher->addListener(Room::EVENT_AFTER_SESSION_LEAVE_CALL, static function(ModifyParticipantEvent $event) {
$room = $event->getRoom();
+
+ if ($event->getParticipant()->getInCallFlags() === Participant::FLAG_DISCONNECTED) {
+ // This happens in case the user was kicked/lobbied
+ return;
+ }
+
/** @var self $listener */
$listener = \OC::$server->query(self::class);
- $listener->sendSystemMessage($room, 'call_left');
+ $listener->sendSystemMessage($room, 'call_left', [], $event->getParticipant());
});
$dispatcher->addListener(Room::EVENT_AFTER_ROOM_CREATE, static function(RoomEvent $event) {
@@ -239,15 +245,22 @@ class Listener {
$dispatcher->addListener(RoomShareProvider::class . '::' . 'share_file_again', $listener);
}
- protected function sendSystemMessage(Room $room, string $message, array $parameters = []): void {
- $user = $this->userSession->getUser();
- if (!$user instanceof IUser) {
- $actorType = 'guests';
- $sessionId = $this->talkSession->getSessionForRoom($room->getToken());
- $actorId = $sessionId ? sha1($sessionId) : 'failed-to-get-session';
+ protected function sendSystemMessage(Room $room, string $message, array $parameters = [], Participant $participant = null): void {
+ if ($participant instanceof Participant) {
+ $actorType = $participant->isGuest() ? 'guests' : 'users';
+ $sessionId = $participant->getSessionId();
+ $sessionHash = $sessionId ? sha1($sessionId) : 'failed-to-get-session';
+ $actorId = $participant->isGuest() ? $sessionHash : $participant->getUser();
} else {
- $actorType = 'users';
- $actorId = $user->getUID();
+ $user = $this->userSession->getUser();
+ if (!$user instanceof IUser) {
+ $actorType = 'guests';
+ $sessionId = $this->talkSession->getSessionForRoom($room->getToken());
+ $actorId = $sessionId ? sha1($sessionId) : 'failed-to-get-session';
+ } else {
+ $actorType = 'users';
+ $actorId = $user->getUID();
+ }
}
$this->chatManager->addSystemMessage(
diff --git a/lib/Controller/CallController.php b/lib/Controller/CallController.php
index dd8a34514..3f743538a 100644
--- a/lib/Controller/CallController.php
+++ b/lib/Controller/CallController.php
@@ -102,7 +102,6 @@ class CallController extends AEnvironmentAwareController {
/**
* @PublicPage
* @RequireParticipant
- * @RequireModeratorOrNoLobby
*
* @return DataResponse
*/
diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php
index 8bf0f372b..c4d76dbf4 100644
--- a/lib/Controller/SignalingController.php
+++ b/lib/Controller/SignalingController.php
@@ -436,10 +436,7 @@ class SignalingController extends OCSController {
'room' => [
'version' => '1.0',
'roomid' => $room->getToken(),
- 'properties' => [
- 'name' => $room->getDisplayName((string) $userId),
- 'type' => $room->getType(),
- ],
+ 'properties' => $room->getPropertiesForSignaling((string) $userId),
],
];
if ($event->getSession()) {
diff --git a/lib/Events/SignalingRoomPropertiesEvent.php b/lib/Events/SignalingRoomPropertiesEvent.php
new file mode 100644
index 000000000..e689be3f5
--- /dev/null
+++ b/lib/Events/SignalingRoomPropertiesEvent.php
@@ -0,0 +1,56 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.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\Room;
+
+class SignalingRoomPropertiesEvent extends RoomEvent {
+
+ /** @var string|null */
+ protected $userId;
+ /** @var array */
+ protected $properties;
+
+ public function __construct(Room $room, ?string $userId, array $properties) {
+ parent::__construct($room);
+ $this->userId = $userId;
+ $this->properties = $properties;
+ }
+
+ public function getUserId(): ?string {
+ return $this->userId;
+ }
+
+ public function getProperties(): array {
+ return $this->properties;
+ }
+
+ public function setProperty(string $property, $data): void {
+ $this->properties[$property] = $data;
+ }
+
+ public function unsetProperty(string $property): void {
+ unset($this->properties[$property]);
+ }
+}
diff --git a/lib/Room.php b/lib/Room.php
index 8420b51d2..d77380093 100644
--- a/lib/Room.php
+++ b/lib/Room.php
@@ -36,6 +36,7 @@ use OCA\Talk\Events\ParticipantEvent;
use OCA\Talk\Events\RemoveParticipantEvent;
use OCA\Talk\Events\RemoveUserEvent;
use OCA\Talk\Events\RoomEvent;
+use OCA\Talk\Events\SignalingRoomPropertiesEvent;
use OCA\Talk\Events\VerifyRoomPasswordEvent;
use OCA\Talk\Exceptions\InvalidPasswordException;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
@@ -100,6 +101,7 @@ class Room {
public const EVENT_AFTER_SESSION_JOIN_CALL = self::class . '::postSessionJoinCall';
public const EVENT_BEFORE_SESSION_LEAVE_CALL = self::class . '::preSessionLeaveCall';
public const EVENT_AFTER_SESSION_LEAVE_CALL = self::class . '::postSessionLeaveCall';
+ public const EVENT_BEFORE_SIGNALING_PROPERTIES = self::class . '::beforeSignalingProperties';
/** @var Manager */
private $manager;
@@ -279,6 +281,27 @@ class Room {
}
/**
+ * Return the room properties to send to the signaling server.
+ *
+ * @param string $userId
+ * @return array
+ */
+ public function getPropertiesForSignaling(string $userId): array {
+ $properties = [
+ 'name' => $this->getDisplayName($userId),
+ 'type' => $this->getType(),
+ 'lobby-state' => $this->getLobbyState(),
+ 'lobby-timer' => $this->getLobbyTimer(),
+ 'read-only' => $this->getReadOnly(),
+ 'active-since' => $this->getActiveSince(),
+ ];
+
+ $event = new SignalingRoomPropertiesEvent($this, $userId, $properties);
+ $this->dispatcher->dispatch(self::EVENT_BEFORE_SIGNALING_PROPERTIES, $event);
+ return $event->getProperties();
+ }
+
+ /**
* @param string|null $userId
* @return Participant
* @throws ParticipantNotFoundException When the user is not a participant
@@ -597,6 +620,17 @@ class Room {
$this->dispatcher->dispatch(self::EVENT_AFTER_LOBBY_STATE_SET, $event);
+ if ($newState === Webinary::LOBBY_NON_MODERATORS) {
+ $participants = $this->getParticipantsInCall();
+ foreach ($participants as $participant) {
+ if ($participant->hasModeratorPermissions()) {
+ continue;
+ }
+
+ $this->changeInCall($participant, Participant::FLAG_DISCONNECTED);
+ }
+ }
+
return true;
}
@@ -962,6 +996,27 @@ class Room {
}
/**
+ * @return Participant[]
+ */
+ public function getParticipantsInCall(): array {
+ $query = $this->db->getQueryBuilder();
+ $query->select('*')
+ ->from('talk_participants')
+ ->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)))
+ ->andWhere($query->expr()->neq('in_call', $query->createNamedParameter(Participant::FLAG_DISCONNECTED)));
+
+ $result = $query->execute();
+
+ $participants = [];
+ while ($row = $result->fetch()) {
+ $participants[] = $this->manager->createParticipantObject($this, $row);
+ }
+ $result->closeCursor();
+
+ return $participants;
+ }
+
+ /**
* @param int $lastPing When the last ping is older than the given timestamp, the user is ignored
* @return array[] Array of users with [users => [userId => [lastPing, sessionId]], guests => [[lastPing, sessionId]]]
* @deprecated Use self::getParticipants() instead
diff --git a/lib/Signaling/BackendNotifier.php b/lib/Signaling/BackendNotifier.php
index 642fc19d2..5750e0d14 100644
--- a/lib/Signaling/BackendNotifier.php
+++ b/lib/Signaling/BackendNotifier.php
@@ -131,10 +131,7 @@ class BackendNotifier {
// TODO(fancycode): We should try to get rid of 'alluserids' and
// find a better way to notify existing users to update the room.
'alluserids' => $room->getParticipantUserIds(),
- 'properties' => [
- 'name' => $room->getDisplayName(''),
- 'type' => $room->getType(),
- ],
+ 'properties' => $room->getPropertiesForSignaling(''),
],
]);
}
@@ -155,10 +152,7 @@ class BackendNotifier {
// TODO(fancycode): We should try to get rid of 'alluserids' and
// find a better way to notify existing users to update the room.
'alluserids' => $room->getParticipantUserIds(),
- 'properties' => [
- 'name' => $room->getDisplayName(''),
- 'type' => $room->getType(),
- ],
+ 'properties' => $room->getPropertiesForSignaling(''),
],
]);
}
@@ -179,10 +173,7 @@ class BackendNotifier {
// TODO(fancycode): We should try to get rid of 'alluserids' and
// find a better way to notify existing users to update the room.
'alluserids' => $room->getParticipantUserIds(),
- 'properties' => [
- 'name' => $room->getDisplayName(''),
- 'type' => $room->getType(),
- ],
+ 'properties' => $room->getPropertiesForSignaling(''),
],
]);
}
@@ -199,10 +190,7 @@ class BackendNotifier {
'type' => 'update',
'update' => [
'userids' => $room->getParticipantUserIds(),
- 'properties' => [
- 'name' => $room->getDisplayName(''),
- 'type' => $room->getType(),
- ],
+ 'properties' => $room->getPropertiesForSignaling(''),
],
]);
}
diff --git a/src/App.vue b/src/App.vue
index 61c78e077..682b43ed4 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -155,6 +155,9 @@ export default {
},
beforeDestroy() {
+ if (!getCurrentUser()) {
+ EventBus.$off('shouldRefreshConversations', this.refreshCurrentConversation)
+ }
document.removeEventListener('visibilitychange', this.changeWindowVisibility)
},
@@ -163,6 +166,7 @@ export default {
EventBus.$once('joinedConversation', () => {
this.fixmeDelayedSetupOfGuestUsers()
})
+ EventBus.$on('shouldRefreshConversations', this.refreshCurrentConversation)
}
if (this.$route.name === 'conversation') {
@@ -199,7 +203,7 @@ export default {
&& !this.$store.getters.conversations[this.token]) {
if (!params.singleConversation) {
console.info('Conversations received, but the current conversation is not in the list, trying to get potential public conversation manually')
- this.fetchSingleConversation(this.token)
+ this.refreshCurrentConversation()
} else {
console.info('Conversation received, but the current conversation is not in the list. Redirecting to /apps/spreed')
this.$router.push('/apps/spreed/not-found')
@@ -278,13 +282,17 @@ export default {
fixmeDelayedSetupOfGuestUsers() {
// FIXME Refresh the data now that the user joined the conversation
// The join request returns this data already, but it's lost in the signaling code
- this.fetchSingleConversation(this.token)
+ this.refreshCurrentConversation()
window.setInterval(() => {
- this.fetchSingleConversation(this.token)
+ this.refreshCurrentConversation()
}, 30000)
},
+ refreshCurrentConversation() {
+ this.fetchSingleConversation(this.token)
+ },
+
changeWindowVisibility() {
this.$store.dispatch('setWindowVisibility', !document.hidden)
if (this.windowIsVisible) {
diff --git a/src/views/MainView.vue b/src/views/MainView.vue
index 4e3867f16..5b938bfb4 100644
--- a/src/views/MainView.vue
+++ b/src/views/MainView.vue
@@ -48,6 +48,18 @@ export default {
},
*/
+ watch: {
+ isInLobby: function(isInLobby) {
+ // User is now blocked by the lobby
+ if (isInLobby && this.participant.inCall !== PARTICIPANT.CALL_FLAG.DISCONNECTED) {
+ this.$store.dispatch('leaveCall', {
+ token: this.token,
+ participantIdentifier: this.$store.getters.getParticipantIdentifier(),
+ })
+ }
+ },
+ },
+
computed: {
conversation() {
return this.$store.getters.conversations[this.token]
diff --git a/tests/php/Controller/SignalingControllerTest.php b/tests/php/Controller/SignalingControllerTest.php
index 930a4a140..a536d37d7 100644
--- a/tests/php/Controller/SignalingControllerTest.php
+++ b/tests/php/Controller/SignalingControllerTest.php
@@ -367,10 +367,6 @@ class SignalingControllerTest extends \Test\TestCase {
$participant = $this->createMock(Participant::class);
$room->expects($this->once())
- ->method('getDisplayName')
- ->with($this->userId)
- ->willReturn($roomName);
- $room->expects($this->once())
->method('getParticipant')
->with($this->userId)
->willReturn($participant);
@@ -378,8 +374,12 @@ class SignalingControllerTest extends \Test\TestCase {
->method('getToken')
->willReturn($roomToken);
$room->expects($this->once())
- ->method('getType')
- ->willReturn(Room::ONE_TO_ONE_CALL);
+ ->method('getPropertiesForSignaling')
+ ->with($this->userId)
+ ->willReturn([
+ 'name' => $roomName,
+ 'type' => Room::ONE_TO_ONE_CALL,
+ ]);
$result = $this->performBackendRequest([
'type' => 'room',
@@ -414,10 +414,6 @@ class SignalingControllerTest extends \Test\TestCase {
$participant = $this->createMock(Participant::class);
$room->expects($this->once())
- ->method('getDisplayName')
- ->with('')
- ->willReturn($roomName);
- $room->expects($this->once())
->method('getParticipantBySession')
->with($sessionId)
->willReturn($participant);
@@ -425,8 +421,12 @@ class SignalingControllerTest extends \Test\TestCase {
->method('getToken')
->willReturn($roomToken);
$room->expects($this->once())
- ->method('getType')
- ->willReturn(Room::PUBLIC_CALL);
+ ->method('getPropertiesForSignaling')
+ ->with('')
+ ->willReturn([
+ 'name' => $roomName,
+ 'type' => Room::PUBLIC_CALL,
+ ]);
$result = $this->performBackendRequest([
'type' => 'room',
@@ -461,10 +461,6 @@ class SignalingControllerTest extends \Test\TestCase {
$participant = $this->createMock(Participant::class);
$room->expects($this->once())
- ->method('getDisplayName')
- ->with($this->userId)
- ->willReturn($roomName);
- $room->expects($this->once())
->method('getParticipant')
->with($this->userId)
->willThrowException(new ParticipantNotFoundException());
@@ -476,8 +472,12 @@ class SignalingControllerTest extends \Test\TestCase {
->method('getToken')
->willReturn($roomToken);
$room->expects($this->once())
- ->method('getType')
- ->willReturn(Room::PUBLIC_CALL);
+ ->method('getPropertiesForSignaling')
+ ->with($this->userId)
+ ->willReturn([
+ 'name' => $roomName,
+ 'type' => Room::PUBLIC_CALL,
+ ]);
$result = $this->performBackendRequest([
'type' => 'room',
@@ -550,10 +550,6 @@ class SignalingControllerTest extends \Test\TestCase {
$participant = $this->createMock(Participant::class);
$room->expects($this->once())
- ->method('getDisplayName')
- ->with($this->userId)
- ->willReturn($roomName);
- $room->expects($this->once())
->method('getParticipant')
->with($this->userId)
->willReturn($participant);
@@ -561,8 +557,12 @@ class SignalingControllerTest extends \Test\TestCase {
->method('getToken')
->willReturn($roomToken);
$room->expects($this->once())
- ->method('getType')
- ->willReturn(Room::ONE_TO_ONE_CALL);
+ ->method('getPropertiesForSignaling')
+ ->with($this->userId)
+ ->willReturn([
+ 'name' => $roomName,
+ 'type' => Room::ONE_TO_ONE_CALL,
+ ]);
$result = $this->performBackendRequest([
'type' => 'room',
diff --git a/tests/php/Signaling/BackendNotifierTest.php b/tests/php/Signaling/BackendNotifierTest.php
index f73653e52..e645328a9 100644
--- a/tests/php/Signaling/BackendNotifierTest.php
+++ b/tests/php/Signaling/BackendNotifierTest.php
@@ -25,6 +25,7 @@ namespace OCA\Talk\Tests\php\Signaling;
use OCA\Talk\AppInfo\Application;
use OCA\Talk\Chat\CommentsManager;
use OCA\Talk\Config;
+use OCA\Talk\Events\SignalingRoomPropertiesEvent;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -42,6 +43,7 @@ use OCP\IUserManager;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\Component\EventDispatcher\GenericEvent;
class CustomBackendNotifier extends BackendNotifier {
@@ -92,6 +94,8 @@ class BackendNotifierTest extends \Test\TestCase {
protected $app;
/** @var BackendNotifier */
protected $originalBackendNotifier;
+ /** @var IEventDispatcher */
+ private $dispatcher;
public function setUp(): void {
parent::setUp();
@@ -125,7 +129,7 @@ class BackendNotifierTest extends \Test\TestCase {
});
$dbConnection = \OC::$server->getDatabaseConnection();
- $dispatcher = \OC::$server->query(IEventDispatcher::class);
+ $this->dispatcher = \OC::$server->query(IEventDispatcher::class);
$this->manager = new Manager(
$dbConnection,
$config,
@@ -133,7 +137,7 @@ class BackendNotifierTest extends \Test\TestCase {
$this->createMock(IUserManager::class),
$this->createMock(CommentsManager::class),
$this->createMock(TalkSession::class),
- $dispatcher,
+ $this->dispatcher,
$this->timeFactory,
$this->createMock(IHasher::class),
$this->createMock(IL10N::class)
@@ -200,6 +204,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
],
],
], $bodies);
@@ -233,6 +241,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
],
],
], $bodies);
@@ -254,6 +266,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
],
],
], $bodies);
@@ -275,6 +291,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
],
],
], $bodies);
@@ -296,6 +316,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
],
],
], $bodies);
@@ -317,6 +341,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_ONLY,
+ 'active-since' => null,
],
],
], $bodies);
@@ -338,6 +366,10 @@ class BackendNotifierTest extends \Test\TestCase {
'properties' => [
'name' => $room->getDisplayName(''),
'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NON_MODERATORS,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
],
],
], $bodies);
@@ -474,4 +506,41 @@ class BackendNotifierTest extends \Test\TestCase {
], $bodies);
}
+ public function testRoomPropertiesEvent(): void {
+ $listener = static function(SignalingRoomPropertiesEvent $event) {
+ $room = $event->getRoom();
+ $event->setProperty('foo', 'bar');
+ $event->setProperty('room', $room->getToken());
+ };
+
+ $this->dispatcher->addListener(Room::EVENT_BEFORE_SIGNALING_PROPERTIES, $listener);
+
+ $room = $this->manager->createPublicRoom();
+ $this->controller->clearRequests();
+ $room->setName('Test room');
+
+ $requests = $this->controller->getRequests();
+ $bodies = array_map(function($request) use ($room) {
+ return json_decode($this->validateBackendRequest($this->baseUrl . '/api/v1/room/' . $room->getToken(), $request), true);
+ }, $requests);
+
+ $this->assertContains([
+ 'type' => 'update',
+ 'update' => [
+ 'userids' => [
+ ],
+ 'properties' => [
+ 'name' => $room->getDisplayName(''),
+ 'type' => $room->getType(),
+ 'lobby-state' => Webinary::LOBBY_NONE,
+ 'lobby-timer' => null,
+ 'read-only' => Room::READ_WRITE,
+ 'active-since' => null,
+ 'foo' => 'bar',
+ 'room' => $room->getToken(),
+ ],
+ ],
+ ], $bodies);
+ }
+
}